factorio -> event -> mod -> console -> kafka pipe -> kafka -> event processor working!!!!!!!!!!!!!!!!!!

This commit is contained in:
Adam 2021-12-03 09:04:18 +01:00
parent 7091f7648d
commit 42b60ac0c3
19 changed files with 152 additions and 87 deletions

View file

@ -9,11 +9,11 @@
## todo ## todo
* add settings * add settings
* is active - whether files are exported or not * is active - whether files are exported or not
* delete files - clean up all files * delete files - clean up all files
* tick-rate - how often reports are generated ( * tick-rate - how often reports are generated (
* requires on some sort of in-mod cache of map<entity-id, event>) * requires on some sort of in-mod cache of map<entity-id, event>)
* also divide by game-speed? to keep ratio the same * also divide by game-speed? to keep ratio the same
### to investigate: ### to investigate:
@ -21,6 +21,11 @@
* https://github.com/grafi-tt/lunajson * https://github.com/grafi-tt/lunajson
* http://lua-users.org/wiki/CompressionAndArchiving * http://lua-users.org/wiki/CompressionAndArchiving
* https://luapower.com/zlib * https://luapower.com/zlib
* https://github.com/appgurueu/modlib#bluon
* https://github.com/dingyi222666/lua-table-serialize
* https://github.com/uriid1/lua-serialize
* https://github.com/rxi/lume#lumeserializex
* https://github.com/SwadicalRag/bON
* https://square.github.io/okio/#communicate-on-a-socket-javakotlin * https://square.github.io/okio/#communicate-on-a-socket-javakotlin
@ -30,6 +35,16 @@
* https://jbrandhorst.com/post/go-protobuf-tips/ * https://jbrandhorst.com/post/go-protobuf-tips/
##### flatbuffers
https://github.com/dvidelabs/flatcc
##### z85 encoding
* Kotlin https://gist.github.com/ischumacher/b4929f26341ebef62cbce35c65543eda
* Lua https://web-eworks.github.io/lZ85/
#### CBOR #### CBOR
https://www.zash.se/lua-cbor.html https://www.zash.se/lua-cbor.html

View file

