Compiles, not yet running
This commit is contained in:
parent
87ee1017ae
commit
69a9aa76da
|
|
@ -12,7 +12,7 @@ dependencies {
|
|||
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
||||
// Do NOT use other classes from fabric loader
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
implementation(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-common:${rootProject.mixinextras_version}"))
|
||||
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}"))
|
||||
|
||||
modCompileOnly("dev.latvian.mods:kubejs:${kubejs_version}") {
|
||||
transitive = false
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
package org.embeddedt.modernfix.util;
|
||||
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
|
||||
public enum BakeReason {
|
||||
FREEZE,
|
||||
REMOTE_SNAPSHOT_INJECT,
|
||||
LOCAL_SNAPSHOT_INJECT,
|
||||
REVERT,
|
||||
UNKNOWN;
|
||||
private static BakeReason currentBakeReason = null;
|
||||
private static boolean bakeReasonWarned = false;
|
||||
|
||||
public static BakeReason getCurrentBakeReason() {
|
||||
if(currentBakeReason == null && !bakeReasonWarned) {
|
||||
ModernFix.LOGGER.warn("No bake reason found, mixin probably not applied correctly", new IllegalStateException());
|
||||
bakeReasonWarned = false;
|
||||
}
|
||||
return currentBakeReason;
|
||||
}
|
||||
|
||||
public static void setCurrentBakeReason(BakeReason reason) {
|
||||
currentBakeReason = reason;
|
||||
}
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ repositories {
|
|||
dependencies {
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
testImplementation "net.fabricmc:fabric-loader-junit:${rootProject.fabric_loader_version}"
|
||||
include(implementation(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-fabric:${rootProject.mixinextras_version}")))
|
||||
include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${rootProject.mixinextras_version}")))
|
||||
|
||||
modCompileOnly(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
|
||||
modCompileOnly(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
org.gradle.jvmargs=-Xmx2G
|
||||
|
||||
junit_version=5.10.0-M1
|
||||
mixinextras_version=0.2.0-beta.9
|
||||
mixinextras_version=0.3.1
|
||||
|
||||
mod_id=modernfix
|
||||
minecraft_version=1.20.2
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
neoForge "net.neoforged:neoforge:${rootProject.forge_version}"
|
||||
implementation(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-common:${rootProject.mixinextras_version}"))
|
||||
implementation(include("com.github.llamalad7.mixinextras:mixinextras-forge:${rootProject.mixinextras_version}"))
|
||||
//implementation(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-common:${rootProject.mixinextras_version}"))
|
||||
//implementation(include("com.github.llamalad7.mixinextras:mixinextras-forge:${rootProject.mixinextras_version}"))
|
||||
// Remove the next line if you don't want to depend on the API
|
||||
// modApi "me.shedaniel:architectury-forge:${rootProject.architectury_version}"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package org.embeddedt.modernfix.forge;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.neoforged.neoforge.common.ModConfigSpec;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -10,10 +10,10 @@ import java.util.function.Predicate;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class ModernFixConfig {
|
||||
private static final ForgeConfigSpec.Builder COMMON_BUILDER = new ForgeConfigSpec.Builder();
|
||||
public static ForgeConfigSpec COMMON_CONFIG;
|
||||
private static final ModConfigSpec.Builder COMMON_BUILDER = new ModConfigSpec.Builder();
|
||||
public static ModConfigSpec COMMON_CONFIG;
|
||||
|
||||
public static ForgeConfigSpec.ConfigValue<List<? extends String>> BLACKLIST_ASYNC_JEI_PLUGINS;
|
||||
public static ModConfigSpec.ConfigValue<List<? extends String>> BLACKLIST_ASYNC_JEI_PLUGINS;
|
||||
|
||||
private static Set<ResourceLocation> jeiPluginBlacklist;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.classloading;
|
||||
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModValidator;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||
import org.embeddedt.modernfix.util.CommonModUtil;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ATInjector {
|
||||
public static void injectModATs() {
|
||||
CommonModUtil.runWithoutCrash(() -> {
|
||||
ModValidator validator = ObfuscationReflectionHelper.getPrivateValue(FMLLoader.class, null, "modValidator");
|
||||
List<ModFile> modFiles = ObfuscationReflectionHelper.getPrivateValue(ModValidator.class, validator, "candidateMods");
|
||||
List<Pair<ModFile, Path>> list = modFiles.stream()
|
||||
.filter(file -> file.getAccessTransformer().isPresent())
|
||||
.map(file -> Pair.of(file, file.getAccessTransformer().get()))
|
||||
.collect(Collectors.toList());
|
||||
if(list.size() > 0) {
|
||||
ModernFixMixinPlugin.instance.logger.warn("Applying ATs from {} mods despite being in errored state, this might cause a crash!", list.size());
|
||||
for(var pair : list) {
|
||||
try {
|
||||
FMLLoader.addAccessTransformer(pair.getRight(), pair.getLeft());
|
||||
} catch(RuntimeException e) {
|
||||
ModernFixMixinPlugin.instance.logger.error("Exception occured applying AT from {}", pair.getLeft().getFileName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "applying mod ATs in errored state");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.classloading;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.minecraftforge.accesstransformer.AccessTransformer;
|
||||
import net.minecraftforge.accesstransformer.AccessTransformerEngine;
|
||||
import net.minecraftforge.accesstransformer.INameHandler;
|
||||
import net.minecraftforge.accesstransformer.Target;
|
||||
import net.minecraftforge.accesstransformer.parser.AccessTransformerList;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class FastAccessTransformerList extends AccessTransformerList {
|
||||
private FastATMap accessTransformerMap;
|
||||
|
||||
public static void attemptReplace() {
|
||||
AccessTransformerList masterList;
|
||||
FastAccessTransformerList myList = new FastAccessTransformerList();
|
||||
try {
|
||||
Field master = AccessTransformerEngine.class.getDeclaredField("masterList");
|
||||
master.setAccessible(true);
|
||||
masterList = (AccessTransformerList)master.get(AccessTransformerEngine.INSTANCE);
|
||||
Field transfomersMap = AccessTransformerList.class.getDeclaredField("accessTransformers");
|
||||
transfomersMap.setAccessible(true);
|
||||
Map<Target<?>, AccessTransformer> map = (Map<Target<?>, AccessTransformer>)transfomersMap.get(masterList);
|
||||
INameHandler nameHandler = ObfuscationReflectionHelper.getPrivateValue(AccessTransformerList.class, masterList, "nameHandler");
|
||||
myList.setNameHandler(nameHandler);
|
||||
myList.accessTransformerMap = new FastATMap(map);
|
||||
ObfuscationReflectionHelper.setPrivateValue(AccessTransformerList.class, myList, myList.accessTransformerMap, "accessTransformers");
|
||||
master.set(AccessTransformerEngine.INSTANCE, myList);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsClassTarget(Type type) {
|
||||
return this.accessTransformerMap.containsType(type);
|
||||
}
|
||||
|
||||
private static class FastATMap implements Map<Target<?>, AccessTransformer> {
|
||||
private final Map<Target<?>, AccessTransformer> delegate;
|
||||
private final Set<Type> allContainedTypes;
|
||||
|
||||
public FastATMap(Map<Target<?>, AccessTransformer> delegate) {
|
||||
this.delegate = new HashMap<>();
|
||||
this.allContainedTypes = new ObjectOpenHashSet<>();
|
||||
this.putAll(delegate);
|
||||
}
|
||||
|
||||
@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(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object o) {
|
||||
return this.delegate.containsValue(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessTransformer get(Object o) {
|
||||
return this.delegate.get(o);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AccessTransformer put(Target<?> target, AccessTransformer accessTransformer) {
|
||||
this.allContainedTypes.add(target.getASMType());
|
||||
return this.delegate.put(target, accessTransformer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessTransformer remove(Object o) {
|
||||
if(o instanceof Target) {
|
||||
this.allContainedTypes.remove(((Target<?>)o).getASMType());
|
||||
}
|
||||
return this.delegate.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NotNull Map<? extends Target<?>, ? extends AccessTransformer> map) {
|
||||
for(Target<?> key : map.keySet()) {
|
||||
this.allContainedTypes.add(key.getASMType());
|
||||
}
|
||||
this.delegate.putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.allContainedTypes.clear();
|
||||
this.delegate.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Target<?>> keySet() {
|
||||
return this.delegate.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<AccessTransformer> values() {
|
||||
return this.delegate.values();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<Target<?>, AccessTransformer>> entrySet() {
|
||||
return this.delegate.entrySet();
|
||||
}
|
||||
|
||||
public boolean containsType(Type type) {
|
||||
return this.allContainedTypes.contains(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ package org.embeddedt.modernfix.forge.classloading;
|
|||
|
||||
import com.google.common.collect.Interner;
|
||||
import com.google.common.collect.Interners;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforgespi.language.ModFileScanData;
|
||||
import net.neoforged.neoforgespi.locating.IModFile;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package org.embeddedt.modernfix.forge.config;
|
||||
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.config.IConfigEvent;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.fml.config.IConfigEvent;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package org.embeddedt.modernfix.forge.config;
|
|||
|
||||
import com.electronwill.nightconfig.core.file.FileWatcher;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||
import org.embeddedt.modernfix.util.CommonModUtil;
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@ import net.minecraft.network.chat.Component;
|
|||
import net.minecraft.server.packs.PackResources;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.resources.MultiPackResourceManager;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.data.event.GatherDataEvent;
|
||||
import net.minecraftforge.data.loading.DatagenModLoader;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.ModLoader;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.neoforge.client.event.ScreenEvent;
|
||||
import net.neoforged.neoforge.common.data.ExistingFileHelper;
|
||||
import net.neoforged.neoforge.data.event.GatherDataEvent;
|
||||
import net.neoforged.neoforge.data.loading.DatagenModLoader;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ import com.google.common.graph.GraphBuilder;
|
|||
import com.google.common.graph.MutableGraph;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforgespi.language.IModInfo;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||
import org.embeddedt.modernfix.util.ForwardingInclDefaultsMap;
|
||||
|
|
@ -35,12 +35,12 @@ public class ModelBakeEventHelper {
|
|||
public ModelBakeEventHelper(Map<ResourceLocation, BakedModel> modelRegistry) {
|
||||
this.modelRegistry = modelRegistry;
|
||||
this.topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
|
||||
for(Block block : ForgeRegistries.BLOCKS) {
|
||||
for(Block block : BuiltInRegistries.BLOCK) {
|
||||
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
|
||||
topLevelModelLocations.add(ModelLocationCache.get(state));
|
||||
}
|
||||
}
|
||||
for(Item item : ForgeRegistries.ITEMS) {
|
||||
for(Item item : BuiltInRegistries.ITEM) {
|
||||
topLevelModelLocations.add(ModelLocationCache.get(item));
|
||||
}
|
||||
this.dependencyGraph = GraphBuilder.undirected().build();
|
||||
|
|
|
|||
|
|
@ -6,24 +6,24 @@ import net.minecraft.client.KeyMapping;
|
|||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.DebugScreenOverlay;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraftforge.client.ConfigScreenHandler;
|
||||
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.minecraftforge.client.event.RecipesUpdatedEvent;
|
||||
import net.minecraftforge.client.event.RegisterClientCommandsEvent;
|
||||
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
|
||||
import net.minecraftforge.client.settings.KeyConflictContext;
|
||||
import net.minecraftforge.event.TagsUpdatedEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.level.LevelEvent;
|
||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.ModLoadingStage;
|
||||
import net.minecraftforge.fml.ModLoadingWarning;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.neoforged.bus.api.EventPriority;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.ModLoader;
|
||||
import net.neoforged.fml.ModLoadingContext;
|
||||
import net.neoforged.fml.ModLoadingStage;
|
||||
import net.neoforged.fml.ModLoadingWarning;
|
||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||
import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.neoforged.neoforge.client.event.RecipesUpdatedEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
||||
import net.neoforged.neoforge.client.settings.KeyConflictContext;
|
||||
import net.neoforged.neoforge.event.TagsUpdatedEvent;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.neoforge.event.level.LevelEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStartedEvent;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
import org.embeddedt.modernfix.forge.config.NightConfigFixer;
|
||||
import org.embeddedt.modernfix.screen.ModernFixConfigScreen;
|
||||
|
|
|
|||
|
|
@ -3,25 +3,25 @@ package org.embeddedt.modernfix.forge.init;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.OnDatapackSyncEvent;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppedEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.*;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegisterEvent;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.EventPriority;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.*;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.config.ModConfig;
|
||||
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStartedEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStoppedEvent;
|
||||
import net.neoforged.neoforge.registries.RegisterEvent;
|
||||
import net.neoforged.neoforge.server.ServerLifecycleHooks;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||
|
|
@ -32,7 +32,6 @@ import org.embeddedt.modernfix.forge.classloading.ModFileScanDataDeduplicator;
|
|||
import org.embeddedt.modernfix.forge.config.ConfigFixer;
|
||||
import org.embeddedt.modernfix.forge.config.NightConfigFixer;
|
||||
import org.embeddedt.modernfix.forge.packet.PacketHandler;
|
||||
import org.embeddedt.modernfix.forge.registry.ObjectHolderClearer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -44,10 +43,10 @@ public class ModernFixForge {
|
|||
public ModernFixForge() {
|
||||
commonMod = new ModernFix();
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
NeoForge.EVENT_BUS.register(this);
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::commonSetup);
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::registerItems);
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> MinecraftForge.EVENT_BUS.register(new ModernFixClientForge()));
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> NeoForge.EVENT_BUS.register(new ModernFixClientForge()));
|
||||
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> IExtensionPoint.DisplayTest.IGNORESERVERONLY, (a, b) -> true));
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModernFixConfig.COMMON_CONFIG);
|
||||
PacketHandler.register();
|
||||
|
|
@ -79,7 +78,7 @@ public class ModernFixForge {
|
|||
|
||||
private void registerItems(RegisterEvent event) {
|
||||
if(Boolean.getBoolean("modernfix.largeRegistryTest")) {
|
||||
event.register(ForgeRegistries.Keys.ITEMS, helper -> {
|
||||
event.register(Registries.ITEM, helper -> {
|
||||
Item.Properties props = new Item.Properties();
|
||||
for(int i = 0; i < 1000000; i++) {
|
||||
helper.register(new ResourceLocation("modernfix", "item_" + i), new Item(props));
|
||||
|
|
@ -108,7 +107,6 @@ public class ModernFixForge {
|
|||
ModLoader.get().addWarning(new ModLoadingWarning(ModLoadingContext.get().getActiveContainer().getModInfo(), ModLoadingStage.COMMON_SETUP, "modernfix.perf_mod_warning"));
|
||||
});
|
||||
}
|
||||
ObjectHolderClearer.clearThrowables();
|
||||
}
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onServerDead(ServerStoppedEvent event) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package org.embeddedt.modernfix.forge.load;
|
||||
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforgespi.language.IModFileInfo;
|
||||
import net.neoforged.neoforgespi.locating.IModFile;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.IdentityHashMap;
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.load;
|
||||
|
||||
import net.minecraftforge.fml.ModWorkManager;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
public class ModWorkManagerQueue extends ConcurrentLinkedDeque<Runnable> {
|
||||
private static final long PARK_TIME = TimeUnit.MILLISECONDS.toNanos(25);
|
||||
|
||||
private static final Runnable DUMMY_TASK = () -> {};
|
||||
|
||||
private boolean shouldReturnDummyTask = false;
|
||||
|
||||
/**
|
||||
* Sleep for a bit if there are no tasks.
|
||||
*/
|
||||
@Override
|
||||
public Runnable pollFirst() {
|
||||
Runnable r = super.pollFirst();
|
||||
if(r == null) {
|
||||
LockSupport.parkNanos(PARK_TIME);
|
||||
boolean isReturning = shouldReturnDummyTask;
|
||||
shouldReturnDummyTask = !shouldReturnDummyTask;
|
||||
/*
|
||||
* We need to kick FML to redraw the loading screen periodically,
|
||||
* but also allow actually exiting the executor loop, so that
|
||||
* loading can complete if async work is done.
|
||||
*
|
||||
* This is accomplished by alternating between returning a dummy
|
||||
* task and nothing.
|
||||
*/
|
||||
return isReturning ? DUMMY_TASK : null;
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static void replace() {
|
||||
try {
|
||||
Class<?> syncExecutorClass = Class.forName("net.minecraftforge.fml.ModWorkManager$SyncExecutor");
|
||||
ConcurrentLinkedDeque<Runnable> taskQueue = (ConcurrentLinkedDeque<Runnable>) ObfuscationReflectionHelper.getPrivateValue((Class)syncExecutorClass, (Object)ModWorkManager.syncExecutor(), "tasks");
|
||||
ModWorkManagerQueue q = new ModWorkManagerQueue();
|
||||
Runnable task;
|
||||
do {
|
||||
task = taskQueue.pollFirst();
|
||||
if(task != null)
|
||||
q.push(task);
|
||||
} while(task != null);
|
||||
ObfuscationReflectionHelper.setPrivateValue((Class)syncExecutorClass, (Object)ModWorkManager.syncExecutor(), q, "tasks");
|
||||
} catch(ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
|||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import net.minecraft.world.level.ChunkPos;
|
|||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.core;
|
||||
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraftforge.network.NetworkInitialization;
|
||||
import org.embeddedt.modernfix.forge.load.ModWorkManagerQueue;
|
||||
import net.neoforged.neoforge.network.NetworkConstants;
|
||||
import org.embeddedt.modernfix.util.TimeFormatter;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
|
|
@ -24,13 +23,12 @@ public class BootstrapMixin {
|
|||
private static void doModernFixBootstrap(CallbackInfo ci) {
|
||||
if(!isBootstrapped) {
|
||||
LOGGER.info("ModernFix reached bootstrap stage ({} after launch)", TimeFormatter.formatNanos(ManagementFactory.getRuntimeMXBean().getUptime() * 1000L * 1000L));
|
||||
ModWorkManagerQueue.replace();
|
||||
}
|
||||
}
|
||||
|
||||
/* for https://github.com/MinecraftForge/MinecraftForge/issues/9505 */
|
||||
@Inject(method = "bootStrap", at = @At("RETURN"))
|
||||
private static void doClassloadHack(CallbackInfo ci) {
|
||||
NetworkInitialization.init();
|
||||
NetworkConstants.init();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.core;
|
||||
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.network.ConnectionType;
|
||||
import net.minecraftforge.network.NetworkContext;
|
||||
import net.neoforged.neoforge.network.NetworkHooks;
|
||||
import org.embeddedt.modernfix.forge.packet.NetworkUtils;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ForgeHooks.class)
|
||||
@Mixin(NetworkHooks.class)
|
||||
public abstract class NetworkHooksMixin {
|
||||
@Inject(method = "handleClientConfigurationComplete", at = @At("RETURN"), remap = false)
|
||||
@Inject(method = "handleClientLoginSuccess", at = @At("RETURN"), remap = false)
|
||||
private static void setVanillaGlobalFlag(Connection manager, CallbackInfo ci) {
|
||||
NetworkUtils.isCurrentlyVanilla = NetworkContext.get(manager).getType() == ConnectionType.VANILLA;
|
||||
NetworkUtils.isCurrentlyVanilla = NetworkHooks.isVanillaConnection(manager);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.devenv;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(GameData.class)
|
||||
public class GameDataMixin {
|
||||
|
||||
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/registries/ForgeRegistry;dump(Lnet/minecraft/resources/ResourceLocation;)V", remap = false))
|
||||
private static void noDump(ForgeRegistry<?> reg, ResourceLocation id) {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.feature.branding;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraftforge.internal.BrandingControl;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforge.internal.BrandingControl;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
|
@ -14,7 +14,7 @@ import java.util.Optional;
|
|||
|
||||
@Mixin(value = BrandingControl.class, remap = false, priority = 1100)
|
||||
public class BrandingControlMixin {
|
||||
@Inject(method = "computeBranding", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModList;get()Lnet/minecraftforge/fml/ModList;"), locals = LocalCapture.CAPTURE_FAILHARD, require = 0)
|
||||
@Inject(method = "computeBranding", at = @At(value = "INVOKE", target = "Lnet/neoforged/fml/ModList;get()Lnet/neoforged/fml/ModList;"), locals = LocalCapture.CAPTURE_FAILHARD, require = 0)
|
||||
private static void addModernFixBranding(CallbackInfo ci, ImmutableList.Builder<String> builder) {
|
||||
Optional<? extends ModContainer> mfContainer = ModList.get().getModContainerById("modernfix");
|
||||
if(mfContainer.isPresent())
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.feature.registry_event_progress;
|
||||
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.StartupMessageManager;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import net.minecraftforge.registries.RegisterEvent;
|
||||
import net.neoforged.bus.api.Event;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.fml.ModLoader;
|
||||
import net.neoforged.fml.ModLoadingContext;
|
||||
import net.neoforged.fml.StartupMessageManager;
|
||||
import net.neoforged.fml.event.IModBusEvent;
|
||||
import net.neoforged.neoforge.registries.GameData;
|
||||
import net.neoforged.neoforge.registries.RegisterEvent;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.forge.util.AsyncLoadingScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
@ -33,7 +33,7 @@ public class GameDataMixin {
|
|||
mfix$asyncScreen = null;
|
||||
}
|
||||
|
||||
@Redirect(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEventWrapContainerInModOrder(Lnet/minecraftforge/eventbus/api/Event;)V"))
|
||||
@Redirect(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Lnet/neoforged/fml/ModLoader;postEventWrapContainerInModOrder(Lnet/neoforged/bus/api/Event;)V"))
|
||||
private static <T extends Event & IModBusEvent> void swapThreadAndPost(ModLoader loader, T event) {
|
||||
RegisterEvent registryEvent = (RegisterEvent)event;
|
||||
var pb = StartupMessageManager.addProgressBar(registryEvent.getRegistryKey().location().toString(), ModList.get().size());
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources;
|
|||
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.event.ModelEvent;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.bus.api.Event;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.fml.ModLoader;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.neoforge.client.ClientHooks;
|
||||
import net.neoforged.neoforge.client.event.ModelEvent;
|
||||
import org.embeddedt.modernfix.forge.dynresources.ModelBakeEventHelper;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
|
@ -17,12 +17,12 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(ForgeHooksClient.class)
|
||||
@Mixin(ClientHooks.class)
|
||||
public class ForgeHooksClientMixin {
|
||||
/**
|
||||
* Generate a more realistic keySet that contains every item and block model location, to help with mod compat.
|
||||
*/
|
||||
@Redirect(method = "onModifyBakingResult", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEvent(Lnet/minecraftforge/eventbus/api/Event;)V"), remap = false)
|
||||
@Redirect(method = "onModifyBakingResult", at = @At(value = "INVOKE", target = "Lnet/neoforged/fml/ModLoader;postEvent(Lnet/neoforged/bus/api/Event;)V"), remap = false)
|
||||
private static void postNamespacedKeySetEvent(ModLoader loader, Event event) {
|
||||
if(!ModLoader.isLoadingStateValid())
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources;
|
||||
|
||||
import net.minecraft.client.renderer.ItemModelShaper;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.client.model.ForgeItemModelShaper;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||
import org.embeddedt.modernfix.util.ItemMesherMap;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(ForgeItemModelShaper.class)
|
||||
@ClientOnlyMixin
|
||||
public abstract class ItemModelMesherForgeMixin extends ItemModelShaper {
|
||||
@Shadow(remap = false) @Final @Mutable private Map<Holder.Reference<Item>, ModelResourceLocation> locations;
|
||||
|
||||
private Map<Holder.Reference<Item>, ModelResourceLocation> overrideLocations;
|
||||
|
||||
public ItemModelMesherForgeMixin(ModelManager arg) {
|
||||
super(arg);
|
||||
}
|
||||
|
||||
private static final ModelResourceLocation SENTINEL = new ModelResourceLocation(new ResourceLocation("modernfix", "sentinel"), "sentinel");
|
||||
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void replaceLocationMap(CallbackInfo ci) {
|
||||
overrideLocations = new HashMap<>();
|
||||
// need to replace this map because mods query locations through it
|
||||
locations = new ItemMesherMap<>(this::mfix$getLocationForge);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private ModelResourceLocation mfix$getLocationForge(Holder.Reference<Item> item) {
|
||||
ModelResourceLocation map = overrideLocations.getOrDefault(item, SENTINEL);
|
||||
if(map == SENTINEL) {
|
||||
/* generate the appropriate location from our cache */
|
||||
map = ModelLocationCache.get(item.get());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Get the stored location for that item and meta, and get the model
|
||||
* from that location from the model manager.
|
||||
**/
|
||||
@Overwrite
|
||||
@Override
|
||||
public BakedModel getItemModel(Item item) {
|
||||
ModelResourceLocation map = mfix$getLocationForge(ForgeRegistries.ITEMS.getDelegateOrThrow(item));
|
||||
return map == null ? null : getModelManager().getModel(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Don't get all models during init (with dynamic loading, that would
|
||||
* generate them all). Just store location instead.
|
||||
**/
|
||||
@Overwrite
|
||||
@Override
|
||||
public void register(Item item, ModelResourceLocation location) {
|
||||
overrideLocations.put(ForgeRegistries.ITEMS.getDelegateOrThrow(item), location);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Disable cache rebuilding (with dynamic loading, that would generate
|
||||
* all models).
|
||||
**/
|
||||
@Overwrite
|
||||
@Override
|
||||
public void rebuildCache() {}
|
||||
}
|
||||
|
|
@ -5,12 +5,12 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
|||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.*;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.client.ChunkRenderTypeSet;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
|
|
@ -60,8 +60,8 @@ public abstract class CTMPackReloadListenerMixin implements ModernFixClientInteg
|
|||
private void refreshLayerHacks() {
|
||||
renderCheckOverrides.clear();
|
||||
if(blockRenderChecks.isEmpty()) {
|
||||
for(Block block : ForgeRegistries.BLOCKS.getValues()) {
|
||||
Holder.Reference<Block> holder = ForgeRegistries.BLOCKS.getDelegateOrThrow(block);
|
||||
for(Block block : BuiltInRegistries.BLOCK) {
|
||||
Holder.Reference<Block> holder = block.builtInRegistryHolder();
|
||||
ChunkRenderTypeSet original = this.getExistingRenderCheck(block);
|
||||
if(original == null)
|
||||
original = DEFAULT_TYPE_SET;
|
||||
|
|
@ -82,11 +82,14 @@ public abstract class CTMPackReloadListenerMixin implements ModernFixClientInteg
|
|||
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState modelState, ModelBakery bakery) {
|
||||
if(!(location instanceof ModelResourceLocation))
|
||||
return originalModel;
|
||||
if(true) throw new UnsupportedOperationException("not ported yet");
|
||||
/*
|
||||
if(!(originalModel instanceof AbstractCTMBakedModel || originalModel instanceof WeightedBakedModel || originalModel instanceof MultiPartBakedModel))
|
||||
return originalModel;
|
||||
*/
|
||||
/* we construct a new ResourceLocation because an MRL is coming in */
|
||||
Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(location.getNamespace(), location.getPath()));
|
||||
Holder.Reference<Block> delegate = block != null ? ForgeRegistries.BLOCKS.getDelegateOrThrow(block) : null;
|
||||
Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(location.getNamespace(), location.getPath())).orElse(null);
|
||||
Holder.Reference<Block> delegate = block != null ? block.builtInRegistryHolder() : null;
|
||||
if(block == null || block == Blocks.AIR || renderCheckOverrides.containsKey(delegate))
|
||||
return originalModel;
|
||||
/* find all states that match this MRL */
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ public abstract class TextureMetadataHandlerMixin implements ModernFixClientInte
|
|||
|
||||
@Override
|
||||
public BakedModel onBakedModelLoad(ResourceLocation rl, UnbakedModel rootModel, BakedModel baked, ModelState state, ModelBakery bakery) {
|
||||
if (!(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()) {
|
||||
if(true) throw new UnsupportedOperationException("not ported yet");
|
||||
if (false /*!(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()*/) {
|
||||
Deque<ResourceLocation> dependencies = new ArrayDeque<>();
|
||||
Set<ResourceLocation> seenModels = new HashSet<>();
|
||||
dependencies.push(rl);
|
||||
|
|
@ -104,6 +105,8 @@ public abstract class TextureMetadataHandlerMixin implements ModernFixClientInte
|
|||
}
|
||||
|
||||
private void handleInit(ResourceLocation key, BakedModel wrappedModel, ModelBakery bakery) {
|
||||
if(true) throw new UnsupportedOperationException("not ported yet");
|
||||
/*
|
||||
if(wrappedModel instanceof AbstractCTMBakedModel baked) {
|
||||
IModelCTM var10 = baked.getModel();
|
||||
if (var10 instanceof ModelCTM ctmModel) {
|
||||
|
|
@ -120,5 +123,6 @@ public abstract class TextureMetadataHandlerMixin implements ModernFixClientInte
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.fast_forge_dummies;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(targets = { "net/minecraftforge/registries/NamespacedWrapper" })
|
||||
public abstract class NamespacedHolderHelperMixin<T> extends MappedRegistry<T> {
|
||||
@Shadow(remap = false) private Map<ResourceLocation, Holder.Reference<T>> holdersByName;
|
||||
|
||||
public NamespacedHolderHelperMixin(ResourceKey<? extends Registry<T>> arg, Lifecycle lifecycle) {
|
||||
super(arg, lifecycle);
|
||||
}
|
||||
|
||||
@Inject(method = "freeze", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraftforge/registries/NamespacedWrapper;holdersByName:Ljava/util/Map;", remap = false), cancellable = true)
|
||||
private void fastDummyCheck(CallbackInfoReturnable<Registry<T>> cir) {
|
||||
// Quickly iterate without making any streams, etc. to see if everything is fine
|
||||
// Use the slow path (by returning without cancelling) when there is an error
|
||||
for(Holder.Reference<T> ref : this.holdersByName.values()) {
|
||||
if(!ref.isBound())
|
||||
return;
|
||||
}
|
||||
if (this.unregisteredIntrusiveHolders != null) {
|
||||
for(Holder.Reference<T> ref : this.unregisteredIntrusiveHolders.values()) {
|
||||
if(ref.getType() == Holder.Reference.Type.INTRUSIVE && !ref.isBound())
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Skip the creation of streams
|
||||
cir.setReturnValue(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.fast_registry_validation;
|
||||
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
@Mixin(value = ForgeRegistry.class, remap = false)
|
||||
public class ForgeRegistryMixin<V> {
|
||||
private int expectedNextBit = -1;
|
||||
|
||||
/**
|
||||
* Avoid calling nextClearBit and scanning the whole registry for every block registration.
|
||||
*/
|
||||
@Redirect(method = "add(ILnet/minecraft/resources/ResourceLocation;Ljava/lang/Object;Ljava/lang/String;)I", at = @At(value = "INVOKE", target = "Ljava/util/BitSet;nextClearBit(I)I"))
|
||||
private int useCachedBit(BitSet availabilityMap, int minimum) {
|
||||
int bit = availabilityMap.nextClearBit(expectedNextBit != -1 ? expectedNextBit : minimum);
|
||||
expectedNextBit = bit + 1;
|
||||
return bit;
|
||||
}
|
||||
|
||||
@Inject(method = { "sync", "clear", "block" }, at = @At("HEAD"))
|
||||
private void clearBitCache(CallbackInfo ci) {
|
||||
expectedNextBit = -1;
|
||||
}
|
||||
|
||||
@Redirect(method = "add(ILnet/minecraft/resources/ResourceLocation;Ljava/lang/Object;Ljava/lang/String;)I", at = @At(value = "INVOKE", target = "Lorg/apache/logging/log4j/Logger;trace(Lorg/apache/logging/log4j/Marker;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V"))
|
||||
private void skipTrace(Logger logger, Marker marker, String s, Object o, Object o1, Object o2, Object o3, Object o4) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.forge_registry_lambda;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(value = RegistryObject.class, remap = false)
|
||||
public class RegistryObjectMixin<T> {
|
||||
@Shadow private @Nullable T value;
|
||||
|
||||
@Shadow @Final private ResourceLocation name;
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason avoid lambda allocation on every call
|
||||
*/
|
||||
@Overwrite
|
||||
public T get() {
|
||||
T ret = this.value;
|
||||
if(ret == null) {
|
||||
throw new NullPointerException("Registry Object not present: " + this.name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.model_optimizations;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.model.obj.ObjLoader;
|
||||
import net.minecraftforge.client.model.obj.ObjMaterialLibrary;
|
||||
import net.minecraftforge.client.model.obj.ObjModel;
|
||||
import net.neoforged.neoforge.client.model.obj.ObjLoader;
|
||||
import net.neoforged.neoforge.client.model.obj.ObjMaterialLibrary;
|
||||
import net.neoforged.neoforge.client.model.obj.ObjModel;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
|
|
@ -27,12 +27,12 @@ public class OBJLoaderMixin {
|
|||
@Mutable
|
||||
@Shadow(remap = false) private Map<ObjModel.ModelSettings, ObjModel> modelCache;
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraftforge/client/model/obj/ObjLoader;materialCache:Ljava/util/Map;", remap = false))
|
||||
@Redirect(method = "<init>", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/neoforged/neoforge/client/model/obj/ObjLoader;materialCache:Ljava/util/Map;", remap = false))
|
||||
private void useConcMap1(ObjLoader instance, Map<ResourceLocation, ObjMaterialLibrary> value) {
|
||||
this.materialCache = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraftforge/client/model/obj/ObjLoader;modelCache:Ljava/util/Map;", remap = false))
|
||||
@Redirect(method = "<init>", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/neoforged/neoforge/client/model/obj/ObjLoader;modelCache:Ljava/util/Map;", remap = false))
|
||||
private void useConcMap2(ObjLoader instance, Map<ResourceLocation, ObjMaterialLibrary> value) {
|
||||
this.modelCache = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package org.embeddedt.modernfix.forge.mixin.perf.patchouli_deduplicate_books;
|
|||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.neoforged.fml.util.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.annotation.RequiresMod;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.reduce_blockstate_cache_rebuilds;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.registries.IForgeRegistryInternal;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import org.embeddedt.modernfix.blockstate.BlockStateCacheHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
|
@ -11,15 +12,16 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(targets = { "net/minecraftforge/registries/GameData$BlockCallbacks" })
|
||||
@Mixin(targets = { "net/neoforged/neoforge/registries/NeoForgeRegistryCallbacks$BlockCallbacks" })
|
||||
public class BlockCallbacksMixin {
|
||||
@Redirect(method = "onBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;initCache()V"))
|
||||
private void skipCache(BlockState instance) {
|
||||
|
||||
@Redirect(method = "onBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;"))
|
||||
private ImmutableList<BlockState> skipCache(StateDefinition<Block, BlockState> definition) {
|
||||
// prevent initCache from being called on these blockstates
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Inject(method = "onBake", at = @At(value = "TAIL"), remap = false)
|
||||
private void computeCaches(IForgeRegistryInternal<Block> owner, RegistryManager stage, CallbackInfo ci) {
|
||||
private void computeCaches(Registry<Block> registry, CallbackInfo ci) {
|
||||
BlockStateCacheHandler.rebuildParallel(false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.reduce_blockstate_cache_rebuilds;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import org.embeddedt.modernfix.util.BakeReason;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(GameData.class)
|
||||
public class GameDataMixin {
|
||||
@Inject(method = "freezeData", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 1), remap = false)
|
||||
private static void markFreezeBakeReason(CallbackInfo ci) {
|
||||
BakeReason.setCurrentBakeReason(BakeReason.FREEZE);
|
||||
}
|
||||
|
||||
@Inject(method = "freezeData", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/registries/GameData;fireRemapEvent(Ljava/util/Map;Z)V"), remap = false)
|
||||
private static void markEmptyBakeReason1(CallbackInfo ci) {
|
||||
BakeReason.setCurrentBakeReason(null);
|
||||
}
|
||||
|
||||
@Inject(method = "revertTo", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 1), remap = false)
|
||||
private static void markRevertBakeReason(CallbackInfo ci) {
|
||||
BakeReason.setCurrentBakeReason(BakeReason.REVERT);
|
||||
}
|
||||
|
||||
@Inject(method = "revertTo", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 1, shift = At.Shift.AFTER), remap = false)
|
||||
private static void markEmptyBakeReason2(CallbackInfo ci) {
|
||||
BakeReason.setCurrentBakeReason(null);
|
||||
}
|
||||
|
||||
@Inject(method = "injectSnapshot", at = @At("HEAD"), remap = false)
|
||||
private static void markSnapshotInjectBakeReason(Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot, boolean injectFrozenData, boolean isLocalWorld, CallbackInfoReturnable<Multimap<ResourceLocation, ResourceLocation>> cir) {
|
||||
BakeReason.setCurrentBakeReason(isLocalWorld ? BakeReason.LOCAL_SNAPSHOT_INJECT : BakeReason.REMOTE_SNAPSHOT_INJECT);
|
||||
}
|
||||
|
||||
@Inject(method = "injectSnapshot", at = @At("RETURN"), remap = false)
|
||||
private static void markEmptyBakeReason2(Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot, boolean injectFrozenData, boolean isLocalWorld, CallbackInfoReturnable<Multimap<ResourceLocation, ResourceLocation>> cir) {
|
||||
BakeReason.setCurrentBakeReason(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
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;
|
||||
import org.embeddedt.modernfix.util.PackTypeHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(PathPackResources.class)
|
||||
public abstract class ForgePathPackResourcesMixin implements ICachingResourcePack {
|
||||
@Shadow(remap = false) protected abstract Path resolve(String... paths);
|
||||
|
||||
@Shadow(remap = false) @NotNull
|
||||
protected abstract Set<String> getNamespacesFromDisk(PackType type);
|
||||
|
||||
@Shadow(remap = false) private static String[] getPathFromLocation(PackType type, ResourceLocation location) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
private PackResourcesCacheEngine cacheEngine;
|
||||
|
||||
private IModFile mfix$resolveFileOverride;
|
||||
|
||||
@Inject(method = "<init>", at = @At("TAIL"))
|
||||
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;
|
||||
if(engine != null)
|
||||
return engine;
|
||||
this.cacheEngine = engine = new PackResourcesCacheEngine(this::getNamespacesFromDisk, (type, namespace) -> this.resolve(type.getDirectory(), namespace));
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCache() {
|
||||
this.cacheEngine = null;
|
||||
}
|
||||
|
||||
@Inject(method = "getNamespaces", at = @At("HEAD"), cancellable = true)
|
||||
private void useCacheForNamespaces(PackType type, CallbackInfoReturnable<Set<String>> cir) {
|
||||
PackResourcesCacheEngine engine = cacheEngine;
|
||||
if(engine != null) {
|
||||
Set<String> namespaces = engine.getNamespaces(type);
|
||||
if(namespaces != null)
|
||||
cir.setReturnValue(namespaces);
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "getRootResource", at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;exists(Ljava/nio/file/Path;[Ljava/nio/file/LinkOption;)Z"))
|
||||
private boolean useCacheForExistence(Path path, LinkOption[] options, String[] originalPaths) {
|
||||
// the cache only stores things with a namespace and pack type
|
||||
if(originalPaths.length < 3)
|
||||
return Files.exists(path, options);
|
||||
else
|
||||
return this.generateResourceCache().hasResource(originalPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Use cached listing of mod resources
|
||||
*/
|
||||
@Inject(method = "listResources", at = @At("HEAD"), cancellable = true)
|
||||
private void fastGetResources(PackType type, String namespace, String path, PackResources.ResourceOutput resourceOutput, CallbackInfo ci)
|
||||
{
|
||||
if(!PackTypeHelper.isVanillaPackType(type))
|
||||
return;
|
||||
ci.cancel();
|
||||
Collection<ResourceLocation> allPossibleResources = this.generateResourceCache().getResources(type, namespace, path, Integer.MAX_VALUE, p -> true);
|
||||
NewResourcePackAdapter.sendToOutput(location -> {
|
||||
Path target = resolve(getPathFromLocation(location.getPath().startsWith("lang/") ? PackType.CLIENT_RESOURCES : type, location));
|
||||
return () -> Files.newInputStream(target);
|
||||
}, resourceOutput, allPossibleResources);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +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 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<V> {
|
||||
@Shadow
|
||||
@Final
|
||||
@Mutable
|
||||
private BiMap<Integer, V> ids;
|
||||
|
||||
@Shadow @Final @Mutable private BiMap<ResourceKey<V>, V> keys;
|
||||
|
||||
@Shadow @Final private ResourceKey<Registry<V>> key;
|
||||
|
||||
@Shadow @Final @Mutable private BiMap<ResourceLocation, V> names;
|
||||
|
||||
@Shadow @Final @Mutable private BiMap owners;
|
||||
|
||||
private FastForgeRegistry<V> 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 = "<init>", 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.rewrite_registry;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
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;
|
||||
|
||||
@Mixin(ForgeRegistry.Snapshot.class)
|
||||
@IgnoreOutsideDev
|
||||
public class ForgeRegistrySnapshotMixin {
|
||||
@Shadow(remap = false) @Final @Mutable public Map<ResourceLocation, Integer> ids;
|
||||
|
||||
/**
|
||||
* 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 = "<init>", at = @At("RETURN"))
|
||||
private void replaceSnapshotMaps(CallbackInfo ci) {
|
||||
this.ids = new Object2ObjectOpenHashMap<>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,33 @@
|
|||
package org.embeddedt.modernfix.forge.packet;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.Channel;
|
||||
import net.minecraftforge.network.ChannelBuilder;
|
||||
import net.minecraftforge.network.SimpleChannel;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
import net.neoforged.neoforge.network.NetworkRegistry;
|
||||
import net.neoforged.neoforge.network.simple.SimpleChannel;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
|
||||
|
||||
public class PacketHandler {
|
||||
private static final int PROTOCOL_VERSION = 1;
|
||||
public static final SimpleChannel INSTANCE = ChannelBuilder
|
||||
.named(new ResourceLocation(ModernFix.MODID, "main"))
|
||||
.networkProtocolVersion(PROTOCOL_VERSION)
|
||||
.serverAcceptedVersions(Channel.VersionTest.ACCEPT_MISSING.or(Channel.VersionTest.exact(PROTOCOL_VERSION)))
|
||||
.clientAcceptedVersions(Channel.VersionTest.ACCEPT_MISSING.or(Channel.VersionTest.exact(PROTOCOL_VERSION)))
|
||||
.simpleChannel();
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
|
||||
new ResourceLocation(ModernFix.MODID, "main"),
|
||||
() -> PROTOCOL_VERSION,
|
||||
NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION),
|
||||
NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION)
|
||||
);
|
||||
|
||||
public static void register() {
|
||||
INSTANCE.messageBuilder(EntityIDSyncPacket.class).encoder(EntityIDSyncPacket::serialize).decoder(EntityIDSyncPacket::deserialize).consumerNetworkThread((msg, ctx) -> {
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
ctx.enqueueWork(() -> ModernFixClient.handleEntityIDSync(msg));
|
||||
ctx.setPacketHandled(true);
|
||||
});
|
||||
}).add();
|
||||
int id = 1;
|
||||
INSTANCE.registerMessage(id++, EntityIDSyncPacket.class, EntityIDSyncPacket::serialize, EntityIDSyncPacket::deserialize, PacketHandler::handleSyncPacket);
|
||||
}
|
||||
|
||||
private static void handleSyncPacket(EntityIDSyncPacket packet, NetworkEvent.Context contextSupplier) {
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
contextSupplier.enqueueWork(() -> ModernFixClient.handleEntityIDSync(packet));
|
||||
contextSupplier.setPacketHandled(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,601 +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 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<V> {
|
||||
private final BiMap<Integer, V> ids;
|
||||
private final DataFieldBiMap<ResourceLocation> names;
|
||||
private final DataFieldBiMap<ResourceKey<V>> keys;
|
||||
private final DataFieldBiMap<?> owners;
|
||||
private final ResourceKey<Registry<V>> registryKey;
|
||||
|
||||
private final ObjectArrayList<V> valuesById;
|
||||
private final Object2ObjectOpenHashMap<V, RegistryValueData> 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<RegistryValueData> 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<Registry<V>> registryKey) {
|
||||
this.registryKey = registryKey;
|
||||
this.valuesById = new ObjectArrayList<>();
|
||||
this.infoByValue = new Object2ObjectOpenHashMap<>();
|
||||
this.keys = new DataFieldBiMap<>(p -> (ResourceKey<V>) 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<Integer, V>() {
|
||||
@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<? extends Integer, ? extends V> map) {
|
||||
map.forEach(this::put);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<V> values() {
|
||||
return Collections.unmodifiableSet(infoByValue.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiMap<V, Integer> inverse() {
|
||||
return new BiMap<V, Integer>() {
|
||||
@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<? extends V, ? extends Integer> map) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> values() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiMap<Integer, V> 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<V> keySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<V, Integer>> 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<Integer> keySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<Integer, V>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BiConsumer<? super Integer, ? super V> 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<Integer, V> getIds() {
|
||||
return ids;
|
||||
}
|
||||
|
||||
public BiMap<ResourceKey<V>, V> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public BiMap<ResourceLocation, V> 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<K> implements BiMap<K, V> {
|
||||
public final Object2ObjectOpenHashMap<K, V> valuesByKey = new Object2ObjectOpenHashMap<>();
|
||||
private final Function<RegistryValueData, K> getter;
|
||||
private final BiConsumer<RegistryValueData, K> setter;
|
||||
|
||||
public DataFieldBiMap(Function<RegistryValueData, K> getter, BiConsumer<RegistryValueData, K> 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<? extends K, ? extends V> map) {
|
||||
map.forEach(this::put);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<V> values() {
|
||||
return Collections.unmodifiableSet(infoByValue.keySet());
|
||||
}
|
||||
|
||||
private DataFieldBiMapInverse<K> inverse = null;
|
||||
|
||||
@Override
|
||||
public BiMap<V, K> 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<K> keySet() {
|
||||
return Collections.unmodifiableSet(valuesByKey.keySet());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
return Collections.unmodifiableSet(valuesByKey.entrySet());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class DataFieldBiMapInverse<K> implements BiMap<V, K> {
|
||||
private final DataFieldBiMap<K> forward;
|
||||
|
||||
public DataFieldBiMapInverse(DataFieldBiMap<K> 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<? extends V, ? extends K> map) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> values() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiMap<K, V> 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<V> keySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<V, K>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
class FastForgeRegistryLocationSet implements Set<ResourceLocation> {
|
||||
private final Set<ResourceKey<V>> backingSet;
|
||||
|
||||
public FastForgeRegistryLocationSet(Set<ResourceKey<V>> 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<ResourceLocation> 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<V>)keyArray[i]).location();
|
||||
}
|
||||
return keyArray;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> 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<V>)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<? extends ResourceLocation> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.registry;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.registries.ObjectHolderRegistry;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ObjectHolderClearer {
|
||||
/**
|
||||
* Many of the built-in Forge holders needlessly hold on to an exception.
|
||||
*/
|
||||
public static void clearThrowables() {
|
||||
Set<Consumer<Predicate<ResourceLocation>>> holders = ObfuscationReflectionHelper.getPrivateValue(ObjectHolderRegistry.class, null, "objectHolders");
|
||||
if(holders != null) {
|
||||
int numCleared = 0;
|
||||
HashMap<Class<?>, Field> throwableField = new HashMap<>();
|
||||
Throwable singletonThrowable = new Throwable("[This stacktrace was cleared to save memory]");
|
||||
try {
|
||||
for(Consumer<Predicate<ResourceLocation>> holder : holders) {
|
||||
Field target = throwableField.computeIfAbsent(holder.getClass(), clz -> {
|
||||
Field[] clzFields = clz.getDeclaredFields();
|
||||
for(Field f : clzFields) {
|
||||
if(Throwable.class.isAssignableFrom(f.getType())) {
|
||||
f.setAccessible(true);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if(target != null) {
|
||||
target.set(holder, singletonThrowable);
|
||||
numCleared++;
|
||||
}
|
||||
}
|
||||
} catch(RuntimeException | ReflectiveOperationException | NoClassDefFoundError ignored) {
|
||||
}
|
||||
ModernFix.LOGGER.debug("Cleared " + numCleared + " object holder stacktrace references");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.rs;
|
||||
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
public interface IFluidExternalStorageCache {
|
||||
boolean initCache(IFluidHandler handler);
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package org.embeddedt.modernfix.forge.rs;
|
||||
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
public interface IItemExternalStorageCache {
|
||||
boolean initCache(IItemHandler handler);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package org.embeddedt.modernfix.forge.util;
|
||||
|
||||
import net.minecraftforge.fml.loading.ImmediateWindowHandler;
|
||||
import net.neoforged.fml.loading.ImmediateWindowHandler;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
|
|
|
|||
|
|
@ -1,51 +1,11 @@
|
|||
package org.embeddedt.modernfix.forge.util;
|
||||
|
||||
import net.minecraftforge.eventbus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.EventListenerHelper;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ModUtil {
|
||||
private static final Set<Class<?>> erroredContexts = new HashSet<>();
|
||||
private static boolean busListensToEvent(EventBus bus, Class<?> eventClazz) {
|
||||
try {
|
||||
int busID = ObfuscationReflectionHelper.getPrivateValue(EventBus.class, bus, "busID");
|
||||
return EventListenerHelper.getListenerList(eventClazz).getListeners(busID).length > 0;
|
||||
} catch(Exception e) {
|
||||
ModernFix.LOGGER.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static Collection<String> findAllModsListeningToEvent(Class<?> eventClazz) {
|
||||
Set<String> modsListening = new HashSet<>();
|
||||
ModList.get().forEachModContainer((modId, container) -> {
|
||||
Supplier<?> languageExtensionSupplier = ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, container, "contextExtension");
|
||||
Object context = languageExtensionSupplier.get();
|
||||
if(context == null)
|
||||
return;
|
||||
if(context instanceof FMLJavaModLoadingContext) {
|
||||
if(busListensToEvent((EventBus)((FMLJavaModLoadingContext) context).getModEventBus(), eventClazz)) {
|
||||
modsListening.add(modId);
|
||||
}
|
||||
} else {
|
||||
synchronized(erroredContexts) {
|
||||
if(!erroredContexts.contains(context.getClass())) {
|
||||
ModernFix.LOGGER.warn("Unknown modloading context: " + context.getClass().getName());
|
||||
erroredContexts.add(context.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return modsListening;
|
||||
}
|
||||
|
||||
private static final ClassLoader targetClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
|
|
|
|||
|
|
@ -9,21 +9,19 @@ import net.minecraft.server.MinecraftServer;
|
|||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.CreativeModeTabSearchRegistry;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.FMLPaths;
|
||||
import net.minecraftforge.fml.loading.LoadingModList;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.ModLoader;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import net.neoforged.fml.loading.FMLPaths;
|
||||
import net.neoforged.fml.loading.LoadingModList;
|
||||
import net.neoforged.fml.loading.moddiscovery.ModInfo;
|
||||
import net.neoforged.neoforge.client.CreativeModeTabSearchRegistry;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import net.neoforged.neoforge.server.ServerLifecycleHooks;
|
||||
import org.embeddedt.modernfix.api.constants.IntegrationConstants;
|
||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||
import org.embeddedt.modernfix.forge.classloading.ATInjector;
|
||||
import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList;
|
||||
import org.embeddedt.modernfix.forge.config.NightConfigFixer;
|
||||
import org.embeddedt.modernfix.forge.init.ModernFixForge;
|
||||
import org.embeddedt.modernfix.forge.packet.PacketHandler;
|
||||
|
|
@ -90,14 +88,10 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks {
|
|||
}
|
||||
|
||||
public void sendPacket(ServerPlayer player, Object packet) {
|
||||
PacketHandler.INSTANCE.send(packet, PacketDistributor.PLAYER.with(player));
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), packet);
|
||||
}
|
||||
|
||||
public void injectPlatformSpecificHacks() {
|
||||
if(!isEarlyLoadingNormally() && ModernFixMixinPlugin.instance.isOptionEnabled("bugfix.forge_at_inject_error.ATInjector")) {
|
||||
ATInjector.injectModATs();
|
||||
}
|
||||
FastAccessTransformerList.attemptReplace();
|
||||
|
||||
/* https://github.com/FabricMC/Mixin/pull/99 */
|
||||
try {
|
||||
|
|
@ -125,7 +119,7 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks {
|
|||
}
|
||||
|
||||
public void onServerCommandRegister(Consumer<CommandDispatcher<CommandSourceStack>> handler) {
|
||||
MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent event) -> {
|
||||
NeoForge.EVENT_BUS.addListener((RegisterCommandsEvent event) -> {
|
||||
handler.accept(event.getDispatcher());
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,19 @@
|
|||
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
|
||||
modLoader = "javafml" #mandatory
|
||||
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
loaderVersion = "[46,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
loaderVersion = "[1,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
|
||||
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
|
||||
license = "GNU LGPL 3.0"
|
||||
# A URL to refer people to when problems occur with this mod
|
||||
issueTrackerURL="https://github.com/embeddedt/ModernFix/issues" #optional
|
||||
|
||||
[[mixins]]
|
||||
config="modernfix-common.mixins.json"
|
||||
|
||||
[[mixins]]
|
||||
config="modernfix-neoforge.mixins.json"
|
||||
|
||||
# A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
# The modid of the mod
|
||||
|
|
@ -36,11 +43,11 @@ Egregious, yet effective performance improvements for modern Minecraft
|
|||
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
|
||||
[[dependencies.modernfix]] #optional
|
||||
# the modid of the dependency
|
||||
modId = "forge" #mandatory
|
||||
modId = "neoforge" #mandatory
|
||||
# Does this dependency have to exist - if not, ordering below must be specified
|
||||
mandatory = true #mandatory
|
||||
# The version range of the dependency
|
||||
versionRange = "[46.0.1,)" #mandatory
|
||||
versionRange = "[20.2.86,23)" #mandatory
|
||||
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
|
||||
ordering = "NONE"
|
||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user