diff --git a/pom.xml b/pom.xml index a9f495c..1d52d74 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ 1.0-SNAPSHOT jar - pixlyzer + PixLyzer UTF-8 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 ebbddd3..e9d2ef2 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BlockGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/BlockGenerator.kt @@ -208,7 +208,9 @@ object BlockGenerator : Generator( val propertyData = JsonObject() for ((property, stateProperty) in state.values) { - addJsonWithType(stateProperty.toString().toLowerCase(), propertyData, property.name.toLowerCase()) + val propertyValue = (PROPERTY_NAME_METHOD.invoke(property) as String).toLowerCase() + val propertyName = stateProperty.toString().toLowerCase() + addJsonWithType(propertyName, propertyData, propertyValue) } if (propertyData.size() > 0) { @@ -316,6 +318,10 @@ object BlockGenerator : Generator( } } + val PROPERTY_METHOD = getClass("net.minecraft.world.level.block.state.properties.Property")!! + + val PROPERTY_NAME_METHOD = PROPERTY_METHOD.getDeclaredMethod("getName") + private fun getOrAddVoxelShape(voxelShape: VoxelShape): Int { if (VOXEL_SHAPES.contains(voxelShape)) { return VOXEL_SHAPES.indexOf(voxelShape) 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 3c3ed2e..71cbd67 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,7 @@ 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.resources.ResourceLocation import net.minecraft.world.level.dimension.DimensionType @@ -12,7 +13,6 @@ object DimensionGenerator : Generator( "dimensions" ) { override fun generate() { - // val registry = Registry.REGISTRY.get(Registry.DIMENSION_TYPE_REGISTRY.location()) as Registry for ((resourceLocation, id, dimension) in getDimensions()) { val dimensionData = JsonObject() @@ -100,6 +100,11 @@ object DimensionGenerator : Generator( private val AMBIENT_LIGHT_FIELD = getField(DIMENSION_TYPE_CLASS, "ambientLight") + private val RESOURCE_KEY_CLASS = getClass("net.minecraft.resources.ResourceKey") + + private val RESOURCE_KEY_LOCATION_METHOD = RESOURCE_KEY_CLASS?.getDeclaredMethod("location") + + private fun getDimensions(): MutableSet> { val types: MutableSet> = mutableSetOf() @@ -121,6 +126,14 @@ object DimensionGenerator : Generator( types.add(Triple(resourceLocation, null, field.get(null) as DimensionType)) } + if (types.isEmpty()) { + val field = getField(DimensionType::class.java, "BUILTIN") ?: return types + + for ((resourceLocation, dimension) in field.get(null) as Map) { + types.add(Triple(RESOURCE_KEY_LOCATION_METHOD!!.invoke(resourceLocation) as ResourceLocation, null, dimension)) + } + } + 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 105066c..4a00a05 100644 --- a/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/EntityGenerator.kt +++ b/src/main/kotlin/de/bixilon/pixlyzer/generator/generators/EntityGenerator.kt @@ -14,6 +14,7 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.ai.attributes.AttributeInstance import java.lang.reflect.Modifier object EntityGenerator : Generator( @@ -49,12 +50,17 @@ object EntityGenerator : Generator( if (entity is LivingEntity && entity2 is LivingEntity) { 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) + val attributes = LIVING_ENTITY_GET_ATTRIBUTES_METHOD.invoke(entity) ?: continue + val instance = BASE_ATTRIBUTE_MAP_GET_INSTANCE_METHOD.invoke(attributes, attribute) as AttributeInstance? ?: continue + val value = ATTRIBUTE_INSTANCE_BASE_VALUE_METHOD.invoke(instance) as Double + + val attributes2 = LIVING_ENTITY_GET_ATTRIBUTES_METHOD.invoke(entity2) ?: continue + val instance2 = BASE_ATTRIBUTE_MAP_GET_INSTANCE_METHOD.invoke(attributes2, attribute) as AttributeInstance? ?: continue + val value2 = ATTRIBUTE_INSTANCE_BASE_VALUE_METHOD.invoke(instance2) as Double + if (value != value2) { + continue } + entityData.addProperty(resourceLocation, value) } // entity.getEatingSound(ItemStack.EMPTY)?.let { @@ -167,9 +173,19 @@ object EntityGenerator : Generator( private val ATTRIBUTE_MAP: Map = getAttributes() + private val BASE_ATTRIBUTE_MAP_CLASS = getClass("net.minecraft.world.entity.ai.attributes.AttributeMap", "net.minecraft.world.entity.ai.attributes.BaseAttributeMap")!! + + private val BASE_ATTRIBUTE_MAP_GET_INSTANCE_METHOD = BASE_ATTRIBUTE_MAP_CLASS.getDeclaredMethod("getInstance", Attribute::class.java) + + private val LIVING_ENTITY_GET_ATTRIBUTES_METHOD = LivingEntity::class.java.getDeclaredMethod("getAttributes") + + private val ATTRIBUTE_INSTANCE_CLASS = getClass("net.minecraft.world.entity.ai.attributes.AttributeInstance")!! + + private val ATTRIBUTE_INSTANCE_BASE_VALUE_METHOD = ATTRIBUTE_INSTANCE_CLASS.getMethod("getBaseValue") + private fun getAttributes(): Map { - val attributeRegistryField = getField(Registry::class.java, "ATTRIBUTE") + val attributeRegistryField = getField(Registry::class.java, "ATTRIBUTE", "ATTRIBUTES") val attributeNameField = try { Attribute::class.java.getMethod("getName") } catch (exception: NoSuchMethodException) { diff --git a/wrapper/PixLyzer.py b/wrapper/PixLyzer.py index 12e3809..8584152 100755 --- a/wrapper/PixLyzer.py +++ b/wrapper/PixLyzer.py @@ -2,7 +2,7 @@ import os import subprocess import urllib.request import zipfile -from enum import Enum +from datetime import datetime from pathlib import Path import ujson @@ -12,12 +12,11 @@ SKIP_VERSIONS = ["19w35a", "19w34a"] HASH_FOLDER = os.path.abspath("data/hash/") + "/" ASSETS_HASH_INDEX_FILE = os.path.abspath("data/index") OUT_FOLDER = os.path.abspath("data/version/") + "/" -LOGS_FOLDER = os.path.abspath("data/logs/") + "/" DATA_FOLDER = os.path.abspath("data/data/") + "/" MC_REMAPPER_EXECUTABLE = "/home/moritz/Games/Minecraft/MC-Remapper/build/install/MC-Remapper/bin/MC-Remapper" JAVA_PATH = "/usr/lib/jvm/java-8-openjdk-amd64/bin/java" -ADDITIONAL_CLASSPATH = "/home/moritz/kotlin-stdlib-1.4.30.jar" +ADDITIONAL_CLASSPATH = "/home/moritz/kotlin-stdlib-1.4.30.jar:/home/moritz/Games/Minecraft/PixLyzer/wrapper/data/objenesis-tck-3.1.jar" VERSION_MANIFEST_URL = "https://launchermeta.mojang.com/mc/game/version_manifest.json" @@ -28,17 +27,6 @@ print("Starting PixLyzer generator") print("Downloading version manifest") VERSION_MANIFEST = ujson.loads(urllib.request.urlopen(VERSION_MANIFEST_URL).read().decode("utf-8")) -rawExecutionMode = input("Enter execution mode (generate, cherry-pick, generate-start-at) [generate]: ") - - -class ExecutionModes(Enum): - GENERATE = 0 - GENERATE_START_WITH = 1 - CHERRY_PICK = 2 - - -executionMode = ExecutionModes.GENERATE - def searchVersion(versionId): global VERSION_MANIFEST @@ -48,45 +36,11 @@ def searchVersion(versionId): raise Exception("Unknown version: %s" % versionId) -class CherryPickOperators(Enum): - EQUALS = 0 - LESS = 1 - GREATER = 2 - - -cherryPickCommit = "" -versionToCherryPick = "" -cherryPickOperator = CherryPickOperators.EQUALS - -startWithVersion = "" - - -def detectExecutionMode(): - global executionMode, cherryPickCommit, versionToCherryPick, cherryPickOperator, startWithVersion - if rawExecutionMode == "generate" or rawExecutionMode == "": - executionMode = ExecutionModes.GENERATE - elif rawExecutionMode == "generate-start-at": - executionMode = ExecutionModes.GENERATE_START_WITH - startWithVersion = input("Enter version to start with: ") - searchVersion(startWithVersion) - elif rawExecutionMode == "cherry-pick": - executionMode = ExecutionModes.CHERRY_PICK - cherryPickCommit = input("Enter commit to cherry-pick: ") - versionToCherryPick = input("Enter versions to cherry-pick (<1.15.2, ...): ") - if versionToCherryPick.startswith("<"): - cherryPickOperator = CherryPickOperators.LESS - versionToCherryPick = versionToCherryPick = versionToCherryPick[1:] - elif versionToCherryPick.startswith(">"): - cherryPickOperator = CherryPickOperators.GREATER - versionToCherryPick = versionToCherryPick = versionToCherryPick[1:] - searchVersion(versionToCherryPick) - - else: - print("Unknown execution mode: %s" % rawExecutionMode) - exit(2) - - -detectExecutionMode() +startWithVersion = input("Enter version to start with: ") +if startWithVersion == "": + startWithVersion = VERSION_MANIFEST["versions"][0]["id"] + print("No version provided, starting with %s" % startWithVersion) +searchVersion(startWithVersion) def runAndWait(command): @@ -118,18 +72,20 @@ def checkDeobfuscatedJar(jarBasePath, jarType, version, versionJson): mojangJarPath = jarBasePath + jarType + "_mojang.jar" if not os.path.isfile(mojangJarPath): print("Downloading mojang %s jar for %s" % (jarType, version["id"])) - urllib.request.urlretrieve(versionJson["downloads"][jarType]["url"], mojangJarPath) + urllib.request.urlretrieve(versionJson["downloads"][jarType]["url"], mojangJarPath + ".tmp") + os.rename(mojangJarPath + ".tmp", mojangJarPath) mojangMappingsPath = jarBasePath + jarType + "_mappings.txt" if not os.path.isfile(mojangMappingsPath): print("Downloading mojang %s mappings for %s" % (jarType, version["id"])) - urllib.request.urlretrieve(versionJson["downloads"][jarType + "_mappings"]["url"], mojangMappingsPath) + urllib.request.urlretrieve(versionJson["downloads"][jarType + "_mappings"]["url"], mojangMappingsPath + ".tmp") + os.rename(mojangMappingsPath + ".tmp", mojangMappingsPath) # deobfuscate print("Deobfuscating %s jar for %s" % (jarType, version["id"])) global MC_REMAPPER_EXECUTABLE - deobfuscateProcess = subprocess.Popen('%s \"%s\" \"%s\" --output-name \"%s\"' % (MC_REMAPPER_EXECUTABLE, mojangJarPath, mojangMappingsPath, jarPath), cwd=r'.', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + deobfuscateProcess = subprocess.Popen('%s \"%s\" \"%s\" --output-name \"%s\"' % (MC_REMAPPER_EXECUTABLE, mojangJarPath, mojangMappingsPath, jarPath + ".tmp"), cwd=r'.', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) exitCode = deobfuscateProcess.wait() if exitCode != 0: print("Could not deobfuscate %s jar for %s" % (jarType, version["id"])) @@ -140,8 +96,8 @@ def checkDeobfuscatedJar(jarBasePath, jarType, version, versionJson): else: # delete mojang jars print("Deleting META-INF folder") - zipIn = zipfile.ZipFile(jarPath, 'r') - zipOut = zipfile.ZipFile(jarPath + ".tmp", 'w') + zipIn = zipfile.ZipFile(jarPath + ".tmp", 'r') + zipOut = zipfile.ZipFile(jarPath + ".tmp2", 'w') for item in zipIn.infolist(): buffer = zipIn.read(item.filename) if not item.filename.startswith("META-INF"): @@ -150,8 +106,8 @@ def checkDeobfuscatedJar(jarBasePath, jarType, version, versionJson): zipOut.close() zipIn.close() - os.remove(jarPath) - os.rename(jarPath + ".tmp", jarPath) + os.remove(jarPath + ".tmp") + os.rename(jarPath + ".tmp2", jarPath) print("Deleting %s jar and mappings for %s" % (jarType, version["id"])) os.remove(mojangJarPath) @@ -172,17 +128,20 @@ def replaceInFile(file, search, replace): fout.write(line.replace(search, replace)) -stopCherryPicking = cherryPickOperator == CherryPickOperators.LESS +def compilePixLyzer(): + print("Compiling pixlyzer...") + if runAndWait('mvn clean verify') != 0: + raise Exception("Can not compile for %s" % version["id"]) + print("PixLyzer is now compiled") -startWorking = executionMode == ExecutionModes.GENERATE + +compilePixLyzer() + +startWorking = False for version in VERSION_MANIFEST["versions"]: - if executionMode == ExecutionModes.CHERRY_PICK: - if version["id"] == versionToCherryPick: - startWorking = True - elif executionMode == ExecutionModes.GENERATE_START_WITH: - if version["id"] == startWithVersion: - startWorking = True + if version["id"] == startWithVersion: + startWorking = True if not startWorking: continue @@ -191,15 +150,6 @@ for version in VERSION_MANIFEST["versions"]: print("Skipping %s" % version["id"]) continue - if cherryPickOperator == CherryPickOperators.GREATER: - if version["id"] == versionToCherryPick: - stopCherryPicking = True - print("Stop cherry picking.") - elif cherryPickOperator == CherryPickOperators.LESS: - if version["id"] == versionToCherryPick: - stopCherryPicking = False - print("Start cherry picking.") - if version["id"] == DOWNLOAD_UNTIL_VERSION: print("Breaking at %s" % version["id"]) break @@ -208,29 +158,13 @@ for version in VERSION_MANIFEST["versions"]: checkDeobfuscatedJars(version, versionJson) - # checkout correct branch, add jars to maven, build and run in maven - if runAndWait('git checkout version-%s' % version["id"].replace(" ", "-")) != 0: - print("WARN: No branch not found (%s). Skipping this version" % version["id"].replace(" ", "-")) - continue - - if executionMode == ExecutionModes.CHERRY_PICK and not stopCherryPicking: - print("Cherry-picking commit %s for %s" % (cherryPickCommit, version["id"])) - if runAndWait("git cherry-pick --strategy=recursive -X theirs %s" % cherryPickCommit) != 0: - print("Failed to cherry-pick commit %s for %s" % (cherryPickCommit, version["id"])) - break - - # build - if runAndWait('mvn clean verify') != 0: - print("Can not compile for %s" % version["id"]) - break - + versionStartTime = datetime.now() + print("Generating data for %s" % version["id"]) # execute if runAndWait("%s -classpath \"%s:%s:%s:%s\" de.bixilon.pixlyzer.PixLyzer %s %s %s" % (JAVA_PATH, ADDITIONAL_CLASSPATH, DATA_FOLDER + version["id"] + "/" + version["id"] + "_client.jar", DATA_FOLDER + version["id"] + "/" + version["id"] + "_server.jar", "target/classes", OUT_FOLDER + version["id"], HASH_FOLDER, ASSETS_HASH_INDEX_FILE)) != 0: print("PixLyzer did not run successfully for %s" % version["id"]) break - print("Done generating %s" % version["id"]) - -runAndWait('git checkout master') + print("Done generating %s in %s" % (version["id"], (datetime.now() - versionStartTime))) print("Done with downloading and generating all data")