port for 1.15.2

This commit is contained in:
Bixilon 2021-03-09 18:24:36 +01:00
parent dce124bb9b
commit 36ad4d5193
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
10 changed files with 290 additions and 148 deletions

View File

@ -9,13 +9,13 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>mainModule</name> <name>pixlyzer</name>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<kotlin.code.style>official</kotlin.code.style> <kotlin.code.style>official</kotlin.code.style>
<kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget> <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
<minecraft.version>21w07a</minecraft.version> <minecraft.version>1.15.2</minecraft.version>
</properties> </properties>
<repositories> <repositories>

View File

@ -1,15 +1,18 @@
package de.bixilon.pixlyzer package de.bixilon.pixlyzer
import com.mojang.authlib.GameProfile 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.getField
import de.bixilon.pixlyzer.util.ReflectionUtil.setFinalField import de.bixilon.pixlyzer.util.ReflectionUtil.setFinalField
import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.client.player.RemotePlayer import net.minecraft.client.player.RemotePlayer
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.EntityType 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.Level
import net.minecraft.world.level.border.WorldBorder 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 net.minecraft.world.scores.Scoreboard
import org.objenesis.Objenesis import org.objenesis.Objenesis
import org.objenesis.ObjenesisStd import org.objenesis.ObjenesisStd
@ -28,7 +31,9 @@ object EntitySpawner {
} }
return when (entityType) { return when (entityType) {
EntityType.PLAYER -> RemotePlayer(CLIENT_LEVEL, GameProfile(UUID.randomUUID(), "dummy")) 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 { init {
setFinalField(getField(Level::class.java, "random")!!, CLIENT_LEVEL, Random()) setFinalField(getField(Level::class.java, "random")!!, CLIENT_LEVEL, Random())
setFinalField(getField(Level::class.java, "worldBorder")!!, CLIENT_LEVEL, WorldBorder()) 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(ClientLevel::class.java, "scoreboard")!!, CLIENT_LEVEL, Scoreboard())
setFinalField(getField(Level::class.java, "dimension")!!, CLIENT_LEVEL, OBJENSIS.newInstance(NormalDimension::class.java))
} }
} }

View File

