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

This commit is contained in:
embeddedt 2023-05-01 19:46:23 -04:00
commit d9c2e0f342
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
189 changed files with 2668 additions and 1910 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,92 +1,128 @@
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.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip")
}
}
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.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}")
@ -101,7 +137,7 @@ dependencies {
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
@ -110,7 +146,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
@ -118,36 +157,6 @@ tasks.withType(JavaCompile) {
*/
}
processResources {
def mixinFileList = []
def mixinDirectory = file("src/main/java/org/embeddedt/modernfix/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
filesMatching("modernfix.mixins.json") {
expand replacements
}
}
task generateChangelog(type: se.bjurr.gitchangelog.plugin.gradle.GitChangelogTask) {
def details = versionDetails();
if(details.commitDistance > 0) {
@ -164,46 +173,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")
@ -247,3 +217,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,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,4 +1,4 @@
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;

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,4 +1,4 @@
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;

View File

@ -1,4 +1,4 @@
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;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.devenv;
package org.embeddedt.modernfix.common.mixin.devenv;
import com.mojang.text2speech.Narrator;
import net.minecraft.client.GameNarrator;

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;
@ -9,12 +9,10 @@ import net.minecraft.core.RegistryAccess;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.Function;
@ -36,8 +34,4 @@ public class MinecraftMixin {
ModernFix.LOGGER.warn("Datapack reload took " + timeSpentReloading + " seconds.");
}
*/
@Inject(method = "m_231380_", 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,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.cache_model_materials;
package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials;
import com.mojang.datafixers.util.Either;
import net.minecraft.client.renderer.block.model.BlockModel;

View File

@ -1,4 +1,4 @@
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;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.cache_model_materials;
package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.block.model.BlockModel;

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;
@ -9,10 +9,10 @@ import net.minecraft.world.level.chunk.ChunkGenerator;
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.resources.ResourceKey;

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.resources.ResourceLocation;

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,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.Minecraft;
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.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.DataFixer;
import net.minecraft.util.datafix.DataFixers;

View File

@ -1,4 +1,4 @@
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;

View File

@ -1,31 +1,16 @@
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

View File

@ -0,0 +1,70 @@
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.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("modernfix", "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,4 +1,4 @@
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;

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,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.faster_font_loading;
package org.embeddedt.modernfix.common.mixin.perf.faster_font_loading;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.client.gui.font.providers.LegacyUnicodeBitmapsProvider;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.mixin.perf.faster_texture_loading;
package org.embeddedt.modernfix.common.mixin.perf.faster_texture_loading;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.datafixers.util.Pair;
@ -9,12 +9,10 @@ import net.minecraft.client.resources.metadata.animation.AnimationMetadataSectio
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.fml.ModLoader;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -44,7 +42,7 @@ public abstract class TextureAtlasMixin {
*/
@Redirect(method = "prepareToStitch", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/TextureAtlas;getBasicSpriteInfos(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/Set;)Ljava/util/Collection;"))
private Collection<TextureAtlasSprite.Info> loadImages(TextureAtlas atlas, ResourceManager manager, Set<ResourceLocation> imageLocations) {
usingFasterLoad = ModLoader.isLoadingStateValid();
usingFasterLoad = ModernFixPlatformHooks.isLoadingNormally();
// bail if Forge is erroring to avoid AT crashes
if(!usingFasterLoad) {
return getBasicSpriteInfos(manager, imageLocations);
@ -103,10 +101,8 @@ public abstract class TextureAtlasMixin {
} else {
TextureAtlasSprite sprite = null;
try {
sprite = ForgeHooksClient.loadTextureAtlasSprite((TextureAtlas)(Object)this, resourceManager, spriteInfo, pair.getFirst(), storageX, storageY, x, y, mipLevel, pair.getSecond());
if(sprite == null)
sprite = new TextureAtlasSprite((TextureAtlas)(Object)this, spriteInfo, mipLevel, storageX, storageY, x, y, pair.getSecond());
} catch(IOException | RuntimeException e) {
sprite = ModernFixPlatformHooks.loadTextureAtlasSprite((TextureAtlas)(Object)this, resourceManager, spriteInfo, pair.getFirst(), storageX, storageY, x, y, mipLevel, pair.getSecond());
} catch(RuntimeException | IOException e) {
ModernFix.LOGGER.error("Error loading texture {}: {}", spriteInfo.name(), e);
}
cir.setReturnValue(sprite);

View File

@ -1,21 +1,19 @@
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;
@ -38,7 +36,7 @@ public class StitcherMixin {
*/
@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;
}
@ -59,7 +57,7 @@ public class StitcherMixin {
*/
@Inject(method = "gatherSprites", at = @At("HEAD"), cancellable = true)
private void gatherSpritesFast(Stitcher.SpriteLoader spriteLoader, CallbackInfo ci) {
if(!ModLoader.isLoadingStateValid())
if(!ModernFixPlatformHooks.isLoadingNormally())
return;
ci.cancel();
for(StbStitcher.LoadableSpriteInfo 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,4 +1,4 @@
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;

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.mojang.math.Matrix4f;
import com.mojang.math.Transformation;

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,9 +7,7 @@ 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.annotation.ClientOnlyMixin;
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.Inject;
@ -20,7 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
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,6 @@
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;

View File

@ -1,4 +1,4 @@
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;

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,31 +1,24 @@
package org.embeddedt.modernfix.core.config;
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 net.minecraftforge.api.distmarker.Dist;
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 net.minecraftforge.forgespi.locating.IModFile;
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 org.objectweb.asm.tree.TypeAnnotationNode;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ModernFixEarlyConfig {
private static final Logger LOGGER = LogManager.getLogger("ModernFixConfig");
@ -50,13 +43,19 @@ 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<>();
@ -65,73 +64,77 @@ public class ModernFixEarlyConfig {
}
private void scanForAndBuildMixinOptions() {
IModFile file = FMLLoader.getLoadingModList().getModFileById("modernfix").getFile();
Path mixinFolder = file.findResource("org", "embeddedt", "modernfix", "mixin");
try(Stream<Path> mixinFiles = Files.find(mixinFolder, Integer.MAX_VALUE, (p, a) -> true)) {
Splitter dotSplitter = Splitter.on('.');
// filter via toString
mixinFiles
.filter(p -> {
Path fileName = p.getFileName();
return fileName != null && fileName.toString().endsWith(".class");
})
.forEach(path -> {
try(InputStream stream = Files.newInputStream(path)) {
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;
}
}
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 = node.name.replace("org/embeddedt/modernfix/mixin/", "").replace('/', '.');
if(!requiredModPresent)
mixinsMissingMods.put(mixinClassName, requiredModId);
else if(isClientOnly && FMLLoader.getDist() != Dist.CLIENT)
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 " + path, e);
}
});
} catch(IOException e) {
ModernFix.LOGGER.error("Error scanning for mixins", e);
}
}
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 = !FMLLoader.isProduction() && FMLLoader.getLoadingModList().getModFileById("modernfix").getFile().getProvider() instanceof ExplodedDirectoryLocator;;
private static final boolean isDevEnv = ModernFixPlatformHooks.isDevEnv();
static {
Optional<ModInfo> jeiMod = FMLLoader.getLoadingModList().getMods().stream().filter(mod -> mod.getModId().equals("jei")).findFirst();
shouldReplaceSearchTrees = (jeiMod.isPresent() && jeiMod.get().getVersion().getMajorVersion() >= 10) || FMLLoader.getLoadingModList().getModFileById("roughlyenoughitems") != null;
shouldReplaceSearchTrees = modPresent("jei");
}
private static final ImmutableMap<String, Boolean> DEFAULT_SETTING_OVERRIDES = ImmutableMap.<String, Boolean>builder()

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

@ -2,7 +2,6 @@ package org.embeddedt.modernfix.dynamicresources;
import com.mojang.math.Transformation;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.BlockModelRotation;
import net.minecraft.client.resources.model.BuiltInModel;
@ -11,7 +10,6 @@ import net.minecraft.resources.ResourceLocation;
import org.apache.commons.lang3.tuple.Triple;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Map;
@ -75,7 +73,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,306 @@
package org.embeddedt.modernfix.dynamicresources;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.gson.*;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.FallbackResourceManager;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
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 org.embeddedt.modernfix.ModernFix;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static net.minecraft.client.resources.model.ModelBakery.BLOCK_ENTITY_MARKER;
import static net.minecraft.client.resources.model.ModelBakery.GENERATION_MARKER;
public class ModelBakeryHelpers {
private static void gatherAdditionalViaManualScan(List<PackResources> untrustedPacks, Set<ResourceLocation> knownLocations,
Collection<ResourceLocation> uncertainLocations, String filePrefix) {
if(untrustedPacks.size() > 0) {
/* Now make a fallback resource manager and use it on the remaining packs to see if they actually contain these files */
FallbackResourceManager frm = new FallbackResourceManager(PackType.CLIENT_RESOURCES, "dummy");
for (int i = untrustedPacks.size() - 1; i >= 0; i--) {
frm.push(untrustedPacks.get(i));
}
for (ResourceLocation blockstate : uncertainLocations) {
if (knownLocations.contains(blockstate))
continue; // don't check ones we know exist
ResourceLocation fileLocation = new ResourceLocation(blockstate.getNamespace(), filePrefix + blockstate.getPath() + ".json");
Optional<Resource> resource = frm.getResource(fileLocation);
if(resource.isPresent())
knownLocations.add(blockstate);
}
}
}
private static final int ERROR_THRESHOLD = 200;
private static void logOrSuppressError(Object2IntOpenHashMap<String> suppressionMap, String type, ResourceLocation location, Throwable e) {
int numErrors;
synchronized (suppressionMap) {
numErrors = suppressionMap.computeInt(location.getNamespace(), (k, oldVal) -> (oldVal == null ? 1 : oldVal + 1));
}
if(numErrors <= ERROR_THRESHOLD)
ModernFix.LOGGER.error("Error reading {} {}: {}", type, location, e);
}
public static void gatherModelMaterials(ResourceManager manager, Predicate<PackResources> isTrustedPack,
Set<Material> materialSet, Set<ResourceLocation> blockStateFiles,
Set<ResourceLocation> modelFiles, UnbakedModel missingModel,
Function<JsonElement, BlockModel> modelDeserializer,
Function<ResourceLocation, UnbakedModel> bakeryModelGetter) {
Stopwatch stopwatch = Stopwatch.createStarted();
final Object2IntOpenHashMap<String> blockstateErrors = new Object2IntOpenHashMap<>();
/*
* First, gather all vanilla packs, and use listResources on them. This will allow us to (hopefully) avoid
* scanning most packs a lot.
*/
List<PackResources> allPackResources = new ArrayList<>(manager.listPacks().collect(Collectors.toList()));
Collections.reverse(allPackResources);
ObjectOpenHashSet<ResourceLocation> allAvailableModels = new ObjectOpenHashSet<>(), allAvailableStates = new ObjectOpenHashSet<>();
allPackResources.removeIf(pack -> {
if(isTrustedPack.test(pack)) {
for(String namespace : pack.getNamespaces(PackType.CLIENT_RESOURCES)) {
Collection<ResourceLocation> allBlockstates = pack.getResources(PackType.CLIENT_RESOURCES, namespace, "blockstates", p -> p.getPath().endsWith(".json"));
for(ResourceLocation blockstate : allBlockstates) {
allAvailableStates.add(new ResourceLocation(blockstate.getNamespace(), blockstate.getPath().replace("blockstates/", "").replace(".json", "")));
}
Collection<ResourceLocation> allModels = pack.getResources(PackType.CLIENT_RESOURCES, namespace, "models", p -> p.getPath().endsWith(".json"));
for(ResourceLocation blockstate : allModels) {
allAvailableModels.add(new ResourceLocation(blockstate.getNamespace(), blockstate.getPath().replace("models/", "").replace(".json", "")));
}
}
return true;
}
ModernFix.LOGGER.debug("Pack with class {} needs manual scan", pack.getClass().getName());
return false;
});
gatherAdditionalViaManualScan(allPackResources, allAvailableStates, blockStateFiles, "blockstates/");
// We now have a list of all blockstates known to exist. Delete anything that we don't have
blockStateFiles.retainAll(allAvailableStates);
allAvailableStates.clear();
allAvailableStates.trim();
ConcurrentLinkedQueue<Pair<ResourceLocation, JsonElement>> blockStateLoadedFiles = new ConcurrentLinkedQueue<>();
List<CompletableFuture<Void>> blockStateData = new ArrayList<>();
for(ResourceLocation blockstate : blockStateFiles) {
blockStateData.add(CompletableFuture.runAsync(() -> {
ResourceLocation fileLocation = new ResourceLocation(blockstate.getNamespace(), "blockstates/" + blockstate.getPath() + ".json");
try {
List<Resource> resources = manager.getResourceStack(fileLocation);
for(Resource resource : resources) {
JsonParser parser = new JsonParser();
try(InputStream stream = resource.open()) {
blockStateLoadedFiles.add(Pair.of(blockstate, parser.parse(new InputStreamReader(stream, StandardCharsets.UTF_8))));
} catch(JsonParseException e) {
logOrSuppressError(blockstateErrors, "blockstate", blockstate, e);
}
}
} catch(IOException e) {
logOrSuppressError(blockstateErrors, "blockstate", blockstate, e);
}
}, ModernFix.resourceReloadExecutor()));
}
blockStateFiles = null;
CompletableFuture.allOf(blockStateData.toArray(new CompletableFuture[0])).join();
for(Pair<ResourceLocation, JsonElement> pair : blockStateLoadedFiles) {
if(pair.getSecond() != null) {
try {
JsonObject obj = pair.getSecond().getAsJsonObject();
if(obj.has("variants")) {
JsonObject eachVariant = obj.getAsJsonObject("variants");
for(Map.Entry<String, JsonElement> entry : eachVariant.entrySet()) {
JsonElement variantData = entry.getValue();
List<JsonObject> variantModels;
if(variantData.isJsonArray()) {
variantModels = new ArrayList<>();
for(JsonElement model : variantData.getAsJsonArray()) {
variantModels.add(model.getAsJsonObject());
}
} else
variantModels = Collections.singletonList(variantData.getAsJsonObject());
for(JsonObject variant : variantModels) {
modelFiles.add(new ResourceLocation(variant.get("model").getAsString()));
}
}
} else {
JsonArray multipartData = obj.get("multipart").getAsJsonArray();
for(JsonElement element : multipartData) {
JsonObject self = element.getAsJsonObject();
JsonElement apply = self.get("apply");
List<JsonObject> applyObjects;
if(apply.isJsonArray()) {
applyObjects = new ArrayList<>();
for(JsonElement e : apply.getAsJsonArray()) {
applyObjects.add(e.getAsJsonObject());
}
} else
applyObjects = Collections.singletonList(apply.getAsJsonObject());
for(JsonObject applyEntry : applyObjects) {
modelFiles.add(new ResourceLocation(applyEntry.get("model").getAsString()));
}
}
}
} catch(RuntimeException e) {
logOrSuppressError(blockstateErrors, "blockstate", pair.getFirst(), e);
}
}
}
blockstateErrors.object2IntEntrySet().forEach(entry -> {
if(entry.getIntValue() > ERROR_THRESHOLD) {
ModernFix.LOGGER.error("Suppressed additional {} blockstate errors for domain {}", entry.getIntValue(), entry.getKey());
}
});
blockstateErrors.clear();
blockStateData = null;
blockStateLoadedFiles.clear();
/* figure out which models we should actually load */
gatherAdditionalViaManualScan(allPackResources, allAvailableModels, modelFiles, "models/");
modelFiles.retainAll(allAvailableModels);
allAvailableModels.clear();
allAvailableModels.trim();
Map<ResourceLocation, BlockModel> basicModels = new HashMap<>();
basicModels.put(ModelBakery.MISSING_MODEL_LOCATION, (BlockModel)missingModel);
basicModels.put(new ResourceLocation("builtin/generated"), GENERATION_MARKER);
basicModels.put(new ResourceLocation("builtin/entity"), BLOCK_ENTITY_MARKER);
Set<Pair<String, String>> errorSet = Sets.newLinkedHashSet();
while(modelFiles.size() > 0) {
List<CompletableFuture<Pair<ResourceLocation, JsonElement>>> modelBytes = new ArrayList<>();
for(ResourceLocation model : modelFiles) {
if(basicModels.containsKey(model))
continue;
ResourceLocation fileLocation = new ResourceLocation(model.getNamespace(), "models/" + model.getPath() + ".json");
modelBytes.add(CompletableFuture.supplyAsync(() -> {
Optional<Resource> resource = manager.getResource(fileLocation);
try(InputStream stream = resource.orElseThrow().open()) {
JsonParser parser = new JsonParser();
return Pair.of(model, parser.parse(new InputStreamReader(stream, StandardCharsets.UTF_8)));
} catch(IOException | NoSuchElementException | JsonParseException e) {
logOrSuppressError(blockstateErrors, "model", fileLocation, e);
return Pair.of(fileLocation, null);
}
}, ModernFix.resourceReloadExecutor()));
}
modelFiles.clear();
CompletableFuture.allOf(modelBytes.toArray(new CompletableFuture[0])).join();
UVController.useDummyUv.set(Boolean.TRUE);
for(CompletableFuture<Pair<ResourceLocation, JsonElement>> future : modelBytes) {
Pair<ResourceLocation, JsonElement> pair = future.join();
try {
if(pair.getSecond() != null) {
BlockModel model = modelDeserializer.apply(pair.getSecond());
model.name = pair.getFirst().toString();
modelFiles.addAll(model.getDependencies());
basicModels.put(pair.getFirst(), model);
continue;
}
} catch(Throwable e) {
logOrSuppressError(blockstateErrors, "model", pair.getFirst(), e);
}
basicModels.put(pair.getFirst(), (BlockModel)missingModel);
}
UVController.useDummyUv.set(Boolean.FALSE);
}
blockstateErrors.object2IntEntrySet().forEach(entry -> {
if(entry.getIntValue() > ERROR_THRESHOLD) {
ModernFix.LOGGER.error("Suppressed additional {} model errors for domain {}", entry.getIntValue(), entry.getKey());
}
});
modelFiles = null;
Function<ResourceLocation, UnbakedModel> modelGetter = loc -> {
UnbakedModel m = basicModels.get(loc);
/* fallback to vanilla loader if missing */
return m != null ? m : bakeryModelGetter.apply(loc);
};
for(BlockModel model : basicModels.values()) {
materialSet.addAll(model.getMaterials(modelGetter, errorSet));
}
//errorSet.stream().filter(pair -> !pair.getSecond().equals(MISSING_MODEL_LOCATION_STRING)).forEach(pair -> LOGGER.warn("Unable to resolve texture reference: {} in {}", pair.getFirst(), pair.getSecond()));
stopwatch.stop();
ModernFix.LOGGER.info("Resolving model textures took " + stopwatch);
}
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,21 +3,12 @@ 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.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
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 {

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,81 @@
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 TextureAtlasSprite loadTextureAtlasSprite(TextureAtlas atlasTexture,
ResourceManager resourceManager, TextureAtlasSprite.Info textureInfo,
Resource resource,
int atlasWidth, int atlasHeight,
int spriteX, int spriteY, int mipmapLevel,
NativeImage image) throws IOException {
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(0, 0, 95, 20, 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.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
@ -9,16 +8,23 @@ import net.minecraft.nbt.NbtUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.datafix.DataFixTypes;
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;

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

@ -13,7 +13,6 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
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 {
@ -42,14 +41,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) {
}
@ -64,7 +62,7 @@ public class DummyServerConfiguration implements WorldData {
}
@Override
public CompoundTag createTag(RegistryAccess registries, @Nullable CompoundTag hostPlayerNBT) {
public CompoundTag createTag(RegistryAccess registries, CompoundTag hostPlayerNBT) {
return null;
}

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