From ad1e12a3bbc793c1378c0f1de88b45379de93920 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:07:56 -0500 Subject: [PATCH] Remove unfinished/obsolete registry & block optimizations These patches were unfinished, are known to be buggy, and won't make sense in modern versions of Minecraft, where many of the underlying issues have been addressed in other ways --- .../DirectObjectMixin.java | 24 - .../MappedRegistryMixin.java | 17 - .../StateDefinitionMixin.java | 26 - .../StateHolderMixin.java | 58 -- .../core/config/ModernFixEarlyConfig.java | 2 - .../registry/DirectStorageBiMap.java | 184 ------ .../registry/DirectStorageRegistryObject.java | 8 - .../modernfix/registry/RegistryStorage.java | 33 - .../modernfix/registry/TransformingBiMap.java | 224 ------- .../rewrite_registry/ForgeRegistryMixin.java | 65 -- .../ForgeRegistrySnapshotMixin.java | 35 - .../forge/registry/FastForgeRegistry.java | 602 ------------------ 12 files changed, 1278 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/DirectObjectMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateDefinitionMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_block_codecs/StateHolderMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageBiMap.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/registry/DirectStorageRegistryObject.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/registry/TransformingBiMap.java delete mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistryMixin.java delete mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistrySnapshotMixin.java delete mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/registry/FastForgeRegistry.java 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 c5e9c813..492176cf 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,17 +1,11 @@ package org.embeddedt.modernfix.common.mixin.perf.compact_mojang_registries; -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableSet; import com.mojang.serialization.Lifecycle; import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import org.embeddedt.modernfix.annotation.IgnoreOutsideDev; -import org.embeddedt.modernfix.core.ModernFixMixinPlugin; -import org.embeddedt.modernfix.registry.DirectStorageRegistryObject; import org.embeddedt.modernfix.registry.LifecycleMap; -import org.embeddedt.modernfix.registry.RegistryStorage; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -29,12 +23,6 @@ public abstract class MappedRegistryMixin extends Registry { @Final @Mutable private Map lifecycles; - @Shadow @Final @Mutable - private BiMap storage; - @Shadow @Final @Mutable - private BiMap, T> keyStorage; - - private static final ImmutableSet MFIX$NEW_STORAGE_KEYS = ImmutableSet.of(new ResourceLocation("block"), new ResourceLocation("item")); protected MappedRegistryMixin(ResourceKey> resourceKey, Lifecycle lifecycle) { super(resourceKey, lifecycle); @@ -43,10 +31,5 @@ public abstract class MappedRegistryMixin extends Registry { @Inject(method = "", at = @At("RETURN")) private void replaceStorage(CallbackInfo ci) { this.lifecycles = 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/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 6af610ef..65696139 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 @@ -168,9 +168,7 @@ public class ModernFixEarlyConfig { .put("mixin.perf.dynamic_resources", false) .putConditionally(() -> !isFabric, "mixin.perf.async_jei", 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) .put("mixin.bugfix.packet_leak", false) .put("mixin.perf.deduplicate_location", false) 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/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistryMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistryMixin.java deleted file mode 100644 index 1e955230..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistryMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.embeddedt.modernfix.forge.mixin.perf.rewrite_registry; - -import com.google.common.collect.BiMap; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.registries.ForgeRegistry; -import net.minecraftforge.registries.IForgeRegistryEntry; -import org.embeddedt.modernfix.annotation.IgnoreOutsideDev; -import org.embeddedt.modernfix.forge.registry.FastForgeRegistry; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -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.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(value = ForgeRegistry.class, remap = false) -@IgnoreOutsideDev -public class ForgeRegistryMixin> { - @Shadow - @Final - @Mutable - private BiMap ids; - - @Shadow @Final @Mutable private BiMap, V> keys; - - @Shadow @Final private ResourceKey> key; - - @Shadow @Final @Mutable private BiMap names; - - @Shadow @Final @Mutable private BiMap owners; - - private FastForgeRegistry fastRegistry; - - /** - * The following code replaces the Forge HashBiMaps with a more efficient data structure based around - * an array list for IDs and one HashMap going from value -> information. - */ - @Inject(method = "", at = @At("RETURN")) - private void replaceBackingMaps(CallbackInfo ci) { - this.fastRegistry = new FastForgeRegistry<>(this.key); - this.ids = fastRegistry.getIds(); - this.keys = fastRegistry.getKeys(); - this.names = fastRegistry.getNames(); - this.owners = fastRegistry.getOwners(); - } - - @Inject(method = "freeze", at = @At("RETURN")) - private void optimizeRegistry(CallbackInfo ci) { - this.fastRegistry.optimize(); - } - - @Redirect(method = "sync", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;clear()V")) - private void clearBiMap(BiMap map) { - if(map == this.owners) { - this.fastRegistry.clear(); - } else if(map == this.keys || map == this.names || map == this.ids) { - // do nothing, the registry is faster at clearing everything at once - } else - map.clear(); - } -} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistrySnapshotMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistrySnapshotMixin.java deleted file mode 100644 index b8dbf343..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/rewrite_registry/ForgeRegistrySnapshotMixin.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.embeddedt.modernfix.forge.mixin.perf.rewrite_registry; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.registries.ForgeRegistry; -import org.embeddedt.modernfix.annotation.IgnoreOutsideDev; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -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.util.Map; -import java.util.Set; - -@Mixin(ForgeRegistry.Snapshot.class) -@IgnoreOutsideDev -public class ForgeRegistrySnapshotMixin { - @Shadow(remap = false) @Final @Mutable public Map ids; - - @Shadow(remap = false) @Final @Mutable public Set dummied; - - /** - * The only good reason to use tree maps here is to keep the order the same. But we are tracking IDs - * anyway so order shouldn't matter. We replace the maps that will be most used. - */ - @Inject(method = "", at = @At("RETURN")) - private void replaceSnapshotMaps(CallbackInfo ci) { - this.ids = new Object2ObjectOpenHashMap<>(); - this.dummied = new ObjectOpenHashSet<>(); - } -} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/registry/FastForgeRegistry.java b/forge/src/main/java/org/embeddedt/modernfix/forge/registry/FastForgeRegistry.java deleted file mode 100644 index 9d4c2f5c..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/registry/FastForgeRegistry.java +++ /dev/null @@ -1,602 +0,0 @@ -package org.embeddedt.modernfix.forge.registry; - -import com.google.common.collect.BiMap; -import com.google.common.collect.Iterators; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.registries.IForgeRegistryEntry; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -public class FastForgeRegistry> { - private final BiMap ids; - private final DataFieldBiMap names; - private final DataFieldBiMap> keys; - private final DataFieldBiMap owners; - private final ResourceKey> registryKey; - - private final ObjectArrayList valuesById; - private final Object2ObjectOpenHashMap infoByValue; - - private void storeId(V value, int id) { - RegistryValueData pair = infoByValue.computeIfAbsent(value, k -> new RegistryValueData()); - pair.id = id; - } - - private void updateInfoPairAndClearIfNull(V v, Consumer consumer) { - infoByValue.compute(v, (oldValue, oldPair) -> { - if(oldPair == null) - oldPair = new RegistryValueData(); - consumer.accept(oldPair); - if(oldPair.isEmpty()) - return null; - else - return oldPair; - }); - } - - private void ensureArrayCanFitId(int id) { - int desiredSize = id + 1; - while(valuesById.size() < desiredSize) { - valuesById.add(null); - } - } - - public void clear() { - this.infoByValue.clear(); - for(int i = 0; i < this.valuesById.size(); i++) { - this.valuesById.set(i, null); - } - this.names.clearUnsafe(); - this.keys.clearUnsafe(); - this.owners.clearUnsafe(); - } - - public FastForgeRegistry(ResourceKey> registryKey) { - this.registryKey = registryKey; - this.valuesById = new ObjectArrayList<>(); - this.infoByValue = new Object2ObjectOpenHashMap<>(); - this.keys = new DataFieldBiMap<>(p -> (ResourceKey) p.key, (p, k) -> p.key = k); - this.owners = new DataFieldBiMap<>(p -> p.overrideOwner, (p, k) -> p.overrideOwner = k); - this.names = new DataFieldBiMap<>(p -> p.location, (p, l) -> p.location = l); - // IDs require a specialized implementation, as we back the K->V direction with an array - this.ids = new BiMap() { - @Nullable - @Override - public V put(@Nullable Integer key, @Nullable V value) { - RegistryValueData data = infoByValue.get(value); - int unboxedKey = key; - if(data != null && data.id != -1 && data.id != unboxedKey) - throw new IllegalArgumentException("Existing mapping for ID " + data.id + " value " + value + " when new ID " + unboxedKey + " was requested"); - ensureArrayCanFitId(unboxedKey); - V oldValue = valuesById.set(unboxedKey, value); - storeId(value, unboxedKey); - return oldValue; - } - - @Nullable - @Override - public V forcePut(@Nullable Integer key, @Nullable V value) { - ensureArrayCanFitId(key); - V oldValue = valuesById.set(key, value); - if(oldValue != null) { - updateInfoPairAndClearIfNull(oldValue, pair -> pair.id = -1); - } - storeId(value, key); - return oldValue; - } - - @Override - public void putAll(Map map) { - map.forEach(this::put); - } - - @Override - public Set values() { - return Collections.unmodifiableSet(infoByValue.keySet()); - } - - @Override - public BiMap inverse() { - return new BiMap() { - @Nullable - @Override - public Integer put(@Nullable V key, @Nullable Integer value) { - throw new UnsupportedOperationException(); - } - - @Nullable - @Override - public Integer forcePut(@Nullable V key, @Nullable Integer value) { - throw new UnsupportedOperationException(); - } - - @Override - public void putAll(Map map) { - throw new UnsupportedOperationException(); - } - - @Override - public Set values() { - throw new UnsupportedOperationException(); - } - - @Override - public BiMap inverse() { - throw new UnsupportedOperationException(); - } - - @Override - public int size() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isEmpty() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsKey(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public Integer get(Object key) { - RegistryValueData pair = infoByValue.get(key); - if(pair == null) - return null; - return pair.id == -1 ? null : pair.id; - } - - @Override - public Integer remove(Object key) { - RegistryValueData pair = infoByValue.get(key); - if(pair == null) - return null; - int id = pair.id; - if(id != -1) - valuesById.set(id, null); - updateInfoPairAndClearIfNull((V)key, p -> p.id = -1); - return id == -1 ? null : id; - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set keySet() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public int size() { - return infoByValue.size(); - } - - @Override - public boolean isEmpty() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsKey(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public V get(Object key) { - int id = (Integer)key; - if(id < 0 || id >= valuesById.size()) - return null; - else - return valuesById.get(id); - } - - @Override - public V remove(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - valuesById.clear(); - infoByValue.values().removeIf(pair -> { - pair.id = -1; - return pair.isEmpty(); - }); - } - - @NotNull - @Override - public Set keySet() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } - - @Override - public void forEach(BiConsumer action) { - for(int i = 0 ; i < valuesById.size(); i++) { - V val = valuesById.get(i); - if(val != null) - action.accept(i, val); - } - } - }; - } - - public void optimize() { - this.keys.optimize(); - this.owners.optimize(); - this.names.optimize(); - this.infoByValue.trim(); - } - - public BiMap getIds() { - return ids; - } - - public BiMap, V> getKeys() { - return keys; - } - - public BiMap getNames() { - return names; - } - - public DataFieldBiMap getOwners() { - return owners; - } - - /** - * Custom BiMap implementation that uses one internal hash map for the K->V direction, and the shared global - * information hash map for the V->K direction. - */ - class DataFieldBiMap implements BiMap { - public final Object2ObjectOpenHashMap valuesByKey = new Object2ObjectOpenHashMap<>(); - private final Function getter; - private final BiConsumer setter; - - public DataFieldBiMap(Function getter, BiConsumer setter) { - this.getter = getter; - this.setter = setter; - } - - public void optimize() { - this.valuesByKey.trim(); - } - - public void clearUnsafe() { - this.valuesByKey.clear(); - } - - private V forcePut(@Nullable K key, @Nullable V value, boolean throwOnExisting) { - if(throwOnExisting) { - RegistryValueData dataForValue = infoByValue.get(value); - // null check could be wrong if null is a valid value but doesn't matter in Forge's use - if(dataForValue != null && getter.apply(dataForValue) != null && !Objects.equals(getter.apply(dataForValue), key)) { - throw new IllegalArgumentException("Existing mapping for key " + key + " value " + value); - } - } - V oldValue = valuesByKey.put(key, value); - if(oldValue != null) { - updateInfoPairAndClearIfNull(oldValue, p -> setter.accept(p, null)); - } - updateInfoPairAndClearIfNull(value, p -> setter.accept(p, key)); - return oldValue; - } - - @Nullable - @Override - public V put(@Nullable K key, @Nullable V value) { - return forcePut(key, value, true); - } - - @Nullable - @Override - public V forcePut(@Nullable K key, @Nullable V value) { - return forcePut(key, value, false); - } - - @Override - public void putAll(Map map) { - map.forEach(this::put); - } - - @Override - public Set values() { - return Collections.unmodifiableSet(infoByValue.keySet()); - } - - private DataFieldBiMapInverse inverse = null; - - @Override - public BiMap inverse() { - if(inverse == null) - inverse = new DataFieldBiMapInverse<>(this); - return inverse; - } - - @Override - public int size() { - return valuesByKey.size(); - } - - @Override - public boolean isEmpty() { - return valuesByKey.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return valuesByKey.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return infoByValue.containsKey(value); - } - - @Override - public V get(Object key) { - return valuesByKey.get(key); - } - - @Override - public V remove(Object key) { - V value = get(key); - if(value == null) - return null; - inverse().remove(value); - return value; - } - - @Override - public void clear() { - valuesByKey.values().forEach(v -> updateInfoPairAndClearIfNull(v, p -> p.key = null)); - valuesByKey.clear(); - } - - @NotNull - @Override - public Set keySet() { - return Collections.unmodifiableSet(valuesByKey.keySet()); - } - - @NotNull - @Override - public Set> entrySet() { - return Collections.unmodifiableSet(valuesByKey.entrySet()); - } - - - } - - class DataFieldBiMapInverse implements BiMap { - private final DataFieldBiMap forward; - - public DataFieldBiMapInverse(DataFieldBiMap forward) { - this.forward = forward; - } - - @Nullable - @Override - public K put(@Nullable V key, @Nullable K value) { - throw new UnsupportedOperationException(); - } - - @Nullable - @Override - public K forcePut(@Nullable V key, @Nullable K value) { - throw new UnsupportedOperationException(); - } - - @Override - public void putAll(Map map) { - throw new UnsupportedOperationException(); - } - - @Override - public Set values() { - throw new UnsupportedOperationException(); - } - - @Override - public BiMap inverse() { - return forward; - } - - @Override - public int size() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isEmpty() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsKey(Object key) { - return infoByValue.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return forward.valuesByKey.containsKey(value); - } - - @Override - public K get(Object key) { - RegistryValueData pair = infoByValue.get(key); - if(pair == null) - return null; - else - return forward.getter.apply(pair); - } - - @Override - public K remove(Object key) { - RegistryValueData pair = infoByValue.get(key); - if(pair == null) - return null; - else { - K rk = forward.getter.apply(pair); - forward.valuesByKey.remove(rk); - updateInfoPairAndClearIfNull((V)key, p -> forward.setter.accept(p, null)); - return rk; - } - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set keySet() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } - } - - class FastForgeRegistryLocationSet implements Set { - private final Set> backingSet; - - public FastForgeRegistryLocationSet(Set> backingSet) { - this.backingSet = backingSet; - } - - @Override - public int size() { - return backingSet.size(); - } - - @Override - public boolean isEmpty() { - return backingSet.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return backingSet.contains(ResourceKey.create(FastForgeRegistry.this.registryKey, (ResourceLocation)o)); - } - - @NotNull - @Override - public Iterator iterator() { - return Iterators.transform(backingSet.iterator(), ResourceKey::location); - } - - @NotNull - @Override - public Object[] toArray() { - Object[] keyArray = backingSet.toArray(); - for(int i = 0; i < keyArray.length; i++) { - keyArray[i] = ((ResourceKey)keyArray[i]).location(); - } - return keyArray; - } - - @NotNull - @Override - public T[] toArray(@NotNull T[] a) { - Object[] keyArray = backingSet.toArray(); - T[] finalArray = Arrays.copyOf(a, keyArray.length); - for(int i = 0; i < keyArray.length; i++) { - finalArray[i] = (T)((ResourceKey)keyArray[i]).location(); - } - return finalArray; - } - - @Override - public boolean add(ResourceLocation resourceLocation) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsAll(@NotNull Collection c) { - for(Object o : c) { - if(!contains(o)) - return false; - } - return true; - } - - @Override - public boolean addAll(@NotNull Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(@NotNull Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(@NotNull Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - } - - static class RegistryValueData { - public ResourceKey key; - public ResourceLocation location; - public int id = -1; - public Object overrideOwner; - - boolean isEmpty() { - return key == null && location == null && id == -1 && overrideOwner == null; - } - } -}