Merge 1.19.4 into 1.20

This commit is contained in:
embeddedt 2023-07-31 15:34:04 -04:00
commit 858325e40d
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
6 changed files with 144 additions and 3 deletions

View File

@ -0,0 +1,56 @@
package org.embeddedt.modernfix.blockstate;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.StateHolder;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
public class FerriteCorePostProcess {
private static final boolean willPostProcess;
private static final MethodHandle theTable, toKeyIndex;
static {
boolean success = true;
MethodHandle table = null, keyIndex = null;
try {
Class<?> fastMap = Class.forName("malte0811.ferritecore.fastmap.FastMap");
Field field = fastMap.getDeclaredField("toKeyIndex");
field.setAccessible(true);
keyIndex = MethodHandles.publicLookup().unreflectSetter(field);
field = StateHolder.class.getDeclaredField("ferritecore_globalTable");
field.setAccessible(true);
table = MethodHandles.publicLookup().unreflectGetter(field);
} catch(ReflectiveOperationException | RuntimeException e) {
e.printStackTrace();
success = false;
}
willPostProcess = success;
theTable = table;
toKeyIndex = keyIndex;
}
private static final Object2IntMap<?> EMPTY_MAP = Object2IntMaps.unmodifiable(new Object2IntArrayMap<>());
public static <O, S extends StateHolder<O, S>> void postProcess(StateDefinition<O, S> state) {
if(!willPostProcess)
return;
try {
if(state.getProperties().size() == 0) {
for(S holder : state.getPossibleStates()) {
// deduplicate Object2IntMap objects from FerriteCore
// will probably be fixed upstream at some point, but likely not for older versions
Object table = theTable.invoke(holder);
toKeyIndex.invoke(table, EMPTY_MAP);
}
}
} catch(Throwable e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,36 @@
package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import net.minecraft.core.MappedRegistry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(MappedRegistry.class)
public class MappedRegistryMixin {
/**
* Avoid copying the ID list to a slightly larger one every time an entry is added to the registry.
* The original behavior causes O(n) time complexity for registration.
*/
@Redirect(
method = "registerMapping(ILnet/minecraft/resources/ResourceKey;Ljava/lang/Object;Lcom/mojang/serialization/Lifecycle;Z)Lnet/minecraft/core/Holder;",
at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectList;size(I)V")
)
private void setSizeSmart(ObjectList<?> list, int size) {
if(list instanceof ObjectArrayList && size > list.size()) {
int requestedSize = size;
/* choose next power of two, or this value if it is a power of two */
int p2Size = Integer.highestOneBit(size);
if(p2Size != size)
size = p2Size << 1;
// grow backing array to power-of-two size, this will return instantly in most cases
((ObjectArrayList<?>)list).ensureCapacity(size);
// write null entries to fill size, to match the behavior of list.size(int)
while(list.size() < requestedSize)
list.add(null);
} else {
list.size(size);
}
}
}

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.forge.mixin.perf.fast_registry_validation;
package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.resources.ResourceKey;
@ -12,7 +12,7 @@ import java.util.Map;
@Mixin(ResourceKey.class)
public class ResourceKeyMixin<T> {
private static Map<ResourceLocation, Map<ResourceLocation, ResourceKey<?>>> INTERNING_MAP = new Object2ObjectOpenHashMap<>();
private static final Map<ResourceLocation, Map<ResourceLocation, ResourceKey<?>>> INTERNING_MAP = new Object2ObjectOpenHashMap<>();
@Inject(method = "create(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/resources/ResourceKey;", at = @At("HEAD"), cancellable = true)
private static <T> void createEfficient(ResourceLocation parent, ResourceLocation location, CallbackInfoReturnable<ResourceKey<T>> cir) {
synchronized (ResourceKey.class) {

View File

@ -6,11 +6,15 @@ import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.blockstate.FakeStateMap;
import org.embeddedt.modernfix.blockstate.FerriteCorePostProcess;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
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.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@ -27,4 +31,11 @@ public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
}
return new FakeStateMap<>(numStates);
}
@Inject(method = "<init>", at = @At("TAIL"))
private void postProcess(CallbackInfo ci) {
// keep in dev only until upstream FC releases
if(ModernFixPlatformHooks.INSTANCE.isDevEnv())
FerriteCorePostProcess.postProcess((StateDefinition<O, S>)(Object)this);
}
}

View File

@ -0,0 +1,21 @@
package org.embeddedt.modernfix.forge.load;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.forgespi.language.IModFileInfo;
import net.minecraftforge.forgespi.locating.IModFile;
import java.nio.file.Path;
import java.util.IdentityHashMap;
public class ModResourcePackPathFixer {
private static final IdentityHashMap<Path, IModFile> modFileByPath = new IdentityHashMap<>();
public static synchronized IModFile getModFileByRootPath(Path path) {
if(modFileByPath.size() == 0) {
for(IModFileInfo info : ModList.get().getModFiles()) {
modFileByPath.put(info.getFile().getFilePath(), info.getFile());
}
}
return modFileByPath.get(path);
}
}

View File

@ -3,7 +3,10 @@ package org.embeddedt.modernfix.forge.mixin.perf.resourcepacks;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.resource.PathPackResources;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.forge.load.ModResourcePackPathFixer;
import org.embeddedt.modernfix.resources.ICachingResourcePack;
import org.embeddedt.modernfix.resources.NewResourcePackAdapter;
import org.embeddedt.modernfix.resources.PackResourcesCacheEngine;
@ -36,12 +39,26 @@ public abstract class ForgePathPackResourcesMixin implements ICachingResourcePac
private PackResourcesCacheEngine cacheEngine;
private IModFile mfix$resolveFileOverride;
@Inject(method = "<init>", at = @At("TAIL"))
private void cacheResources(CallbackInfo ci) {
private void cacheResources(String packId, boolean isBuiltin, final Path source, CallbackInfo ci) {
// handle buggy mods instantiating at the root path, but only if they didn't override at all
// (otherwise they may have handled resolve() already)
if(((Object)this).getClass() == PathPackResources.class)
this.mfix$resolveFileOverride = ModResourcePackPathFixer.getModFileByRootPath(source);
if(this.mfix$resolveFileOverride != null)
ModernFix.LOGGER.warn("PathResourcePack base class instantiated with root path of mod file {}. This probably means a mod should be calling ResourcePackLoader.createPackForMod instead. Applying workaround.", mfix$resolveFileOverride.getFileName());
invalidateCache();
PackResourcesCacheEngine.track(this);
}
@Inject(method = "resolve", at = @At("HEAD"), cancellable = true, remap = false)
private void resolveViaModFile(String[] paths, CallbackInfoReturnable<Path> cir) {
if(this.mfix$resolveFileOverride != null)
cir.setReturnValue(this.mfix$resolveFileOverride.findResource(paths));
}
private PackResourcesCacheEngine generateResourceCache() {
synchronized (this) {
PackResourcesCacheEngine engine = this.cacheEngine;