From 36ad4d519344e1f91136e928605da1766f224129 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Tue, 9 Mar 2021 18:24:36 +0100 Subject: [PATCH] port for 1.15.2 --- pom.xml | 4 +- .../de/bixilon/pixlyzer/EntitySpawner.kt | 12 +- .../generator/generators/BiomeGenerator.kt | 102 ++++++++++++---- .../generator/generators/BlockGenerator.kt | 43 +++---- .../generators/DimensionGenerator.kt | 114 +++++++++++++----- .../generator/generators/EntityGenerator.kt | 109 +++++++++-------- .../generator/generators/ItemGenerator.kt | 33 +++-- .../generator/generators/MaterialGenerator.kt | 2 +- .../generators/MobEffectGenerator.kt | 2 +- .../bixilon/pixlyzer/util/ReflectionUtil.kt | 17 ++- 10 files changed, 290 insertions(+), 148 deletions(-) diff --git a/pom.xml b/pom.xml index 3b42475..3f9a571 100644 --- a/pom.xml +++ b/pom.xml @@ -9,13 +9,13 @@ 1.0-SNAPSHOT jar - mainModule + pixlyzer UTF-8 official 1.8 - 21w07a + 1.15.2 diff --git a/src/main/kotlin/de/bixilon/pixlyzer/EntitySpawner.kt b/src/main/kotlin/de/bixilon/pixlyzer/EntitySpawner.kt index f708afc..14ab96f 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/EntitySpawner.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/EntitySpawner.kt @@ -1,15 +1,18 @@ package de.bixilon.pixlyzer import com.mojang.authlib.GameProfile +import de.bixilon.pixlyzer.util.ReflectionUtil.getClass import de.bixilon.pixlyzer.util.ReflectionUtil.getField import de.bixilon.pixlyzer.util.ReflectionUtil.setFinalField import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.client.player.RemotePlayer import net.minecraft.world.entity.Entity import net.minecraft.world.entity.EntityType +import net.minecraft.world.entity.fishing.FishingHook +import net.minecraft.world.entity.global.LightningBolt import net.minecraft.world.level.Level import net.minecraft.world.level.border.WorldBorder -import net.minecraft.world.level.storage.PrimaryLevelData +import net.minecraft.world.level.dimension.NormalDimension import net.minecraft.world.scores.Scoreboard import org.objenesis.Objenesis import org.objenesis.ObjenesisStd @@ -28,7 +31,9 @@ object EntitySpawner { } return when (entityType) { EntityType.PLAYER -> RemotePlayer(CLIENT_LEVEL, GameProfile(UUID.randomUUID(), "dummy")) - else -> TODO() + EntityType.LIGHTNING_BOLT -> OBJENSIS.newInstance(LightningBolt::class.java) + EntityType.FISHING_BOBBER -> OBJENSIS.newInstance(FishingHook::class.java) + else -> TODO("Entity type: $entityType") } } @@ -42,8 +47,9 @@ object EntitySpawner { init { setFinalField(getField(Level::class.java, "random")!!, CLIENT_LEVEL, Random()) setFinalField(getField(Level::class.java, "worldBorder")!!, CLIENT_LEVEL, WorldBorder()) - setFinalField(getField(Level::class.java, "levelData")!!, CLIENT_LEVEL, OBJENSIS.newInstance(PrimaryLevelData::class.java)) + setFinalField(getField(Level::class.java, "levelData")!!, CLIENT_LEVEL, OBJENSIS.newInstance(getClass("net.minecraft.world.level.storage.PrimaryLevelData", "net.minecraft.world.level.storage.LevelData"))) setFinalField(getField(ClientLevel::class.java, "scoreboard")!!, CLIENT_LEVEL, Scoreboard()) + setFinalField(getField(Level::class.java, "dimension")!!, CLIENT_LEVEL, OBJENSIS.newInstance(NormalDimension::class.java)) } } diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BiomeGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BiomeGenerator.kt index b2c757b..23f3cd6 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BiomeGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BiomeGenerator.kt @@ -2,49 +2,105 @@ package de.bixilon.pixlyzer.generator.generators import com.google.gson.JsonObject import de.bixilon.pixlyzer.generator.Generator +import de.bixilon.pixlyzer.util.ReflectionUtil.getClass +import de.bixilon.pixlyzer.util.ReflectionUtil.getField import net.minecraft.core.Registry -import net.minecraft.data.BuiltinRegistries +import net.minecraft.resources.ResourceLocation +import net.minecraft.sounds.SoundEvent +import net.minecraft.world.level.biome.Biome +import java.util.* object BiomeGenerator : Generator( "biomes" ) { override fun generate() { - for (biome in BuiltinRegistries.BIOME) { - val resourceIdentifier = BuiltinRegistries.BIOME.getKey(biome) + for ((resourceLocation, id, biome) in getBiomes()) { val biomeData = JsonObject() - biomeData.addProperty("id", BuiltinRegistries.BIOME.getId(biome)) + biomeData.addProperty("id", id) biomeData.addProperty("depth", biome.depth) biomeData.addProperty("scale", biome.scale) - biomeData.addProperty("temperature", biome.baseTemperature) - biomeData.addProperty("downfall", biome.downfall) biomeData.addProperty("water_color", biome.waterColor) biomeData.addProperty("water_fog_color", biome.waterFogColor) biomeData.addProperty("category", biome.biomeCategory.ordinal) - biomeData.addProperty("precipitation", biome.precipitation.ordinal) + val climateParameters = CLIMATE_PARAMETERS_FIELD?.get(biome) ?: biome - biome.specialEffects?.let { - biomeData.addProperty("fog_color", it.fogColor) - biomeData.addProperty("water_color", it.waterColor) - biomeData.addProperty("water_fog_color", it.waterFogColor) - biomeData.addProperty("sky_color", it.skyColor) - if (it.foliageColorOverride.isPresent) { - biomeData.addProperty("foliage_color_override", it.foliageColorOverride.get()) + biomeData.addProperty("precipitation", (PRECIPITATION_FIELD.get(climateParameters) as Enum<*>?)?.ordinal) + biomeData.addProperty("temperature", TEMPERATURE_FIELD.getFloat(climateParameters)) + (TEMPERATURE_MODIFIER_FIELD?.get(climateParameters) as Enum<*>?)?.let { + biomeData.addProperty("temperature_modifier", it.name) + } + biomeData.addProperty("downfall", DOWNFALL_FIELD.getFloat(climateParameters)) + + + + getField(Biome::class.java, "specialEffects")?.get(biome)?.let { + FOG_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let { + biomeData.addProperty("fog_color", it) } - if (it.grassColorOverride.isPresent) { - biomeData.addProperty("grass_color_override", it.grassColorOverride.get()) + WATER_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let { + biomeData.addProperty("water_color", it) } - it.grassColorModifier?.let { - biomeData.addProperty("grass_color_modifier", it.name.toLowerCase()) + WATER_FOG_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let { + biomeData.addProperty("water_fog_color", it) } - if (it.ambientLoopSoundEvent.isPresent) { - biomeData.addProperty("ambient_sound_event_loop", Registry.SOUND_EVENT.getId(it.ambientLoopSoundEvent.get())) + SKY_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let { + biomeData.addProperty("sky_color", it) } - if (it.backgroundMusic.isPresent) { - biomeData.addProperty("background_music", Registry.SOUND_EVENT.getId(it.backgroundMusic.get().event)) + (FOLIAGE_COLOR_OVERRIDE_SPECIAL_EFFECTS_FIELD?.get(it) as Optional?)?.ifPresent { + biomeData.addProperty("foliage_color_override", it) + } + (GRASS_COLOR_OVERRIDE_SPECIAL_EFFECTS_FIELD?.get(it) as Optional?)?.ifPresent { + biomeData.addProperty("grass_color_override", it) + } + (GRASS_COLOR_MODIFIER_SPECIAL_EFFECTS_FIELD?.get(it) as Enum<*>?)?.name?.let { + biomeData.addProperty("grass_color_modifier", it) + } + + (AMBIENT_SOUND_LOOP_EVENT_SPECIAL_EFFECTS_FIELD?.get(it) as Optional?)?.ifPresent { + biomeData.addProperty("ambient_sound_event_loop", Registry.SOUND_EVENT.getId(it)) + } + + (BACKGROUND_MUSIC_SPECIAL_EFFECTS_FIELD?.get(it) as Optional?)?.ifPresent { + biomeData.addProperty("background_music", Registry.SOUND_EVENT.getId(MUSIC_CLASS_EVENT_FIELD!!.get(it) as SoundEvent)) } } - data.add(resourceIdentifier.toString(), biomeData) + data.add(resourceLocation.toString(), biomeData) } } + + private val SPECIAL_EFFECTS_CLASS = getClass("net.minecraft.world.level.biome.BiomeSpecialEffects") + private val CLIMATE_SETTINGS_CLASS = getClass("net.minecraft.world.level.biome.Biome\$ClimateSettings", "net.minecraft.world.level.biome.Biome")!! + + private val FOG_COLOR_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "fogColor") + private val WATER_COLOR_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "waterColor") + private val WATER_FOG_COLOR_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "waterFogColor") + private val SKY_COLOR_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "skyColor") + private val FOLIAGE_COLOR_OVERRIDE_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "foliageColorOverride") + private val GRASS_COLOR_OVERRIDE_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "grassColorOverride") + private val GRASS_COLOR_MODIFIER_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "grassColorModifier") + private val AMBIENT_SOUND_LOOP_EVENT_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "ambientLoopSoundEvent") + private val BACKGROUND_MUSIC_SPECIAL_EFFECTS_FIELD = getField(SPECIAL_EFFECTS_CLASS, "backgroundMusic") + + + private val CLIMATE_PARAMETERS_FIELD = getField(Biome::class.java, "climateSettings") + private val PRECIPITATION_FIELD = getField(CLIMATE_SETTINGS_CLASS, "precipitation")!! + private val TEMPERATURE_FIELD = getField(CLIMATE_SETTINGS_CLASS, "temperature", "baseTemperature")!! + private val TEMPERATURE_MODIFIER_FIELD = getField(CLIMATE_SETTINGS_CLASS, "temperatureModifier") + private val DOWNFALL_FIELD = getField(CLIMATE_SETTINGS_CLASS, "downfall")!! + + + private val MUSIC_CLASS_EVENT_FIELD = getField(getClass("net.minecraft.sounds.Music"), "event") + + private fun getBiomes(): Set> { + val biomes = getField(getClass("net.minecraft.data.BuiltinRegistries", Registry::class.java.name)!!, "BIOME")!!.get(null) as Registry + + val ret: MutableSet> = mutableSetOf() + + for (biome in biomes) { + ret.add(Triple(biomes.getKey(biome)!!, biomes.getId(biome), biome)) + } + + return ret + } } diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BlockGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BlockGenerator.kt index 2c95e36..23183d5 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BlockGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BlockGenerator.kt @@ -4,13 +4,15 @@ import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject import de.bixilon.pixlyzer.generator.Generator +import de.bixilon.pixlyzer.util.ReflectionUtil.getClass +import de.bixilon.pixlyzer.util.ReflectionUtil.getField import de.bixilon.pixlyzer.util.Util import net.minecraft.client.color.block.BlockColors import net.minecraft.core.IdMapper import net.minecraft.core.Registry import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Blocks -import net.minecraft.world.level.block.state.BlockBehaviour +import net.minecraft.world.level.block.state.AbstractStateHolder import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.StateHolder import net.minecraft.world.phys.shapes.VoxelShape @@ -49,17 +51,13 @@ object BlockGenerator : Generator( blockData.addProperty("jump_factor", block.jumpFactor) } blockData.addProperty("default_state", Block.getId(block.defaultBlockState())) - BLOCK_HAS_COLLISION_FIELD.getBoolean(block).let { - if (it) { - return@let - } - blockData.addProperty("has_collision", it) - } if (block.hasDynamicShape()) { blockData.addProperty("has_dynamic_shape", block.hasDynamicShape()) } - - blockData.addProperty("default_material_color", block.defaultMaterialColor().col) + try { + blockData.addProperty("destroy_speed", BLOCK_DESTROY_SPEED_FIELD.getFloat(block)) + } catch (exception: IllegalArgumentException) { + } val render = Util.readJsonMinecraftResource("assets/${resourceIdentifier.namespace}/blockstates/${resourceIdentifier.path}.json") @@ -177,13 +175,17 @@ object BlockGenerator : Generator( stateData.addProperty("fall_sound_type", Registry.SOUND_EVENT.getId(state.soundType.fallSound)) - if (state.requiresCorrectToolForDrops()) { - stateData.addProperty("requires_correct_tool_for_drop", state.requiresCorrectToolForDrops()) + REQUIRES_CORRECT_TOOL_FOR_DROP_FIELDS?.let { + stateData.addProperty("requires_correct_tool_for_drop", it.getBoolean(state)) } + if (!state.canOcclude()) { stateData.addProperty("can_occlude", state.canOcclude()) } - stateData.addProperty("destroy_speed", BLOCK_DESTROY_SPEED_FIELD.getFloat(state)) + try { + stateData.addProperty("destroy_speed", BLOCK_DESTROY_SPEED_FIELD.getFloat(state)) + } catch (exception: IllegalArgumentException) { + } stateData.addProperty("material", MaterialGenerator.MATERIALS.inverse()[state.material].toString()) @@ -330,17 +332,18 @@ object BlockGenerator : Generator( return true } - private val BLOCK_STATE_BASE_CLASS = BlockBehaviour.BlockStateBase::class.java - private val BLOCK_DESTROY_SPEED_FIELD = BLOCK_STATE_BASE_CLASS.getDeclaredField("destroySpeed") - private val BLOCK_HAS_COLLISION_FIELD = BlockBehaviour::class.java.getDeclaredField("hasCollision") - private val BLOCK_STATE_OWNER_FIELD = StateHolder::class.java.getDeclaredField("owner") - private val BLOCK_STATE_CACHE_FIELD = BlockBehaviour.BlockStateBase::class.java.getDeclaredField("cache") + private val BLOCK_STATE_BASE_CLASS = getClass("net.minecraft.world.level.block.state.BlockBehaviour\$BlockStateBase", "net.minecraft.world.level.block.state.BlockState")!! + private val BLOCK_DESTROY_SPEED_FIELD = getField(BLOCK_STATE_BASE_CLASS, "destroySpeed") ?: getField(Block::class.java, "destroySpeed")!! + private val BLOCK_STATE_OWNER_FIELD = getField(StateHolder::class.java, "owner") ?: getField(AbstractStateHolder::class.java, "owner")!! + private val BLOCK_STATE_CACHE_FIELD = BLOCK_STATE_BASE_CLASS.getDeclaredField("cache") + + private val REQUIRES_CORRECT_TOOL_FOR_DROP_FIELDS = getField(BlockState::class.java, "requiresCorrectToolForDrops") private lateinit var BLOCK_STATE_CACHE_CLASS: Class<*> init { for (clazz in BLOCK_STATE_BASE_CLASS.declaredClasses) { - if (clazz.name == "net.minecraft.world.level.block.state.BlockBehaviour\$BlockStateBase\$Cache") { + if (clazz.name == "net.minecraft.world.level.block.state.BlockBehaviour\$BlockStateBase\$Cache" || clazz.name == "net.minecraft.world.level.block.state.BlockState\$Cache") { BLOCK_STATE_CACHE_CLASS = clazz break } @@ -353,14 +356,12 @@ object BlockGenerator : Generator( private val CACHE_OCCLUSION_SHAPES_FIELD = BLOCK_STATE_CACHE_CLASS.getDeclaredField("occlusionShapes") private val CACHE_COLLISION_SHAPES_FIELD = BLOCK_STATE_CACHE_CLASS.getDeclaredField("collisionShape") private val LARGE_COLLISION_SHAPE_FIELD = BLOCK_STATE_CACHE_CLASS.getDeclaredField("largeCollisionShape") - private val IS_FACE_STURDY = BLOCK_STATE_CACHE_CLASS.getDeclaredField("faceSturdy") + private val IS_FACE_STURDY = getField(BLOCK_STATE_CACHE_CLASS, "faceSturdy", "isFaceSturdy")!! private val IS_COLLISION_SHAPE_FULL_BLOCK = BLOCK_STATE_CACHE_CLASS.getDeclaredField("isCollisionShapeFullBlock") init { BLOCK_DESTROY_SPEED_FIELD.isAccessible = true - BLOCK_HAS_COLLISION_FIELD.isAccessible = true - BLOCK_STATE_OWNER_FIELD.isAccessible = true BLOCK_STATE_CACHE_FIELD.isAccessible = true CACHE_SOLID_RENDER_FIELD.isAccessible = true diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/DimensionGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/DimensionGenerator.kt index 0bb364e..3c3ed2e 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/DimensionGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/DimensionGenerator.kt @@ -2,6 +2,8 @@ package de.bixilon.pixlyzer.generator.generators import com.google.gson.JsonObject import de.bixilon.pixlyzer.generator.Generator +import de.bixilon.pixlyzer.util.ReflectionUtil.getField +import net.minecraft.resources.ResourceLocation import net.minecraft.world.level.dimension.DimensionType import java.lang.reflect.Modifier import java.util.* @@ -11,46 +13,95 @@ object DimensionGenerator : Generator( ) { override fun generate() { // val registry = Registry.REGISTRY.get(Registry.DIMENSION_TYPE_REGISTRY.location()) as Registry - for (dimension in getDimensions()) { + for ((resourceLocation, id, dimension) in getDimensions()) { val dimensionData = JsonObject() + id?.let { + dimensionData.addProperty("id", id) + } + dimensionData.addProperty("file_suffix", dimension.fileSuffix) - (FIXED_TIME_FIELD.get(dimension) as OptionalLong?)?.let { + (FIXED_TIME_FIELD?.get(dimension) as OptionalLong?)?.let { if (it.isPresent) { dimensionData.addProperty("fixed_time", it.asLong) } } - dimensionData.addProperty("has_sky_light", dimension.hasSkyLight()) - dimensionData.addProperty("has_ceiling", dimension.hasCeiling()) - dimensionData.addProperty("ultra_warm", dimension.ultraWarm()) - dimensionData.addProperty("natural", dimension.natural()) - dimensionData.addProperty("coordinate_scale", dimension.coordinateScale()) - dimensionData.addProperty("create_dragon_fight", dimension.createDragonFight()) - dimensionData.addProperty("piglin_safe", dimension.piglinSafe()) - dimensionData.addProperty("bed_works", dimension.bedWorks()) - dimensionData.addProperty("respawn_anchor_works", dimension.respawnAnchorWorks()) - dimensionData.addProperty("has_raids", dimension.hasRaids()) - dimensionData.addProperty("min_y", dimension.minY()) - dimensionData.addProperty("height", dimension.height()) - dimensionData.addProperty("logical_height", dimension.logicalHeight()) - dimensionData.addProperty("infiniburn", dimension.infiniburn().toString()) - dimensionData.addProperty("effects_location", dimension.effectsLocation().toString()) - dimensionData.addProperty("ambient_light", AMBIENT_LIGHT_FIELD.getFloat(dimension)) + HAS_SKYLIGHT_FIELD?.let { + dimensionData.addProperty("has_sky_light", it.getBoolean(dimension)) + } + HAS_CEILING_FIELD?.let { + dimensionData.addProperty("has_ceiling", it.getBoolean(dimension)) + } + ULTRA_WARM_FIELD?.let { + dimensionData.addProperty("ultra_warm", it.getBoolean(dimension)) + } + NATURAL_FIELD?.let { + dimensionData.addProperty("natural", it.getBoolean(dimension)) + } + COORDINATE_SCALE_FIELD?.let { + dimensionData.addProperty("coordinate_scale", it.getDouble(dimension)) + } + CREATE_DRAGON_FIGHT_FIELD?.let { + dimensionData.addProperty("create_dragon_fight", it.getBoolean(dimension)) + } + PIGLIN_SAFE_FIELD?.let { + dimensionData.addProperty("piglin_safe", it.getBoolean(dimension)) + } + BED_WORKS_FIELD?.let { + dimensionData.addProperty("bed_works", it.getBoolean(dimension)) + } + RESPAWN_ANCHOR_WORKS_FIELD?.let { + dimensionData.addProperty("respawn_anchor_works", it.getBoolean(dimension)) + } + HAS_RAIDS_FIELD?.let { + dimensionData.addProperty("has_raids", it.getBoolean(dimension)) + } + MIN_Y_FIELD?.let { + dimensionData.addProperty("min_y", it.getInt(dimension)) + } + HEIGHT_FIELD?.let { + dimensionData.addProperty("height", it.getInt(dimension)) + } + LOGICAL_HEIGHT_FIELD?.let { + dimensionData.addProperty("logical_height", it.getInt(dimension)) + } + INFINIBURN_FIELD?.let { + dimensionData.addProperty("infiniburn", (it.get(dimension) as ResourceLocation).toString()) + } + EFFECTS_LOCATION_FIELD?.let { + dimensionData.addProperty("effects_location", (it.get(dimension) as ResourceLocation).toString()) + } + AMBIENT_LIGHT_FIELD?.let { + dimensionData.addProperty("ambient_light", it.getFloat(dimension)) + } - data.add(dimension.effectsLocation().toString(), dimensionData) + data.add(resourceLocation.toString(), dimensionData) } } - private val FIXED_TIME_FIELD = DimensionType::class.java.getDeclaredField("fixedTime") - private val AMBIENT_LIGHT_FIELD = DimensionType::class.java.getDeclaredField("ambientLight") + private val DIMENSION_TYPE_CLASS = DimensionType::class.java - init { - FIXED_TIME_FIELD.isAccessible = true - AMBIENT_LIGHT_FIELD.isAccessible = true - } + private val FIXED_TIME_FIELD = getField(DIMENSION_TYPE_CLASS, "fixedTime") + private val HAS_SKYLIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "hasSkylight") + private val HAS_CEILING_FIELD = getField(DIMENSION_TYPE_CLASS, "hasCeiling") + private val ULTRA_WARM_FIELD = getField(DIMENSION_TYPE_CLASS, "ultraWarm") + private val NATURAL_FIELD = getField(DIMENSION_TYPE_CLASS, "natural") + private val COORDINATE_SCALE_FIELD = getField(DIMENSION_TYPE_CLASS, "coordinateScale") + private val CREATE_DRAGON_FIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "createDragonFight") + private val PIGLIN_SAFE_FIELD = getField(DIMENSION_TYPE_CLASS, "piglinSafe") + private val BED_WORKS_FIELD = getField(DIMENSION_TYPE_CLASS, "bedWorks") + private val RESPAWN_ANCHOR_WORKS_FIELD = getField(DIMENSION_TYPE_CLASS, "respawnAnchorWorks") + private val HAS_RAIDS_FIELD = getField(DIMENSION_TYPE_CLASS, "hasRaids") + private val MIN_Y_FIELD = getField(DIMENSION_TYPE_CLASS, "minY") + private val HEIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "height") + private val LOGICAL_HEIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "logicalHeight") + private val INFINIBURN_FIELD = getField(DIMENSION_TYPE_CLASS, "infiniburn") + private val EFFECTS_LOCATION_FIELD = getField(DIMENSION_TYPE_CLASS, "effectsLocation") + private val AMBIENT_LIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "ambientLight") - private fun getDimensions(): List { - val types: MutableList = mutableListOf() + + private fun getDimensions(): MutableSet> { + val types: MutableSet> = mutableSetOf() for (field in DimensionType::class.java.declaredFields) { if (field.type != DimensionType::class.java) { @@ -60,7 +111,14 @@ object DimensionGenerator : Generator( continue } field.isAccessible = true - types.add(field.get(null) as DimensionType) + val resourceLocation = when (field.name) { + "DEFAULT_OVERWORLD", "OVERWORLD" -> ResourceLocation("overworld") + "DEFAULT_OVERWORLD_CAVES" -> ResourceLocation("overworld_caves") + "DEFAULT_NETHER", "NETHER" -> ResourceLocation("the_nether") + "DEFAULT_END", "THE_END" -> ResourceLocation("the_end") + else -> TODO("Can not find dimension ${field.name}") + } + types.add(Triple(resourceLocation, null, field.get(null) as DimensionType)) } return types diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/EntityGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/EntityGenerator.kt index 49bc4b7..3764f59 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/EntityGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/EntityGenerator.kt @@ -4,13 +4,16 @@ import com.google.gson.JsonObject import de.bixilon.pixlyzer.EntitySpawner import de.bixilon.pixlyzer.PixLyzer import de.bixilon.pixlyzer.generator.Generator +import de.bixilon.pixlyzer.util.ReflectionUtil.getClass +import net.minecraft.client.player.AbstractClientPlayer +import net.minecraft.client.player.RemotePlayer import net.minecraft.core.Registry import net.minecraft.network.syncher.EntityDataAccessor import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.entity.ai.attributes.Attributes -import net.minecraft.world.entity.player.Player +import net.minecraft.world.entity.ai.attributes.Attribute +import java.lang.reflect.Modifier object EntityGenerator : Generator( "entities" @@ -44,53 +47,13 @@ object EntityGenerator : Generator( // some entities have random values, we can and will ignore these ones if (entity is LivingEntity && entity2 is LivingEntity) { - entity.attributes.getInstance(Attributes.MAX_HEALTH)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.MAX_HEALTH)?.value) { - return@let + for ((resourceLocation, attribute) in ATTRIBUTE_MAP) { + entity.attributes.getInstance(attribute)?.value?.let { + if (it != entity2.attributes.getInstance(attribute)?.value) { + return@let + } + entityData.addProperty(resourceIdentifier.toString(), it) } - entityData.addProperty("max_health", it) - } - entity.attributes.getInstance(Attributes.FOLLOW_RANGE)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.FOLLOW_RANGE)?.value) { - return@let - } - entityData.addProperty("follow_range", it) - } - entity.attributes.getInstance(Attributes.MOVEMENT_SPEED)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.MOVEMENT_SPEED)?.value) { - return@let - } - entityData.addProperty("movement_speed", it) - } - entity.attributes.getInstance(Attributes.FLYING_SPEED)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.FLYING_SPEED)?.value) { - return@let - } - entityData.addProperty("flying_speed", it) - } - entity.attributes.getInstance(Attributes.ATTACK_DAMAGE)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.ATTACK_DAMAGE)?.value) { - return@let - } - entityData.addProperty("attack_damage", it) - } - entity.attributes.getInstance(Attributes.ARMOR)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.ARMOR)?.value) { - return@let - } - entityData.addProperty("armor", it) - } - entity.attributes.getInstance(Attributes.ARMOR_TOUGHNESS)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.ARMOR_TOUGHNESS)?.value) { - return@let - } - entityData.addProperty("armor_toughness", it) - } - entity.attributes.getInstance(Attributes.LUCK)?.value?.let { - if (it != entity2.attributes.getInstance(Attributes.LUCK)?.value) { - return@let - } - entityData.addProperty("luck", it) } // entity.getEatingSound(ItemStack.EMPTY)?.let { @@ -124,14 +87,21 @@ object EntityGenerator : Generator( } // Fix player - data[ResourceLocation("player").toString()]?.asJsonObject?.let { - val playerClassName = Player::class.simpleName.toString() - val player = data[playerClassName].asJsonObject - for ((key, value) in player.entrySet()) { - it.add(key, value) + data["minecraft:player"]?.asJsonObject?.let { playerJson -> + fun mergePlayerDate(name: String) { + data[name]?.asJsonObject?.let { + for ((key, value) in it.entrySet()) { + playerJson.add(key, value) + } + it.remove("class") + it.remove("parent") + data.remove(name) + } } - it.addProperty("class", playerClassName) - data.remove(playerClassName) + mergePlayerDate(RemotePlayer::class.simpleName.toString()) + mergePlayerDate(AbstractClientPlayer::class.simpleName.toString()) + mergePlayerDate("Player") + playerJson.addProperty("class", "Player") } } @@ -191,4 +161,33 @@ object EntityGenerator : Generator( return json } + + private val ATTRIBUTE_CLASS = getClass("net.minecraft.world.entity.ai.attributes.Attributes", "net.minecraft.world.entity.monster.SharedMonsterAttributes")!! + + private val ATTRIBUTE_MAP: Map = getAttributes() + + + private fun getAttributes(): Map { + val ret: MutableMap = mutableMapOf() + for (field in ATTRIBUTE_CLASS.declaredFields) { + if (field.type != Attribute::class.java) { + continue + } + if (!Modifier.isStatic(field.modifiers)) { + continue + } + val attribute = field.get(null) as Attribute + ret[attribute.name] = attribute + } + return ret + } + + fun getKeyFromMobEffect(attribute: Attribute): String { + for ((resourceLocation, found) in ATTRIBUTE_MAP) { + if (found == attribute) { + return resourceLocation + } + } + TODO() + } } diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/ItemGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/ItemGenerator.kt index a9ce2d0..1fb570e 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/ItemGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/ItemGenerator.kt @@ -3,6 +3,8 @@ package de.bixilon.pixlyzer.generator.generators import com.google.gson.JsonArray import com.google.gson.JsonObject import de.bixilon.pixlyzer.generator.Generator +import de.bixilon.pixlyzer.util.ReflectionUtil.getClass +import de.bixilon.pixlyzer.util.ReflectionUtil.getField import net.minecraft.core.Registry import net.minecraft.sounds.SoundEvent import net.minecraft.world.entity.EntityType @@ -27,7 +29,9 @@ object ItemGenerator : Generator( itemData.addProperty("rarity", item.getRarity(ItemStack.EMPTY).ordinal) itemData.addProperty("max_stack_size", item.maxStackSize) itemData.addProperty("max_damage", item.maxDamage) - itemData.addProperty("is_fire_resistant", item.isFireResistant) + IS_FIRE_RESISTANT_FIELD?.let { + itemData.addProperty("is_fire_resistant", it.getBoolean(item)) + } itemData.addProperty("is_complex", item.isComplex) item.descriptionId?.let { itemData.addProperty("description_id", it) @@ -67,7 +71,9 @@ object ItemGenerator : Generator( itemData.addProperty("defense", item.defense) itemData.addProperty("toughness", ARMOR_ITEM_TOUGHNESS_FIELD.getFloat(item)) itemData.addProperty("armor_material", item.material.name.toLowerCase()) - itemData.addProperty("knockback_resistance", ARMOR_ITEM_KNOCKBACK_RESISTANCE.getFloat(item)) + ARMOR_ITEM_KNOCKBACK_RESISTANCE?.getFloat(item)?.let { + itemData.addProperty("knockback_resistance", it) + } } if (item is AxeItem) { @@ -89,11 +95,11 @@ object ItemGenerator : Generator( if (item is DyeItem) { itemData.addProperty("dye_color", item.dyeColor.name.toLowerCase()) } - if (item is MobBucketItem) { - (MOB_BUCKED_ITEM_TYPE_FIELD.get(item) as EntityType<*>?)?.let { + if (item::class.java == MOB_BUCKED_ITEM_CLASS) { + (MOB_BUCKED_ITEM_TYPE_FIELD?.get(item) as EntityType<*>?)?.let { itemData.addProperty("bucket_fish_type", Registry.ENTITY_TYPE.getId(it)) } - (MOB_BUCKED_ITEM_EMPTY_SOUND_FIELD.get(item) as SoundEvent?)?.let { + (MOB_BUCKED_ITEM_EMPTY_SOUND_FIELD?.get(item) as SoundEvent?)?.let { itemData.addProperty("bucket_empty_sound", Registry.SOUND_EVENT.getId(it)) } } @@ -159,34 +165,35 @@ object ItemGenerator : Generator( return data } + private val MOB_BUCKED_ITEM_CLASS = getClass("net.minecraft.world.item.MobBucketItem", "net.minecraft.world.item.BucketItem") + + + private val IS_FIRE_RESISTANT_FIELD = getField(Item::class.java, "blocks") + private val DIGGER_ITEM_BLOCKS_FIELD = DiggerItem::class.java.getDeclaredField("blocks") private val DIGGER_ITEM_SPEED_FIELD = DiggerItem::class.java.getDeclaredField("speed") - private val DIGGER_ITEM_ATTACK_DAMAGE = DiggerItem::class.java.getDeclaredField("attackDamageBaseline") + private val DIGGER_ITEM_ATTACK_DAMAGE = getField(DiggerItem::class.java, "attackDamageBaseline", "attackDamage")!! private val ARMOR_ITEM_EQUIPMENT_SLOT_FIELD = ArmorItem::class.java.getDeclaredField("slot") private val ARMOR_ITEM_TOUGHNESS_FIELD = ArmorItem::class.java.getDeclaredField("toughness") private val AXE_ITEM_STRIPABLES_FIELD = AxeItem::class.java.getDeclaredField("STRIPABLES") private val BUCKED_ITEM_CONTENT_FIELD = BucketItem::class.java.getDeclaredField("content") - private val MOB_BUCKED_ITEM_TYPE_FIELD = MobBucketItem::class.java.getDeclaredField("type") - private val MOB_BUCKED_ITEM_EMPTY_SOUND_FIELD = MobBucketItem::class.java.getDeclaredField("emptySound") + private val MOB_BUCKED_ITEM_TYPE_FIELD = getField(MOB_BUCKED_ITEM_CLASS, "type") + private val MOB_BUCKED_ITEM_EMPTY_SOUND_FIELD = getField(MOB_BUCKED_ITEM_CLASS, "emptySound") private val HOE_ITEM_TILLABLES_FIELD = HoeItem::class.java.getDeclaredField("TILLABLES") private val SHOVEL_ITEM_FLATTENABLES_FIELD = ShovelItem::class.java.getDeclaredField("FLATTENABLES") private val SPAWN_EGG_ITEM_ENTITY_TYPE_FIELD = SpawnEggItem::class.java.getDeclaredField("defaultType") - private val ARMOR_ITEM_KNOCKBACK_RESISTANCE = ArmorItem::class.java.getDeclaredField("knockbackResistance") + private val ARMOR_ITEM_KNOCKBACK_RESISTANCE = getField(ArmorItem::class.java, "knockbackResistance") init { DIGGER_ITEM_BLOCKS_FIELD.isAccessible = true DIGGER_ITEM_SPEED_FIELD.isAccessible = true - DIGGER_ITEM_ATTACK_DAMAGE.isAccessible = true ARMOR_ITEM_EQUIPMENT_SLOT_FIELD.isAccessible = true ARMOR_ITEM_TOUGHNESS_FIELD.isAccessible = true AXE_ITEM_STRIPABLES_FIELD.isAccessible = true BUCKED_ITEM_CONTENT_FIELD.isAccessible = true - MOB_BUCKED_ITEM_TYPE_FIELD.isAccessible = true - MOB_BUCKED_ITEM_EMPTY_SOUND_FIELD.isAccessible = true HOE_ITEM_TILLABLES_FIELD.isAccessible = true SHOVEL_ITEM_FLATTENABLES_FIELD.isAccessible = true SPAWN_EGG_ITEM_ENTITY_TYPE_FIELD.isAccessible = true - ARMOR_ITEM_KNOCKBACK_RESISTANCE.isAccessible = true } diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MaterialGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MaterialGenerator.kt index d42f253..7335151 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MaterialGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MaterialGenerator.kt @@ -20,7 +20,7 @@ object MaterialGenerator : Generator( materialData.addProperty("liquid", material.isLiquid) materialData.addProperty("solid_blocking", material.isSolidBlocking) materialData.addProperty("replaceable", material.isReplaceable) - materialData.addProperty("sold", material.isSolid) + materialData.addProperty("solid", material.isSolid) data.add(resourceLocation.toString(), materialData) diff --git a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MobEffectGenerator.kt b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MobEffectGenerator.kt index 3e4ac99..59007c8 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MobEffectGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/MobEffectGenerator.kt @@ -34,7 +34,7 @@ object MobEffectGenerator : Generator( modifierData.addProperty("amount", modifier.amount) modifierData.addProperty("operation", modifier.operation.name.toLowerCase()) - modifiers.add(Registry.ATTRIBUTE.getKey(attribute).toString(), modifierData) + modifiers.add(EntityGenerator.getKeyFromMobEffect(attribute), modifierData) } if (modifiers.size() > 0) { diff --git a/src/main/kotlin/de/bixilon/pixlyzer/util/ReflectionUtil.kt b/src/main/kotlin/de/bixilon/pixlyzer/util/ReflectionUtil.kt index 31152ea..e3e3929 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/util/ReflectionUtil.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/util/ReflectionUtil.kt @@ -4,7 +4,22 @@ import org.apache.commons.lang3.reflect.FieldUtils import java.lang.reflect.Field object ReflectionUtil { - fun getField(clazz: Class<*>, vararg names: String): Field? { + + fun getClass(vararg names: String): Class<*>? { + for (name in names) { + try { + return Class.forName(name) + } catch (exception: ClassNotFoundException) { + + } + } + return null + } + + fun getField(clazz: Class<*>?, vararg names: String): Field? { + if (clazz == null) { + return null + } for (name in names) { try { val field = clazz.getDeclaredField(name)