diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/buffer_builder_leak/BufferBuilderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/buffer_builder_leak/BufferBuilderMixin.java deleted file mode 100644 index 432e9117..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/buffer_builder_leak/BufferBuilderMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.buffer_builder_leak; - -import com.mojang.blaze3d.vertex.BufferBuilder; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.render.UnsafeBufferHelper; -import org.spongepowered.asm.mixin.Dynamic; -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.nio.ByteBuffer; - -@Mixin(value = BufferBuilder.class, priority = 1500) -@ClientOnlyMixin -public class BufferBuilderMixin { - @Shadow private ByteBuffer buffer; - @Shadow private boolean closed; - - private static boolean leakReported = false; - - private boolean mfix$shouldFree = true; - - @Dynamic - @Inject(method = "flywheel$injectForRender", at = @At("RETURN"), remap = false, require = 0) - private void preventFree(CallbackInfo ci) { - mfix$shouldFree = false; - } - - /** - * Ensure UnsafeBufferHelper is classloaded early, to avoid Forge's event transformer showing an error in the log. - */ - @Inject(method = "", at = @At(value = "RETURN")) - private static void initUnsafeBufferHelper(CallbackInfo ci) { - UnsafeBufferHelper.init(); - } - - @Override - protected void finalize() throws Throwable { - try { - ByteBuffer buf = buffer; - // can be null if a mod already tried to free the buffer - if(!this.closed && buf != null && mfix$shouldFree) { - if(!leakReported) { - leakReported = true; - ModernFix.LOGGER.warn("One or more BufferBuilders have been leaked, ModernFix will attempt to correct this."); - } - UnsafeBufferHelper.free(buf); - buffer = null; - } - } finally { - super.finalize(); - } - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/DirectObjectMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/DirectObjectMixin.java deleted file mode 100644 index 02d346d2..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/DirectObjectMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.compact_mojang_registries; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import org.embeddedt.modernfix.annotation.IgnoreOutsideDev; -import org.embeddedt.modernfix.registry.DirectStorageRegistryObject; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin({ Block.class, Item.class }) -@IgnoreOutsideDev -public class DirectObjectMixin implements DirectStorageRegistryObject { - private ResourceLocation mfix$resourceKey; - - @Override - public ResourceLocation mfix$getResourceKey() { - return mfix$resourceKey; - } - - @Override - public void mfix$setResourceKey(ResourceLocation key) { - mfix$resourceKey = key; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/MappedRegistryMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/MappedRegistryMixin.java index fc1ce59b..90c50a1b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/MappedRegistryMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/MappedRegistryMixin.java @@ -1,10 +1,8 @@ package org.embeddedt.modernfix.common.mixin.perf.compact_mojang_registries; -import com.google.common.collect.ImmutableSet; import net.minecraft.core.MappedRegistry; import net.minecraft.core.RegistrationInfo; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import org.embeddedt.modernfix.annotation.IgnoreOutsideDev; import org.embeddedt.modernfix.registry.LifecycleMap; import org.spongepowered.asm.mixin.Final; @@ -25,17 +23,8 @@ public abstract class MappedRegistryMixin { @Mutable private Map, RegistrationInfo> registrationInfos; - private static final ImmutableSet MFIX$NEW_STORAGE_KEYS = ImmutableSet.of(new ResourceLocation("block"), new ResourceLocation("item")); - - @Inject(method = "(Lnet/minecraft/resources/ResourceKey;Lcom/mojang/serialization/Lifecycle;Z)V", at = @At("RETURN")) + @Inject(method = "", at = @At("RETURN")) private void replaceStorage(CallbackInfo ci) { this.registrationInfos = new LifecycleMap<>(); - /* - if(MFIX$NEW_STORAGE_KEYS.contains(this.key().location())) { - ModernFixMixinPlugin.instance.logger.info("Using experimental registry storage for {}", this.key()); - this.storage = (BiMap) RegistryStorage.createStorage(); - this.keyStorage = (BiMap, T>)RegistryStorage.createKeyStorage(this.key(), (BiMap)this.storage); - } - */ } } 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 deleted file mode 100644 index 82ae09df..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateDefinitionMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 540c7495..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateHolderMixin.java +++ /dev/null @@ -1,58 +0,0 @@ -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;", remap = false)) - 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/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java index 61f86bd4..9ba89eeb 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java @@ -1,12 +1,12 @@ package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap; import net.minecraft.client.renderer.block.BlockModelShaper; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.world.level.block.state.BlockState; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.dynamicresources.DynamicModelCache; import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; import org.embeddedt.modernfix.util.DynamicOverridableMap; import org.spongepowered.asm.mixin.*; @@ -24,14 +24,13 @@ public class BlockModelShaperMixin { @Shadow private Map modelByStateCache; - private final DynamicModelCache mfix$modelCache = new DynamicModelCache<>(k -> this.cacheBlockModel((BlockState)k), false); + private ThreadLocal> mfix$modelCache = ThreadLocal.withInitial(Reference2ReferenceLinkedOpenHashMap::new); @Inject(method = { "", "replaceCache" }, at = @At("RETURN")) private void replaceModelMap(CallbackInfo ci) { // replace the backing map for mods which will access it this.modelByStateCache = new DynamicOverridableMap<>(state -> modelManager.getModel(ModelLocationCache.get(state))); - if(this.mfix$modelCache != null) - this.mfix$modelCache.clear(); + this.mfix$modelCache = ThreadLocal.withInitial(Reference2ReferenceLinkedOpenHashMap::new); } private BakedModel cacheBlockModel(BlockState state) { @@ -51,6 +50,18 @@ public class BlockModelShaperMixin { */ @Overwrite public BakedModel getBlockModel(BlockState state) { - return this.mfix$modelCache.get(state); + Reference2ReferenceLinkedOpenHashMap map = this.mfix$modelCache.get(); + BakedModel model = map.get(state); + + if(model != null) { + return model; + } + + model = this.cacheBlockModel(state); + map.putAndMoveToFirst(state, model); + if(map.size() > 500) { + map.removeLast(); + } + return model; } } 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 ee759241..747c0afe 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 @@ -162,9 +162,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) .put("mixin.perf.deduplicate_climate_parameters", false) .put("mixin.bugfix.packet_leak", false) @@ -228,6 +226,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.perf.reuse_datapacks", "tac"); disableIfModPresent("mixin.launch.class_search_cache", "optifine"); disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine"); + disableIfModPresent("mixin.bugfix.entity_pose_stack", "optifine"); disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide"); disableIfModPresent("mixin.bugfix.buffer_builder_leak", "isometric-renders"); disableIfModPresent("mixin.feature.remove_chat_signing", "nochatreports"); diff --git a/common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageBiMap.java b/common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageBiMap.java deleted file mode 100644 index 9aa1442a..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageBiMap.java +++ /dev/null @@ -1,184 +0,0 @@ -package org.embeddedt.modernfix.registry; - -import com.google.common.collect.BiMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.NotNull; - -import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.stream.Collectors; - -@SuppressWarnings("unchecked") -public class DirectStorageBiMap implements BiMap { - private final Function keyGetter; - private final BiConsumer keySetter; - private final Map forwardMap; - - public DirectStorageBiMap(Function keyGetter, BiConsumer keySetter) { - Objects.requireNonNull(keyGetter); - Objects.requireNonNull(keySetter); - this.keyGetter = keyGetter; - this.keySetter = keySetter; - this.forwardMap = new Object2ObjectOpenHashMap<>(); - } - - @Override - public int size() { - return this.forwardMap.size(); - } - - @Override - public boolean isEmpty() { - return this.forwardMap.isEmpty(); - } - - @Override - public boolean containsKey(Object o) { - return this.forwardMap.containsKey(o); - } - - @Override - public boolean containsValue(Object o) { - return o != null && keyGetter.apply((V)o) != null; - } - - @Override - public V get(Object o) { - return this.forwardMap.get(o); - } - - @Override - public V put(K key, V value) { - if(this.forwardMap.containsKey(key) || (value != null && keyGetter.apply(value) != null)) - throw new IllegalArgumentException("Already have mapping for " + key); - return forcePut(key, value); - } - - @Override - public V remove(Object o) { - return put((K)o, null); - } - - @Override - public V forcePut(K key, V value) { - V previousValue = this.forwardMap.put(key, value); - if(previousValue != null) - keySetter.accept(previousValue, null); - if(value != null) - keySetter.accept(value, key); - return previousValue; - } - - @Override - public void putAll(Map map) { - map.forEach(this::put); - } - - @Override - public void clear() { - for(V value : this.forwardMap.values()) { - if(value != null) - keySetter.accept(value, null); - } - this.forwardMap.clear(); - } - - @NotNull - @Override - public Set keySet() { - return this.forwardMap.keySet(); - } - - @Override - public Set values() { - return new HashSet<>(this.forwardMap.values()); - } - - @NotNull - @Override - public Set> entrySet() { - return this.forwardMap.entrySet(); - } - - @Override - public BiMap inverse() { - return new Reverse(); - } - - class Reverse implements BiMap { - @Override - public int size() { - return DirectStorageBiMap.this.size(); - } - - @Override - public boolean isEmpty() { - return DirectStorageBiMap.this.isEmpty(); - } - - @Override - public boolean containsKey(Object o) { - return DirectStorageBiMap.this.containsValue(o); - } - - @Override - public boolean containsValue(Object o) { - return DirectStorageBiMap.this.containsKey(o); - } - - @Override - public K get(Object o) { - return o == null ? null : keyGetter.apply((V)o); - } - - @Override - public K put(V key, K value) { - throw new UnsupportedOperationException(); - } - - @Override - public K remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public K forcePut(V key, K value) { - throw new UnsupportedOperationException(); - } - - @Override - public void putAll(Map map) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set keySet() { - return DirectStorageBiMap.this.values(); - } - - @Override - public Set values() { - return DirectStorageBiMap.this.keySet(); - } - - @NotNull - @Override - public Set> entrySet() { - return DirectStorageBiMap.this.entrySet().stream() - .map(entry -> new AbstractMap.SimpleImmutableEntry<>(entry.getValue(), entry.getKey())) - .collect(Collectors.toSet()); - } - - @Override - public BiMap inverse() { - return DirectStorageBiMap.this; - } - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageRegistryObject.java b/common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageRegistryObject.java deleted file mode 100644 index c18ac699..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageRegistryObject.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.embeddedt.modernfix.registry; - -import net.minecraft.resources.ResourceLocation; - -public interface DirectStorageRegistryObject { - ResourceLocation mfix$getResourceKey(); - void mfix$setResourceKey(ResourceLocation key); -} diff --git a/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java b/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java deleted file mode 100644 index 5d2fb207..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.embeddedt.modernfix.registry; - -import com.google.common.collect.BiMap; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; - -import java.util.Map; -import java.util.function.Function; - -public class RegistryStorage { - public static BiMap createStorage() { - return new DirectStorageBiMap<>(DirectStorageRegistryObject::mfix$getResourceKey, DirectStorageRegistryObject::mfix$setResourceKey); - } - - public static BiMap, DirectStorageRegistryObject> createKeyStorage(ResourceKey> registryKey, BiMap storage) { - if(storage instanceof DirectStorageBiMap) { - // silently ignore put/putAll calls on this map - return new TransformingBiMap, DirectStorageRegistryObject>(storage, loc -> ResourceKey.create(registryKey, loc), ResourceKey::location, Function.identity(), Function.identity()) { - @Override - public DirectStorageRegistryObject put(ResourceKey key, DirectStorageRegistryObject value) { - return null; - } - - @Override - public void putAll(Map, ? extends DirectStorageRegistryObject> map) { - - } - }; - } else - throw new UnsupportedOperationException(); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/registry/TransformingBiMap.java b/common/src/main/java/org/embeddedt/modernfix/registry/TransformingBiMap.java deleted file mode 100644 index 2fb1beb1..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/registry/TransformingBiMap.java +++ /dev/null @@ -1,224 +0,0 @@ -package org.embeddedt.modernfix.registry; - -import com.google.common.collect.BiMap; -import com.google.common.collect.Collections2; -import com.google.common.collect.Iterators; -import org.jetbrains.annotations.NotNull; - -import java.util.*; -import java.util.function.Function; - -public class TransformingBiMap implements BiMap { - private final BiMap delegate; - private final Function keyFwd; - private final Function keyBack; - private final Function valueFwd; - private final Function valueBack; - - public TransformingBiMap(BiMap map, Function keyFwd, Function keyBack, Function valueFwd, Function valueBack) { - this.delegate = map; - this.keyFwd = keyFwd; - this.keyBack = keyBack; - this.valueFwd = valueFwd; - this.valueBack = valueBack; - } - - private KFrom keyBack(KTo key) { - return key == null ? null : this.keyBack.apply(key); - } - - private KTo keyFwd(KFrom key) { - return key == null ? null : this.keyFwd.apply(key); - } - - private VFrom valueBack(VTo value) { - return value == null ? null : this.valueBack.apply(value); - } - - private VTo valueFwd(VFrom value) { - return value == null ? null : this.valueFwd.apply(value); - } - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean isEmpty() { - return this.delegate.isEmpty(); - } - - @Override - public boolean containsKey(Object o) { - return this.delegate.containsKey(keyBack((KTo)o)); - } - - @Override - public boolean containsValue(Object o) { - return false; - } - - @Override - public VTo get(Object o) { - return valueFwd(this.delegate.get(keyBack((KTo)o))); - } - - @Override - public VTo put(KTo key, VTo value) { - return valueFwd(this.delegate.put(keyBack(key), valueBack(value))); - } - - @Override - public VTo remove(Object o) { - return valueFwd(this.delegate.remove(keyBack((KTo)o))); - } - - @Override - public VTo forcePut(KTo key, VTo value) { - return valueFwd(this.delegate.forcePut(keyBack(key), valueBack(value))); - } - - @Override - public void putAll(Map map) { - map.forEach((key, value) -> { - this.delegate.put(keyBack(key), valueBack(value)); - }); - } - - @Override - public void clear() { - this.delegate.clear(); - } - - @NotNull - @Override - public Set keySet() { - return new TransformingSet<>(this.delegate.keySet(), this.keyFwd, this.keyBack); - } - - @Override - public Set values() { - return new TransformingSet<>(this.delegate.values(), this.valueFwd, this.valueBack); - } - - @NotNull - @Override - public Set> entrySet() { - return new TransformingSet<>(this.delegate.entrySet(), entry -> { - return new AbstractMap.SimpleImmutableEntry<>(keyFwd(entry.getKey()), valueFwd(entry.getValue())); - }, entry -> { - return new AbstractMap.SimpleImmutableEntry<>(keyBack(entry.getKey()), valueBack(entry.getValue())); - }); - } - - @Override - public BiMap inverse() { - return new TransformingBiMap<>(this.delegate.inverse(), this.valueFwd, this.valueBack, this.keyFwd, this.keyBack); - } - - static class TransformingSet implements Set { - private final Set delegate; - private final Function forward; - private final Function reverse; - - public TransformingSet(Set set, Function forward, Function reverse) { - this.delegate = set; - this.forward = forward; - this.reverse = reverse; - } - - private TypeTo forward(TypeFrom t) { - return t == null ? null : this.forward.apply(t); - } - - private TypeFrom reverse(TypeTo t) { - return t == null ? null : this.reverse.apply(t); - } - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public boolean isEmpty() { - return this.delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return this.delegate.contains(reverse((TypeTo)o)); - } - - @NotNull - @Override - public Iterator iterator() { - return Iterators.transform(this.delegate.iterator(), this::forward); - } - - @NotNull - @Override - public Object[] toArray() { - Object[] array = this.delegate.toArray(); - for(int i = 0; i < array.length; i++) { - array[i] = this.forward((TypeFrom)array[i]); - } - return array; - } - - @NotNull - @Override - public T[] toArray(@NotNull T[] ts) { - if(ts.length >= this.delegate.size()) { - Object[] setContents = toArray(); - System.arraycopy(setContents, 0, ts, 0, Math.min(setContents.length, ts.length)); - if(ts.length > setContents.length) - ts[setContents.length] = null; - return ts; - } else { - T[] realArray = Arrays.copyOf(ts, this.delegate.size()); - Iterator iterator = this.iterator(); - int i = 0; - while(iterator.hasNext()) - realArray[i++] = (T)iterator.next(); - return realArray; - } - } - - @Override - public boolean add(TypeTo typeFrom) { - return this.delegate.add(reverse(typeFrom)); - } - - @Override - public boolean remove(Object o) { - return this.delegate.remove(reverse((TypeTo)o)); - } - - @Override - public boolean containsAll(@NotNull Collection collection) { - return this.delegate.containsAll(Collections2.transform(collection, obj -> reverse((TypeTo)obj))); - } - - @Override - public boolean addAll(@NotNull Collection collection) { - return this.delegate.addAll(Collections2.transform(collection, this::reverse)); - } - - @Override - public boolean retainAll(@NotNull Collection collection) { - return this.delegate.retainAll(Collections2.transform(collection, obj -> reverse((TypeTo)obj))); - } - - @Override - public boolean removeAll(@NotNull Collection collection) { - return this.delegate.removeAll(Collections2.transform(collection, obj -> reverse((TypeTo)obj))); - } - - @Override - public void clear() { - this.delegate.clear(); - } - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/render/UnsafeBufferHelper.java b/common/src/main/java/org/embeddedt/modernfix/render/UnsafeBufferHelper.java deleted file mode 100644 index 69ab0cfe..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/render/UnsafeBufferHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.embeddedt.modernfix.render; - -import org.embeddedt.modernfix.ModernFix; -import org.lwjgl.system.MemoryUtil; -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.nio.ByteBuffer; - -/** - * Helper that frees ByteBuffers allocated by BufferBuilders, and nulls out the address pointer - * to prevent double frees. - * - * @author Moulberry - */ -public class UnsafeBufferHelper { - private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false); - - private static sun.misc.Unsafe UNSAFE = null; - private static long ADDRESS = -1; - - static { - try { - final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe)theUnsafe.get(null); - - final Field addressField = MemoryUtil.class.getDeclaredField("ADDRESS"); - addressField.setAccessible(true); - ADDRESS = addressField.getLong(null); - } catch(Throwable t) { - ModernFix.LOGGER.error("Could load unsafe/buffer address", t); - } - } - - public static void init() { - - } - - public static void free(ByteBuffer buf) { - if(UNSAFE != null && ADDRESS >= 0) { - // set the address to 0 to prevent double free - long address = UNSAFE.getAndSetLong(buf, ADDRESS, 0); - if(address != 0) { - ALLOCATOR.free(address); - } - } else { - ALLOCATOR.free(MemoryUtil.memAddress0(buf)); - } - } -} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java deleted file mode 100644 index 5fba1b2e..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.embeddedt.modernfix.forge.mixin.bugfix.model_data_manager_cme; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraftforge.client.model.data.ModelDataManager; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -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.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; - -/** - * Fix several concurrency issues in the default ModelDataManager. - */ -@Mixin(ModelDataManager.class) -@ClientOnlyMixin -public abstract class ModelDataManagerMixin { - @Shadow protected abstract void refreshAt(ChunkPos chunk); - - @Shadow @Final private Map> needModelDataRefresh; - - /** - * Make the set of positions to refresh a real concurrent hash set rather than relying on synchronizedSet, - * because the returned iterator won't be thread-safe otherwise. See https://github.com/AppliedEnergistics/Applied-Energistics-2/issues/7511 - */ - @ModifyArg(method = "requestRefresh", at = @At(value = "INVOKE", target = "Ljava/util/Map;computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;", ordinal = 0), index = 1, remap = false) - private Function> changeTypeOfSetUsed(Function> mappingFunction) { - return pos -> Collections.newSetFromMap(new ConcurrentHashMap<>()); - } - - @Redirect(method = "getAt(Lnet/minecraft/world/level/ChunkPos;)Ljava/util/Map;", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/model/data/ModelDataManager;refreshAt(Lnet/minecraft/world/level/ChunkPos;)V"), remap = false) - private void onlyRefreshOnMainThread(ModelDataManager instance, ChunkPos pos) { - // Only refresh model data on the main thread. This prevents calling getBlockEntity from worker threads - // which could cause weird CMEs or other behavior. - // Avoid the loop if no model data needs to be refreshed, to prevent unnecessary allocation. - if(Minecraft.getInstance().isSameThread() && !needModelDataRefresh.isEmpty()) { - // Refresh the given chunk, and all its neighbors. This is less efficient than the default code - // but we have no choice since we need to not do refreshing on workers, and blocks might - // try to access model data in neighboring chunks. - for(int x = -1; x <= 1; x++) { - for(int z = -1; z <= 1; z++) { - refreshAt(new ChunkPos(pos.x + x, pos.z + z)); - } - } - } - } -} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java deleted file mode 100644 index 68e86aab..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.embeddedt.modernfix.forge.mixin.perf.forge_cap_retrieval; - -import net.minecraft.core.Direction; -import net.minecraft.world.entity.LivingEntity; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import javax.annotation.Nullable; - -@Mixin(LivingEntity.class) -public class LivingEntityMixin { - /** - * @author embeddedt (issue noted by XFactHD) - * @reason check capability equality before checking that entity is alive, the latter requires a lot more - * indirection - */ - @Redirect(method = "getCapability", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isAlive()Z")) - private boolean checkAliveAfterCap(LivingEntity entity, Capability capability, @Nullable Direction facing) { - return capability == ForgeCapabilities.ITEM_HANDLER && entity.isAlive(); - } -} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_registry_alloc/ForgeRegistryMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_registry_alloc/ForgeRegistryMixin.java deleted file mode 100644 index bf045369..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_registry_alloc/ForgeRegistryMixin.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.embeddedt.modernfix.forge.mixin.perf.forge_registry_alloc; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.registries.ForgeRegistry; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Locale; -import java.util.Map; - -@Mixin(value = ForgeRegistry.class, remap = false) -public abstract class ForgeRegistryMixin { - // Replace the backing maps with fastutil maps for a bit more speed, since value->holder lookups in particular - // are a bottleneck in many areas (e.g. render type lookup) - @Shadow @Final private Map> delegatesByName = new Object2ObjectOpenHashMap<>(); - - @Shadow @Final private Map> delegatesByValue = new Object2ObjectOpenHashMap<>(); - - /** - * @author embeddedt - * @reason stop allocating so many unneeded objects. stop. - */ - @Overwrite - public Holder.Reference getDelegateOrThrow(ResourceLocation location) { - Holder.Reference holder = delegatesByName.get(location); - - if (holder == null) { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No delegate exists for location %s", location)); - } - - return holder; - } - - /** - * @author embeddedt - * @reason see above - */ - @Overwrite - public Holder.Reference getDelegateOrThrow(ResourceKey rkey) { - Holder.Reference holder = delegatesByName.get(rkey.location()); - - if (holder == null) { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No delegate exists for key %s", rkey)); - } - - return holder; - } - - /** - * @author embeddedt - * @reason see above - */ - @Overwrite - public Holder.Reference getDelegateOrThrow(V value) { - Holder.Reference holder = delegatesByValue.get(value); - - if (holder == null) { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No delegate exists for value %s", value)); - } - - return holder; - } -} diff --git a/gradle.properties b/gradle.properties index 1bf7e7b0..910b500b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ mixinextras_version=0.3.2 mod_id=modernfix minecraft_version=24w09a enabled_platforms=fabric -forge_version=20.4.132-beta +forge_version=20.4.190 # parchment_version=2023.07.09 refined_storage_version=4392788 jei_version=16.0.0.28 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index e46564d0..280e84db 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -50,8 +50,6 @@ dependencies { modCompileOnly("curse.maven:supermartijncore-454372:4455391") modCompileOnly("vazkii.patchouli:Patchouli:1.19.2-77") - modCompileOnly("curse.maven:blueprint-382216:3991478") - // runtime remapping at home for (extraModJar in fileTree(dir: extraModsDir, include: '*.jar')) { def basename = extraModJar.name.substring(0, extraModJar.name.length() - ".jar".length()) diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/blueprint_modif_memory_leak/ObjectModificationManagerMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/blueprint_modif_memory_leak/ObjectModificationManagerMixin.java deleted file mode 100644 index b3610d11..00000000 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/blueprint_modif_memory_leak/ObjectModificationManagerMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.embeddedt.modernfix.neoforge.mixin.bugfix.blueprint_modif_memory_leak; - -import com.google.gson.Gson; -import com.teamabnormals.blueprint.core.util.modification.ObjectModificationManager; -import com.teamabnormals.blueprint.core.util.modification.selection.SelectionSpace; -import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; -import org.embeddedt.modernfix.annotation.RequiresMod; -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ObjectModificationManager.class) -@RequiresMod("blueprint") -public abstract class ObjectModificationManagerMixin extends SimpleJsonResourceReloadListener { - @Shadow(remap = false) protected SelectionSpace selectionSpace; - - public ObjectModificationManagerMixin(Gson gson, String string) { - super(gson, string); - } - - @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At("RETURN"), remap = false) - private void clearSelectionSpace(CallbackInfo ci) { - this.selectionSpace = consumer -> {}; - } -} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java similarity index 64% rename from forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java rename to neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java index 10109809..186934c7 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java @@ -1,10 +1,10 @@ -package org.embeddedt.modernfix.forge.mixin.bugfix.entity_pose_stack; +package org.embeddedt.modernfix.neoforge.mixin.bugfix.entity_pose_stack; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.minecraftforge.client.event.RenderLivingEvent; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.IEventBus; +import net.neoforged.neoforge.client.event.RenderLivingEvent; +import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.IEventBus; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,18 +13,17 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(LivingEntityRenderer.class) @ClientOnlyMixin public class LivingEntityRendererMixin { - @Redirect(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z", ordinal = 0)) - private boolean fireCheckingPoseStack(IEventBus instance, Event event) { + @Redirect(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;", ordinal = 0)) + private Event fireCheckingPoseStack(IEventBus instance, Event event) { PoseStack stack = ((RenderLivingEvent)event).getPoseStack(); int size = ((PoseStackAccessor)stack).getPoseStack().size(); - if (instance.post(event)) { + instance.post(event); + if (((RenderLivingEvent.Pre)event).isCanceled()) { // Pop the stack if someone pushed it in the event while (((PoseStackAccessor)stack).getPoseStack().size() > size) { stack.popPose(); } - return true; - } else { - return false; } + return event; } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java similarity index 63% rename from forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java rename to neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java index 71180460..f38abc42 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java @@ -1,10 +1,10 @@ -package org.embeddedt.modernfix.forge.mixin.bugfix.entity_pose_stack; +package org.embeddedt.modernfix.neoforge.mixin.bugfix.entity_pose_stack; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.entity.player.PlayerRenderer; -import net.minecraftforge.client.event.RenderPlayerEvent; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.IEventBus; +import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.client.event.RenderPlayerEvent; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,18 +13,17 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(PlayerRenderer.class) @ClientOnlyMixin public class PlayerRendererMixin { - @Redirect(method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z", ordinal = 0)) - private boolean fireCheckingPoseStack(IEventBus instance, Event event) { + @Redirect(method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;", ordinal = 0)) + private Event fireCheckingPoseStack(IEventBus instance, Event event) { PoseStack stack = ((RenderPlayerEvent)event).getPoseStack(); int size = ((PoseStackAccessor)stack).getPoseStack().size(); - if (instance.post(event)) { + instance.post(event); + if (((RenderPlayerEvent.Pre)event).isCanceled()) { // Pop the stack if someone pushed it in the event while (((PoseStackAccessor)stack).getPoseStack().size() > size) { stack.popPose(); } - return true; - } else { - return false; } + return event; } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java similarity index 83% rename from forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java rename to neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java index a0a8ec30..ee018ed3 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java @@ -1,4 +1,4 @@ -package org.embeddedt.modernfix.forge.mixin.bugfix.entity_pose_stack; +package org.embeddedt.modernfix.neoforge.mixin.bugfix.entity_pose_stack; import com.mojang.blaze3d.vertex.PoseStack; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;