Add option to generate block codecs on the fly instead of at startup
This commit is contained in:
parent
c8c316a06f
commit
11fe75578c
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
Loading…
Reference in New Issue
Block a user