From ccefc510e64062bd130dfc299ce3878c0d96ef3c Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Thu, 21 May 2020 19:21:46 -0700 Subject: [PATCH] Improve identification of BlockState The previous heuristic broke in 20w21a. --- burger/toppings/entitymetadata.py | 10 +++------- burger/toppings/identify.py | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/burger/toppings/entitymetadata.py b/burger/toppings/entitymetadata.py index 47eebdb2..ad50a6c0 100644 --- a/burger/toppings/entitymetadata.py +++ b/burger/toppings/entitymetadata.py @@ -352,6 +352,8 @@ def identify_serializer(classloader, cls, classes, verbose): name = "Chat" elif inner_type == classes["position"]: name = "BlockPos" + elif inner_type == classes["blockstate"]: + name = "BlockState" else: # Try some more tests, based on the class itself: try: @@ -360,18 +362,12 @@ def identify_serializer(classloader, cls, classes, verbose): name = "Rotations" elif content_cf.constants.find_one(type_=String, f=lambda c: c == "down"): name = "Facing" - elif content_cf.constants.find_one(type_=String, f=lambda c: c == "minecraft:air"): - # This method only works in 1.14, where BlockState isn't an interface - name = "BlockState" elif content_cf.constants.find_one(type_=String, f=lambda c: c == "FALL_FLYING"): assert content_cf.access_flags.acc_enum name = "Pose" elif content_cf.access_flags.acc_interface: # Make some _very_ bad assumptions here; both of these are hard to identify: - if name_prefix == "Opt": - name = "BlockState" - else: - name = "Particle" + name = "Particle" except: if verbose: print("Failed to determine name of metadata content type %s" % inner_type) diff --git a/burger/toppings/identify.py b/burger/toppings/identify.py index 7ce51158..0bc79f50 100644 --- a/burger/toppings/identify.py +++ b/burger/toppings/identify.py @@ -196,6 +196,21 @@ def is_protected_final(m): if cf: return 'position', cf.this.name.value + if value == 'Getting block state': + # This message is found in Chunk, in the method getBlockState. + # We could also theoretically identify BlockPos from this method, + # but currently identify only allows marking one class at a time. + class_file = classloader[path] + + for method in class_file.methods: + for ins in method.code.disassemble(): + if ins.mnemonic in ("ldc", "ldc_w"): + if ins.operands[0] == 'Getting block state': + return 'blockstate', method.returns.name + else: + if verbose: + print("Found chunk, but didn't find the method that returns blockstate") + class IdentifyTopping(Topping): """Finds important superclasses needed by other toppings.""" @@ -207,6 +222,7 @@ class IdentifyTopping(Topping): "identify.block.list", "identify.block.register", "identify.blockstatecontainer", + "identify.blockstate", "identify.chatcomponent", "identify.entity.list", "identify.entity.trackerentry",