@ -6,7 +6,7 @@ plugins {
} }
group = "dev.adamko" group = "dev.adamko"
version = "0.0.7" version = "0.1.1"
tasks.wrapper { tasks.wrapper {
gradleVersion = "7.3" gradleVersion = "7.3"
@ -26,7 +26,7 @@ val runKafkatorio by tasks.registering {
group = project.name group = project.name
dependsOn( dependsOn(
":modules:infra-factorio-client:processRun", ":modules:infra-factorio-client:processRestart",
":modules:infra-factorio-server:processRun", ":modules:infra-factorio-server:processRestart",
) )
} }

View file

@ -0,0 +1,9 @@
package dev.adamko.kafkatorio
import kotlinx.serialization.json.Json
val jsonMapper = Json {
prettyPrint = true
prettyPrintIndent = " "
}

View file

@ -1,8 +1,13 @@
package dev.adamko.kafkatorio.gradle package dev.adamko.kafkatorio.gradle
import dev.adamko.kafkatorio.jsonMapper
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.logging.LogLevel
import org.gradle.api.specs.Spec import org.gradle.api.specs.Spec
import org.gradle.kotlin.dsl.invoke import org.gradle.kotlin.dsl.invoke
@ -12,10 +17,28 @@ fun Project.isProcessRunning(process: String, ignoreCase: Boolean = true): Spec<
Spec<Task> { Spec<Task> {
ByteArrayOutputStream().use { outputStream -> ByteArrayOutputStream().use { outputStream ->
project.exec { project.exec {
commandLine("tasklist") commandLine("tasklist") // Windows only for now...
standardOutput = outputStream standardOutput = outputStream
} }
outputStream.toString() outputStream.toString()
.contains(process, ignoreCase) .contains(process, ignoreCase)
} }
} }
fun Project.areJsonPropertiesUpToDate(
packageJsonFile: RegularFileProperty,
properties: () -> Map<String, String>
): Spec<Task> = Spec<Task> {
val packageJsonContent = packageJsonFile.get().asFile.readText()
val packageJson = jsonMapper.parseToJsonElement(packageJsonContent).jsonObject
properties().all { (key, expectedVal) ->
val actualVal = packageJson[key]?.jsonPrimitive?.content
(expectedVal == actualVal).also {
logger.log(
if (it) LogLevel.LIFECYCLE else LogLevel.INFO,
"package.json has outdated property '$key' (expected: $expectedVal, actual: $actualVal)"
)
}
}
}

View file

@ -1,20 +1,17 @@
package dev.adamko.kafkatorio.lang package dev.adamko.kafkatorio.lang
import com.github.gradle.node.NodePlugin import com.github.gradle.node.NodePlugin
import dev.adamko.kafkatorio.task.UpdatePackageJson import dev.adamko.kafkatorio.gradle.areJsonPropertiesUpToDate
import dev.adamko.kafkatorio.gradle.not import dev.adamko.kafkatorio.gradle.not
import dev.adamko.kafkatorio.jsonMapper
import dev.adamko.kafkatorio.task.UpdatePackageJson
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import org.gradle.kotlin.dsl.support.useToRun import org.gradle.kotlin.dsl.support.useToRun
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin
import org.jetbrains.kotlin.util.suffixIfNot import org.jetbrains.kotlin.util.suffixIfNot
plugins { plugins {
id("com.github.node-gradle.node") id("com.github.node-gradle.node")
id("dev.adamko.kafkatorio.base") id("dev.adamko.kafkatorio.base")
@ -27,32 +24,6 @@ node {
distBaseUrl.set(null as String?) // set by dependencyResolutionManagement distBaseUrl.set(null as String?) // set by dependencyResolutionManagement
} }
project.plugins.withType<KotlinJsPlugin>()
project.plugins.withType<KotlinMultiplatformPlugin>()
val jsonMapper = Json {
prettyPrint = true
prettyPrintIndent = " "
}
fun arePropertiesUpToDate(
packageJsonFile: RegularFileProperty,
properties: () -> Map<String, String>
): Spec<Task> = Spec<Task> {
val packageJsonContent = packageJsonFile.get().asFile.readText()
val packageJson = jsonMapper.parseToJsonElement(packageJsonContent).jsonObject
properties().all { (key, expectedVal) ->
val actualVal = packageJson[key]?.jsonPrimitive?.content
(expectedVal == actualVal).also {
if (!it)
logger.lifecycle("package.json has outdated property '$key' (expected: $expectedVal, actual: $actualVal)")
}
}
}
val updatePackageJson by tasks.registering(UpdatePackageJson::class) { val updatePackageJson by tasks.registering(UpdatePackageJson::class) {
group = NodePlugin.NODE_GROUP group = NodePlugin.NODE_GROUP
description = "Read the package.json file and update the version and name, based on the project." description = "Read the package.json file and update the version and name, based on the project."
@ -60,7 +31,7 @@ val updatePackageJson by tasks.registering(UpdatePackageJson::class) {
propertiesToCheck["version"] = "${project.version}" propertiesToCheck["version"] = "${project.version}"
// check to see if the properties are already up-to-date // check to see if the properties are already up-to-date
onlyIf(!arePropertiesUpToDate(packageJsonFile) { propertiesToCheck }) onlyIf(!areJsonPropertiesUpToDate(packageJsonFile) { propertiesToCheck })
doLast { doLast {
val packageJsonContent = packageJsonFile.get().asFile.readText() val packageJsonContent = packageJsonFile.get().asFile.readText()
@ -74,7 +45,7 @@ val updatePackageJson by tasks.registering(UpdatePackageJson::class) {
.encodeToString(packageJsonUpdate) .encodeToString(packageJsonUpdate)
.suffixIfNot("\n") .suffixIfNot("\n")
logger.lifecycle(packageJsonContentUpdated) logger.debug(packageJsonContentUpdated)
packageJsonFile.get().asFile.writer().useToRun { packageJsonFile.get().asFile.writer().useToRun {
write(packageJsonContentUpdated) write(packageJsonContentUpdated)

View file

@ -52,7 +52,7 @@ val typescriptToLua by tasks.registering(NpmTask::class) {
description = "Convert Typescript To Lua" description = "Convert Typescript To Lua"
group = project.name group = project.name
dependsOn(tasks.npmInstall) dependsOn(tasks.npmInstall, fetchEventsSchema)
execOverrides { standardOutput = System.out } execOverrides { standardOutput = System.out }
@ -121,12 +121,13 @@ distributions {
contents { contents {
from(layout.projectDirectory.dir("src/main/resources/mod-data")) { from(layout.projectDirectory.dir("src/main/resources/mod-data")) {
include("**/**") include("**/**")
filter<ReplaceTokens>("tokens" to tokens)
} }
from(licenseFile) from(licenseFile)
from(typescriptToLua.map { it.outputs }) from(typescriptToLua.map { it.outputs })
filter<ReplaceTokens>("tokens" to tokens)
includeEmptyDirs = false includeEmptyDirs = false
exclude { exclude {
// exclude empty lines
it.file.run { it.file.run {
isFile && useLines { lines -> lines.all { line -> line.isBlank() } } isFile && useLines { lines -> lines.all { line -> line.isBlank() } }
} }

View file

@ -1,6 +1,7 @@
import {Serdes} from "./serdes/serdes" import {Serdes} from "./serdes/serdes"
const MOD_VERSION = script.active_mods["factorio-web-map"] const MOD_VERSION = script.active_mods["@mod.name@"] ?? "UNKNOWN"
const FACTORIO_VERSION = script.active_mods["base"] ?? "UNKNOWN"
const mapEventIdToName = new LuaTable<defines.Events, keyof typeof defines.events>() const mapEventIdToName = new LuaTable<defines.Events, keyof typeof defines.events>()
for (const [k, v] of pairs(defines.events)) { for (const [k, v] of pairs(defines.events)) {
@ -48,6 +49,7 @@ function emitEvent<T extends FactorioObjectData>(eventData: T, tick: uint, event
data: eventData, data: eventData,
event_type: eventType, event_type: eventType,
mod_version: MOD_VERSION, mod_version: MOD_VERSION,
factorio_version: FACTORIO_VERSION,
tick: tick tick: tick
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "kafkatorio-events-mod", "name": "kafkatorio-events-mod",
"version": "0.0.7", "version": "0.1.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "kafkatorio-events-mod", "name": "kafkatorio-events-mod",
"version": "0.0.7", "version": "0.1.1",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "tstl", "build": "tstl",
@ -9,7 +9,8 @@
"engines": { "engines": {
"node": ">=10.13.0" "node": ">=10.13.0"
}, },
"devDependencies": {}, "devDependencies": {
},
"dependencies": { "dependencies": {
"lua-types": "^2.11.0", "lua-types": "^2.11.0",
"@types/node": "^12.0.8", "@types/node": "^12.0.8",
@ -20,7 +21,10 @@
"//": { "//": {
"typed-factorio": "0.10.0" "typed-factorio": "0.10.0"
}, },
"peerDependencies": {}, "peerDependencies": {
"optionalDependencies": {}, },
"bundledDependencies": [] "optionalDependencies": {
},
"bundledDependencies": [
]
} }

View file

@ -8,6 +8,7 @@ interface FactorioObjectData {
interface FactorioEvent<T extends FactorioObjectData> { interface FactorioEvent<T extends FactorioObjectData> {
data: T; data: T;
event_type: string; event_type: string;
factorio_version: string;
mod_version: string; mod_version: string;
tick: uint; tick: uint;
} }
@ -21,7 +22,6 @@ interface PlayerData extends FactorioObjectData {
associated_characters_unit_numbers: uint[]; associated_characters_unit_numbers: uint[];
character_unit_number: uint | null; character_unit_number: uint | null;
name: string; name: string;
object_name: string;
position: PositionData; position: PositionData;
} }
@ -30,7 +30,6 @@ interface EntityData extends FactorioObjectData {
health: double | null; health: double | null;
health_ratio: double; health_ratio: double;
name: string; name: string;
object_name: string;
player_index: uint | null; player_index: uint | null;
position: PositionData; position: PositionData;
surface_index: int; surface_index: int;
@ -42,5 +41,4 @@ interface SurfaceData extends FactorioObjectData {
daytime: double; daytime: double;
index: uint; index: uint;
name: string; name: string;
object_name: string;
} }

View file

@ -5,13 +5,40 @@ import dev.adamko.kafkatorio.events.schema.FactorioObjectData
import dev.adamko.kafkatorio.events.schema.jsonMapper import dev.adamko.kafkatorio.events.schema.jsonMapper
import dev.adamko.kafkatorio.processor.config.ApplicationProperties import dev.adamko.kafkatorio.processor.config.ApplicationProperties
import java.time.Duration import java.time.Duration
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.modules.SerializersModule
import org.apache.kafka.common.serialization.Deserializer
import org.apache.kafka.common.serialization.Serde
import org.apache.kafka.common.serialization.Serdes import org.apache.kafka.common.serialization.Serdes
import org.apache.kafka.common.serialization.Serializer
import org.apache.kafka.streams.KafkaStreams import org.apache.kafka.streams.KafkaStreams
import org.apache.kafka.streams.StreamsBuilder import org.apache.kafka.streams.StreamsBuilder
import org.apache.kafka.streams.TopologyDescription import org.apache.kafka.streams.TopologyDescription
import org.apache.kafka.streams.kstream.Consumed import org.apache.kafka.streams.kstream.Consumed
import org.apache.kafka.streams.processor.TopicNameExtractor import org.apache.kafka.streams.kstream.Produced
import org.http4k.format.KotlinxSerialization import org.http4k.format.ConfigurableKotlinxSerialization
import org.http4k.format.asConfigurable
import org.http4k.format.withStandardMappings
object KSX : ConfigurableKotlinxSerialization({
ignoreUnknownKeys = true
prettyPrint = true
prettyPrintIndent = " "
asConfigurable().withStandardMappings().done()
serializersModule = SerializersModule { }
})
object JsonSerdes : Serde<FactorioEvent<FactorioObjectData>> {
override fun serializer() = Serializer<FactorioEvent<FactorioObjectData>> { _, message ->
jsonMapper.encodeToString<FactorioEvent<FactorioObjectData>>(message).encodeToByteArray()
}
override fun deserializer() = Deserializer<FactorioEvent<FactorioObjectData>> { _, bytes ->
jsonMapper.decodeFromString(bytes.decodeToString())
}
}
fun main() { fun main() {
@ -25,16 +52,18 @@ fun main() {
) )
.mapValues { readOnlyKey, value -> .mapValues { readOnlyKey, value ->
println("Mapping $readOnlyKey:$value") println("Mapping $readOnlyKey:$value")
// jsonMapper.decodeFromString<FactorioEvent<*>>(value) jsonMapper.decodeFromString<FactorioEvent<FactorioObjectData>>(value)
KotlinxSerialization.asA<FactorioEvent<FactorioObjectData>>(value) // KSX.asA<FactorioEvent<FactorioObjectData>>(value)
} }
.to(TopicNameExtractor { key, value, recordContext -> .to(
value.data.objectName { key, value, recordContext -> value.data.objectName },
}) Produced.with(Serdes.String(), JsonSerdes)
)
val topology = builder.build() val topology = builder.build()
val properties = appProps.kafkaConfig val properties = appProps.kafkaConfig
val streams = KafkaStreams(topology, properties) val streams = KafkaStreams(topology, properties)
streams.setUncaughtExceptionHandler(StreamsExceptionHandler()) streams.setUncaughtExceptionHandler(StreamsExceptionHandler())

View file

@ -14,6 +14,8 @@ dependencies {
implementation("com.github.ntrrgc:ts-generator:1.1.2") implementation("com.github.ntrrgc:ts-generator:1.1.2")
implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation(libs.kotest.datatest)
} }
val generateTypescript by tasks.registering(JavaExec::class) { val generateTypescript by tasks.registering(JavaExec::class) {

View file

@ -1,8 +1,11 @@
package dev.adamko.kafkatorio.events.schema package dev.adamko.kafkatorio.events.schema
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.findAnnotations
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlinx.serialization.json.JsonClassDiscriminator import kotlinx.serialization.json.JsonClassDiscriminator
@ -15,6 +18,8 @@ data class FactorioEvent<out T : FactorioObjectData>(
/** Schema versioning */ /** Schema versioning */
@SerialName("mod_version") @SerialName("mod_version")
val modVersion: String, val modVersion: String,
@SerialName("factorio_version")
val factorioVersion: String,
/** game time */ /** game time */
@SerialName("tick") @SerialName("tick")
val tick: UInt, val tick: UInt,
@ -29,17 +34,19 @@ const val FactorioObjectDataDiscriminatorKey: String = "object_name"
@Serializable @Serializable
@JsonClassDiscriminator(FactorioObjectDataDiscriminatorKey) @JsonClassDiscriminator(FactorioObjectDataDiscriminatorKey)
sealed class FactorioObjectData { sealed class FactorioObjectData private constructor() {
@SerialName(FactorioObjectDataDiscriminatorKey)
abstract val objectName: String // workaround - https://github.com/Kotlin/kotlinx.serialization/issues/1664
val objectName : String by lazy {
requireNotNull(this::class.findAnnotation<SerialName>()?.value) {
"Couldn't find @SerialName for ${this::class}!"
}
}
} }
@Serializable @Serializable
@SerialName("LuaPlayer") @SerialName("LuaPlayer")
data class PlayerData( data class PlayerData(
@SerialName(FactorioObjectDataDiscriminatorKey)
override val objectName: String,
@Serializable(with = ListAsObjectSerializer::class) @Serializable(with = ListAsObjectSerializer::class)
@SerialName("associated_characters_unit_numbers") @SerialName("associated_characters_unit_numbers")
val associatedCharactersUnitNumbers: List<UInt>, val associatedCharactersUnitNumbers: List<UInt>,
@ -54,9 +61,6 @@ data class PlayerData(
@Serializable @Serializable
@SerialName("LuaEntity") @SerialName("LuaEntity")
data class EntityData( data class EntityData(
@SerialName(FactorioObjectDataDiscriminatorKey)
override val objectName: String,
@SerialName("active") @SerialName("active")
val active: Boolean, val active: Boolean,
@SerialName("health") @SerialName("health")
@ -72,7 +76,7 @@ data class EntityData(
@SerialName("type") @SerialName("type")
val type: String, val type: String,
@SerialName("unit_number") @SerialName("unit_number")
val unitNumber: UInt?, val unitNumber: UInt? = null,
@SerialName("player_index") @SerialName("player_index")
val playerIndex: UInt? = null, val playerIndex: UInt? = null,
@ -81,9 +85,6 @@ data class EntityData(
@Serializable @Serializable
@SerialName("LuaSurface") @SerialName("LuaSurface")
data class SurfaceData( data class SurfaceData(
@SerialName(FactorioObjectDataDiscriminatorKey)
override val objectName: String,
@SerialName("daytime") @SerialName("daytime")
val daytime: Double, val daytime: Double,
@SerialName("index") @SerialName("index")

View file

@ -1,14 +1,8 @@
package dev.adamko.kafkatorio.events.schema package dev.adamko.kafkatorio.events.schema
import dev.adamko.kafkatorio.events.schema.EntityData
import dev.adamko.kafkatorio.events.schema.FactorioEvent
import dev.adamko.kafkatorio.events.schema.FactorioObjectData
import dev.adamko.kafkatorio.events.schema.PlayerData
import dev.adamko.kafkatorio.events.schema.PositionData
import dev.adamko.kafkatorio.events.schema.SurfaceData
import dev.adamko.kafkatorio.events.schema.jsonMapper
import io.kotest.core.spec.style.BehaviorSpec import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.equality.shouldBeEqualToComparingFields import io.kotest.matchers.equality.shouldBeEqualToComparingFields
import io.kotest.matchers.shouldBe
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import org.intellij.lang.annotations.Language import org.intellij.lang.annotations.Language
@ -31,6 +25,7 @@ class FactorioEventTest : BehaviorSpec({
}, },
"event_type": "on_player_joined_game", "event_type": "on_player_joined_game",
"mod_version": "0.0.4", "mod_version": "0.0.4",
"factorio_version": "1.1.48",
"tick": 1278458 "tick": 1278458
} }
""".trimIndent() """.trimIndent()
@ -40,7 +35,6 @@ class FactorioEventTest : BehaviorSpec({
val expected = FactorioEvent( val expected = FactorioEvent(
data = PlayerData( data = PlayerData(
objectName = "LuaPlayer",
name = "fredthedeadhead", name = "fredthedeadhead",
characterUnitNumber = 1u, characterUnitNumber = 1u,
associatedCharactersUnitNumbers = emptyList(), associatedCharactersUnitNumbers = emptyList(),
@ -51,10 +45,13 @@ class FactorioEventTest : BehaviorSpec({
), ),
eventType = "on_player_joined_game", eventType = "on_player_joined_game",
modVersion = "0.0.4", modVersion = "0.0.4",
factorioVersion = "1.1.48",
tick = 1278458u tick = 1278458u
) )
actual shouldBeEqualToComparingFields expected actual shouldBeEqualToComparingFields expected
expected.data.objectName shouldBe "LuaPlayer"
} }
} }
@ -70,6 +67,7 @@ class FactorioEventTest : BehaviorSpec({
}, },
"event_type": "on_tick", "event_type": "on_tick",
"mod_version": "0.0.4", "mod_version": "0.0.4",
"factorio_version": "1.1.48",
"tick": 1278480 "tick": 1278480
} }
""".trimIndent() """.trimIndent()
@ -78,17 +76,19 @@ class FactorioEventTest : BehaviorSpec({
val expected = FactorioEvent( val expected = FactorioEvent(
data = SurfaceData( data = SurfaceData(
objectName = "LuaSurface",
name = "nauvis", name = "nauvis",
index = 1u, index = 1u,
daytime = 0.8390800000511436707029133685864508152008056640625 daytime = 0.8390800000511436707029133685864508152008056640625
), ),
eventType = "on_tick", eventType = "on_tick",
modVersion = "0.0.4", modVersion = "0.0.4",
factorioVersion = "1.1.48",
tick = 1278480u tick = 1278480u
) )
actual shouldBeEqualToComparingFields expected actual shouldBeEqualToComparingFields expected
expected.data.objectName shouldBe "LuaSurface"
} }
} }
@ -112,6 +112,7 @@ class FactorioEventTest : BehaviorSpec({
}, },
"event_type": "on_player_changed_position", "event_type": "on_player_changed_position",
"mod_version": "0.0.6", "mod_version": "0.0.6",
"factorio_version": "1.1.48",
"tick": 1384507 "tick": 1384507
} }
""".trimIndent() """.trimIndent()
@ -120,7 +121,6 @@ class FactorioEventTest : BehaviorSpec({
val expected = FactorioEvent( val expected = FactorioEvent(
data = EntityData( data = EntityData(
objectName = "LuaEntity",
name = "character", name = "character",
type = "character", type = "character",
active = true, active = true,
@ -136,10 +136,13 @@ class FactorioEventTest : BehaviorSpec({
), ),
eventType = "on_player_changed_position", eventType = "on_player_changed_position",
modVersion = "0.0.6", modVersion = "0.0.6",
factorioVersion = "1.1.48",
tick = 1384507u tick = 1384507u
) )
actual shouldBeEqualToComparingFields expected actual shouldBeEqualToComparingFields expected
expected.data.objectName shouldBe "LuaEntity"
} }
} }

View file

@ -45,7 +45,7 @@ val clientLaunch by tasks.registering(Exec::class) {
onlyIf(!isFactorioRunning()) onlyIf(!isFactorioRunning())
dependsOn(deployModToClient) dependsOn(deployModToClient)
mustRunAfter(clientKill) mustRunAfter(clientKill, ":modules:infra-factorio-server:processRun")
commandLine = parseSpaceSeparatedArgs( commandLine = parseSpaceSeparatedArgs(
// """explorer "steam://rungameid/$factorioGameId// --mp-connect localhost/" """ // not working // """explorer "steam://rungameid/$factorioGameId// --mp-connect localhost/" """ // not working

View file

@ -1,5 +1,6 @@
import dev.adamko.kafkatorio.gradle.asConsumer import dev.adamko.kafkatorio.gradle.asConsumer
import dev.adamko.kafkatorio.gradle.factorioModAttributes import dev.adamko.kafkatorio.gradle.factorioModAttributes
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
plugins { plugins {
id("dev.adamko.kafkatorio.infra.docker-compose") id("dev.adamko.kafkatorio.infra.docker-compose")
@ -29,6 +30,10 @@ val deployModToServer by tasks.registering(Copy::class) {
} }
} }
tasks.dockerDown {
commandLine = parseSpaceSeparatedArgs(""" docker-compose stop """)
}
tasks.dockerUp { tasks.dockerUp {
dependsOn( dependsOn(
deployModToServer, deployModToServer,

View file

@ -8,6 +8,7 @@ services:
restart: "unless-stopped" restart: "unless-stopped"
build: build:
dockerfile: "kafka.Dockerfile" dockerfile: "kafka.Dockerfile"
context: "."
target: "kafka-kraft" target: "kafka-kraft"
args: args:
KAFKA_DL_URL: "https://dlcdn.apache.org/kafka/3.0.0/kafka_2.13-3.0.0.tgz" KAFKA_DL_URL: "https://dlcdn.apache.org/kafka/3.0.0/kafka_2.13-3.0.0.tgz"

View file

@ -6,6 +6,7 @@ services:
container_name: "kafka-pipe" container_name: "kafka-pipe"
build: build:
dockerfile: "kafka-pipe.Dockerfile" dockerfile: "kafka-pipe.Dockerfile"
context: "."
restart: "unless-stopped" restart: "unless-stopped"
privileged: true privileged: true
networks: networks: