diff --git a/src/main/java/de/bixilon/minosoft/data/inventory/ItemStack.kt b/src/main/java/de/bixilon/minosoft/data/inventory/ItemStack.kt index f124381a4..d0fe31b81 100644 --- a/src/main/java/de/bixilon/minosoft/data/inventory/ItemStack.kt +++ b/src/main/java/de/bixilon/minosoft/data/inventory/ItemStack.kt @@ -26,7 +26,6 @@ import de.bixilon.minosoft.data.inventory.ItemNBTValues.UNBREAKABLE_TAG import de.bixilon.minosoft.data.mappings.Enchantment import de.bixilon.minosoft.data.mappings.items.Item import de.bixilon.minosoft.data.mappings.versions.Version -import de.bixilon.minosoft.data.mappings.versions.VersionMapping import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.util.BitByte import de.bixilon.minosoft.util.nbt.tag.* @@ -110,7 +109,7 @@ class ItemStack( additionalNBT = nbt } - fun getNbt(mapping: VersionMapping): CompoundTag { + fun getNBT(): CompoundTag { val nbt = additionalNBT?.clone() ?: CompoundTag() if (repairCost != 0) { nbt.writeTag(REPAIR_COST_TAG, IntTag(repairCost)) @@ -147,13 +146,13 @@ class ItemStack( val enchantmentTag = CompoundTag() enchantmentTag.writeTag(ENCHANTMENT_ID_TAG, StringTag(id.toString())) - enchantmentTag.writeTag(ENCHANTMENT_LEVEL_TAG, if (mapping.version!!.isFlattened()) { + enchantmentTag.writeTag(ENCHANTMENT_LEVEL_TAG, if (version!!.isFlattened()) { IntTag(level) } else { ShortTag(level.toShort()) }) } - if (mapping.version!!.isFlattened()) { + if (version!!.isFlattened()) { nbt.writeTag(ENCHANTMENT_FLATTENING_TAG, enchantmentList) } else { nbt.writeTag(ENCHANTMENT_PRE_FLATTENING_TAG, enchantmentList) diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/registry/EnumRegistry.kt b/src/main/java/de/bixilon/minosoft/data/mappings/registry/EnumRegistry.kt index 135d943f0..e63cf3273 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/registry/EnumRegistry.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/registry/EnumRegistry.kt @@ -24,7 +24,7 @@ class EnumRegistry>( private var parentRegistry: EnumRegistry? = null, var values: ValuesEnum, private val mutable: Boolean = true, -) : Clearable { +) : Clearable, Parentable> { private var initialized = false private val idValueMap: MutableMap = mutableMapOf() private val valueIdMap: MutableMap = mutableMapOf() @@ -37,11 +37,11 @@ class EnumRegistry>( return valueIdMap[value] ?: parentRegistry?.getId(value)!! } - fun setParent(registry: EnumRegistry?) { + override fun setParent(parent: EnumRegistry?) { if (!mutable) { throw IllegalStateException("Registry is immutable!") } - this.parentRegistry = registry + this.parentRegistry = parent } private fun getEnum(data: Any): T { diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/registry/FakeEnumRegistry.kt b/src/main/java/de/bixilon/minosoft/data/mappings/registry/FakeEnumRegistry.kt index a0ef47f62..5c436e74f 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/registry/FakeEnumRegistry.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/registry/FakeEnumRegistry.kt @@ -19,7 +19,7 @@ import de.bixilon.minosoft.util.collections.Clearable class FakeEnumRegistry( private var parentRegistry: FakeEnumRegistry? = null, -) : Clearable { +) : Clearable, Parentable> { private var initialized = false private val idValueMap: MutableMap = mutableMapOf() private val valueIdMap: MutableMap = mutableMapOf() @@ -37,9 +37,9 @@ class FakeEnumRegistry( return valueIdMap[value] ?: parentRegistry?.getId(value)!! } - fun setParent(registry: FakeEnumRegistry?) { - check(registry !== this) { "Can not set our self as parent!" } - this.parentRegistry = registry + override fun setParent(parent: FakeEnumRegistry?) { + check(parent !== this) { "Can not set our self as parent!" } + this.parentRegistry = parent } fun initialize(data: JsonObject?, mappings: VersionMapping, deserializer: IdDeserializer): FakeEnumRegistry { diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/registry/Parentable.kt b/src/main/java/de/bixilon/minosoft/data/mappings/registry/Parentable.kt new file mode 100644 index 000000000..54c0e6942 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/mappings/registry/Parentable.kt @@ -0,0 +1,19 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program.If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.data.mappings.registry + +interface Parentable { + + fun setParent(parent: T?) +} diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/registry/Registry.kt b/src/main/java/de/bixilon/minosoft/data/mappings/registry/Registry.kt index 7811bd831..b775e3b30 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/registry/Registry.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/registry/Registry.kt @@ -21,7 +21,7 @@ import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationM open class Registry( private var parentRegistry: Registry? = null, -) : Iterable, Clearable { +) : Iterable, Clearable, Parentable> { private var initialized = false private val idValueMap: MutableMap = mutableMapOf() private val valueIdMap: MutableMap = mutableMapOf() @@ -40,8 +40,8 @@ open class Registry( return valueIdMap[value] ?: parentRegistry?.getId(value)!! } - fun setParent(registry: Registry?) { - this.parentRegistry = registry + override fun setParent(parent: Registry?) { + this.parentRegistry = parent } open fun initialize(data: Map?, mappings: VersionMapping?, deserializer: ResourceLocationDeserializer, flattened: Boolean = true, metaType: MetaTypes = MetaTypes.NONE): Registry { diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/versions/Version.kt b/src/main/java/de/bixilon/minosoft/data/mappings/versions/Version.kt index bada64c18..9633557b3 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/versions/Version.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/versions/Version.kt @@ -36,7 +36,7 @@ data class Version( ) { var isLoaded = false var isGettingLoaded = false - val mapping: VersionMapping = VersionMapping(this) + val mapping: VersionMapping = VersionMapping() lateinit var assetsManager: MinecraftAssetsManager lateinit var localeManager: MinecraftLocaleManager @@ -110,8 +110,7 @@ data class Version( JsonObject() } latch.addCount(1) - mapping.version = this - mapping.load(pixlyzerData) + mapping.load(this, pixlyzerData) latch.countDown() if (pixlyzerData.size() > 0) { Log.verbose(String.format("Loaded mappings for version %s in %dms (%s)", this, (System.currentTimeMillis() - startTime), versionName)) diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt b/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt index 323c15a7f..00f774bac 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.kt @@ -31,10 +31,7 @@ import de.bixilon.minosoft.data.mappings.items.Item import de.bixilon.minosoft.data.mappings.items.ItemRegistry import de.bixilon.minosoft.data.mappings.materials.Material import de.bixilon.minosoft.data.mappings.particle.Particle -import de.bixilon.minosoft.data.mappings.registry.EnumRegistry -import de.bixilon.minosoft.data.mappings.registry.FakeEnumRegistry -import de.bixilon.minosoft.data.mappings.registry.PerEnumVersionRegistry -import de.bixilon.minosoft.data.mappings.registry.Registry +import de.bixilon.minosoft.data.mappings.registry.* import de.bixilon.minosoft.data.mappings.statistics.Statistic import de.bixilon.minosoft.gui.rendering.chunk.VoxelShape import de.bixilon.minosoft.gui.rendering.chunk.models.AABB @@ -43,10 +40,11 @@ import de.bixilon.minosoft.protocol.packets.clientbound.play.title.TitlePacketFa import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.util.collections.Clearable import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap +import java.lang.reflect.Field import java.util.* -class VersionMapping(var version: Version?) { +class VersionMapping { var shapes: MutableList = mutableListOf() val motiveRegistry: Registry = Registry() val blockRegistry: Registry = Registry() @@ -94,32 +92,9 @@ class VersionMapping(var version: Version?) { set(value) { _parentMapping = value - // ToDo: Use reflections for this - - motiveRegistry.setParent(value?.motiveRegistry) - itemRegistry.setParent(value?.itemRegistry) - enchantmentRegistry.setParent(value?.enchantmentRegistry) - particleRegistry.setParent(value?.particleRegistry) - statusEffectRegistry.setParent(value?.statusEffectRegistry) - blockRegistry.setParent(value?.blockRegistry) - statisticRegistry.setParent(value?.statisticRegistry) - biomeRegistry.setParent(value?.biomeRegistry) - dimensionRegistry.setParent(value?.dimensionRegistry) - biomePrecipitationRegistry.setParent(value?.biomePrecipitationRegistry) - biomeCategoryRegistry.setParent(value?.biomeCategoryRegistry) - materialRegistry.setParent(value?.materialRegistry) - villagerProfessionRegistry.setParent(value?.villagerProfessionRegistry) - - equipmentSlotRegistry.setParent(value?.equipmentSlotRegistry) - handEquipmentSlotRegistry.setParent(value?.handEquipmentSlotRegistry) - armorEquipmentSlotRegistry.setParent(value?.armorEquipmentSlotRegistry) - armorStandEquipmentSlotRegistry.setParent(value?.armorStandEquipmentSlotRegistry) - entityMetaDataDataDataTypesRegistry.setParent(value?.entityMetaDataDataDataTypesRegistry) - creativeModeTabRegistry.setParent(value?.creativeModeTabRegistry) - - titleActionsRegistry.setParent(value?.titleActionsRegistry) - - entityRegistry.setParent(value?.entityRegistry) + for (field in PARENTABLE_FIELDS) { + PARENTABLE_SET_PARENT_METHOD.invoke(field.get(this), value?.let { field.get(it) }) + } } fun getBlockState(blockState: Int): BlockState? { @@ -133,30 +108,29 @@ class VersionMapping(var version: Version?) { return entityMetaIndexMap[field] ?: _parentMapping?.getEntityMetaDataIndex(field) } - private fun > loadEnumRegistry(data: JsonElement?, registry: EnumRegistry, alternative: PerEnumVersionRegistry) { + private fun > loadEnumRegistry(version: Version, data: JsonElement?, registry: EnumRegistry, alternative: PerEnumVersionRegistry) { data?.let { registry.initialize(it) } ?: let { - registry.setParent(alternative.forVersion(version!!)) + registry.setParent(alternative.forVersion(version)) } } - fun load(pixlyzerData: JsonObject) { - val version = version!! + fun load(version: Version, pixlyzerData: JsonObject) { // pre init stuff loadShapes(pixlyzerData["shapes"]?.asJsonObject) loadBlockModels(pixlyzerData["models"].asJsonObject.toResourceLocationMap()) // enums - loadEnumRegistry(pixlyzerData["equipment_slots"], equipmentSlotRegistry, DefaultRegistries.EQUIPMENT_SLOTS_REGISTRY) - loadEnumRegistry(pixlyzerData["hand_equipment_slots"], handEquipmentSlotRegistry, DefaultRegistries.HAND_EQUIPMENT_SLOTS_REGISTRY) - loadEnumRegistry(pixlyzerData["armor_equipment_slots"], armorEquipmentSlotRegistry, DefaultRegistries.ARMOR_EQUIPMENT_SLOTS_REGISTRY) - loadEnumRegistry(pixlyzerData["armor_stand_equipment_slots"], armorStandEquipmentSlotRegistry, DefaultRegistries.ARMOR_STAND_EQUIPMENT_SLOTS_REGISTRY) + loadEnumRegistry(version, pixlyzerData["equipment_slots"], equipmentSlotRegistry, DefaultRegistries.EQUIPMENT_SLOTS_REGISTRY) + loadEnumRegistry(version, pixlyzerData["hand_equipment_slots"], handEquipmentSlotRegistry, DefaultRegistries.HAND_EQUIPMENT_SLOTS_REGISTRY) + loadEnumRegistry(version, pixlyzerData["armor_equipment_slots"], armorEquipmentSlotRegistry, DefaultRegistries.ARMOR_EQUIPMENT_SLOTS_REGISTRY) + loadEnumRegistry(version, pixlyzerData["armor_stand_equipment_slots"], armorStandEquipmentSlotRegistry, DefaultRegistries.ARMOR_STAND_EQUIPMENT_SLOTS_REGISTRY) - loadEnumRegistry(pixlyzerData["entity_meta_data_data_types"], entityMetaDataDataDataTypesRegistry, DefaultRegistries.ENTITY_META_DATA_DATA_TYPES_REGISTRY) + loadEnumRegistry(version, pixlyzerData["entity_meta_data_data_types"], entityMetaDataDataDataTypesRegistry, DefaultRegistries.ENTITY_META_DATA_DATA_TYPES_REGISTRY) - loadEnumRegistry(pixlyzerData["title_actions"], titleActionsRegistry, DefaultRegistries.TITLE_ACTIONS_REGISTRY) + loadEnumRegistry(version, pixlyzerData["title_actions"], titleActionsRegistry, DefaultRegistries.TITLE_ACTIONS_REGISTRY) // id stuff biomeCategoryRegistry.initialize(pixlyzerData["biome_categories"]?.asJsonObject, this, BiomeCategory) @@ -242,4 +216,22 @@ class VersionMapping(var version: Version?) { field.javaClass.getMethod("clear").invoke(this) } } + + companion object { + private val PARENTABLE_FIELDS: List + private val PARENTABLE_SET_PARENT_METHOD = Parentable::class.java.getDeclaredMethod("setParent", Any::class.java) + + init { + val fields: MutableList = mutableListOf() + + for (field in VersionMapping::class.java.declaredFields) { + if (!Parentable::class.java.isAssignableFrom(field.type)) { + continue + } + fields.add(field) + } + + PARENTABLE_FIELDS = fields.toList() + } + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java index ad65a584e..6bbd8d4e2 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java @@ -75,7 +75,7 @@ public class Connection { private int desiredVersionNumber = -1; private ServerAddress address; private Version version = Versions.LOWEST_VERSION_SUPPORTED; // default - private final VersionMapping customMapping = new VersionMapping(this.version); + private final VersionMapping customMapping = new VersionMapping(); private ConnectionStates state = ConnectionStates.DISCONNECTED; private ConnectionReasons reason; private ConnectionReasons nextReason; @@ -144,7 +144,6 @@ public class Connection { setVersion(version); try { version.load(latch); // ToDo: show gui loader - this.customMapping.setVersion(version); this.customMapping.setParentMapping(version.getMapping()); this.player = new Player(this.account, this); @@ -159,10 +158,6 @@ public class Connection { } catch (Throwable exception) { Log.printException(exception, LogLevels.DEBUG); Log.fatal(String.format("Could not load version %s. This version seems to be unsupported!", version)); - if (this.customMapping.getVersion() != null) { - this.customMapping.getVersion().getMapping().setParentMapping(null); - } - this.customMapping.setVersion(null); version.unload(); this.lastException = new MappingsLoadingException("Mappings could not be loaded", exception); setConnectionState(ConnectionStates.FAILED_NO_RETRY); diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java index 72677ecf9..40e954dad 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java @@ -190,7 +190,7 @@ public class OutByteBuffer { writeShort((short) this.connection.getMapping().getItemRegistry().getId(itemStack.getItem())); writeByte((byte) itemStack.getItemCount()); writeShort((short) itemStack.getItemMetadata()); - writeNBT(itemStack.getNbt(this.connection.getMapping())); + writeNBT(itemStack.getNBT()); } if (itemStack == null) { writeBoolean(false); @@ -198,7 +198,7 @@ public class OutByteBuffer { } writeVarInt(this.connection.getMapping().getItemRegistry().getId(itemStack.getItem())); writeByte((byte) itemStack.getItemCount()); - writeNBT(itemStack.getNbt(this.connection.getMapping())); + writeNBT(itemStack.getNBT()); } void writeNBT(CompoundTag nbt) {