diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java new file mode 100644 index 00000000..cfc92448 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java @@ -0,0 +1,23 @@ +package org.embeddedt.modernfix.common.mixin.bugfix.packet_leak; + +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IClientNetHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ClientPacketListener.class) +@ClientOnlyMixin +public class ClientPlayNetHandlerMixin { + /** + * @author embeddedt + * @reason allow the other function to track use of the buffer + */ + @Redirect(method = "handleCustomPayload", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;getData()Lnet/minecraft/network/FriendlyByteBuf;")) + private FriendlyByteBuf saveCopyForRelease(ClientboundCustomPayloadPacket instance) { + return ((IClientNetHandler)instance).getCopiedCustomBuffer(); + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compress_blockstate/BlockBehaviourMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compress_blockstate/BlockBehaviourMixin.java deleted file mode 100644 index 2f307825..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compress_blockstate/BlockBehaviourMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.compress_blockstate; - -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(BlockBehaviour.class) -public class BlockBehaviourMixin { - @Overwrite(remap = false) - protected boolean isAir(BlockState state) { - return state.getBlock().properties.isAir; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compress_blockstate/BlockStateBaseMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compress_blockstate/BlockStateBaseMixin.java deleted file mode 100644 index 630c0234..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compress_blockstate/BlockStateBaseMixin.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.compress_blockstate; - -import com.google.common.collect.ImmutableMap; -import com.mojang.serialization.MapCodec; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateHolder; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.material.Material; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(BlockBehaviour.BlockStateBase.class) -public abstract class BlockStateBaseMixin extends StateHolder { - protected BlockStateBaseMixin(Block object, ImmutableMap, Comparable> immutableMap, MapCodec mapCodec) { - super(object, immutableMap, mapCodec); - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;material:Lnet/minecraft/world/level/material/Material;" - )) - private Material getMaterial(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.material; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;destroySpeed:F" - )) - private float getDestroyTime(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.destroyTime; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;requiresCorrectToolForDrops:Z" - )) - private boolean getRequiresTool(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.requiresCorrectToolForDrops; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;canOcclude:Z" - )) - private boolean getCanOcclude(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.canOcclude; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;isRedstoneConductor:Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;" - )) - private BlockBehaviour.StatePredicate getRedstoneConductor(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.isRedstoneConductor; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;isSuffocating:Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;" - )) - private BlockBehaviour.StatePredicate getSuffocating(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.isSuffocating; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;isViewBlocking:Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;" - )) - private BlockBehaviour.StatePredicate getViewBlocking(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.isViewBlocking; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;hasPostProcess:Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;" - )) - private BlockBehaviour.StatePredicate getPostProcess(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.hasPostProcess; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;emissiveRendering:Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;" - )) - private BlockBehaviour.StatePredicate getEmissiveRendering(BlockBehaviour.BlockStateBase base) { - return this.owner.properties.emissiveRendering; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java b/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java index e5bb2f2d..05bd219b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java +++ b/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java @@ -77,11 +77,15 @@ public class CanonizingStringMap implements Map { public void putAll(@NotNull Map map) { if(map.size() == 0) return; + // grow early if we know there are enough non-overlapping keys + if((map.size() - backingMap.size()) > GROWTH_THRESHOLD && !(backingMap instanceof Object2ObjectOpenHashMap)) { + backingMap = new Object2ObjectOpenHashMap<>(backingMap); + } map.forEach((String key, T val) -> { key = KEY_INTERNER.intern(key); backingMap.put(key, val); }); - // if it's too big to be an array, grow it + // if it's still an array, and now too big, grow it if(backingMap.size() > GROWTH_THRESHOLD && !(backingMap instanceof Object2ObjectOpenHashMap)) { backingMap = new Object2ObjectOpenHashMap<>(backingMap); } diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 7480e262..344227a9 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -12,16 +12,6 @@ accessible field net/minecraft/client/renderer/texture/Stitcher$Holder width I accessible field net/minecraft/client/renderer/texture/Stitcher$Holder height I accessible field net/minecraft/network/syncher/EntityDataAccessor id I mutable field net/minecraft/network/syncher/EntityDataAccessor id I -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isAir Z -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties material Lnet/minecraft/world/level/material/Material; -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties destroyTime F -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties requiresCorrectToolForDrops Z -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties canOcclude Z -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isRedstoneConductor Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isSuffocating Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isViewBlocking Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties hasPostProcess Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; -accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties emissiveRendering Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; accessible class net/minecraft/client/resources/model/ModelBakery$BlockStateDefinitionException accessible field net/minecraft/network/syncher/SynchedEntityData itemsById Lit/unimi/dsi/fastutil/ints/Int2ObjectMap; accessible field net/minecraft/network/syncher/SynchedEntityData ENTITY_ID_POOL Lit/unimi/dsi/fastutil/objects/Object2IntMap; diff --git a/fabric/build.gradle b/fabric/build.gradle index 47220caf..0a7f2f6c 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -35,6 +35,7 @@ dependencies { modIncludeImplementation(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modIncludeImplementation(fabricApi.module("fabric-models-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modImplementation(fabricApi.module("fabric-data-generation-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false } // Remove the next line if you don't want to depend on the API // modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}" diff --git a/fabric/src/main/java/org/embeddedt/modernfix/ModernFixClientFabric.java b/fabric/src/main/java/org/embeddedt/modernfix/ModernFixClientFabric.java index b7f8db62..7fd97b77 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/ModernFixClientFabric.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/ModernFixClientFabric.java @@ -4,7 +4,9 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; +import org.embeddedt.modernfix.fabric.datagen.RuntimeDatagen; import java.util.concurrent.atomic.AtomicBoolean; @@ -29,5 +31,8 @@ public class ModernFixClientFabric implements ClientModInitializer { ServerLifecycleEvents.SERVER_STARTED.register(server -> { commonMod.onServerStarted(server); }); + if(FabricLoader.getInstance().isModLoaded("fabric-data-generation-api-v1")) { + RuntimeDatagen.init(); + } } } diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/datagen/RuntimeDatagen.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/datagen/RuntimeDatagen.java new file mode 100644 index 00000000..82863666 --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/datagen/RuntimeDatagen.java @@ -0,0 +1,40 @@ +package org.embeddedt.modernfix.fabric.datagen; + +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.impl.datagen.FabricDataGenHelper; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.network.chat.Component; +import org.embeddedt.modernfix.ModernFix; + +import java.lang.reflect.Method; + +public class RuntimeDatagen { + private static final boolean SHOULD_RUNTIME_DATAGEN = System.getProperty("fabric-api.datagen.output-dir") != null; + + private static void runRuntimeDatagen() { + // call runInternal directly to avoid exiting immediately + try { + System.setProperty("fabric-api.datagen", "true"); + Method method = FabricDataGenHelper.class.getDeclaredMethod("runInternal"); + method.setAccessible(true); + method.invoke(null); + } catch(Throwable e) { + ModernFix.LOGGER.error("Error running datagen", e); + } finally { + System.clearProperty("fabric-api.datagen"); + } + } + + public static void init() { + if(!SHOULD_RUNTIME_DATAGEN) + return; + ScreenEvents.AFTER_INIT.register(((client, s, scaledWidth, scaledHeight) -> { + if(s instanceof TitleScreen screen) { + screen.addRenderableWidget(Button.builder(Component.literal("DG"), (arg) -> { + runRuntimeDatagen(); + }).pos(screen.width / 2 - 100 - 50, screen.height / 4 + 48).size(50, 20).build()); + } + })); + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index 60240a84..b9252259 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -1,6 +1,5 @@ package org.embeddedt.modernfix.platform.forge; -import cpw.mods.modlauncher.api.INameMappingService; import com.mojang.brigadier.CommandDispatcher; import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; @@ -13,23 +12,18 @@ import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator; -import net.minecraftforge.fml.util.ObfuscationReflectionHelper; import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.server.ServerLifecycleHooks; -import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; +import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList; import org.embeddedt.modernfix.forge.packet.PacketHandler; import org.embeddedt.modernfix.util.DummyList; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.*; +import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.injection.struct.InjectorGroupInfo; import java.lang.reflect.Field; import java.nio.file.Path; -import java.util.*; import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class ModernFixPlatformHooksImpl { public static boolean isClient() { @@ -90,40 +84,7 @@ public class ModernFixPlatformHooksImpl { } public static void applyASMTransformers(String mixinClassName, ClassNode targetClass) { - if(mixinClassName.equals("org.embeddedt.modernfix.common.compress_blockstate.perf.mixin.BlockStateBaseMixin")) { - // Delete unused fields off BlockStateBase - Set fieldsToDelete = Stream.of( - "field_235702_f_", // isAir - "field_235703_g_", // material - "field_235705_i_", // destroySpeed - "field_235706_j_", // requiresCorrectToolForDrops - "field_235707_k_", // canOcclude - "field_235708_l_", // isRedstoneConductor - "field_235709_m_", // isSuffocating - "field_235710_n_", // isViewBlocking - "field_235711_o_", // hasPostProcess - "field_235712_p_" // emissiveRendering - ).map(name -> ObfuscationReflectionHelper.remapName(INameMappingService.Domain.FIELD, name)).collect(Collectors.toSet()); - targetClass.fields.removeIf(field -> { - if(fieldsToDelete.contains(field.name)) { - return true; - } - return false; - }); - for(MethodNode m : targetClass.methods) { - if(m.name.equals("")) { - ListIterator iter = m.instructions.iterator(); - while(iter.hasNext()) { - AbstractInsnNode node = iter.next(); - if(node.getOpcode() == Opcodes.PUTFIELD) { - if(fieldsToDelete.contains(((FieldInsnNode)node).name)) { - iter.remove(); - } - } - } - } - } - } + } public static void onServerCommandRegister(Consumer> handler) {