From 50377a1b898f1aeaa3469f18afa0583ac12673a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Mon, 11 Jul 2022 21:49:16 -0700 Subject: [PATCH] Fabric/Quilt fertilization support --- buildSrc/src/main/kotlin/Versions.kt | 10 ++- .../config/VanillaBiomeProperties.java | 4 +- platforms/fabric/build.gradle.kts | 6 ++ .../terra/fabric/FabricASMEntryPoint.java | 19 +++++ .../terra/fabric/util/FabricLoaderUtil.java | 18 +++++ .../fabric/src/main/resources/fabric.mod.json | 3 + .../mod/config/VanillaBiomeProperties.java | 38 ++++++--- .../terra/mod/mixin/FertilizableMixin.java | 10 +++ .../com/dfsek/terra/mod/util/BiomeUtil.java | 27 +++++-- .../terra/mod/util/FertilizableUtil.java | 34 ++++++++ .../dfsek/terra/mod/util/MinecraftUtil.java | 6 -- .../com/dfsek/terra/mod/util/TagUtil.java | 2 +- platforms/mixin-lifecycle/build.gradle.kts | 5 ++ .../terra/lifecycle/asm/FertilizableASM.java | 81 +++++++++++++++++++ .../dfsek/terra/lifecycle/util/ASMUtil.java | 56 +++++++++++++ .../terra/lifecycle/util/LoaderUtil.java | 9 +++ platforms/quilt/build.gradle.kts | 8 ++ .../dfsek/terra/quilt/QuiltASMEntryPoint.java | 17 ++++ .../terra/quilt/util/QuiltLoaderUtil.java | 18 +++++ .../quilt/src/main/resources/quilt.mod.json | 3 + 20 files changed, 342 insertions(+), 32 deletions(-) create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricASMEntryPoint.java create mode 100644 platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricLoaderUtil.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/FertilizableMixin.java create mode 100644 platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/FertilizableUtil.java create mode 100644 platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/asm/FertilizableASM.java create mode 100644 platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/ASMUtil.java create mode 100644 platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LoaderUtil.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltASMEntryPoint.java create mode 100644 platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/QuiltLoaderUtil.java diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 6d0a1e2e0..d2d0af695 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -29,16 +29,18 @@ object Versions { object Mod { const val mixin = "0.11.2+mixin.0.8.5" - + const val minecraft = "1.19" const val yarn = "$minecraft+build.1" const val fabricLoader = "0.14.2" - + + const val minecraftGudAsm = "v0.3.1" + const val architecuryLoom = "0.12.0.290" const val architecturyPlugin = "3.4-SNAPSHOT" - + const val loomQuiltflower = "1.7.1" - + const val lazyDfu = "0.1.2" } diff --git a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/config/VanillaBiomeProperties.java b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/config/VanillaBiomeProperties.java index bc3e10930..ebe54c996 100644 --- a/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/config/VanillaBiomeProperties.java +++ b/platforms/bukkit/nms/v1_19_R1/src/main/java/com/dfsek/terra/bukkit/nms/v1_19_R1/config/VanillaBiomeProperties.java @@ -3,7 +3,6 @@ package com.dfsek.terra.bukkit.nms.v1_19_R1.config; import com.dfsek.tectonic.api.config.template.ConfigTemplate; import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; -import java.util.List; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.Music; import net.minecraft.sounds.SoundEvent; @@ -15,6 +14,9 @@ import net.minecraft.world.level.biome.Biome.Precipitation; import net.minecraft.world.level.biome.Biome.TemperatureModifier; import net.minecraft.world.level.biome.BiomeSpecialEffects.GrassColorModifier; import net.minecraft.world.level.biome.MobSpawnSettings; + +import java.util.List; + import com.dfsek.terra.api.properties.Properties; diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 7ed3f2e75..dbe104cdd 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -12,6 +12,12 @@ architectury { dependencies { shadedApi(project(":common:implementation:base")) + annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") + annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") + + modImplementation("com.github.the-glitch-network:minecraft-gudasm:${Versions.Mod.minecraftGudAsm}") + include("com.github.the-glitch-network:minecraft-gudasm:${Versions.Mod.minecraftGudAsm}") + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } "developmentFabric"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionFabric")) { isTransitive = false } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricASMEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricASMEntryPoint.java new file mode 100644 index 000000000..afd877f0b --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricASMEntryPoint.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.fabric; + +import com.dfsek.terra.fabric.util.FabricLoaderUtil; + +import net.gudenau.minecraft.asm.api.v1.AsmInitializer; +import net.gudenau.minecraft.asm.api.v1.AsmRegistry; + +import com.dfsek.terra.lifecycle.asm.FertilizableASM; +import com.dfsek.terra.lifecycle.util.LoaderUtil; +import com.dfsek.terra.quilt.util.QuiltLoaderUtil; + + +public class FabricASMEntryPoint implements AsmInitializer { + @Override + public void onInitializeAsm() { + LoaderUtil.INSTANCE = new FabricLoaderUtil(); + AsmRegistry.getInstance().registerTransformer(new FertilizableASM()); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricLoaderUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricLoaderUtil.java new file mode 100644 index 000000000..a9813edbf --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricLoaderUtil.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.fabric.util; + +import com.dfsek.terra.lifecycle.util.LoaderUtil; + +import net.fabricmc.loader.api.FabricLoader; + + +public class FabricLoaderUtil extends LoaderUtil { + @Override + public String mapClassName(String namespace, String className) { + return FabricLoader.getInstance().getMappingResolver().mapClassName(namespace, className); + } + + @Override + public String mapMethodName(String namespace, String owner, String name, String descriptor) { + return FabricLoader.getInstance().getMappingResolver().mapMethodName(namespace, owner, name, descriptor); + } +} diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index e71bcfeac..4647d6933 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -18,6 +18,9 @@ "entrypoints": { "main": [ "com.dfsek.terra.fabric.FabricEntryPoint" + ], + "gud_asm": [ + "com.dfsek.terra.fabric.FabricASMEntryPoint" ] }, "mixins": [ diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java index 34a75d50d..f996b31b5 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/VanillaBiomeProperties.java @@ -15,44 +15,52 @@ import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; import net.minecraft.world.biome.BiomeParticleConfig; import net.minecraft.world.biome.SpawnSettings; +import java.util.Collections; import java.util.List; +import java.util.Map; import com.dfsek.terra.api.properties.Properties; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; public class VanillaBiomeProperties implements ConfigTemplate, Properties { + @Value("minecraft.fertilizables") + @Default + private Map> fertilizables = Collections.emptyMap(); + @Value("minecraft.tags") @Default - private List tags = null; + private List tags = Collections.emptyList(); @Value("minecraft.colors.grass") @Default - private Integer grassColor = null; + private Integer grassColor = 0; @Value("minecraft.colors.fog") @Default - private Integer fogColor = null; + private Integer fogColor = 0; @Value("minecraft.colors.water") @Default - private Integer waterColor = null; + private Integer waterColor = 0; @Value("minecraft.colors.water-fog") @Default - private Integer waterFogColor = null; + private Integer waterFogColor = 0; @Value("minecraft.colors.foliage") @Default - private Integer foliageColor = null; + private Integer foliageColor = 0; @Value("minecraft.colors.sky") @Default - private Integer skyColor = null; + private Integer skyColor = 0; @Value("minecraft.colors.modifier") @Default - private GrassColorModifier grassColorModifier = null; + private GrassColorModifier grassColorModifier = GrassColorModifier.NONE; @Value("minecraft.particles") @Default @@ -60,19 +68,19 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Value("minecraft.climate.precipitation") @Default - private Precipitation precipitation = null; + private Precipitation precipitation = Precipitation.NONE; @Value("minecraft.climate.temperature") @Default - private Float temperature = null; + private Float temperature = 0.0f; @Value("minecraft.climate.temperature-modifier") @Default - private TemperatureModifier temperatureModifier = null; + private TemperatureModifier temperatureModifier = TemperatureModifier.NONE; @Value("minecraft.climate.downfall") @Default - private Float downfall = null; + private Float downfall = 0.0f; @Value("minecraft.sound.loop-sound.sound") @Default @@ -92,12 +100,16 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties { @Value("minecraft.spawning") @Default - private SpawnSettings spawnSettings = null; + private SpawnSettings spawnSettings = SpawnSettings.INSTANCE; @Value("minecraft.villager-type") @Default private VillagerType villagerType = null; + public Map> getFertilizables() { + return fertilizables; + } + public List getTags() { return tags; } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/FertilizableMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/FertilizableMixin.java new file mode 100644 index 000000000..141e5a79b --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/FertilizableMixin.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.mod.mixin; + +import net.minecraft.block.Fertilizable; +import org.spongepowered.asm.mixin.Mixin; + + +@Mixin(Fertilizable.class) +public class FertilizableMixin { + +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/BiomeUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/BiomeUtil.java index 2b592e812..9da187845 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/BiomeUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/BiomeUtil.java @@ -4,16 +4,21 @@ import net.minecraft.tag.TagKey; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.village.VillagerType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.mod.CommonPlatform; import com.dfsek.terra.mod.config.ProtoPlatformBiome; @@ -24,6 +29,12 @@ import com.dfsek.terra.mod.mixin.access.VillagerTypeAccessor; public class BiomeUtil { private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); + public static final Map, Map>> + TERRA_BIOME_FERTILIZABLE_MAP = new HashMap<>(); + + public static final Map, List> + TERRA_BIOME_TAG_MAP = new HashMap<>(); + public static void registerBiomes() { logger.info("Registering biomes..."); CommonPlatform.get().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. @@ -55,20 +66,22 @@ public class BiomeUtil { protected static void registerBiome(Biome biome, ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey id) { VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); - + net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(vanillaBiomeProperties); - + Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); - + biome.setPlatformBiome(new ProtoPlatformBiome(identifier, registerBiome(identifier, minecraftBiome))); - + Map villagerMap = VillagerTypeAccessor.getBiomeTypeToIdMap(); - + villagerMap.put(RegistryKey.of(Registry.BIOME_KEY, identifier), Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(), VillagerType.PLAINS)); - + + TERRA_BIOME_FERTILIZABLE_MAP.put(RegistryEntry.of(minecraftBiome), vanillaBiomeProperties.getFertilizables()); + for(Identifier tag : vanillaBiomeProperties.getTags()) { - MinecraftUtil.TERRA_BIOME_TAG_MAP.getOrDefault(TagKey.of(Registry.BIOME_KEY, tag), new ArrayList<>()).add(identifier); + TERRA_BIOME_TAG_MAP.getOrDefault(TagKey.of(Registry.BIOME_KEY, tag), new ArrayList<>()).add(identifier); } } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/FertilizableUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/FertilizableUtil.java new file mode 100644 index 000000000..67a17e96b --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/FertilizableUtil.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.mod.util; + +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3Int; + +import com.dfsek.terra.api.world.WritableWorld; + +import net.minecraft.block.BlockState; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.registry.Registry; + +import java.util.Map; + +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class FertilizableUtil { + public static boolean grow(ServerWorld world, Random random, BlockPos pos, BlockState state) { + Map> fertilizables = BiomeUtil.TERRA_BIOME_FERTILIZABLE_MAP.get(world.getBiome(pos)); + if (fertilizables != null) { + ProbabilityCollection probabilityCollection = fertilizables.get(Registry.BLOCK.getId(state.getBlock())); + if (probabilityCollection != null) { + ConfiguredStructure structure = probabilityCollection.get((java.util.Random) random); + structure.getStructure().get((java.util.Random) random).generate(Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, (java.util.Random) random, Rotation.NONE); + return true; + } + } + return false; + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java index 7bc86be92..941f85b2c 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/MinecraftUtil.java @@ -3,7 +3,6 @@ package com.dfsek.terra.mod.util; import net.minecraft.block.entity.LootableContainerBlockEntity; import net.minecraft.block.entity.MobSpawnerBlockEntity; import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.tag.TagKey; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; @@ -17,10 +16,7 @@ import net.minecraft.world.biome.GenerationSettings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.HashMap; -import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -35,8 +31,6 @@ import com.dfsek.terra.mod.config.VanillaBiomeProperties; public final class MinecraftUtil { public static final Logger logger = LoggerFactory.getLogger(MinecraftUtil.class); - public static final Map, List> - TERRA_BIOME_TAG_MAP = new HashMap<>(); private MinecraftUtil() { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java index e8adbf829..e9c6151c5 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/TagUtil.java @@ -56,7 +56,7 @@ public final class TagUtil { logger.info("who let this data drive?"); Map, List>> collect = tagsToMutableMap(registry); - MinecraftUtil.TERRA_BIOME_TAG_MAP.forEach((tag, biomeList) -> { + BiomeUtil.TERRA_BIOME_TAG_MAP.forEach((tag, biomeList) -> { collect.getOrDefault(tag, new ArrayList<>()) .addAll(biomeList.stream() .map(registry::getOrEmpty) diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index e8b852dc5..f3cbd5486 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -11,6 +11,11 @@ dependencies { annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") + modImplementation("com.github.the-glitch-network:minecraft-gudasm:${Versions.Mod.minecraftGudAsm}") { + exclude("net.fabricmc") + exclude("net.fabricmc.fabric-api") + } + implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/asm/FertilizableASM.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/asm/FertilizableASM.java new file mode 100644 index 000000000..1f32e2d99 --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/asm/FertilizableASM.java @@ -0,0 +1,81 @@ +package com.dfsek.terra.lifecycle.asm; + +import com.dfsek.terra.mod.util.FertilizableUtil; + +import net.gudenau.minecraft.asm.api.v1.Identifier; +import net.gudenau.minecraft.asm.api.v1.Transformer; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import java.io.IOException; + +import com.dfsek.terra.lifecycle.util.ASMUtil; +import com.dfsek.terra.lifecycle.util.LoaderUtil; + +import org.objectweb.asm.tree.VarInsnNode; + +import static org.objectweb.asm.Opcodes.ACC_STATIC; + + +public class FertilizableASM implements Transformer { + + private static String fertilizableClassName = LoaderUtil.INSTANCE.mapClassName("intermediary", "net.minecraft.class_2256"); + + private static String fertilizableGrowMethodSignatureBase = String.format("(L%1$s;L%2$s;L%3$s;L%4$s;)", + LoaderUtil.INSTANCE.mapClassName("intermediary", "net.minecraft.class_3218").replace(".", "/"), + LoaderUtil.INSTANCE.mapClassName("intermediary", "net.minecraft.class_5819").replace(".", "/"), + LoaderUtil.INSTANCE.mapClassName("intermediary", "net.minecraft.class_2338").replace(".", "/"), + LoaderUtil.INSTANCE.mapClassName("intermediary", "net.minecraft.class_2680").replace(".", "/")); + + private static String fertilizableGrowMethodSignature = fertilizableGrowMethodSignatureBase + "V"; + + private static String fertilizableGrowMethodName = LoaderUtil.INSTANCE.mapMethodName("intermediary", "net.minecraft.class_2256", "method_9652", "(Lnet/minecraft/class_3218;Lnet/minecraft/class_5819;Lnet/minecraft/class_2338;Lnet/minecraft/class_2680;)V"); + + @Override + public Identifier getName() { + return new Identifier("terra", "asm_test"); + } + + @Override + public boolean handlesClass(String name, String transformedName) { + return true; + } + + @Override + public boolean transform(ClassNode classNode, Flags flags) { + try { + if (ASMUtil.inheritsFrom(classNode, fertilizableClassName.replace(".", "/"))) { + for (MethodNode method : classNode.methods) { + if (method.name.equals(fertilizableGrowMethodName)) { + if ((method.access & ACC_STATIC) == 0) { + if(method.desc.equals(fertilizableGrowMethodSignature)) { + InsnList list = new InsnList(); + list.add(new VarInsnNode(Opcodes.ALOAD, 1)); + list.add(new VarInsnNode(Opcodes.ALOAD, 2)); + list.add(new VarInsnNode(Opcodes.ALOAD, 3)); + list.add(new VarInsnNode(Opcodes.ALOAD, 4)); + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, FertilizableUtil.class.getName().replace(".", "/"), "grow", fertilizableGrowMethodSignatureBase + "Z", false)); + LabelNode jmp = new LabelNode(); + list.add(new JumpInsnNode(Opcodes.IFNE, jmp)); + list.add(new InsnNode(Opcodes.RETURN)); + list.add(jmp); + method.instructions.insertBefore(method.instructions.getFirst(), list); + flags.requestFrames(); + return true; + } + } + } + } + } + } catch(IOException e) { + throw new RuntimeException(e); + } + return false; + } +} diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/ASMUtil.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/ASMUtil.java new file mode 100644 index 000000000..918c398b1 --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/ASMUtil.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.lifecycle.util; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.tree.ClassNode; + +import java.io.IOException; +import java.util.WeakHashMap; + +import static org.objectweb.asm.ClassReader.SKIP_CODE; +import static org.objectweb.asm.ClassReader.SKIP_DEBUG; +import static org.objectweb.asm.ClassReader.SKIP_FRAMES; + + +public class ASMUtil { + static final ThreadLocal>> INHERITANCE_CACHE = new ThreadLocal<>(); + + public static boolean inheritsFrom(ClassNode classNode, String interfaceName) throws IOException { + if (INHERITANCE_CACHE.get() == null) { + INHERITANCE_CACHE.set(new WeakHashMap<>()); + } + return inheritsFromInternal(classNode, interfaceName); + } + + protected static boolean inheritsFromInternal(ClassNode classNode, String interfaceName) throws IOException { + if (INHERITANCE_CACHE.get().containsKey(classNode.name)) { + if (INHERITANCE_CACHE.get().get(classNode.name).containsKey(interfaceName)) { + return INHERITANCE_CACHE.get().get(classNode.name).get(interfaceName); + } + } + for (String parent : classNode.interfaces) { + if (checkClass(parent, interfaceName)) { + return true; + } + } + if (checkClass(classNode.superName, interfaceName)) { + return true; + } + INHERITANCE_CACHE.get().getOrDefault(classNode.name, new WeakHashMap<>()).put(interfaceName, false); + return false; + } + + protected static boolean checkClass(String name, String interfaceName) throws IOException { + if (name.startsWith("java/")) { + return false; + } + + boolean isClass = name.equals(interfaceName); + INHERITANCE_CACHE.get().getOrDefault(name, new WeakHashMap<>()).put(interfaceName, isClass); + if (isClass) { + return true; + } + ClassNode node = new ClassNode(); + new ClassReader(name).accept(node, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES); + return inheritsFromInternal(node, interfaceName); + } +} diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LoaderUtil.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LoaderUtil.java new file mode 100644 index 000000000..3fc7898c6 --- /dev/null +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LoaderUtil.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.lifecycle.util; + +public abstract class LoaderUtil { + public static LoaderUtil INSTANCE; + + public abstract String mapClassName(String namespace, String className); + + public abstract String mapMethodName(String namespace, String owner, String name, String descriptor); +} diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts index 940045d47..52af2ed18 100644 --- a/platforms/quilt/build.gradle.kts +++ b/platforms/quilt/build.gradle.kts @@ -15,6 +15,14 @@ dependencies { annotationProcessor("net.fabricmc:sponge-mixin:${Versions.Mod.mixin}") annotationProcessor("dev.architectury:architectury-loom:${Versions.Mod.architecuryLoom}") + modImplementation("com.github.the-glitch-network:minecraft-gudasm:${Versions.Mod.minecraftGudAsm}") { + exclude("net.fabricmc") + exclude("net.fabricmc.fabric-api") + } + include("com.github.the-glitch-network:minecraft-gudasm:${Versions.Mod.minecraftGudAsm}") { + exclude("net.fabricmc") + exclude("net.fabricmc.fabric-api") + } implementation(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } "developmentQuilt"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false } diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltASMEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltASMEntryPoint.java new file mode 100644 index 000000000..4ecd2b7d7 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltASMEntryPoint.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.quilt; + +import net.gudenau.minecraft.asm.api.v1.AsmInitializer; +import net.gudenau.minecraft.asm.api.v1.AsmRegistry; + +import com.dfsek.terra.lifecycle.asm.FertilizableASM; +import com.dfsek.terra.lifecycle.util.LoaderUtil; +import com.dfsek.terra.quilt.util.QuiltLoaderUtil; + + +public class QuiltASMEntryPoint implements AsmInitializer { + @Override + public void onInitializeAsm() { + LoaderUtil.INSTANCE = new QuiltLoaderUtil(); + AsmRegistry.getInstance().registerTransformer(new FertilizableASM()); + } +} diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/QuiltLoaderUtil.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/QuiltLoaderUtil.java new file mode 100644 index 000000000..19a3f4bf3 --- /dev/null +++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/QuiltLoaderUtil.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.quilt.util; + +import com.dfsek.terra.lifecycle.util.LoaderUtil; + +import org.quiltmc.loader.api.QuiltLoader; + + +public class QuiltLoaderUtil extends LoaderUtil { + @Override + public String mapClassName(String namespace, String className) { + return QuiltLoader.getMappingResolver().mapClassName(namespace, className); + } + + @Override + public String mapMethodName(String namespace, String owner, String name, String descriptor) { + return QuiltLoader.getMappingResolver().mapMethodName(namespace, owner, name, descriptor); + } +} diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index 0f53988ec..e2151593d 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -26,6 +26,9 @@ ], "pre_launch": [ "com.dfsek.terra.quilt.QuiltPreLaunchEntryPoint" + ], + "gud_asm": [ + "com.dfsek.terra.quilt.QuiltASMEntryPoint" ] }, "depends": [