diff --git a/ADDITIONS.md b/ADDITIONS.md index 913e4b23..f3af2c87 100644 --- a/ADDITIONS.md +++ b/ADDITIONS.md @@ -1,7 +1,7 @@ -# Modding changes +# Modding and behavior changes -This document briefly documents what have been added (or removed) regarding modding capabilities +This document briefly documents what have been added (or removed) regarding modding capabilities or engine behavior(s) ## JSON additions @@ -35,7 +35,6 @@ This document briefly documents what have been added (or removed) regarding modd * Original engine always generates two tree types when processing placeable items, new engine however, allows to generate any number of trees. #### Dungeons - * All brushes are now deterministic, and will produce _exact_ results given same seed (this fixes dungeons being generated differently on each machine despite players visiting exactly same coordinates in universe) * `front` and `back` brushes now can properly accept detailed data as json object on second position (e.g. `["front", { "material": ... }]`), with following structure (previously, due to oversight in code, it was impossible to specify this structure through any means, because brush definition itself can't be an object): ```kotlin val material: Registry.Ref = BuiltinMetaMaterials.EMPTY.ref @@ -101,4 +100,15 @@ val color: TileColor = TileColor.DEFAULT * Added `animator.sounds(): List` * Added `animator.effects(): List` * Added `animator.hasEffect(effect: string): boolean` - * Added `animator.parts(): List` \ No newline at end of file + * Added `animator.parts(): List` + +## Behavior + +--------------- + +### Worldgen + * Major dungeon placement on planets is now deterministic + * Container item population in dungeons is now deterministic and is based on dungeon seed + +#### Dungeons + * All brushes are now deterministic diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/dungeon/DungeonWorld.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/dungeon/DungeonWorld.kt index 93fe3fc2..6068af6c 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/dungeon/DungeonWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/dungeon/DungeonWorld.kt @@ -484,7 +484,7 @@ class DungeonWorld(val parent: ServerWorld, val random: RandomGenerator, val mar val placedObjects = placedObjects.entries .map { (pos, data) -> - WorldObject.create(data.prototype, pos, data.parameters) to data.direction + WorldObject.create(data.prototype, pos, data.parameters).also { it?.randomize(random) } to data.direction } .filter { it.first != null } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/ContainerObject.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/ContainerObject.kt index 43b5119f..9da85dd4 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/ContainerObject.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/ContainerObject.kt @@ -35,6 +35,7 @@ import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.entities.ItemDropEntity import java.io.DataInputStream import java.io.DataOutputStream +import java.util.random.RandomGenerator class ContainerObject(config: Registry.Entry) : WorldObject(config) { var opened by networkedSignedInt().also { networkGroup.upstream.add(it) } @@ -109,6 +110,45 @@ class ContainerObject(config: Registry.Entry) : WorldObject(co return data } + private fun randomizeContents(random: RandomGenerator) { + var level = world.template.threatLevel + level = lookupProperty("level") { JsonPrimitive(level) }.asDouble + level += lookupProperty("levelAdjustment") { JsonPrimitive(0.0) }.asDouble + + val initialItems = lookupProperty("initialItems") + + if (!initialItems.isJsonNull) { + for (item in initialItems.asJsonArray) { + items.add(ItemDescriptor(item).build(level, random.nextLong(), random)) + } + } + + val treasurePools = lookupProperty("treasurePools") + + if (!treasurePools.isJsonNull) { + val get = treasurePools.asJsonArray.random(random).asString + val treasurePool = Registries.treasurePools[get] + + if (treasurePool == null) { + LOGGER.error("Unknown treasure pool $get! Can't generate container contents at $tilePosition.") + } else { + for (item in treasurePool.value.evaluate(random, level)) { + val leftover = items.add(item) + + if (leftover.isNotEmpty) { + LOGGER.warn("Tried to overfill container at $tilePosition") + lostItems.add(leftover) + } + } + } + } + } + + override fun randomize(random: RandomGenerator) { + super.randomize(random) + randomizeContents(random) + } + override fun onJoinWorld(world: World<*, *>) { if (!isRemote) isInteractive = true @@ -119,38 +159,12 @@ class ContainerObject(config: Registry.Entry) : WorldObject(co if (isInitialized) return isInitialized = true - var level = world.template.threatLevel - val seed = lookupProperty("treasureSeed") { JsonPrimitive(world.random.nextLong()) }.asLong - level = lookupProperty("level") { JsonPrimitive(level) }.asDouble - level += lookupProperty("levelAdjustment") { JsonPrimitive(0.0) }.asDouble + val seed = lookupProperty("treasureSeed") - val initialItems = lookupProperty("initialItems") - - if (!initialItems.isJsonNull) { - for (item in initialItems.asJsonArray) { - items.add(ItemDescriptor(item).build(level, seed)) - } - } - - val treasurePools = lookupProperty("treasurePools") - - if (!treasurePools.isJsonNull) { - val random = random(seed) - val get = treasurePools.asJsonArray.random(random).asString - val treasurePool = Registries.treasurePools[get] - - if (treasurePool == null) { - LOGGER.error("Unknown treasure pool $get! Can't generate container contents at $tilePosition.") - } else { - for (item in treasurePool.value.evaluate(random, level)) { - val leftover = items.add(item) - - if (leftover.isNotEmpty) { - LOGGER.warn("Tried to overfill container at $tilePosition") - lostItems.add(leftover) - } - } - } + if (seed.isJsonNull) { + randomizeContents(world.random) + } else { + randomizeContents(random(seed.asLong)) } } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt index ca2e7d8e..6a170261 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt @@ -86,6 +86,7 @@ import ru.dbotthepony.kstarbound.world.entities.Animator import ru.dbotthepony.kstarbound.world.entities.wire.WireConnection import java.io.DataOutputStream import java.util.HashMap +import java.util.random.RandomGenerator open class WorldObject(val config: Registry.Entry) : TileEntity() { open fun deserialize(data: JsonObject) { @@ -134,6 +135,13 @@ open class WorldObject(val config: Registry.Entry) : TileEntit return into } + /** + * called by DungeonWorld to deterministically randomize parameters + */ + open fun randomize(random: RandomGenerator) { + + } + protected val orientationLazies = ArrayList>() protected val parametersLazies = ArrayList>() protected val spacesLazies = ArrayList>()