diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt index c22f8dfe..e4e64947 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt @@ -65,6 +65,7 @@ import ru.dbotthepony.kstarbound.math.Vector3iTypeAdapter import ru.dbotthepony.kstarbound.math.Vector4dTypeAdapter import ru.dbotthepony.kstarbound.math.Vector4fTypeAdapter import ru.dbotthepony.kstarbound.math.Vector4iTypeAdapter +import ru.dbotthepony.kstarbound.util.AssetPathStack import ru.dbotthepony.kstarbound.util.BlockableEventLoop import ru.dbotthepony.kstarbound.util.ExecutorWithScheduler import ru.dbotthepony.kstarbound.util.Directives @@ -433,6 +434,14 @@ object Starbound : BlockableEventLoop("Universe Thread"), Scheduler, ISBFileLoca return JsonPath.query(jsonPath).get(json) } + fun loadJsonAsset(path: JsonElement, relative: String): JsonElement? { + if (path is JsonPrimitive) { + return loadJsonAsset(AssetPathStack.relativeTo(relative, path.asString)) + } else { + return path + } + } + private val fileSystems = ArrayList() private val toLoadPaks = ObjectArraySet() private val toLoadPaths = ObjectArraySet() @@ -573,7 +582,7 @@ object Starbound : BlockableEventLoop("Universe Thread"), Scheduler, ISBFileLoca // same assets from other PAKs fileSystems.forEach { it.explore { file -> - if (file.isFile) + if (file.isFile && file.name.contains('.')) fileTree.computeIfAbsent(file.name.substringAfterLast('.')) { HashSet() }.add(file) } } @@ -582,7 +591,7 @@ object Starbound : BlockableEventLoop("Universe Thread"), Scheduler, ISBFileLoca fileSystems.asReversed().forEach { it.explore { file -> if (file.isFile && file.name.endsWith(".patch")) - patchTree.computeIfAbsent(file.computeFullPath().substringAfterLast('.')) { ArrayList() }.add(file) + patchTree.computeIfAbsent(file.computeFullPath().substringBeforeLast('.')) { ArrayList() }.add(file) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/EntityType.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/EntityType.kt index 7cf27e89..fdc6220f 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/EntityType.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/EntityType.kt @@ -14,7 +14,7 @@ import ru.dbotthepony.kstarbound.world.entities.tile.PlantPieceEntity import ru.dbotthepony.kstarbound.world.entities.tile.WorldObject import java.io.DataInputStream -enum class EntityType(override val jsonName: String, val storeName: String, val canBeCreatedByClient: Boolean, val canBeSpawnedByClient: Boolean) : IStringSerializable { +enum class EntityType(override val jsonName: String, val storeName: String, val canBeCreatedByClient: Boolean, val canBeSpawnedByClient: Boolean, val ephemeralIfSpawnedByClient: Boolean = true) : IStringSerializable { PLANT("plant", "PlantEntity", false, false) { override fun fromNetwork(stream: DataInputStream, isLegacy: Boolean): AbstractEntity { return PlantEntity(stream, isLegacy) @@ -38,7 +38,7 @@ enum class EntityType(override val jsonName: String, val storeName: String, val } }, - VEHICLE("vehicle", "VehicleEntity", false, true) { + VEHICLE("vehicle", "VehicleEntity", false, true, false) { override fun fromNetwork(stream: DataInputStream, isLegacy: Boolean): AbstractEntity { TODO("VEHICLE") } @@ -48,7 +48,7 @@ enum class EntityType(override val jsonName: String, val storeName: String, val } }, - ITEM_DROP("itemDrop", "ItemDropEntity", false, true) { + ITEM_DROP("itemDrop", "ItemDropEntity", false, true, false) { override fun fromNetwork(stream: DataInputStream, isLegacy: Boolean): AbstractEntity { return ItemDropEntity(stream, isLegacy) } @@ -78,7 +78,7 @@ enum class EntityType(override val jsonName: String, val storeName: String, val } }, - STAGEHAND("stagehand", "StagehandEntity", false, false) { + STAGEHAND("stagehand", "StagehandEntity", true, true) { override fun fromNetwork(stream: DataInputStream, isLegacy: Boolean): AbstractEntity { TODO("STAGEHAND") } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/item/ActiveItemStack.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/item/ActiveItemStack.kt index 4770b3e2..1c2bdd2c 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/item/ActiveItemStack.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/item/ActiveItemStack.kt @@ -32,8 +32,7 @@ class ActiveItemStack(entry: ItemRegistry.Entry, config: JsonObject, parameters: val animator: Animator init { - val animationPath = AssetPathStack.relativeTo(entry.directory, lookupProperty("animation").asString) - var animationConfig = Starbound.loadJsonAsset(animationPath) ?: JsonNull.INSTANCE + var animationConfig = Starbound.loadJsonAsset(lookupProperty("animation"), entry.directory) ?: JsonNull.INSTANCE val animationCustom = lookupProperty("animationCustom") if (!animationCustom.isJsonNull) { @@ -41,13 +40,13 @@ class ActiveItemStack(entry: ItemRegistry.Entry, config: JsonObject, parameters: } try { - if (animationCustom.isJsonNull) { + if (animationConfig.isJsonNull) { animator = Animator() } else { animator = Animator(Starbound.gson.fromJson(animationConfig, AnimationDefinition::class.java)) } } catch (err: Throwable) { - throw RuntimeException("Unable to instance animator for ${entry.name} (animation config: $animationPath)", err) + throw RuntimeException("Unable to instance animator for ${entry.name} (animation config: ${lookupProperty("animation")})", err) } networkElement.add(animator.networkGroup) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/item/ItemRegistry.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/item/ItemRegistry.kt index 6f175d4a..98b6740e 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/item/ItemRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/item/ItemRegistry.kt @@ -142,7 +142,7 @@ object ItemRegistry { for (file in files) { futures.add(Starbound.EXECUTOR.submit { try { - val read = JsonPatch.apply(Starbound.ELEMENTS_ADAPTER.read(file.jsonReader()), patches[file.computeFullPath()]) as JsonObject + val read = JsonPatch.apply(Starbound.ELEMENTS_ADAPTER.read(file.jsonReader()), patches[file.computeFullPath()]).asJsonObject val readData = data.fromJsonTree(read) tasks.add { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/json/JsonPatch.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/json/JsonPatch.kt index b79f99e3..2ea8665b 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/json/JsonPatch.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/json/JsonPatch.kt @@ -19,16 +19,26 @@ enum class JsonPatch(val key: String) { val get = path.find(base) ?: JsonNull.INSTANCE - if (inverse && get == value) { - throw IllegalStateException("Expected $path to not contain $value") - } else if (!inverse && get != value && value != JsonNull.INSTANCE) { - var text = get.toString() - - if (text.length > 40) { - text = text.substring(0, 40) + "..." + if (inverse) { + if (value == JsonNull.INSTANCE && get != JsonNull.INSTANCE) { + throw IllegalStateException("Expected $path to not contain anything") + } else if (value != JsonNull.INSTANCE && value == get) { + throw IllegalStateException("Expected $path to not contain $value") } + } else { + if (value == JsonNull.INSTANCE && get == JsonNull.INSTANCE) { + throw IllegalStateException("Expected $path to contain anything") + } else if (value != JsonNull.INSTANCE && get == JsonNull.INSTANCE) { + throw IllegalStateException("Expected $path to contain '$value', but found nothing") + } else if (value != JsonNull.INSTANCE && get != JsonNull.INSTANCE && value != get) { + var text = get.toString() - throw IllegalStateException("Expected $path to contain $value, but found $text") + if (text.length > 40) { + text = text.substring(0, 40) + "..." + } + + throw IllegalStateException("Expected $path to contain $value, but found $text") + } } return base diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/LegacyWorldStorage.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/LegacyWorldStorage.kt index fab14dc7..a0f83ddb 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/LegacyWorldStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/LegacyWorldStorage.kt @@ -10,6 +10,8 @@ import ru.dbotthepony.kommons.io.readVarInt import ru.dbotthepony.kommons.io.writeVarInt import ru.dbotthepony.kommons.util.KOptional import ru.dbotthepony.kstarbound.Starbound +import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials +import ru.dbotthepony.kstarbound.defs.tile.isNullTile import ru.dbotthepony.kstarbound.io.BTreeDB5 import ru.dbotthepony.kstarbound.json.VersionedJson import ru.dbotthepony.kstarbound.math.vector.Vector2i @@ -72,7 +74,17 @@ sealed class LegacyWorldStorage() : WorldStorage() { for (y in 0 until CHUNK_SIZE) { for (x in 0 until CHUNK_SIZE) { - result[x, y] = MutableCell().readLegacy(reader, tileSerializationVersion).immutable() + val read = MutableCell().readLegacy(reader, tileSerializationVersion) + + if (read.foreground.material == BuiltinMetaMaterials.STRUCTURE) { + read.foreground.material = BuiltinMetaMaterials.EMPTY + } + + if (read.background.material == BuiltinMetaMaterials.STRUCTURE) { + read.background.material = BuiltinMetaMaterials.EMPTY + } + + result[x, y] = read.immutable() } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Animator.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Animator.kt index f85f1c6a..d91fc380 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Animator.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Animator.kt @@ -1018,5 +1018,7 @@ class Animator() { private val missing = Collections.synchronizedSet(ObjectOpenHashSet()) private val vectors by lazy { Starbound.gson.getAdapter(Vector2d::class.java) } private val polies by lazy { Starbound.gson.getAdapter(Poly::class.java) } + + } } diff --git a/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt b/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt index e01c0ed2..74c5fe26 100644 --- a/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt +++ b/src/test/kotlin/ru/dbotthepony/kstarbound/test/MiscTests.kt @@ -1,10 +1,13 @@ package ru.dbotthepony.kstarbound.test +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import ru.dbotthepony.kommons.arrays.Int2DArray import ru.dbotthepony.kstarbound.defs.dungeon.VectorizedBitSet +import ru.dbotthepony.kstarbound.json.JsonPath import ru.dbotthepony.kstarbound.util.random.random import java.rmi.UnexpectedException @@ -35,4 +38,13 @@ object MiscTests { } } } + + @Test + @DisplayName("Json patch test") + fun jsonPatchTest() { + val json = JsonObject() + + JsonPath.pointer("/element").add(json, JsonPrimitive(1)) + assertEquals(json["element"], JsonPrimitive(1)) + } }