Merge remote-tracking branch 'origin/1.19.2' into 1.19.4

This commit is contained in:
embeddedt 2023-05-01 20:30:25 -04:00
commit ea25f2e854
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
189 changed files with 2558 additions and 1966 deletions

View File

@ -22,5 +22,9 @@ jobs:
run: ./gradlew --no-daemon build
- uses: actions/upload-artifact@v2
with:
name: Package
path: build/libs
name: Forge
path: forge/build/libs
- uses: actions/upload-artifact@v2
with:
name: Fabric
path: fabric/build/libs

View File

@ -1,109 +1,140 @@
plugins {
id "dev.architectury.loom" version "1.1-SNAPSHOT"
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.1-SNAPSHOT" apply false
id "maven-publish"
id 'com.matthewprenger.cursegradle' version '1.4.0'
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
id 'com.palantir.git-version' version '1.0.0'
id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.0'
id "com.modrinth.minotaur" version "2.+"
id "com.modrinth.minotaur" version "2.+" apply false
id("com.diffplug.spotless") version "6.18.0" apply false
}
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
group = 'org.embeddedt'
version = gitVersion()
java {
archivesBaseName = 'modernfix-mc' + minecraft_version
architectury {
minecraft = rootProject.minecraft_version
}
loom {
// use this if you are using the official mojang mappings
// and want loom to stop warning you about their license
silentMojangMappingsLicense()
ext.archives_base_name = 'modernfix-mc' + minecraft_version
// since loom 0.10, you are **required** to use the
// "forge" block to configure forge-specific features,
// such as the mixinConfigs array or datagen
forge {
// specify the mixin configs used in this mod
// this will be added to the jar manifest as well!
mixinConfigs = [
"modernfix.mixins.json"
allprojects {
apply plugin: "java"
apply plugin: "architectury-plugin"
apply plugin: "maven-publish"
apply plugin: "com.diffplug.spotless"
spotless {
java {
removeUnusedImports()
}
}
group = 'org.embeddedt'
version = gitVersion()
archivesBaseName = rootProject.archives_base_name + '-' + project.name
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
repositories {
maven { url 'https://modmaven.dev/' }
maven {
url "https://cursemaven.com"
content {
includeGroup "curse.maven"
}
}
maven {
name = 'ParchmentMC'
url = 'https://maven.parchmentmc.org'
}
maven {
// Shedaniel's maven (Architectury API)
url = "https://maven.architectury.dev"
content {
includeGroup "me.shedaniel"
}
}
maven {
// saps.dev Maven (KubeJS and Rhino)
url = "https://maven.saps.dev/minecraft"
content {
includeGroup "dev.latvian.mods"
}
}
maven { // CTM
url "https://maven.tterrag.com/"
}
maven { url 'https://maven.blamejared.com' }
repositories {
maven {
name = "Fuzs Mod Resources"
url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/"
}
}
}
}
subprojects {
apply plugin: "dev.architectury.loom"
loom {
silentMojangMappingsLicense()
}
dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings loom.officialMojangMappings()
}
processResources {
def mixinFileList = []
def mixinDirectory = file("src/main/java/org/embeddedt/modernfix/" + project.name + "/mixin")
fileTree(mixinDirectory).visit { FileVisitDetails details ->
if(details.file.isFile()) {
def fileName = mixinDirectory.relativePath(details.file).toString().replaceFirst(/\.java$/, "").replace('/', '.')
mixinFileList << fileName
}
}
def mixinClassesStringB = new StringBuilder()
for(int i = 0; i < mixinFileList.size(); i++) {
mixinClassesStringB.append(" \"")
mixinClassesStringB.append(mixinFileList.get(i))
mixinClassesStringB.append('"')
if(i < (mixinFileList.size() - 1))
mixinClassesStringB.append(',')
mixinClassesStringB.append('\n')
}
def replacements = [
mixin_classes: mixinClassesStringB.toString()
]
inputs.properties replacements
def filePattern = "modernfix-" + project.name + ".mixins.json"
filesMatching(filePattern) {
expand replacements
}
}
mixin.defaultRefmapName = "modernfix.refmap.json"
}
repositories {
maven { url 'https://modmaven.dev/' }
maven {
url "https://cursemaven.com"
content {
includeGroup "curse.maven"
}
}
maven {
name = 'ParchmentMC'
url = 'https://maven.parchmentmc.org'
}
maven {
// Shedaniel's maven (Architectury API)
url = "https://maven.architectury.dev"
content {
includeGroup "me.shedaniel"
}
}
maven {
// saps.dev Maven (KubeJS and Rhino)
url = "https://maven.saps.dev/minecraft"
content {
includeGroup "dev.latvian.mods"
}
}
maven { // CTM
url "https://maven.tterrag.com/"
}
maven { url "https://maven.shedaniel.me" }
maven { url 'https://maven.blamejared.com' }
}
dependencies {
// to change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
// choose what mappings you want to use here
// leave this uncommented if you want to use
// mojang's official mappings, or feel free
// to add your own mappings here (how about
// mojmap layered with parchment, for example?)
mappings loom.officialMojangMappings()
/*
mappings loom.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip")
}
*/
// uncomment this if you want to use yarn mappings
// mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
// your forge dependency, this is **required** when using Forge Loom in forge mode!
forge "net.minecraftforge:forge:${project.forge_version}"
/*
modCompileOnly("mezz.jei:jei-${minecraft_version}:${jei_version}")
//modRuntimeOnly("mezz.jei:jei-${minecraft_version}:${jei_version}")
modCompileOnly("curse.maven:refinedstorage-243076:${refined_storage_version}")
// compile against the JEI API but do not include it at runtime
modCompileOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}")
modCompileOnly("curse.maven:jeresources-240630:3951643")
modCompileOnly "me.shedaniel:RoughlyEnoughItems-forge:${rei_version}"
modCompileOnly("dev.latvian.mods:kubejs-forge:${kubejs_version}")
modRuntimeOnly("curse.maven:ferritecore-429235:4441949")
modRuntimeOnly("curse.maven:ferritecore-429235:4117906")
modCompileOnly("team.chisel.ctm:CTM:${ctm_version}")
modCompileOnly("curse.maven:supermartijncore-454372:4484241")
modCompileOnly("curse.maven:supermartijncore-454372:4455391")
modCompileOnly("appeng:appliedenergistics2-forge:12.9.4")
modCompileOnly("vazkii.patchouli:Patchouli:1.19.2-77")
}
*/
tasks.withType(JavaCompile) {
// ensure that the encoding is set to UTF-8, no matter what the system default is
@ -112,7 +143,10 @@ tasks.withType(JavaCompile) {
// If Javadoc is generated, this must be specified in that task too.
options.encoding = "UTF-8"
def targetVersion = 17
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
// We'll use that if it's available, but otherwise we'll use the older option.
def targetVersion = 8
/*
if (JavaVersion.current().isJava9Compatible()) {
options.release = targetVersion
@ -136,46 +170,7 @@ task generateChangelog(type: se.bjurr.gitchangelog.plugin.gradle.GitChangelogTas
toCommit = "HEAD";
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
// withSourcesJar()
}
// Example for how to get properties into the manifest for reading at runtime.
jar {
manifest {
attributes([
"Specification-Title" : "modernfix",
"Operative-Class" : "org.embeddedt.modernfix.agent.Agent",
//"Specification-Vendor": "modernfix authors",
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.jar.archiveVersion,
//"Implementation-Vendor": "modernfix authors",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}
/*
curseforge {
if (System.getenv("CURSEFORGE_TOKEN") != null) {
apiKey = System.getenv("CURSEFORGE_TOKEN")
@ -219,3 +214,4 @@ tasks.register('publishToModSites') {
publishToModSites.dependsOn(tasks.modrinth)
publishToModSites.dependsOn(tasks.curseforge)
}
*/

42
common/build.gradle Normal file
View File

@ -0,0 +1,42 @@
architectury {
common(rootProject.enabled_platforms.split(","))
}
loom {
accessWidenerPath = file("src/main/resources/modernfix.accesswidener")
}
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}"
modApi("dev.latvian.mods:kubejs:${kubejs_version}") {
transitive = false
}
modApi("dev.latvian.mods:rhino:${rhino_version}") {
transitive = false
}
modApi("me.shedaniel:RoughlyEnoughItems-api:${rei_version}") {
transitive = false
}
modCompileOnly("me.shedaniel:RoughlyEnoughItems-fabric:${rei_version}") {
transitive = false
}
// Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury:${rootProject.architectury_version}"
}
publishing {
publications {
mavenCommon(MavenPublication) {
artifactId = rootProject.archives_base_name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}

View File

@ -0,0 +1,73 @@
package org.embeddedt.modernfix;
import net.minecraft.Util;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.util.ClassInfoManager;
import java.lang.management.ManagementFactory;
import java.util.concurrent.*;
// The value here should match an entry in the META-INF/mods.toml file
public class ModernFix {
// Directly reference a log4j logger.
public static final Logger LOGGER = LogManager.getLogger("ModernFix");
public static final String MODID = "modernfix";
public static ModernFix INSTANCE;
// Used to skip computing the blockstate caches twice
public static boolean runningFirstInjection = false;
private static ExecutorService resourceReloadService = null;
static {
if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.dedicated_reload_executor.ReloadExecutor")) {
resourceReloadService = Util.makeExecutor("ResourceReload");
} else {
resourceReloadService = Util.backgroundExecutor();
}
}
public static ExecutorService resourceReloadExecutor() {
return resourceReloadService;
}
public ModernFix() {
INSTANCE = this;
}
public void onServerStarted() {
if(ModernFixPlatformHooks.isDedicatedServer()) {
float gameStartTime = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f;
ModernFix.LOGGER.warn("Dedicated server took " + gameStartTime + " seconds to load");
}
ClassInfoManager.clear();
}
public void onLoadComplete() {
ClassInfoManager.clear();
}
public void onServerDead(MinecraftServer server) {
/* Clear as much data from the integrated server as possible, in case a mod holds on to it */
try {
for(ServerLevel level : server.getAllLevels()) {
ChunkMap chunkMap = level.getChunkSource().chunkMap;
chunkMap.updatingChunkMap.clear();
chunkMap.visibleChunkMap.clear();
chunkMap.pendingUnloads.clear();
}
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Couldn't clear chunk data", e);
}
}
}

View File

@ -0,0 +1,180 @@
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.Screen;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.MemoryReserve;
import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.world.IntegratedWatchdog;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.util.*;
public class ModernFixClient {
public static long worldLoadStartTime;
private static int numRenderTicks;
public static float gameStartTimeSeconds = -1;
private static boolean recipesUpdated, tagsUpdated = false;
public String brandingString = null;
public ModernFixClient() {
// clear reserve as it's not needed
MemoryReserve.release();
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.branding.F3Screen")) {
brandingString = "ModernFix " + ModernFixPlatformHooks.getVersionString();
}
}
public void resetWorldLoadStateMachine() {
numRenderTicks = 0;
worldLoadStartTime = -1;
recipesUpdated = false;
tagsUpdated = false;
}
public void onScreenOpening(Screen openingScreen) {
if(openingScreen instanceof ConnectScreen) {
worldLoadStartTime = System.nanoTime();
} else if (openingScreen instanceof TitleScreen && gameStartTimeSeconds < 0) {
gameStartTimeSeconds = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f;
ModernFix.LOGGER.warn("Game took " + gameStartTimeSeconds + " seconds to start");
}
}
public void onRecipesUpdated() {
recipesUpdated = true;
}
public void onTagsUpdated() {
tagsUpdated = true;
}
public void onRenderTickEnd() {
if(recipesUpdated
&& tagsUpdated
&& worldLoadStartTime != -1
&& Minecraft.getInstance().player != null
&& numRenderTicks++ >= 10) {
float timeSpentLoading = ((float)(System.nanoTime() - worldLoadStartTime) / 1000000000f);
ModernFix.LOGGER.warn("Time from main menu to in-game was " + timeSpentLoading + " seconds");
ModernFix.LOGGER.warn("Total time to load game and open world was " + (timeSpentLoading + gameStartTimeSeconds) + " seconds");
resetWorldLoadStateMachine();
}
}
/**
* 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) {
Map<Class<? extends Entity>, List<Pair<String, Integer>>> info = packet.getFieldInfo();
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();
}
}
public void onServerStarted(MinecraftServer server) {
IntegratedWatchdog watchdog = new IntegratedWatchdog(server);
watchdog.start();
}
}

View File

@ -0,0 +1,11 @@
package org.embeddedt.modernfix.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface ClientOnlyMixin {
}

View File

@ -0,0 +1,12 @@
package org.embeddedt.modernfix.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface RequiresMod {
String value() default "";
}

View File

@ -0,0 +1,16 @@
package org.embeddedt.modernfix.blockstate;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import org.embeddedt.modernfix.duck.IBlockState;
public class BlockStateCacheHandler {
public static void rebuildParallel(boolean force) {
synchronized (BlockBehaviour.BlockStateBase.class) {
for (BlockState blockState : Block.BLOCK_STATE_REGISTRY) {
((IBlockState)blockState).clearCache();
}
}
}
}

View File

@ -1,6 +1,5 @@
package org.embeddedt.modernfix.blockstate;
import com.google.common.collect.ImmutableSet;
import net.minecraft.world.level.block.state.properties.Property;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.bugfix.chunk_deadlock;
package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock;
import com.mojang.datafixers.util.Either;
import net.minecraft.core.Holder;

View File

@ -1,13 +1,15 @@
package org.embeddedt.modernfix.mixin.bugfix.concurrency;
package org.embeddedt.modernfix.common.mixin.bugfix.concurrency;
import net.minecraft.client.Minecraft;
import net.minecraft.util.thread.BlockableEventLoop;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import java.util.function.BooleanSupplier;
@Mixin(Minecraft.class)
@ClientOnlyMixin
public abstract class MinecraftMixin<R extends Runnable> extends BlockableEventLoop<R> {
protected MinecraftMixin(String p_i50403_1_) {

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.bugfix.edge_chunk_not_saved;
package org.embeddedt.modernfix.common.mixin.bugfix.edge_chunk_not_saved;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.bugfix.paper_chunk_patches;
package org.embeddedt.modernfix.common.mixin.bugfix.paper_chunk_patches;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.level.ChunkHolder;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.bugfix.paper_chunk_patches;
package org.embeddedt.modernfix.common.mixin.bugfix.paper_chunk_patches;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.MinecraftServer;
@ -9,8 +9,8 @@ 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.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraftforge.server.ServerLifecycleHooks;
import org.embeddedt.modernfix.duck.IPaperChunkHolder;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -45,10 +45,10 @@ public abstract class ChunkMapMixin {
@Shadow @Final private StructureTemplateManager structureTemplateManager;
private Executor mainInvokingExecutor;
@Inject(method = "<init>", at = @At("RETURN"), cancellable = true)
@Inject(method = "<init>", at = @At("RETURN"))
private void setup(CallbackInfo ci) {
this.mainInvokingExecutor = (runnable) -> {
if(ServerLifecycleHooks.getCurrentServer().isSameThread())
if(ModernFixPlatformHooks.getCurrentServer().isSameThread())
runnable.run();
else
this.mainThreadExecutor.execute(runnable);

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.bugfix.paper_chunk_patches;
package org.embeddedt.modernfix.common.mixin.bugfix.paper_chunk_patches;
import net.minecraft.util.SortedArraySet;
import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,14 +1,16 @@
package org.embeddedt.modernfix.mixin.core;
package org.embeddedt.modernfix.common.mixin.core;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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)
@ClientOnlyMixin
public class SynchedEntityDataMixin {
/**
* Store this in our set of all entity data objects.

View File

@ -1,13 +1,15 @@
package org.embeddedt.modernfix.mixin.devenv;
package org.embeddedt.modernfix.common.mixin.devenv;
import com.mojang.authlib.minecraft.UserApiService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.GameConfig;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(Minecraft.class)
@ClientOnlyMixin
public class MinecraftMixin {
@Overwrite
private UserApiService createUserApiService(YggdrasilAuthenticationService yggdrasilAuthenticationService, GameConfig arg) {

View File

@ -1,12 +1,14 @@
package org.embeddedt.modernfix.mixin.devenv;
package org.embeddedt.modernfix.common.mixin.devenv;
import com.mojang.text2speech.Narrator;
import net.minecraft.client.GameNarrator;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(GameNarrator.class)
@ClientOnlyMixin
public class NarratorMixin {
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/text2speech/Narrator;getNarrator()Lcom/mojang/text2speech/Narrator;", remap = false))
private Narrator useDummyNarrator() {

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.feature.direct_stack_trace;
package org.embeddedt.modernfix.common.mixin.feature.direct_stack_trace;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.feature.measure_time;
package org.embeddedt.modernfix.common.mixin.feature.measure_time;
import com.google.common.base.Stopwatch;
import net.minecraft.server.Bootstrap;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.feature.measure_time;
package org.embeddedt.modernfix.common.mixin.feature.measure_time;
import com.mojang.datafixers.util.Function4;
import net.minecraft.client.Minecraft;
@ -10,6 +10,7 @@ import net.minecraft.world.level.storage.WorldData;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -19,6 +20,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.Function;
@Mixin(Minecraft.class)
@ClientOnlyMixin
public class MinecraftMixin {
/* not supported in 1.19
private long datapackReloadStartTime;
@ -34,7 +36,7 @@ public class MinecraftMixin {
ModernFix.LOGGER.warn("Datapack reload took " + timeSpentReloading + " seconds.");
}
*/
@Inject(method = "m_261031_", at = @At("HEAD"), remap = false)
@Inject(method = "doWorldLoad", at = @At("HEAD"), remap = false)
private void recordWorldLoadStart(CallbackInfo ci) {
ModernFixClient.worldLoadStartTime = System.nanoTime();
}

View File

@ -1,11 +1,10 @@
package org.embeddedt.modernfix.mixin.feature.measure_time;
package org.embeddedt.modernfix.common.mixin.feature.measure_time;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.ProfiledReloadInstance;
import org.embeddedt.modernfix.util.NamedPreparableResourceListener;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.ArrayList;

View File

@ -1,22 +1,20 @@
package org.embeddedt.modernfix.mixin.feature.measure_time;
package org.embeddedt.modernfix.common.mixin.feature.measure_time;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import org.embeddedt.modernfix.core.config.ModernFixConfig;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(ReloadableResourceManager.class)
public class SimpleReloadableResourceManagerMixin {
// TODO maybe expose as a mixin config
private static final boolean ENABLE_DEBUG_RELOADER = Boolean.getBoolean("modernfix.debugReloader");
/**
* @author embeddedt
* @reason add ability to use this feature in modpacks
*/
@ModifyArg(method = "createReload", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleReloadInstance;create(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/List;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Z)Lnet/minecraft/server/packs/resources/ReloadInstance;"), index = 5)
private boolean enableDebugReloader(boolean bl) {
return bl || (ModernFixConfig.isLoaded() && ModernFixConfig.ENABLE_DEBUG_RELOADER.get());
return bl || ENABLE_DEBUG_RELOADER;
}
}

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.cache_blockstate_cache_arrays;
package org.embeddedt.modernfix.common.mixin.perf.cache_blockstate_cache_arrays;
import net.minecraft.world.level.block.SupportType;
import net.minecraft.core.Direction;

View File

@ -1,7 +1,8 @@
package org.embeddedt.modernfix.mixin.perf.cache_model_materials;
package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials;
import net.minecraft.client.renderer.block.model.multipart.MultiPart;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -10,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Collection;
@Mixin(MultiPart.class)
@ClientOnlyMixin
public class MultipartMixin {
private Collection<ResourceLocation> dependencyCache = null;
@Inject(method = "getDependencies", at = @At("HEAD"), cancellable = true)

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.cache_strongholds;
package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds;
import net.minecraft.Util;
import net.minecraft.core.Holder;
@ -10,10 +10,10 @@ import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraftforge.server.ServerLifecycleHooks;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.cache_strongholds;
package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.cache_upgraded_structures;
package org.embeddedt.modernfix.common.mixin.perf.cache_upgraded_structures;
import com.mojang.datafixers.DataFixer;
import net.minecraft.core.HolderGetter;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.compress_blockstate;
package org.embeddedt.modernfix.common.mixin.perf.compress_blockstate;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.compress_blockstate;
package org.embeddedt.modernfix.common.mixin.perf.compress_blockstate;
import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.MapCodec;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.dedicated_reload_executor;
package org.embeddedt.modernfix.common.mixin.perf.dedicated_reload_executor;
import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen;
import org.embeddedt.modernfix.ModernFix;

View File

@ -1,7 +1,8 @@
package org.embeddedt.modernfix.mixin.perf.dedicated_reload_executor;
package org.embeddedt.modernfix.common.mixin.perf.dedicated_reload_executor;
import net.minecraft.client.Minecraft;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@ -10,6 +11,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
@Mixin(Minecraft.class)
@ClientOnlyMixin
public class MinecraftMixin {
@Redirect(method = { "<init>", "reloadResourcePacks(Z)Ljava/util/concurrent/CompletableFuture;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;backgroundExecutor()Ljava/util/concurrent/ExecutorService;", ordinal = 0))
private ExecutorService getResourceReloadExecutor() {

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.dedicated_reload_executor;
package org.embeddedt.modernfix.common.mixin.perf.dedicated_reload_executor;
import net.minecraft.server.MinecraftServer;
import org.embeddedt.modernfix.ModernFix;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.dedicated_reload_executor;
package org.embeddedt.modernfix.common.mixin.perf.dedicated_reload_executor;
import net.minecraft.client.gui.screens.worldselection.WorldOpenFlows;
import org.embeddedt.modernfix.ModernFix;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.deduplicate_location;
package org.embeddedt.modernfix.common.mixin.perf.deduplicate_location;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.dedup.IdentifierCaches;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.dynamic_dfu;
package org.embeddedt.modernfix.common.mixin.perf.dynamic_dfu;
import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFixer;

View File

@ -1,8 +1,9 @@
package org.embeddedt.modernfix.mixin.perf.dynamic_resources;
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import net.minecraft.client.renderer.block.model.BlockElementFace;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.UVController;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -11,6 +12,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import java.lang.reflect.Type;
@Mixin(BlockElementFace.Deserializer.class)
@ClientOnlyMixin
public class BlockElementFaceDeserializerMixin {
@Redirect(method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/client/renderer/block/model/BlockElementFace;",

View File

@ -1,32 +1,19 @@
package org.embeddedt.modernfix.mixin.perf.dynamic_resources;
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.Util;
import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
@Mixin(BlockModelShaper.class)
@ClientOnlyMixin
public class BlockModelShaperMixin {
@Shadow @Final private ModelManager modelManager;

View File

@ -0,0 +1,71 @@
package org.embeddedt.modernfix.common.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.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
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(ItemModelShaper.class)
public abstract class ItemModelShaperMixin {
@Shadow public abstract ModelManager getModelManager();
private Map<Item, ModelResourceLocation> overrideLocationsVanilla;
public ItemModelShaperMixin() {
super();
}
private static final ModelResourceLocation SENTINEL_VANILLA = new ModelResourceLocation(new ResourceLocation("modernfix", "sentinel"), "sentinel");
@Inject(method = "<init>", at = @At("RETURN"))
private void replaceLocationMap(CallbackInfo ci) {
overrideLocationsVanilla = new HashMap<>();
}
@Unique
private ModelResourceLocation mfix$getLocation(Item item) {
ModelResourceLocation map = overrideLocationsVanilla.getOrDefault(item, SENTINEL_VANILLA);
if(map == SENTINEL_VANILLA) {
/* generate the appropriate location from our cache */
map = ModelLocationCache.get(item);
}
return map;
}
/**
* @reason Get the stored location for that item and meta, and get the model
* from that location from the model manager.
**/
@Overwrite
public BakedModel getItemModel(Item item) {
ModelResourceLocation map = mfix$getLocation(item);
return map == null ? null : getModelManager().getModel(map);
}
/**
* @reason Don't get all models during init (with dynamic loading, that would
* generate them all). Just store location instead.
**/
@Overwrite
public void register(Item item, ModelResourceLocation location) {
overrideLocationsVanilla.put(item, location);
}
/**
* @reason Disable cache rebuilding (with dynamic loading, that would generate
* all models).
**/
@Overwrite
public void rebuildCache() {}
}

View File

@ -1,14 +1,16 @@
package org.embeddedt.modernfix.mixin.perf.dynamic_resources;
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import net.minecraft.client.renderer.ItemModelShaper;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.world.item.Item;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ItemRenderer.class)
@ClientOnlyMixin
public class ItemRendererMixin {
/**
* Don't waste space putting all these locations into the cache, compute them on demand later.

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.dynamic_structure_manager;
package org.embeddedt.modernfix.common.mixin.perf.dynamic_structure_manager;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

View File

@ -1,25 +1,25 @@
package org.embeddedt.modernfix.mixin.perf.faster_texture_stitching;
package org.embeddedt.modernfix.common.mixin.perf.faster_texture_stitching;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.renderer.texture.Stitcher;
import net.minecraftforge.fml.ModLoader;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.textures.StbStitcher;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
@Mixin(Stitcher.class)
@ClientOnlyMixin
public class StitcherMixin<T extends Stitcher.Entry> {
@Shadow @Final private List<Stitcher.Holder<T>> texturesToBeStitched;
@ -36,7 +36,7 @@ public class StitcherMixin<T extends Stitcher.Entry> {
*/
@Inject(method = "stitch", at = @At("HEAD"), cancellable = true)
private void stitchFast(CallbackInfo ci) {
if(!ModLoader.isLoadingStateValid()) {
if(!ModernFixPlatformHooks.isLoadingNormally()) {
ModernFix.LOGGER.error("Using vanilla stitcher implementation due to invalid loading state");
return;
}
@ -57,7 +57,7 @@ public class StitcherMixin<T extends Stitcher.Entry> {
*/
@Inject(method = "gatherSprites", at = @At("HEAD"), cancellable = true)
private void gatherSpritesFast(Stitcher.SpriteLoader<T> spriteLoader, CallbackInfo ci) {
if(!ModLoader.isLoadingStateValid())
if(!ModernFixPlatformHooks.isLoadingNormally())
return;
ci.cancel();
for(StbStitcher.LoadableSpriteInfo<T> info : loadableSpriteInfos) {

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.model_optimizations;
package org.embeddedt.modernfix.common.mixin.perf.model_optimizations;
import com.google.common.collect.ImmutableSet;
import net.minecraft.world.level.block.state.properties.BooleanProperty;

View File

@ -1,10 +1,9 @@
package org.embeddedt.modernfix.mixin.perf.model_optimizations;
package org.embeddedt.modernfix.common.mixin.perf.model_optimizations;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.dedup.IdentifierCaches;
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.Redirect;
@Mixin(Property.class)

View File

@ -1,9 +1,10 @@
package org.embeddedt.modernfix.mixin.perf.model_optimizations;
package org.embeddedt.modernfix.common.mixin.perf.model_optimizations;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.client.renderer.block.model.multipart.Selector;
import net.minecraft.world.level.block.state.StateDefinition;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -13,6 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
@Mixin(Selector.class)
@ClientOnlyMixin
public class SelectorMixin {
private ConcurrentHashMap<StateDefinition<Block, BlockState>, Predicate<BlockState>> predicateCache = new ConcurrentHashMap<>();
@Inject(method = "getPredicate", at = @At("HEAD"), cancellable = true)

View File

@ -1,7 +1,8 @@
package org.embeddedt.modernfix.mixin.perf.model_optimizations;
package org.embeddedt.modernfix.common.mixin.perf.model_optimizations;
import com.mojang.math.Transformation;
import org.joml.Matrix4f;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@ -10,6 +11,7 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.Objects;
@Mixin(Transformation.class)
@ClientOnlyMixin
public class TransformationMatrixMixin {
@Shadow @Final private Matrix4f matrix;
private Integer cachedHashCode = null;

View File

@ -1,15 +1,12 @@
package org.embeddedt.modernfix.mixin.perf.nbt_memory_usage;
package org.embeddedt.modernfix.common.mixin.perf.nbt_memory_usage;
import com.google.common.collect.Maps;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import org.embeddedt.modernfix.util.CanonizingStringMap;
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.ModifyArg;
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.util.Map;

View File

@ -1,18 +1,13 @@
package org.embeddedt.modernfix.mixin.perf.reduce_blockstate_cache_rebuilds;
package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.duck.IBlockState;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.atomic.AtomicInteger;
@Mixin(BlockBehaviour.BlockStateBase.class)
public abstract class BlockStateBaseMixin implements IBlockState {

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.reduce_blockstate_cache_rebuilds;
package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds;
import net.minecraft.world.level.block.Blocks;
import org.embeddedt.modernfix.blockstate.BlockStateCacheHandler;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.remove_biome_temperature_cache;
package org.embeddedt.modernfix.common.mixin.perf.remove_biome_temperature_cache;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.biome.Biome;

View File

@ -1,10 +1,8 @@
package org.embeddedt.modernfix.mixin.perf.remove_spawn_chunks;
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.remove_spawn_chunks;
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerChunkCache;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.remove_spawn_chunks;
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;

View File

@ -1,10 +1,10 @@
package org.embeddedt.modernfix.mixin.perf.state_definition_construct;
package org.embeddedt.modernfix.common.mixin.perf.state_definition_construct;
import com.google.common.collect.ImmutableSortedMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.blockstate.FakeStateMap;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -15,6 +15,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.Map;
@Mixin(StateDefinition.class)
@RequiresMod("ferritecore")
public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
@Shadow @Final private ImmutableSortedMap<String, Property<?>> propertiesByName;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.thread_priorities;
package org.embeddedt.modernfix.common.mixin.perf.thread_priorities;
import net.minecraft.client.Minecraft;
import net.minecraft.server.Services;
@ -7,18 +7,18 @@ import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.client.server.IntegratedServer;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.config.ModernFixConfig;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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(IntegratedServer.class)
@ClientOnlyMixin
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();
int pri = 4;
thread.setPriority(pri);
}
}

View File

@ -1,8 +1,6 @@
package org.embeddedt.modernfix.mixin.perf.thread_priorities;
package org.embeddedt.modernfix.common.mixin.perf.thread_priorities;
import net.minecraft.Util;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.config.ModernFixConfig;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;

View File

@ -1,9 +1,7 @@
package org.embeddedt.modernfix.mixin.safety;
package org.embeddedt.modernfix.common.mixin.safety;
import net.minecraft.world.level.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.color.block.BlockColor;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -13,6 +11,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@Mixin(value = BlockColors.class, priority = 700)
@ClientOnlyMixin
public class BlockColorsMixin {
private Lock mapLock = new ReentrantLock();
@Inject(method = "register", at = @At("HEAD"))

View File

@ -1,6 +1,7 @@
package org.embeddedt.modernfix.mixin.safety;
package org.embeddedt.modernfix.common.mixin.safety;
import net.minecraft.client.color.item.ItemColors;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -10,6 +11,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@Mixin(value = ItemColors.class, priority = 700)
@ClientOnlyMixin
public class ItemColorsMixin {
private Lock mapLock = new ReentrantLock();
@Inject(method = "register", at = @At("HEAD"))

View File

@ -0,0 +1,128 @@
package org.embeddedt.modernfix.core;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.embeddedt.modernfix.core.config.ModernFixEarlyConfig;
import org.embeddedt.modernfix.core.config.Option;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.objectweb.asm.tree.*;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.io.File;
import java.util.*;
import java.util.regex.Pattern;
public class ModernFixMixinPlugin implements IMixinConfigPlugin {
private static final String MIXIN_PACKAGE_ROOT = "org.embeddedt.modernfix.mixin.";
public final Logger logger = LogManager.getLogger("ModernFix");
public ModernFixEarlyConfig config = null;
public static ModernFixMixinPlugin instance;
public ModernFixMixinPlugin() {
boolean firstConfig = instance == null;
if(firstConfig) {
instance = this;
try {
config = ModernFixEarlyConfig.load(new File("./config/modernfix-mixins.properties"));
} catch (Exception e) {
throw new RuntimeException("Could not load configuration file for ModernFix", e);
}
this.logger.info("Loaded configuration file for ModernFix: {} options available, {} override(s) found",
config.getOptionCount(), config.getOptionOverrideCount());
if(ModernFixEarlyConfig.OPTIFINE_PRESENT)
this.logger.fatal("OptiFine detected. Use of ModernFix with OptiFine is not supported due to its impact on launch time and breakage of Forge features.");
try {
Class.forName("sun.misc.Unsafe").getDeclaredMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class);
} catch(ReflectiveOperationException | NullPointerException e) {
this.logger.info("Applying Nashorn fix");
Properties properties = System.getProperties();
properties.setProperty("nashorn.args", properties.getProperty("nashorn.args", "") + " --anonymous-classes=false");
}
/* We abuse the constructor of a mixin plugin as a safe location to start modifying the classloader */
ModernFixPlatformHooks.injectPlatformSpecificHacks();
}
}
@Override
public void onLoad(String mixinPackage) {
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
mixinClassName = ModernFixEarlyConfig.sanitize(mixinClassName);
if (!mixinClassName.startsWith(MIXIN_PACKAGE_ROOT)) {
this.logger.error("Expected mixin '{}' to start with package root '{}', treating as foreign and " +
"disabling!", mixinClassName, MIXIN_PACKAGE_ROOT);
return false;
}
String mixin = mixinClassName.substring(MIXIN_PACKAGE_ROOT.length());
if(!instance.isOptionEnabled(mixin))
return false;
String disabledBecauseMod = instance.config.getPermanentlyDisabledMixins().get(mixin);
return disabledBecauseMod == null;
}
public boolean isOptionEnabled(String mixin) {
Option option = instance.config.getEffectiveOptionForMixin(mixin);
if (option == null) {
this.logger.error("No rules matched mixin '{}', treating as foreign and disabling!", mixin);
return false;
}
if (option.isOverridden()) {
String source = "[unknown]";
if (option.isUserDefined()) {
source = "user configuration";
} else if (option.isModDefined()) {
source = "mods [" + String.join(", ", option.getDefiningMods()) + "]";
}
if (option.isEnabled()) {
this.logger.warn("Force-enabling mixin '{}' as rule '{}' (added by {}) enables it", mixin,
option.getName(), source);
} else {
this.logger.warn("Force-disabling mixin '{}' as rule '{}' (added by {}) disables it and children", mixin,
option.getName(), source);
}
}
return option.isEnabled();
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
ModernFixPlatformHooks.applyASMTransformers(mixinClassName, targetClass);
}
}

View File

@ -1,16 +1,23 @@
package org.embeddedt.modernfix.core.config;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
import net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import net.minecraftforge.forgespi.locating.IModLocator;
import net.minecraftforge.forgespi.locating.IModProvider;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class ModernFixEarlyConfig {
@ -36,65 +43,140 @@ public class ModernFixEarlyConfig {
if(modId.equals("optifine"))
return OPTIFINE_PRESENT;
else
return FMLLoader.getLoadingModList().getModFileById(modId) != null;
return ModernFixPlatformHooks.modPresent(modId);
}
private static final String MIXIN_DESC = "Lorg/spongepowered/asm/mixin/Mixin;";
private static final String MIXIN_CLIENT_ONLY_DESC = "Lorg/embeddedt/modernfix/annotation/ClientOnlyMixin;";
private static final String MIXIN_REQUIRES_MOD_DESC = "Lorg/embeddedt/modernfix/annotation/RequiresMod;";
private static final Pattern PLATFORM_PREFIX = Pattern.compile("(forge|fabric|common)\\.");
public static String sanitize(String mixinClassName) {
return PLATFORM_PREFIX.matcher(mixinClassName).replaceFirst("");
}
private final Set<String> mixinOptions = new ObjectOpenHashSet<>();
private final Map<String, String> mixinsMissingMods = new Object2ObjectOpenHashMap<>();
public Map<String, String> getPermanentlyDisabledMixins() {
return mixinsMissingMods;
}
private void scanForAndBuildMixinOptions() {
List<String> configFiles = ImmutableList.of("modernfix-common.mixins.json", "modernfix-fabric.mixins.json", "modernfix-forge.mixins.json");
List<String> mixinPaths = new ArrayList<>();
for(String configFile : configFiles) {
InputStream stream = ModernFixEarlyConfig.class.getClassLoader().getResourceAsStream(configFile);
if(stream == null)
continue;
try(Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
JsonObject configObject = (JsonObject)new JsonParser().parse(reader);
JsonArray mixinList = configObject.getAsJsonArray("mixins");
String packageName = configObject.get("package").getAsString().replace('.', '/');
for(JsonElement mixin : mixinList) {
mixinPaths.add(packageName + "/" + mixin.getAsString().replace('.', '/') + ".class");
}
} catch(IOException | JsonParseException e) {
LOGGER.error("Error loading config " + configFile, e);
}
}
Splitter dotSplitter = Splitter.on('.');
for(String mixinPath : mixinPaths) {
try(InputStream stream = ModernFixEarlyConfig.class.getClassLoader().getResourceAsStream(mixinPath)) {
ClassReader reader = new ClassReader(stream);
ClassNode node = new ClassNode();
reader.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
if(node.invisibleAnnotations == null)
return;
boolean isMixin = false, isClientOnly = false, requiredModPresent = true;
String requiredModId = "";
for(AnnotationNode annotation : node.invisibleAnnotations) {
if(Objects.equals(annotation.desc, MIXIN_DESC)) {
isMixin = true;
} else if(Objects.equals(annotation.desc, MIXIN_CLIENT_ONLY_DESC)) {
isClientOnly = true;
} else if(Objects.equals(annotation.desc, MIXIN_REQUIRES_MOD_DESC)) {
for(int i = 0; i < annotation.values.size(); i += 2) {
if(annotation.values.get(i).equals("value")) {
String modId = (String)annotation.values.get(i + 1);
if(modId != null) {
requiredModPresent = modPresent(modId);
requiredModId = modId;
}
break;
}
}
}
}
if(isMixin) {
String mixinClassName = sanitize(node.name.replace('/', '.')).replace("org.embeddedt.modernfix.mixin.", "");
if(!requiredModPresent)
mixinsMissingMods.put(mixinClassName, requiredModId);
else if(isClientOnly && !ModernFixPlatformHooks.isClient())
mixinsMissingMods.put(mixinClassName, "[not client]");
List<String> mixinOptionNames = dotSplitter.splitToList(mixinClassName);
StringBuilder optionBuilder = new StringBuilder(mixinClassName.length());
optionBuilder.append("mixin");
for(int i = 0; i < mixinOptionNames.size() - 1; i++) {
optionBuilder.append('.');
optionBuilder.append(mixinOptionNames.get(i));
mixinOptions.add(optionBuilder.toString());
}
}
} catch(IOException e) {
ModernFix.LOGGER.error("Error scanning file " + mixinPath, e);
}
}
}
private static final boolean shouldReplaceSearchTrees;
private static final boolean isDevEnv = ModernFixPlatformHooks.isDevEnv();
static {
shouldReplaceSearchTrees = modPresent("jei");
}
private static final ImmutableMap<String, Boolean> DEFAULT_SETTING_OVERRIDES = ImmutableMap.<String, Boolean>builder()
.put("mixin.perf.dynamic_resources", false)
.put("mixin.feature.reduce_loading_screen_freezes", false)
.put("mixin.feature.direct_stack_trace", false)
.put("mixin.perf.rewrite_registry", false)
.put("mixin.perf.clear_mixin_classinfo", false)
.put("mixin.perf.compress_blockstate", false)
.put("mixin.bugfix.packet_leak", false)
.put("mixin.perf.deduplicate_location", false)
.put("mixin.perf.preload_block_classes", false)
.put("mixin.perf.faster_singleplayer_load", false)
.put("mixin.perf.blast_search_trees", shouldReplaceSearchTrees)
.put("mixin.devenv", isDevEnv)
.put("mixin.perf.remove_spawn_chunks", isDevEnv)
.build();
private ModernFixEarlyConfig(File file) {
this.configFile = file;
this.scanForAndBuildMixinOptions();
for(String optionName : mixinOptions) {
boolean defaultEnabled = DEFAULT_SETTING_OVERRIDES.getOrDefault(optionName, true);
this.options.putIfAbsent(optionName, new Option(optionName, defaultEnabled, false));
}
// Defines the default rules which can be configured by the user or other mods.
// You must manually add a rule for any new mixins not covered by an existing package rule.
this.addMixinRule("core", true); // TODO: Don't actually allow the user to disable this
this.addMixinRule("perf.modern_resourcepacks", true);
this.addMixinRule("feature.branding", true);
this.addMixinRule("feature.measure_time", true);
this.addMixinRule("feature.reduce_loading_screen_freezes", false);
this.addMixinRule("feature.direct_stack_trace", false);
this.addMixinRule("perf.fast_registry_validation", true);
this.addMixinRule("perf.skip_first_datapack_reload", true);
// not stable yet
this.addMixinRule("perf.rewrite_registry", false);
this.addMixinRule("perf.remove_biome_temperature_cache", true);
this.addMixinRule("perf.reduce_blockstate_cache_rebuilds", true);
this.addMixinRule("perf.model_optimizations", true);
this.addMixinRule("perf.dynamic_resources", false);
this.addMixinRule("perf.dynamic_entity_renderers", true);
this.addMixinRule("perf.dedicated_reload_executor", true);
/* Use a simpler ArrayMap if FerriteCore is using the map intelligently anyway */
this.addMixinRule("perf.state_definition_construct", modPresent("ferritecore"));
this.addMixinRule("perf.cache_strongholds", true);
this.addMixinRule("perf.clear_mixin_classinfo", false);
this.addMixinRule("perf.cache_upgraded_structures", true);
this.addMixinRule("perf.compress_blockstate", false);
this.addMixinRule("bugfix.concurrency", true);
this.addMixinRule("bugfix.edge_chunk_not_saved", true);
this.addMixinRule("perf.fast_forge_dummies", true);
this.addMixinRule("perf.dynamic_structure_manager", true);
this.addMixinRule("bugfix.chunk_deadlock", true);
this.addMixinRule("bugfix.remove_block_chunkloading", true);
this.addMixinRule("bugfix.paper_chunk_patches", true);
this.addMixinRule("perf.thread_priorities", true);
this.addMixinRule("perf.scan_cache", true);
this.addMixinRule("perf.kubejs", modPresent("kubejs"));
this.addMixinRule("perf.flatten_model_predicates", true);
this.addMixinRule("perf.tag_id_caching", true);
this.addMixinRule("perf.deduplicate_location", false);
this.addMixinRule("perf.cache_blockstate_cache_arrays", true);
this.addMixinRule("perf.cache_model_materials", true);
this.addMixinRule("perf.nbt_memory_usage", true);
this.addMixinRule("perf.patchouli_deduplicate_books", modPresent("patchouli"));
this.addMixinRule("perf.datapack_reload_exceptions", true);
this.addMixinRule("perf.dynamic_dfu", true);
this.addMixinRule("perf.faster_texture_stitching", true);
/* 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/REI isn't installed to prevent breaking vanilla gameplay */
this.addMixinRule("perf.blast_search_trees", FMLLoader.getLoadingModList().getModFileById("jei") != null || FMLLoader.getLoadingModList().getModFileById("roughlyenoughitems") != null);
this.addMixinRule("safety", true);
this.addMixinRule("launch.class_search_cache", true);
IModProvider mfLocator = FMLLoader.getLoadingModList().getModFileById("modernfix").getFile().getProvider();
boolean isDevEnv = !FMLLoader.isProduction() && (mfLocator instanceof ExplodedDirectoryLocator || mfLocator instanceof MinecraftLocator);
this.addMixinRule("devenv", isDevEnv);
this.addMixinRule("perf.remove_spawn_chunks", isDevEnv);
/*
this.addMixinRule("perf.use_integrated_resources.jepb", modPresent("jepb"));
this.addMixinRule("perf.use_integrated_resources.jeresources", modPresent("jeresources"));
this.addMixinRule("perf.jeresources_startup", modPresent("jeresources"));
this.addMixinRule("perf.state_definition_construct", modPresent("ferritecore"));
this.addMixinRule("bugfix.starlight_emptiness", modPresent("starlight"));
this.addMixinRule("bugfix.chunk_deadlock.valhesia", modPresent("valhelsia_structures"));
this.addMixinRule("bugfix.tf_cme_on_load", modPresent("twilightforest"));
this.addMixinRule("bugfix.refinedstorage", modPresent("refinedstorage"));
this.addMixinRule("perf.async_jei", modPresent("jei"));
this.addMixinRule("perf.patchouli_deduplicate_books", modPresent("patchouli"));
this.addMixinRule("perf.kubejs", modPresent("kubejs"));
*/
/* Mod compat */
disableIfModPresent("mixin.perf.thread_priorities", "smoothboot");

View File

@ -12,7 +12,6 @@ import org.embeddedt.modernfix.ModernFix;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.IntFunction;

View File

@ -1,7 +1,6 @@
package org.embeddedt.modernfix.dfu;
import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFix;
import com.mojang.datafixers.DataFixUtils;
import com.mojang.datafixers.DataFixer;
import com.mojang.datafixers.schemas.Schema;

View File

@ -1,6 +1,5 @@
package org.embeddedt.modernfix.duck;
import org.embeddedt.modernfix.util.BakeReason;
public interface IBlockState {
void clearCache();

View File

@ -11,7 +11,6 @@ import org.apache.commons.lang3.tuple.Triple;
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Map;
@ -76,7 +75,6 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
}
}
@Nullable
@Override
public BakedModel put(ResourceLocation resourceLocation, BakedModel bakedModel) {
BakedModel m = permanentOverrides.put(resourceLocation, bakedModel);

View File

@ -0,0 +1,65 @@
package org.embeddedt.modernfix.dynamicresources;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.*;
public class ModelBakeryHelpers {
private static <T extends Comparable<T>, V extends T> BlockState setPropertyGeneric(BlockState state, Property<T> prop, Object o) {
return state.setValue(prop, (V)o);
}
private static <T extends Comparable<T>> T getValueHelper(Property<T> property, String value) {
return property.getValue(value).orElse((T) null);
}
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
private static final Splitter EQUAL_SPLITTER = Splitter.on('=').limit(2);
public static ImmutableList<BlockState> getBlockStatesForMRL(StateDefinition<Block, BlockState> stateDefinition, ModelResourceLocation location) {
if(Objects.equals(location.getVariant(), "inventory"))
return ImmutableList.of();
Set<Property<?>> fixedProperties = new HashSet<>();
BlockState fixedState = stateDefinition.any();
for(String s : COMMA_SPLITTER.split(location.getVariant())) {
Iterator<String> iterator = EQUAL_SPLITTER.split(s).iterator();
if (iterator.hasNext()) {
String s1 = iterator.next();
Property<?> property = stateDefinition.getProperty(s1);
if (property != null && iterator.hasNext()) {
String s2 = iterator.next();
Object value = getValueHelper(property, s2);
if (value == null) {
throw new RuntimeException("Unknown value: '" + s2 + "' for blockstate property: '" + s1 + "' " + property.getPossibleValues());
}
fixedState = setPropertyGeneric(fixedState, property, value);
fixedProperties.add(property);
} else if (!s1.isEmpty()) {
throw new RuntimeException("Unknown blockstate property: '" + s1 + "'");
}
}
}
// generate all possible blockstates from the remaining properties
ArrayList<Property<?>> anyProperties = new ArrayList<>(stateDefinition.getProperties());
anyProperties.removeAll(fixedProperties);
ArrayList<BlockState> finalList = new ArrayList<>();
finalList.add(fixedState);
for(Property<?> property : anyProperties) {
ArrayList<BlockState> newPermutations = new ArrayList<>();
for(BlockState state : finalList) {
for(Comparable<?> value : property.getPossibleValues()) {
newPermutations.add(setPropertyGeneric(state, property, value));
}
}
finalList = newPermutations;
}
return ImmutableList.copyOf(finalList);
}
}

View File

@ -3,22 +3,13 @@ package org.embeddedt.modernfix.dynamicresources;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.Util;
import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class ModelLocationCache {
@ -36,7 +27,7 @@ public class ModelLocationCache {
.build(new CacheLoader<Item, ModelResourceLocation>() {
@Override
public ModelResourceLocation load(Item key) throws Exception {
return new ModelResourceLocation(ForgeRegistries.ITEMS.getKey(key), "inventory");
return new ModelResourceLocation(BuiltInRegistries.ITEM.getKey(key), "inventory");
}
});

View File

@ -0,0 +1,57 @@
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.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
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;
@SuppressWarnings("unchecked")
public static void onDatapackSyncEvent(ServerPlayer targetPlayer) {
if(targetPlayer != null) {
/* Compute the current set of serializer IDs in use and send them */
if(fieldsToSyncMap == null) {
fieldsToSyncMap = new HashMap<>();
Map<Class<? extends Entity>, Integer> entityPoolMap = SynchedEntityData.ENTITY_ID_POOL;
List<Field> fieldsToSync = new ArrayList<>();
for(Class<? extends Entity> eClass : entityPoolMap.keySet()) {
fieldsToSync.clear();
try {
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));
}
} catch(Throwable e) {
ModernFix.LOGGER.error("Skipping entity ID sync for {}: {}", eClass.getName(), e);
}
}
}
EntityIDSyncPacket packet = new EntityIDSyncPacket(fieldsToSyncMap);
ModernFix.LOGGER.debug("Sending ID correction packet to client with " + fieldsToSyncMap.size() + " classes");
ModernFixPlatformHooks.sendPacket(targetPlayer, packet);
}
}
}

View File

@ -0,0 +1,71 @@
package org.embeddedt.modernfix.platform;
import com.mojang.blaze3d.platform.NativeImage;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import org.objectweb.asm.tree.ClassNode;
import java.io.IOException;
import java.nio.file.Path;
public class ModernFixPlatformHooks {
@ExpectPlatform
public static boolean isClient() {
throw new AssertionError();
}
@ExpectPlatform
public static boolean isDedicatedServer() {
throw new AssertionError();
}
@ExpectPlatform
public static String getVersionString() {
throw new AssertionError();
}
@ExpectPlatform
public static boolean modPresent(String modId) {
throw new AssertionError();
}
@ExpectPlatform
public static boolean isDevEnv() {
throw new AssertionError();
}
@ExpectPlatform
public static void injectPlatformSpecificHacks() {
throw new AssertionError();
}
@ExpectPlatform
public static void applyASMTransformers(String mixinClassName, ClassNode targetClass) {
throw new AssertionError();
}
@ExpectPlatform
public static MinecraftServer getCurrentServer() {
throw new AssertionError();
}
@ExpectPlatform
public static boolean isLoadingNormally() {
throw new AssertionError();
}
@ExpectPlatform
public static Path getGameDirectory() {
throw new AssertionError();
}
@ExpectPlatform
public static void sendPacket(ServerPlayer player, Object packet) {
throw new AssertionError();
}
}

View File

@ -2,8 +2,6 @@ package org.embeddedt.modernfix.resources;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;

View File

@ -6,15 +6,13 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import javax.annotation.Nullable;
public class ModernFixConfigScreen extends Screen {
private OptionList optionList;
private Screen lastScreen;
public boolean madeChanges = false;
private Button doneButton;
public ModernFixConfigScreen(@Nullable Screen lastScreen) {
public ModernFixConfigScreen(Screen lastScreen) {
super(Component.translatable("modernfix.config"));
this.lastScreen = lastScreen;
}

View File

@ -3,12 +3,10 @@ package org.embeddedt.modernfix.screen;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.ChatFormatting;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
@ -20,7 +18,6 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
@ -38,7 +35,7 @@ public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
this.mainScreen = arg;
int maxW = 0;
Map<String, Option> optionMap = ModernFixMixinPlugin.config.getOptionMap();
Map<String, Option> optionMap = ModernFixMixinPlugin.instance.config.getOptionMap();
List<String> sortedKeys = optionMap.keySet().stream().filter(key -> !key.equals("mixin.core")).sorted().collect(Collectors.toList());
for(String key : sortedKeys) {
Option option = optionMap.get(key);
@ -69,7 +66,7 @@ public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
this.toggleButton = new Button.Builder(Component.literal(""), (arg) -> {
this.option.setEnabled(!this.option.isEnabled(), !this.option.isUserDefined());
try {
ModernFixMixinPlugin.config.save();
ModernFixMixinPlugin.instance.config.save();
if(!OptionList.this.mainScreen.madeChanges) {
OptionList.this.mainScreen.madeChanges = true;
}

View File

@ -1,7 +1,6 @@
package org.embeddedt.modernfix.structure;
import com.mojang.datafixers.DataFixer;
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import net.minecraft.SharedConstants;
import net.minecraft.core.HolderGetter;
import net.minecraft.nbt.CompoundTag;
@ -11,16 +10,23 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.datafix.DataFixTypes;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraftforge.fml.loading.FMLPaths;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.util.FileUtil;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class CachingStructureManager {
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> LamdbaExceptionUtils.uncheck(() -> MessageDigest.getInstance("SHA-256")));
private static final File STRUCTURE_CACHE_FOLDER = FileUtil.childFile(FMLPaths.GAMEDIR.get().resolve("modernfix").resolve("structureCacheV1").toFile());
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
try {
return MessageDigest.getInstance("SHA-256");
} catch(NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
});
private static final File STRUCTURE_CACHE_FOLDER = FileUtil.childFile(ModernFixPlatformHooks.getGameDirectory().resolve("modernfix").resolve("structureCacheV1").toFile());
static {
STRUCTURE_CACHE_FOLDER.mkdirs();

View File

@ -16,7 +16,6 @@ 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;
@ -191,10 +190,13 @@ public class StbStitcher {
throw new StitcherException(holder.entry(),
Stream.of(holders).map(Stitcher.Holder::entry).collect(ImmutableList.toImmutableList()));
}
}
for (STBRPRect rect : rectBuf) {
Stitcher.Holder<T> holder = holders[rect.id()];
// Initialize the sprite now with the position and size that we've calculated so far
infoList.add(new LoadableSpriteInfo(holder.entry(), longestWidth, longestHeight, getX(rect), getY(rect)));
//holder.spriteInfo.initSprite(size, size, rect.x(), rect.y(), false);
}
return Pair.of(Pair.of(longestWidth, longestHeight), infoList);

View File

@ -1,10 +1,6 @@
package org.embeddedt.modernfix.util;
import com.google.common.collect.ImmutableMap;
import cpw.mods.jarhandling.SecureJar;
import cpw.mods.jarhandling.impl.Jar;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.forgespi.language.IModFileInfo;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.jetbrains.annotations.NotNull;
@ -41,6 +37,8 @@ public class ClassInfoManager {
// Clear manifest entries
int numManifestsCleared = 0;
// TODO port
/*
for(IModFileInfo mod : ModList.get().getModFiles()) {
Manifest manifest = mod.getFile().getSecureJar().moduleDataProvider().getManifest();
if(manifest.getEntries() instanceof HashMap<String, Attributes> entryMap) {
@ -56,6 +54,8 @@ public class ClassInfoManager {
}
}
}
*/
if(numManifestsCleared > 0)
ModernFix.LOGGER.info("Cleared {} manifest attributes", numManifestsCleared);
@ -68,6 +68,7 @@ public class ClassInfoManager {
}
private static void clearSecureJarStructs() throws Throwable {
/*
// Clear Jar signing data
Unsafe unsafe;
Field f = Unsafe.class.getDeclaredField("theUnsafe");
@ -91,6 +92,8 @@ public class ClassInfoManager {
unsafe.putObject(secureJar, verifiedSignersOffset, EmptyCodeSignerTable.INSTANCE);
}
}
*/
}
static class EmptyCodeSignerTable extends Hashtable<String, CodeSigner[]> {

View File

@ -11,7 +11,6 @@ import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.WorldData;
import net.minecraft.world.level.storage.ServerLevelData;
import javax.annotation.Nullable;
import java.util.Set;
public class DummyServerConfiguration implements WorldData {
@ -40,14 +39,13 @@ public class DummyServerConfiguration implements WorldData {
}
@Nullable
@Override
public CompoundTag getCustomBossEvents() {
return null;
}
@Override
public void setCustomBossEvents(@Nullable CompoundTag nbt) {
public void setCustomBossEvents(CompoundTag nbt) {
}
@ -62,7 +60,7 @@ public class DummyServerConfiguration implements WorldData {
}
@Override
public CompoundTag createTag(RegistryAccess registries, @Nullable CompoundTag hostPlayerNBT) {
public CompoundTag createTag(RegistryAccess registries, CompoundTag hostPlayerNBT) {
return null;
}

View File

@ -1,7 +1,6 @@
package org.embeddedt.modernfix.util;
import java.io.File;
import java.util.regex.Pattern;
public class FileUtil {
public static File childFile(File file) {

View File

@ -1,9 +1,8 @@
package org.embeddedt.modernfix.util;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.Holder;
import net.minecraft.world.item.Item;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -12,16 +11,16 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public class ItemMesherMap implements Map<Holder.Reference<Item>, ModelResourceLocation> {
private final Function<Item, ModelResourceLocation> getLocation;
public class ItemMesherMap<K> implements Map<K, ModelResourceLocation> {
private final Function<K, ModelResourceLocation> getLocation;
public ItemMesherMap(Function<Item, ModelResourceLocation> getLocation) {
public ItemMesherMap(Function<K, ModelResourceLocation> getLocation) {
this.getLocation = getLocation;
}
@Override
public int size() {
return ForgeRegistries.ITEMS.getValues().size();
return BuiltInRegistries.ITEM.keySet().size();
}
@Override
@ -41,12 +40,12 @@ public class ItemMesherMap implements Map<Holder.Reference<Item>, ModelResourceL
@Override
public ModelResourceLocation get(Object key) {
return getLocation.apply(((Holder.Reference<Item>)key).get());
return getLocation.apply((K)key);
}
@Nullable
@Override
public ModelResourceLocation put(Holder.Reference<Item> key, ModelResourceLocation value) {
public ModelResourceLocation put(K key, ModelResourceLocation value) {
throw new UnsupportedOperationException();
}
@ -56,7 +55,7 @@ public class ItemMesherMap implements Map<Holder.Reference<Item>, ModelResourceL
}
@Override
public void putAll(@NotNull Map<? extends Holder.Reference<Item>, ? extends ModelResourceLocation> m) {
public void putAll(@NotNull Map<? extends K, ? extends ModelResourceLocation> m) {
throw new UnsupportedOperationException();
}
@ -67,7 +66,7 @@ public class ItemMesherMap implements Map<Holder.Reference<Item>, ModelResourceL
@NotNull
@Override
public Set<Holder.Reference<Item>> keySet() {
public Set<K> keySet() {
throw new UnsupportedOperationException();
}
@ -79,7 +78,7 @@ public class ItemMesherMap implements Map<Holder.Reference<Item>, ModelResourceL
@NotNull
@Override
public Set<Map.Entry<Holder.Reference<Item>, ModelResourceLocation>> entrySet() {
public Set<Map.Entry<K, ModelResourceLocation>> entrySet() {
throw new UnsupportedOperationException();
}
}

Some files were not shown because too many files have changed in this diff Show More