Add option to generate block codecs on the fly instead of at startup

This commit is contained in:
embeddedt 2023-07-31 21:51:45 -04:00
parent c8c316a06f
commit 11fe75578c
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
4 changed files with 85 additions and 0 deletions

View File

@ -0,0 +1,23 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_block_codecs;
import com.mojang.serialization.MapCodec;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.StateHolder;
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;
@Mixin(StateDefinition.class)
public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
@Shadow @Final private O owner;
@ModifyVariable(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;newLinkedHashMap()Ljava/util/LinkedHashMap;"), ordinal = 0)
private MapCodec<?> replaceMapCodec(MapCodec<?> codec) {
if(this.owner instanceof Block)
return null;
return codec;
}
}

View File

@ -0,0 +1,60 @@
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.core.Registry;
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<Block, MapCodec<BlockState>> MODERNFIX_CODEC_CACHE = CacheBuilder.newBuilder()
.maximumSize(100000)
.build(new CacheLoader<Block, MapCodec<BlockState>>() {
@Override
public MapCodec<BlockState> load(Block block) throws Exception {
System.out.println("Generating codec for " + Registry.BLOCK.getKey(block));
Supplier<BlockState> stateSupplier = block::defaultBlockState;
MapCodec<BlockState> 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 <O, S extends StateHolder<O, S>> Codec<S> obtainCodec(Codec<O> codec, String typeKey, Function<S, O> type, Function<O, ? extends Codec<S>> codecFn, Codec<O> codecMethodArg, Function<O, S> 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<S> mapCodec;
try {
mapCodec = (MapCodec<S>)MODERNFIX_CODEC_CACHE.get((Block)block);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
return mapCodec.fieldOf("Properties").codec();
} else {
return codecFn.apply(block);
}
});
}
}

View File

@ -161,6 +161,7 @@ public class ModernFixEarlyConfig {
private static final ImmutableMap<String, Boolean> DEFAULT_SETTING_OVERRIDES = new DefaultSettingMapBuilder()
.put("mixin.perf.dynamic_resources", false)
.put("mixin.perf.reuse_datapacks", 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)

View File

@ -31,3 +31,4 @@ accessible field net/minecraft/client/renderer/RenderStateShard name Ljava/lang/
accessible method net/minecraft/client/gui/screens/Screen addButton (Lnet/minecraft/client/gui/components/AbstractWidget;)Lnet/minecraft/client/gui/components/AbstractWidget;
accessible field net/minecraft/server/packs/resources/SimpleReloadableResourceManager namespacedPacks Ljava/util/Map;
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;