Merge remote-tracking branch 'origin/1.18' into 1.19.2
This commit is contained in:
commit
5d317b6d94
|
|
@ -88,6 +88,9 @@ dependencies {
|
|||
|
||||
// compile against the JEI API but do not include it at runtime
|
||||
modCompileOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}")
|
||||
modRuntimeOnly("curse.maven:jei-238222:4405346")
|
||||
|
||||
modCompileOnly("curse.maven:jeresources-240630:3951643")
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
|
|
@ -153,7 +156,7 @@ curseforge {
|
|||
id = "790626"
|
||||
changelog = '[Changelog is not currently available]'
|
||||
changelogType = "markdown"
|
||||
releaseType = "release"
|
||||
releaseType = "beta"
|
||||
addGameVersion "Forge"
|
||||
addGameVersion minecraft_version
|
||||
mainArtifact remapJar
|
||||
|
|
|
|||
|
|
@ -4,18 +4,20 @@ import net.minecraftforge.api.distmarker.Dist;
|
|||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.IExtensionPoint;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
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.network.NetworkConstants;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.embeddedt.modernfix.core.config.ModernFixConfig;
|
||||
import org.embeddedt.modernfix.entity.EntityDataIDSyncHandler;
|
||||
import org.embeddedt.modernfix.packet.PacketHandler;
|
||||
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
|
@ -62,9 +64,30 @@ public class ModernFix {
|
|||
INSTANCE = this;
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::commonSetup);
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> MinecraftForge.EVENT_BUS.register(new ModernFixClient()));
|
||||
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (a, b) -> true));
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModernFixConfig.COMMON_CONFIG);
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(EntityDataIDSyncHandler.class);
|
||||
PacketHandler.register();
|
||||
}
|
||||
|
||||
private static boolean dfuModPresent() {
|
||||
for(String modId : new String[] { "lazydfu", "datafixerslayer" }) {
|
||||
if(ModList.get().isLoaded(modId))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void commonSetup(FMLCommonSetupEvent event) {
|
||||
if(!dfuModPresent()) {
|
||||
event.enqueueWork(() -> {
|
||||
ModLoader.get().addWarning(new ModLoadingWarning(ModLoadingContext.get().getActiveContainer().getModInfo(), ModLoadingStage.COMMON_SETUP, "modernfix.no_lazydfu"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
|||
|
|
@ -1,22 +1,32 @@
|
|||
package org.embeddedt.modernfix;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.ConnectScreen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||
import org.embeddedt.modernfix.load.LoadEvents;
|
||||
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
|
||||
import org.embeddedt.modernfix.screen.DeferredLevelLoadingScreen;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Optional;
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.Ref;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ModernFixClient {
|
||||
public static long worldLoadStartTime;
|
||||
|
|
@ -71,4 +81,106 @@ public class ModernFixClient {
|
|||
event.getLeft().add(brandingString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the IDs match and remap them if not.
|
||||
* @return true if ID remap was needed
|
||||
*/
|
||||
private static boolean compareAndSwitchIds(Class<? extends Entity> eClass, String fieldName, EntityDataAccessor<?> accessor, int newId) {
|
||||
if(accessor.id != newId) {
|
||||
ModernFix.LOGGER.warn("Corrected ID mismatch on {} field {}. Client had {} but server wants {}.",
|
||||
eClass,
|
||||
fieldName,
|
||||
accessor.id,
|
||||
newId);
|
||||
accessor.id = newId;
|
||||
return true;
|
||||
} else {
|
||||
ModernFix.LOGGER.debug("{} {} ID fine: {}", eClass, fieldName, newId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Horrendous hack to allow tracking every synced entity data manager.
|
||||
*
|
||||
* This is to ensure we can perform ID fixup on already constructed managers.
|
||||
*/
|
||||
public static final Set<SynchedEntityData> allEntityDatas = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
private static final Field entriesArrayField;
|
||||
static {
|
||||
Field field;
|
||||
try {
|
||||
field = SynchedEntityData.class.getDeclaredField("entriesArray");
|
||||
field.setAccessible(true);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
field = null;
|
||||
}
|
||||
entriesArrayField = field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extremely hacky method to detect and correct mismatched entity data parameter IDs on the client and server.
|
||||
*
|
||||
* The technique is far from ideal, but it should detect reliably and also not break already constructed entities.
|
||||
*/
|
||||
public static void handleEntityIDSync(EntityIDSyncPacket packet, Supplier<NetworkEvent.Context> context) {
|
||||
Map<Class<? extends Entity>, List<Pair<String, Integer>>> info = packet.getFieldInfo();
|
||||
context.get().enqueueWork(() -> {
|
||||
boolean fixNeeded = false;
|
||||
for(Map.Entry<Class<? extends Entity>, List<Pair<String, Integer>>> entry : info.entrySet()) {
|
||||
Class<? extends Entity> eClass = entry.getKey();
|
||||
for(Pair<String, Integer> field : entry.getValue()) {
|
||||
String fieldName = field.getFirst();
|
||||
int newId = field.getSecond();
|
||||
try {
|
||||
Field f = eClass.getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
EntityDataAccessor<?> accessor = (EntityDataAccessor<?>)f.get(null);
|
||||
if(compareAndSwitchIds(eClass, fieldName, accessor, newId))
|
||||
fixNeeded = true;
|
||||
} catch(NoSuchFieldException e) {
|
||||
ModernFix.LOGGER.warn("Couldn't find field on {}: {}", eClass, fieldName);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Unexpected exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Now the ID mappings on synced entity data instances are probably all wrong. Fix that. */
|
||||
List<SynchedEntityData> dataEntries;
|
||||
synchronized (allEntityDatas) {
|
||||
if(fixNeeded) {
|
||||
dataEntries = new ArrayList<>(allEntityDatas);
|
||||
for(SynchedEntityData manager : dataEntries) {
|
||||
Int2ObjectOpenHashMap<SynchedEntityData.DataItem<?>> fixedMap = new Int2ObjectOpenHashMap<>();
|
||||
List<SynchedEntityData.DataItem<?>> items = new ArrayList<>(manager.itemsById.values());
|
||||
for(SynchedEntityData.DataItem<?> item : items) {
|
||||
fixedMap.put(item.getAccessor().id, item);
|
||||
}
|
||||
manager.lock.writeLock().lock();
|
||||
try {
|
||||
manager.itemsById.replaceAll((id, parameter) -> fixedMap.get((int)id));
|
||||
if(entriesArrayField != null) {
|
||||
try {
|
||||
SynchedEntityData.DataItem<?>[] dataArray = new SynchedEntityData.DataItem[items.size()];
|
||||
for(int i = 0; i < dataArray.length; i++) {
|
||||
dataArray[i] = fixedMap.get(i);
|
||||
}
|
||||
entriesArrayField.set(manager, dataArray);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
ModernFix.LOGGER.error(e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
manager.lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
allEntityDatas.clear();
|
||||
}
|
||||
});
|
||||
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class BlockStateCacheHandler {
|
|||
currentRebuildThread = null;
|
||||
}
|
||||
} else {
|
||||
ModernFix.LOGGER.warn("Deferred blockstate cache rebuild");
|
||||
ModernFix.LOGGER.debug("Deferred blockstate cache rebuild");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.embeddedt.modernfix.core.config;
|
||||
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
|
@ -22,6 +23,7 @@ public class ModernFixEarlyConfig {
|
|||
this.addMixinRule("feature.measure_time", true);
|
||||
this.addMixinRule("feature.reduce_loading_screen_freezes", false);
|
||||
this.addMixinRule("perf.fast_registry_validation", true);
|
||||
this.addMixinRule("perf.use_integrated_resources", true);
|
||||
this.addMixinRule("perf.remove_biome_temperature_cache", true);
|
||||
this.addMixinRule("perf.reduce_blockstate_cache_rebuilds", true);
|
||||
this.addMixinRule("perf.parallelize_model_loading", true);
|
||||
|
|
@ -30,6 +32,7 @@ public class ModernFixEarlyConfig {
|
|||
this.addMixinRule("perf.cache_upgraded_structures", true);
|
||||
this.addMixinRule("bugfix.concurrency", true);
|
||||
this.addMixinRule("bugfix.edge_chunk_not_saved", true);
|
||||
this.addMixinRule("perf.async_jei", true);
|
||||
this.addMixinRule("perf.thread_priorities", true);
|
||||
this.addMixinRule("perf.sync_executor_sleep", true);
|
||||
this.addMixinRule("perf.scan_cache", true);
|
||||
|
|
@ -43,7 +46,8 @@ public class ModernFixEarlyConfig {
|
|||
/* off by default in 1.18 because it doesn't work as well */
|
||||
this.addMixinRule("perf.faster_singleplayer_load", false);
|
||||
/* Keep this off if JEI isn't installed to prevent breaking vanilla gameplay */
|
||||
this.addMixinRule("perf.blast_search_trees", FMLLoader.getLoadingModList().getModFileById("jei") != null);
|
||||
Optional<ModInfo> jeiMod = FMLLoader.getLoadingModList().getMods().stream().filter(mod -> mod.getModId().equals("jei")).findFirst();
|
||||
this.addMixinRule("perf.blast_search_trees", jeiMod.isPresent() && jeiMod.get().getVersion().getMajorVersion() >= 10);
|
||||
this.addMixinRule("safety", true);
|
||||
this.addMixinRule("launch.transformer_cache", false);
|
||||
this.addMixinRule("launch.class_search_cache", true);
|
||||
|
|
@ -52,6 +56,7 @@ public class ModernFixEarlyConfig {
|
|||
disableIfModPresent("mixin.perf.thread_priorities", "smoothboot");
|
||||
disableIfModPresent("mixin.perf.async_jei", "modernui");
|
||||
disableIfModPresent("mixin.perf.compress_biome_container", "chocolate");
|
||||
disableIfModPresent("mixin.bugfix.mc218112", "performant");
|
||||
}
|
||||
|
||||
private void disableIfModPresent(String configName, String... ids) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package org.embeddedt.modernfix.duck.reuse_datapacks;
|
||||
|
||||
import net.minecraft.server.ReloadableServerResources;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ICachingResourceClient {
|
||||
void setCachedResources(ReloadableServerResources r);
|
||||
void setCachedDataPackConfig(Collection<String> c);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package org.embeddedt.modernfix.entity;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.event.OnDatapackSyncEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
|
||||
import org.embeddedt.modernfix.packet.PacketHandler;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntityDataIDSyncHandler {
|
||||
private static Map<Class<? extends Entity>, List<Pair<String, Integer>>> fieldsToSyncMap;
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onDatapackSyncEvent(OnDatapackSyncEvent event) {
|
||||
if(event.getPlayer() != null) {
|
||||
if(!ServerLifecycleHooks.getCurrentServer().isDedicatedServer() && event.getPlayerList().getPlayerCount() == 0) {
|
||||
ModernFix.LOGGER.debug("Not syncing IDs on integrated server");
|
||||
return;
|
||||
}
|
||||
/* Compute the current set of serializer IDs in use and send them */
|
||||
try {
|
||||
if(fieldsToSyncMap == null) {
|
||||
fieldsToSyncMap = new HashMap<>();
|
||||
Field entityPoolField = ObfuscationReflectionHelper.findField(SynchedEntityData.class, "f_135343_");
|
||||
Map<Class<? extends Entity>, Integer> entityPoolMap = (Map<Class<? extends Entity>, Integer>)entityPoolField.get(null);
|
||||
List<Field> fieldsToSync = new ArrayList<>();
|
||||
for(Class<? extends Entity> eClass : entityPoolMap.keySet()) {
|
||||
fieldsToSync.clear();
|
||||
Field[] classFields = eClass.getDeclaredFields();
|
||||
for(Field field : classFields) {
|
||||
if(!Modifier.isStatic(field.getModifiers()))
|
||||
continue;
|
||||
field.setAccessible(true);
|
||||
Object o = field.get(null);
|
||||
if(o != null && EntityDataAccessor.class.isAssignableFrom(o.getClass())) {
|
||||
fieldsToSync.add(field);
|
||||
}
|
||||
}
|
||||
for(Field field : fieldsToSync) {
|
||||
int id = ((EntityDataAccessor<?>)field.get(null)).id;
|
||||
fieldsToSyncMap.computeIfAbsent(eClass, k -> new ArrayList<>()).add(Pair.of(field.getName(), id));
|
||||
}
|
||||
}
|
||||
}
|
||||
EntityIDSyncPacket packet = new EntityIDSyncPacket(fieldsToSyncMap);
|
||||
ModernFix.LOGGER.debug("Sending ID correction packet to client with " + fieldsToSyncMap.size() + " classes");
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(event::getPlayer), packet);
|
||||
} catch(ObfuscationReflectionHelper.UnableToFindFieldException | ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package org.embeddedt.modernfix.mixin.core;
|
||||
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
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(SynchedEntityData.class)
|
||||
public class SynchedEntityDataMixin {
|
||||
/**
|
||||
* Store this in our set of all entity data objects.
|
||||
*
|
||||
* Not an ideal solution, but it should guarantee compatibility with mods.
|
||||
*/
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void storeInSet(Entity arg, CallbackInfo ci) {
|
||||
synchronized (ModernFixClient.allEntityDatas) {
|
||||
ModernFixClient.allEntityDatas.add((SynchedEntityData)(Object)this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,9 +13,9 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(value = BrandingControl.class, remap = false)
|
||||
@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)
|
||||
@Inject(method = "computeBranding", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModList;get()Lnet/minecraftforge/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())
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package org.embeddedt.modernfix.mixin.perf.blast_search_trees;
|
|||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.searchtree.SearchRegistry;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import org.embeddedt.modernfix.searchtree.DummySearchTree;
|
||||
import org.embeddedt.modernfix.searchtree.JEIBackedSearchTree;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
|
|
@ -12,6 +14,8 @@ 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.Optional;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public class MinecraftMixin {
|
||||
@Shadow @Final private SearchRegistry searchRegistry;
|
||||
|
|
@ -19,7 +23,8 @@ public class MinecraftMixin {
|
|||
@Inject(method = "createSearchTrees", at = @At("HEAD"), cancellable = true)
|
||||
private void replaceSearchTrees(CallbackInfo ci) {
|
||||
ci.cancel();
|
||||
if(ModList.get().getModFileById("jei") != null) {
|
||||
Optional<? extends ModContainer> jeiContainer = ModList.get().getModContainerById("jei");
|
||||
if(jeiContainer.isPresent() && jeiContainer.get().getModInfo().getVersion().getMajorVersion() >= 10) {
|
||||
this.searchRegistry.register(SearchRegistry.CREATIVE_NAMES, list -> new JEIBackedSearchTree(false));
|
||||
this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, list -> new JEIBackedSearchTree(true));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ public class IntegratedServerMixin {
|
|||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void adjustServerPriority(Thread thread, Minecraft arg, LevelStorageSource.LevelStorageAccess arg2, PackRepository arg3, WorldStem arg4, Services arg5, ChunkProgressListenerFactory arg6, CallbackInfo ci) {
|
||||
int pri = ModernFixConfig.INTEGRATED_SERVER_PRIORITY.get();
|
||||
ModernFix.LOGGER.info("Changing server thread priority to " + pri);
|
||||
thread.setPriority(pri);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package org.embeddedt.modernfix.mixin.perf.use_integrated_resources;
|
||||
|
||||
import jeresources.util.LootTableHelper;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(LootTableHelper.class)
|
||||
public class LootTableHelperMixin {
|
||||
@Redirect(method = "getLootTables", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getServer()Lnet/minecraft/server/MinecraftServer;"))
|
||||
private static MinecraftServer useIntegrated(Level level) {
|
||||
MinecraftServer server = level.getServer();
|
||||
if(server != null)
|
||||
return server;
|
||||
return ServerLifecycleHooks.getCurrentServer();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package org.embeddedt.modernfix.packet;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
|
||||
public class EntityIDSyncPacket {
|
||||
private Map<Class<? extends Entity>, List<Pair<String, Integer>>> map;
|
||||
|
||||
public EntityIDSyncPacket(Map<Class<? extends Entity>, List<Pair<String, Integer>>> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public Map<Class<? extends Entity>, List<Pair<String, Integer>>> getFieldInfo() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
public EntityIDSyncPacket() {
|
||||
this.map = new HashMap<>();
|
||||
}
|
||||
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeVarInt(map.keySet().size());
|
||||
for(Map.Entry<Class<? extends Entity>, List<Pair<String, Integer>>> entry : map.entrySet()) {
|
||||
buf.writeUtf(entry.getKey().getName());
|
||||
buf.writeVarInt(entry.getValue().size());
|
||||
for(Pair<String, Integer> field : entry.getValue()) {
|
||||
buf.writeUtf(field.getFirst());
|
||||
buf.writeVarInt(field.getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static EntityIDSyncPacket deserialize(FriendlyByteBuf buf) {
|
||||
EntityIDSyncPacket self = new EntityIDSyncPacket();
|
||||
int numEntityClasses = buf.readVarInt();
|
||||
for(int i = 0; i < numEntityClasses; i++) {
|
||||
String clzName = buf.readUtf();
|
||||
try {
|
||||
Class<?> clz;
|
||||
try {
|
||||
clz = Class.forName(clzName);
|
||||
} catch(ClassNotFoundException e) {
|
||||
ModernFix.LOGGER.warn("Entity class not found: {}", clzName);
|
||||
break;
|
||||
}
|
||||
if(!Entity.class.isAssignableFrom(clz)) {
|
||||
ModernFix.LOGGER.error("Not an entity: " + clzName);
|
||||
break;
|
||||
}
|
||||
int numFields = buf.readVarInt();
|
||||
for(int j = 0; j < numFields; j++) {
|
||||
String fieldName = buf.readUtf();
|
||||
int id = buf.readVarInt();
|
||||
Field f = clz.getDeclaredField(fieldName);
|
||||
if(!Modifier.isStatic(f.getModifiers()))
|
||||
continue;
|
||||
f.setAccessible(true);
|
||||
if(!EntityDataAccessor.class.isAssignableFrom(f.get(null).getClass())) {
|
||||
ModernFix.LOGGER.error("Not a data accessor field: " + clz + "." + fieldName);
|
||||
continue;
|
||||
}
|
||||
self.map.computeIfAbsent((Class<? extends Entity>)clz, k -> new ArrayList<>()).add(Pair.of(fieldName, id));
|
||||
}
|
||||
} catch(ReflectiveOperationException e) {
|
||||
ModernFix.LOGGER.error("Error deserializing packet", e);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.embeddedt.modernfix.packet;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
|
||||
public class PacketHandler {
|
||||
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() {
|
||||
int id = 1;
|
||||
INSTANCE.registerMessage(id++, EntityIDSyncPacket.class, EntityIDSyncPacket::serialize, EntityIDSyncPacket::deserialize, ModernFixClient::handleEntityIDSync);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,119 @@ import org.lwjgl.stb.STBRPNode;
|
|||
import org.lwjgl.stb.STBRPRect;
|
||||
import org.lwjgl.stb.STBRectPack;
|
||||
|
||||
import static java.lang.invoke.MethodHandles.*;
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.sql.Ref;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/* Source: https://github.com/GTNewHorizons/lwjgl3ify/blob/f21364cd3d178aef863458a2faa1f5718a4e350d/src/main/java/me/eigenraven/lwjgl3ify/textures/StbStitcher.java */
|
||||
public class StbStitcher {
|
||||
/* Most of this logic is to allow use of LWJGL versions where coordinates are short and versions where they are int */
|
||||
private static final MethodHandle MH_rect_shortSet, MH_rect_intSet, MH_rect_intX, MH_rect_intY, MH_rect_shortX,
|
||||
MH_rect_shortY;
|
||||
|
||||
static {
|
||||
MethodHandle shortM = null, intM = null;
|
||||
List<ReflectiveOperationException> exceptions = new ArrayList<>();
|
||||
try {
|
||||
intM = publicLookup().findVirtual(STBRPRect.class, "set", methodType(STBRPRect.class,
|
||||
int.class, /* id */
|
||||
int.class,
|
||||
int.class,
|
||||
int.class,
|
||||
int.class,
|
||||
boolean.class));
|
||||
} catch(ReflectiveOperationException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
try {
|
||||
shortM = publicLookup().findVirtual(STBRPRect.class, "set", methodType(STBRPRect.class,
|
||||
int.class, /* id */
|
||||
short.class,
|
||||
short.class,
|
||||
short.class,
|
||||
short.class,
|
||||
boolean.class));
|
||||
} catch(ReflectiveOperationException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
if(shortM == null && intM == null) {
|
||||
IllegalStateException e = new IllegalStateException("An STBRPRect set method could not be located");
|
||||
exceptions.forEach(e::addSuppressed);
|
||||
throw e;
|
||||
}
|
||||
MH_rect_shortSet = shortM;
|
||||
MH_rect_intSet = intM;
|
||||
/* Now look for X methods */
|
||||
exceptions.clear();
|
||||
try {
|
||||
intM = publicLookup().findVirtual(STBRPRect.class, "x", methodType(int.class));
|
||||
} catch(ReflectiveOperationException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
try {
|
||||
shortM = publicLookup().findVirtual(STBRPRect.class, "x", methodType(short.class));
|
||||
} catch(ReflectiveOperationException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
if(shortM == null && intM == null) {
|
||||
IllegalStateException e = new IllegalStateException("An STBRPRect x() method could not be located");
|
||||
exceptions.forEach(e::addSuppressed);
|
||||
throw e;
|
||||
}
|
||||
MH_rect_shortX = shortM;
|
||||
MH_rect_intX = intM;
|
||||
/* Assume that Y is the same */
|
||||
try {
|
||||
if(MH_rect_shortX != null) {
|
||||
MH_rect_shortY = publicLookup().findVirtual(STBRPRect.class, "y", methodType(short.class));
|
||||
MH_rect_intY = null;
|
||||
} else { /* it must be int */
|
||||
MH_rect_intY = publicLookup().findVirtual(STBRPRect.class, "y", methodType(int.class));
|
||||
MH_rect_shortY = null;
|
||||
}
|
||||
} catch(ReflectiveOperationException e) {
|
||||
throw new IllegalStateException("An STBRPRect y() method could not be located", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static STBRPRect setWrapper(STBRPRect rect, int id, int width, int height, int x, int y, boolean was_packed) {
|
||||
try {
|
||||
if(MH_rect_shortSet != null)
|
||||
return (STBRPRect)MH_rect_shortSet.invokeExact(rect, id, (short)width, (short)height, (short)0, (short)0, false);
|
||||
else
|
||||
return (STBRPRect)MH_rect_intSet.invokeExact(rect, id, width, height, 0, 0, false);
|
||||
} catch(Throwable e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getX(STBRPRect rect) {
|
||||
try {
|
||||
if(MH_rect_shortX != null)
|
||||
return (short)MH_rect_shortX.invokeExact(rect);
|
||||
else
|
||||
return (int)MH_rect_intX.invokeExact(rect);
|
||||
} catch(Throwable e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getY(STBRPRect rect) {
|
||||
try {
|
||||
if(MH_rect_shortX != null)
|
||||
return (short)MH_rect_shortY.invokeExact(rect);
|
||||
else
|
||||
return (int)MH_rect_intY.invokeExact(rect);
|
||||
} catch(Throwable e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Pair<Pair<Integer, Integer>, List<LoadableSpriteInfo>> packRects(Stitcher.Holder[] holders) {
|
||||
int holderSize = holders.length;
|
||||
|
||||
|
|
@ -36,7 +143,9 @@ public class StbStitcher {
|
|||
int height = holder.height;
|
||||
|
||||
// The ID here is just the array index, for easy lookup later
|
||||
rectBuf.get(j).set(j, (short)width, (short)height, (short)0, (short)0, false);
|
||||
STBRPRect rect = rectBuf.get(j);
|
||||
|
||||
setWrapper(rect, j, width, height, 0, 0, false);
|
||||
|
||||
sqSize += (width * height);
|
||||
}
|
||||
|
|
@ -63,7 +172,7 @@ public class StbStitcher {
|
|||
}
|
||||
|
||||
// Initialize the sprite now with the position and size that we've calculated so far
|
||||
infoList.add(new LoadableSpriteInfo(holder.spriteInfo, width, height, rect.x(), rect.y()));
|
||||
infoList.add(new LoadableSpriteInfo(holder.spriteInfo, width, height, getX(rect), getY(rect)));
|
||||
//holder.spriteInfo.initSprite(size, size, rect.x(), rect.y(), false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,22 @@
|
|||
package org.embeddedt.modernfix.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FileUtil {
|
||||
public static File childFile(File file) {
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
private static final Pattern SLASH_PATTERN = Pattern.compile("(?:\\\\+|\\/+)");
|
||||
|
||||
/**
|
||||
* Normalize a path by removing double slashes, etc.
|
||||
* @param path input path
|
||||
* @return a normalized version of the path
|
||||
*/
|
||||
public static String normalize(String path) {
|
||||
return SLASH_PATTERN.matcher(path).replaceAll("/");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,4 +8,7 @@ public net.minecraft.client.renderer.model.ModelBakery field_217849_F # unbakedC
|
|||
public net.minecraft.client.renderer.texture.Stitcher$Holder
|
||||
public net.minecraft.util.thread.BlockableEventLoop m_18699_()V # runAllTasks
|
||||
public net.minecraft.server.MinecraftServer f_129726_ # nextTickTime
|
||||
public net.minecraft.client.Minecraft f_90999_ # progressListener
|
||||
public net.minecraft.client.Minecraft f_90999_ # progressListener
|
||||
public-f net.minecraft.network.syncher.EntityDataAccessor f_135010_ # id
|
||||
public-f net.minecraft.network.syncher.SynchedEntityData f_135345_ # itemsById
|
||||
public-f net.minecraft.network.syncher.SynchedEntityData f_135346_ # lock
|
||||
|
|
|
|||
|
|
@ -60,6 +60,6 @@ side = "BOTH"
|
|||
modId = "jei"
|
||||
mandatory = false
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange = "[9.9999,)"
|
||||
versionRange = "[11,)"
|
||||
ordering = "BEFORE"
|
||||
side = "CLIENT"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"modernfix.jei_load": "Loading JEI, this may take a while",
|
||||
"modernfix.no_lazydfu": "ModernFix detected that DFU rules were compiled on startup. This slows down game launching. Installing LazyDFU to resolve this is highly recommended.",
|
||||
"asynclocator.map.locating": "Map (Locating...)",
|
||||
"asynclocator.map.none": "Map (No nearby feature found)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"modernfix.jei_load": "正在加载JEI,这需要一点时间",
|
||||
"asynclocator.map.locating": "地图(正在定位...)",
|
||||
"modernfix.jei_load": "正在加载JEI,这需要一点时间。",
|
||||
"modernfix.no_lazydfu": "现代化修复检测到DFU规则在游戏启动时已被编译。这会降低游戏启动速度。非常推荐安装DFU载入优化来解决这个问题。",
|
||||
"asynclocator.map.locating": "地图(定位中……)",
|
||||
"asynclocator.map.none": "地图(未能找到相关地物)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
],
|
||||
"client": [
|
||||
"core.MinecraftMixin",
|
||||
"core.SynchedEntityDataMixin",
|
||||
"feature.measure_time.MinecraftMixin",
|
||||
"feature.reduce_loading_screen_freezes.ModelBakeryMixin",
|
||||
"bugfix.concurrency.MinecraftMixin",
|
||||
|
|
@ -56,6 +57,7 @@
|
|||
"perf.cache_model_materials.VanillaModelMixin",
|
||||
"perf.cache_model_materials.MultipartMixin",
|
||||
"perf.faster_texture_stitching.StitcherMixin",
|
||||
"perf.use_integrated_resources.LootTableHelperMixin",
|
||||
"perf.faster_singleplayer_load.MinecraftServerMixin"
|
||||
],
|
||||
"injectors": {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user