diff --git a/build.gradle b/build.gradle index ce302f10..e211d7a3 100644 --- a/build.gradle +++ b/build.gradle @@ -200,6 +200,12 @@ configure(subprojects.findAll {it.name == "forge" || it.name == "fabric"}) { sourceSet project(':common').sourceSets.main } } + runs { + client { + vmArgs "-Xmx512m" + vmArgs "-Xms512m" + } + } } def copyJarNameConsistent = tasks.register('copyJarNameConsistent', Copy) { diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateDefinitionMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateDefinitionMixin.java new file mode 100644 index 00000000..82ae09df --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateDefinitionMixin.java @@ -0,0 +1,26 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_block_codecs; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.StateHolder; +import net.minecraft.world.level.block.state.properties.Property; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import java.util.Map; +import java.util.function.Function; + +@Mixin(StateDefinition.class) +public class StateDefinitionMixin> { + @Shadow @Final private O owner; + + @ModifyVariable(method = "", at = @At("HEAD"), ordinal = 0, argsOnly = true) + private static > StateDefinition.Factory replaceMapCodec(StateDefinition.Factory factory, Function function, O object, StateDefinition.Factory factory2, Map> map) { + if(object instanceof Block) + return (o, m, c) -> factory.create(o, m, null); + return factory; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateHolderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateHolderMixin.java new file mode 100644 index 00000000..7455fcbb --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateHolderMixin.java @@ -0,0 +1,58 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_block_codecs; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.mojang.serialization.Codec; +import com.mojang.serialization.Decoder; +import com.mojang.serialization.Encoder; +import com.mojang.serialization.MapCodec; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.StateHolder; +import net.minecraft.world.level.block.state.properties.Property; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.concurrent.ExecutionException; +import java.util.function.Function; +import java.util.function.Supplier; + +@Mixin(StateHolder.class) +public class StateHolderMixin { + private static final LoadingCache> MODERNFIX_CODEC_CACHE = CacheBuilder.newBuilder() + .maximumSize(100000) + .build(new CacheLoader>() { + @Override + public MapCodec load(Block block) throws Exception { + Supplier stateSupplier = block::defaultBlockState; + MapCodec mapCodec = MapCodec.of(Encoder.empty(), Decoder.unit(stateSupplier)); + for(Property property : block.getStateDefinition().getProperties()) { + mapCodec = StateDefinition.appendPropertyCodec(mapCodec, stateSupplier, property.getName(), property); + } + return mapCodec; + } + }); + + @Redirect(method = "codec", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;dispatch(Ljava/lang/String;Ljava/util/function/Function;Ljava/util/function/Function;)Lcom/mojang/serialization/Codec;")) + private static > Codec obtainCodec(Codec codec, String typeKey, Function type, Function> codecFn, Codec codecMethodArg, Function stateSupplier) { + return codec.dispatch(typeKey, type, block -> { + if(block instanceof Block) { + S state = stateSupplier.apply(block); + if(state.getValues().isEmpty()) + return Codec.unit(state); + MapCodec mapCodec; + try { + mapCodec = (MapCodec)MODERNFIX_CODEC_CACHE.get((Block)block); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + return mapCodec.fieldOf("Properties").codec(); + } else { + return codecFn.apply(block); + } + }); + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index c5407fa6..b247fbb4 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -155,6 +155,7 @@ public class ModernFixEarlyConfig { private static final ImmutableMap DEFAULT_SETTING_OVERRIDES = new DefaultSettingMapBuilder() .put("mixin.perf.dynamic_resources", false) + .put("mixin.perf.dynamic_block_codecs", false) .put("mixin.feature.direct_stack_trace", false) .putConditionally(ModernFixPlatformHooks.INSTANCE::isDevEnv, "mixin.perf.rewrite_registry", false) .put("mixin.perf.clear_mixin_classinfo", false) diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 3e0503ec..a03e8bc9 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -35,3 +35,4 @@ accessible field net/minecraft/resources/RegistryOps registryAccess Lnet/minecra accessible field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel; mutable field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel; accessible field net/minecraft/client/renderer/entity/EnderDragonRenderer$DragonModel entity Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon; +accessible method net/minecraft/world/level/block/state/StateDefinition appendPropertyCodec (Lcom/mojang/serialization/MapCodec;Ljava/util/function/Supplier;Ljava/lang/String;Lnet/minecraft/world/level/block/state/properties/Property;)Lcom/mojang/serialization/MapCodec; \ No newline at end of file