@ -2,49 +2,105 @@ package de.bixilon.pixlyzer.generator.generators
import com.google.gson.JsonObject import com.google.gson.JsonObject
import de.bixilon.pixlyzer.generator.Generator 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.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( object BiomeGenerator : Generator(
"biomes" "biomes"
) { ) {
override fun generate() { override fun generate() {
for (biome in BuiltinRegistries.BIOME) { for ((resourceLocation, id, biome) in getBiomes()) {
val resourceIdentifier = BuiltinRegistries.BIOME.getKey(biome)
val biomeData = JsonObject() val biomeData = JsonObject()
biomeData.addProperty("id", BuiltinRegistries.BIOME.getId(biome)) biomeData.addProperty("id", id)
biomeData.addProperty("depth", biome.depth) biomeData.addProperty("depth", biome.depth)
biomeData.addProperty("scale", biome.scale) biomeData.addProperty("scale", biome.scale)
biomeData.addProperty("temperature", biome.baseTemperature)
biomeData.addProperty("downfall", biome.downfall)
biomeData.addProperty("water_color", biome.waterColor) biomeData.addProperty("water_color", biome.waterColor)
biomeData.addProperty("water_fog_color", biome.waterFogColor) biomeData.addProperty("water_fog_color", biome.waterFogColor)
biomeData.addProperty("category", biome.biomeCategory.ordinal) 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("precipitation", (PRECIPITATION_FIELD.get(climateParameters) as Enum<*>?)?.ordinal)
biomeData.addProperty("fog_color", it.fogColor) biomeData.addProperty("temperature", TEMPERATURE_FIELD.getFloat(climateParameters))
biomeData.addProperty("water_color", it.waterColor) (TEMPERATURE_MODIFIER_FIELD?.get(climateParameters) as Enum<*>?)?.let {
biomeData.addProperty("water_fog_color", it.waterFogColor) biomeData.addProperty("temperature_modifier", it.name)
biomeData.addProperty("sky_color", it.skyColor) }
if (it.foliageColorOverride.isPresent) { biomeData.addProperty("downfall", DOWNFALL_FIELD.getFloat(climateParameters))
biomeData.addProperty("foliage_color_override", it.foliageColorOverride.get())
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) { WATER_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let {
biomeData.addProperty("grass_color_override", it.grassColorOverride.get()) biomeData.addProperty("water_color", it)
} }
it.grassColorModifier?.let { WATER_FOG_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let {
biomeData.addProperty("grass_color_modifier", it.name.toLowerCase()) biomeData.addProperty("water_fog_color", it)
} }
if (it.ambientLoopSoundEvent.isPresent) { SKY_COLOR_SPECIAL_EFFECTS_FIELD?.getInt(it)?.let {
biomeData.addProperty("ambient_sound_event_loop", Registry.SOUND_EVENT.getId(it.ambientLoopSoundEvent.get())) biomeData.addProperty("sky_color", it)
} }
if (it.backgroundMusic.isPresent) { (FOLIAGE_COLOR_OVERRIDE_SPECIAL_EFFECTS_FIELD?.get(it) as Optional<Int>?)?.ifPresent {
biomeData.addProperty("background_music", Registry.SOUND_EVENT.getId(it.backgroundMusic.get().event)) biomeData.addProperty("foliage_color_override", it)
}
(GRASS_COLOR_OVERRIDE_SPECIAL_EFFECTS_FIELD?.get(it) as Optional<Int>?)?.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<SoundEvent>?)?.ifPresent {
biomeData.addProperty("ambient_sound_event_loop", Registry.SOUND_EVENT.getId(it))
}
(BACKGROUND_MUSIC_SPECIAL_EFFECTS_FIELD?.get(it) as Optional<Any>?)?.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<Triple<ResourceLocation, Int, Biome>> {
val biomes = getField(getClass("net.minecraft.data.BuiltinRegistries", Registry::class.java.name)!!, "BIOME")!!.get(null) as Registry<Biome>
val ret: MutableSet<Triple<ResourceLocation, Int, Biome>> = mutableSetOf()
for (biome in biomes) {
ret.add(Triple(biomes.getKey(biome)!!, biomes.getId(biome), biome))
}
return ret
}
} }

View File

@ -4,13 +4,15 @@ import com.google.gson.JsonArray
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import de.bixilon.pixlyzer.generator.Generator 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 de.bixilon.pixlyzer.util.Util
import net.minecraft.client.color.block.BlockColors import net.minecraft.client.color.block.BlockColors
import net.minecraft.core.IdMapper import net.minecraft.core.IdMapper
import net.minecraft.core.Registry import net.minecraft.core.Registry
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.Blocks 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.BlockState
import net.minecraft.world.level.block.state.StateHolder import net.minecraft.world.level.block.state.StateHolder
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
@ -49,17 +51,13 @@ object BlockGenerator : Generator(
blockData.addProperty("jump_factor", block.jumpFactor) blockData.addProperty("jump_factor", block.jumpFactor)
} }
blockData.addProperty("default_state", Block.getId(block.defaultBlockState())) 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()) { if (block.hasDynamicShape()) {
blockData.addProperty("has_dynamic_shape", block.hasDynamicShape()) blockData.addProperty("has_dynamic_shape", block.hasDynamicShape())
} }
try {
blockData.addProperty("default_material_color", block.defaultMaterialColor().col) blockData.addProperty("destroy_speed", BLOCK_DESTROY_SPEED_FIELD.getFloat(block))
} catch (exception: IllegalArgumentException) {
}
val render = Util.readJsonMinecraftResource("assets/${resourceIdentifier.namespace}/blockstates/${resourceIdentifier.path}.json") 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)) stateData.addProperty("fall_sound_type", Registry.SOUND_EVENT.getId(state.soundType.fallSound))
if (state.requiresCorrectToolForDrops()) { REQUIRES_CORRECT_TOOL_FOR_DROP_FIELDS?.let {
stateData.addProperty("requires_correct_tool_for_drop", state.requiresCorrectToolForDrops()) stateData.addProperty("requires_correct_tool_for_drop", it.getBoolean(state))
} }
if (!state.canOcclude()) { if (!state.canOcclude()) {
stateData.addProperty("can_occlude", 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()) stateData.addProperty("material", MaterialGenerator.MATERIALS.inverse()[state.material].toString())
@ -330,17 +332,18 @@ object BlockGenerator : Generator(
return true return true
} }
private val BLOCK_STATE_BASE_CLASS = BlockBehaviour.BlockStateBase::class.java 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 = BLOCK_STATE_BASE_CLASS.getDeclaredField("destroySpeed") private val BLOCK_DESTROY_SPEED_FIELD = getField(BLOCK_STATE_BASE_CLASS, "destroySpeed") ?: getField(Block::class.java, "destroySpeed")!!
private val BLOCK_HAS_COLLISION_FIELD = BlockBehaviour::class.java.getDeclaredField("hasCollision") private val BLOCK_STATE_OWNER_FIELD = getField(StateHolder::class.java, "owner") ?: getField(AbstractStateHolder::class.java, "owner")!!
private val BLOCK_STATE_OWNER_FIELD = StateHolder::class.java.getDeclaredField("owner") private val BLOCK_STATE_CACHE_FIELD = BLOCK_STATE_BASE_CLASS.getDeclaredField("cache")
private val BLOCK_STATE_CACHE_FIELD = BlockBehaviour.BlockStateBase::class.java.getDeclaredField("cache")
private val REQUIRES_CORRECT_TOOL_FOR_DROP_FIELDS = getField(BlockState::class.java, "requiresCorrectToolForDrops")
private lateinit var BLOCK_STATE_CACHE_CLASS: Class<*> private lateinit var BLOCK_STATE_CACHE_CLASS: Class<*>
init { init {
for (clazz in BLOCK_STATE_BASE_CLASS.declaredClasses) { 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 BLOCK_STATE_CACHE_CLASS = clazz
break break
} }
@ -353,14 +356,12 @@ object BlockGenerator : Generator(
private val CACHE_OCCLUSION_SHAPES_FIELD = BLOCK_STATE_CACHE_CLASS.getDeclaredField("occlusionShapes") 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 CACHE_COLLISION_SHAPES_FIELD = BLOCK_STATE_CACHE_CLASS.getDeclaredField("collisionShape")
private val LARGE_COLLISION_SHAPE_FIELD = BLOCK_STATE_CACHE_CLASS.getDeclaredField("largeCollisionShape") 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") private val IS_COLLISION_SHAPE_FULL_BLOCK = BLOCK_STATE_CACHE_CLASS.getDeclaredField("isCollisionShapeFullBlock")
init { init {
BLOCK_DESTROY_SPEED_FIELD.isAccessible = true BLOCK_DESTROY_SPEED_FIELD.isAccessible = true
BLOCK_HAS_COLLISION_FIELD.isAccessible = true
BLOCK_STATE_OWNER_FIELD.isAccessible = true
BLOCK_STATE_CACHE_FIELD.isAccessible = true BLOCK_STATE_CACHE_FIELD.isAccessible = true
CACHE_SOLID_RENDER_FIELD.isAccessible = true CACHE_SOLID_RENDER_FIELD.isAccessible = true

View File

@ -2,6 +2,8 @@ package de.bixilon.pixlyzer.generator.generators
import com.google.gson.JsonObject import com.google.gson.JsonObject
import de.bixilon.pixlyzer.generator.Generator 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 net.minecraft.world.level.dimension.DimensionType
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.* import java.util.*
@ -11,46 +13,95 @@ object DimensionGenerator : Generator(
) { ) {
override fun generate() { override fun generate() {
// val registry = Registry.REGISTRY.get(Registry.DIMENSION_TYPE_REGISTRY.location()) as Registry<DimensionType> // val registry = Registry.REGISTRY.get(Registry.DIMENSION_TYPE_REGISTRY.location()) as Registry<DimensionType>
for (dimension in getDimensions()) { for ((resourceLocation, id, dimension) in getDimensions()) {
val dimensionData = JsonObject() val dimensionData = JsonObject()
id?.let {
dimensionData.addProperty("id", id)
}
dimensionData.addProperty("file_suffix", dimension.fileSuffix) 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) { if (it.isPresent) {
dimensionData.addProperty("fixed_time", it.asLong) dimensionData.addProperty("fixed_time", it.asLong)
} }
} }
dimensionData.addProperty("has_sky_light", dimension.hasSkyLight()) HAS_SKYLIGHT_FIELD?.let {
dimensionData.addProperty("has_ceiling", dimension.hasCeiling()) dimensionData.addProperty("has_sky_light", it.getBoolean(dimension))
dimensionData.addProperty("ultra_warm", dimension.ultraWarm()) }
dimensionData.addProperty("natural", dimension.natural()) HAS_CEILING_FIELD?.let {
dimensionData.addProperty("coordinate_scale", dimension.coordinateScale()) dimensionData.addProperty("has_ceiling", it.getBoolean(dimension))
dimensionData.addProperty("create_dragon_fight", dimension.createDragonFight()) }
dimensionData.addProperty("piglin_safe", dimension.piglinSafe()) ULTRA_WARM_FIELD?.let {
dimensionData.addProperty("bed_works", dimension.bedWorks()) dimensionData.addProperty("ultra_warm", it.getBoolean(dimension))
dimensionData.addProperty("respawn_anchor_works", dimension.respawnAnchorWorks()) }
dimensionData.addProperty("has_raids", dimension.hasRaids()) NATURAL_FIELD?.let {
dimensionData.addProperty("min_y", dimension.minY()) dimensionData.addProperty("natural", it.getBoolean(dimension))
dimensionData.addProperty("height", dimension.height()) }
dimensionData.addProperty("logical_height", dimension.logicalHeight()) COORDINATE_SCALE_FIELD?.let {
dimensionData.addProperty("infiniburn", dimension.infiniburn().toString()) dimensionData.addProperty("coordinate_scale", it.getDouble(dimension))
dimensionData.addProperty("effects_location", dimension.effectsLocation().toString()) }
dimensionData.addProperty("ambient_light", AMBIENT_LIGHT_FIELD.getFloat(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 DIMENSION_TYPE_CLASS = DimensionType::class.java
private val AMBIENT_LIGHT_FIELD = DimensionType::class.java.getDeclaredField("ambientLight")
init { private val FIXED_TIME_FIELD = getField(DIMENSION_TYPE_CLASS, "fixedTime")
FIXED_TIME_FIELD.isAccessible = true private val HAS_SKYLIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "hasSkylight")
AMBIENT_LIGHT_FIELD.isAccessible = true 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<DimensionType> {
val types: MutableList<DimensionType> = mutableListOf() private fun getDimensions(): MutableSet<Triple<ResourceLocation, Int?, DimensionType>> {
val types: MutableSet<Triple<ResourceLocation, Int?, DimensionType>> = mutableSetOf()
for (field in DimensionType::class.java.declaredFields) { for (field in DimensionType::class.java.declaredFields) {
if (field.type != DimensionType::class.java) { if (field.type != DimensionType::class.java) {
@ -60,7 +111,14 @@ object DimensionGenerator : Generator(
continue continue
} }
field.isAccessible = true 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 return types

View File

@ -4,13 +4,16 @@ import com.google.gson.JsonObject
import de.bixilon.pixlyzer.EntitySpawner import de.bixilon.pixlyzer.EntitySpawner
import de.bixilon.pixlyzer.PixLyzer import de.bixilon.pixlyzer.PixLyzer
import de.bixilon.pixlyzer.generator.Generator 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.core.Registry
import net.minecraft.network.syncher.EntityDataAccessor import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.Attributes import net.minecraft.world.entity.ai.attributes.Attribute
import net.minecraft.world.entity.player.Player import java.lang.reflect.Modifier
object EntityGenerator : Generator( object EntityGenerator : Generator(
"entities" "entities"
@ -44,53 +47,13 @@ object EntityGenerator : Generator(
// some entities have random values, we can and will ignore these ones // some entities have random values, we can and will ignore these ones
if (entity is LivingEntity && entity2 is LivingEntity) { if (entity is LivingEntity && entity2 is LivingEntity) {
entity.attributes.getInstance(Attributes.MAX_HEALTH)?.value?.let { for ((resourceLocation, attribute) in ATTRIBUTE_MAP) {
if (it != entity2.attributes.getInstance(Attributes.MAX_HEALTH)?.value) { entity.attributes.getInstance(attribute)?.value?.let {
return@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 { // entity.getEatingSound(ItemStack.EMPTY)?.let {
@ -124,14 +87,21 @@ object EntityGenerator : Generator(
} }
// Fix player // Fix player
data[ResourceLocation("player").toString()]?.asJsonObject?.let { data["minecraft:player"]?.asJsonObject?.let { playerJson ->
val playerClassName = Player::class.simpleName.toString() fun mergePlayerDate(name: String) {
val player = data[playerClassName].asJsonObject data[name]?.asJsonObject?.let {
for ((key, value) in player.entrySet()) { for ((key, value) in it.entrySet()) {
it.add(key, value) playerJson.add(key, value)
}
it.remove("class")
it.remove("parent")
data.remove(name)
}
} }
it.addProperty("class", playerClassName) mergePlayerDate(RemotePlayer::class.simpleName.toString())
data.remove(playerClassName) mergePlayerDate(AbstractClientPlayer::class.simpleName.toString())
mergePlayerDate("Player")
playerJson.addProperty("class", "Player")
} }
} }
@ -191,4 +161,33 @@ object EntityGenerator : Generator(
return json 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<String, Attribute> = getAttributes()
private fun getAttributes(): Map<String, Attribute> {
val ret: MutableMap<String, Attribute> = 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()
}
} }

View File

@ -3,6 +3,8 @@ package de.bixilon.pixlyzer.generator.generators
import com.google.gson.JsonArray import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import de.bixilon.pixlyzer.generator.Generator 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.core.Registry
import net.minecraft.sounds.SoundEvent import net.minecraft.sounds.SoundEvent
import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.EntityType
@ -27,7 +29,9 @@ object ItemGenerator : Generator(
itemData.addProperty("rarity", item.getRarity(ItemStack.EMPTY).ordinal) itemData.addProperty("rarity", item.getRarity(ItemStack.EMPTY).ordinal)
itemData.addProperty("max_stack_size", item.maxStackSize) itemData.addProperty("max_stack_size", item.maxStackSize)
itemData.addProperty("max_damage", item.maxDamage) 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) itemData.addProperty("is_complex", item.isComplex)
item.descriptionId?.let { item.descriptionId?.let {
itemData.addProperty("description_id", it) itemData.addProperty("description_id", it)
@ -67,7 +71,9 @@ object ItemGenerator : Generator(
itemData.addProperty("defense", item.defense) itemData.addProperty("defense", item.defense)
itemData.addProperty("toughness", ARMOR_ITEM_TOUGHNESS_FIELD.getFloat(item)) itemData.addProperty("toughness", ARMOR_ITEM_TOUGHNESS_FIELD.getFloat(item))
itemData.addProperty("armor_material", item.material.name.toLowerCase()) 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) { if (item is AxeItem) {
@ -89,11 +95,11 @@ object ItemGenerator : Generator(
if (item is DyeItem) { if (item is DyeItem) {
itemData.addProperty("dye_color", item.dyeColor.name.toLowerCase()) itemData.addProperty("dye_color", item.dyeColor.name.toLowerCase())
} }
if (item is MobBucketItem) { if (item::class.java == MOB_BUCKED_ITEM_CLASS) {
(MOB_BUCKED_ITEM_TYPE_FIELD.get(item) as EntityType<*>?)?.let { (MOB_BUCKED_ITEM_TYPE_FIELD?.get(item) as EntityType<*>?)?.let {
itemData.addProperty("bucket_fish_type", Registry.ENTITY_TYPE.getId(it)) 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)) itemData.addProperty("bucket_empty_sound", Registry.SOUND_EVENT.getId(it))
} }
} }
@ -159,34 +165,35 @@ object ItemGenerator : Generator(
return data 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_BLOCKS_FIELD = DiggerItem::class.java.getDeclaredField("blocks")
private val DIGGER_ITEM_SPEED_FIELD = DiggerItem::class.java.getDeclaredField("speed") 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_EQUIPMENT_SLOT_FIELD = ArmorItem::class.java.getDeclaredField("slot")
private val ARMOR_ITEM_TOUGHNESS_FIELD = ArmorItem::class.java.getDeclaredField("toughness") private val ARMOR_ITEM_TOUGHNESS_FIELD = ArmorItem::class.java.getDeclaredField("toughness")
private val AXE_ITEM_STRIPABLES_FIELD = AxeItem::class.java.getDeclaredField("STRIPABLES") private val AXE_ITEM_STRIPABLES_FIELD = AxeItem::class.java.getDeclaredField("STRIPABLES")
private val BUCKED_ITEM_CONTENT_FIELD = BucketItem::class.java.getDeclaredField("content") 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_TYPE_FIELD = getField(MOB_BUCKED_ITEM_CLASS, "type")
private val MOB_BUCKED_ITEM_EMPTY_SOUND_FIELD = MobBucketItem::class.java.getDeclaredField("emptySound") 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 HOE_ITEM_TILLABLES_FIELD = HoeItem::class.java.getDeclaredField("TILLABLES")
private val SHOVEL_ITEM_FLATTENABLES_FIELD = ShovelItem::class.java.getDeclaredField("FLATTENABLES") 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 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 { init {
DIGGER_ITEM_BLOCKS_FIELD.isAccessible = true DIGGER_ITEM_BLOCKS_FIELD.isAccessible = true
DIGGER_ITEM_SPEED_FIELD.isAccessible = true DIGGER_ITEM_SPEED_FIELD.isAccessible = true
DIGGER_ITEM_ATTACK_DAMAGE.isAccessible = true
ARMOR_ITEM_EQUIPMENT_SLOT_FIELD.isAccessible = true ARMOR_ITEM_EQUIPMENT_SLOT_FIELD.isAccessible = true
ARMOR_ITEM_TOUGHNESS_FIELD.isAccessible = true ARMOR_ITEM_TOUGHNESS_FIELD.isAccessible = true
AXE_ITEM_STRIPABLES_FIELD.isAccessible = true AXE_ITEM_STRIPABLES_FIELD.isAccessible = true
BUCKED_ITEM_CONTENT_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 HOE_ITEM_TILLABLES_FIELD.isAccessible = true
SHOVEL_ITEM_FLATTENABLES_FIELD.isAccessible = true SHOVEL_ITEM_FLATTENABLES_FIELD.isAccessible = true
SPAWN_EGG_ITEM_ENTITY_TYPE_FIELD.isAccessible = true SPAWN_EGG_ITEM_ENTITY_TYPE_FIELD.isAccessible = true
ARMOR_ITEM_KNOCKBACK_RESISTANCE.isAccessible = true
} }

View File

@ -20,7 +20,7 @@ object MaterialGenerator : Generator(
materialData.addProperty("liquid", material.isLiquid) materialData.addProperty("liquid", material.isLiquid)
materialData.addProperty("solid_blocking", material.isSolidBlocking) materialData.addProperty("solid_blocking", material.isSolidBlocking)
materialData.addProperty("replaceable", material.isReplaceable) materialData.addProperty("replaceable", material.isReplaceable)
materialData.addProperty("sold", material.isSolid) materialData.addProperty("solid", material.isSolid)
data.add(resourceLocation.toString(), materialData) data.add(resourceLocation.toString(), materialData)

View File

@ -34,7 +34,7 @@ object MobEffectGenerator : Generator(
modifierData.addProperty("amount", modifier.amount) modifierData.addProperty("amount", modifier.amount)
modifierData.addProperty("operation", modifier.operation.name.toLowerCase()) 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) { if (modifiers.size() > 0) {

View File

@ -4,7 +4,22 @@ import org.apache.commons.lang3.reflect.FieldUtils
import java.lang.reflect.Field import java.lang.reflect.Field
object ReflectionUtil { 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) { for (name in names) {
try { try {
val field = clazz.getDeclaredField(name) val field = clazz.getDeclaredField(name)