Merge remote-tracking branch 'origin/main' into 1.18
This commit is contained in:
commit
9dd9ef923c
8
.github/workflows/gradle.yml
vendored
8
.github/workflows/gradle.yml
vendored
|
|
@ -22,5 +22,9 @@ jobs:
|
||||||
run: ./gradlew --no-daemon build
|
run: ./gradlew --no-daemon build
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: Package
|
name: Forge
|
||||||
path: build/libs
|
path: forge/build/libs
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Fabric
|
||||||
|
path: fabric/build/libs
|
||||||
286
build.gradle
286
build.gradle
|
|
@ -1,107 +1,144 @@
|
||||||
plugins {
|
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 "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 'com.palantir.git-version' version '1.0.0'
|
||||||
id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.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
|
architectury {
|
||||||
|
minecraft = rootProject.minecraft_version
|
||||||
group = 'org.embeddedt'
|
|
||||||
version = gitVersion()
|
|
||||||
|
|
||||||
java {
|
|
||||||
archivesBaseName = 'modernfix-mc' + minecraft_version
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
ext.archives_base_name = 'modernfix-mc' + minecraft_version
|
||||||
// use this if you are using the official mojang mappings
|
|
||||||
// and want loom to stop warning you about their license
|
|
||||||
silentMojangMappingsLicense()
|
|
||||||
|
|
||||||
// since loom 0.10, you are **required** to use the
|
allprojects {
|
||||||
// "forge" block to configure forge-specific features,
|
apply plugin: "java"
|
||||||
// such as the mixinConfigs array or datagen
|
apply plugin: "architectury-plugin"
|
||||||
forge {
|
apply plugin: "maven-publish"
|
||||||
// specify the mixin configs used in this mod
|
apply plugin: "com.diffplug.spotless"
|
||||||
// this will be added to the jar manifest as well!
|
|
||||||
mixinConfigs = [
|
spotless {
|
||||||
"modernfix.mixins.json"
|
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/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/' }
|
modCompileOnly("mezz.jei:jei-${minecraft_version}:${jei_version}")
|
||||||
maven {
|
//modRuntimeOnly("mezz.jei:jei-${minecraft_version}:${jei_version}")
|
||||||
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("curse.maven:refinedstorage-243076:${refined_storage_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:3831559")
|
|
||||||
modCompileOnly "me.shedaniel:RoughlyEnoughItems-forge:${rei_version}"
|
|
||||||
modCompileOnly("dev.latvian.mods:kubejs-forge:${kubejs_version}")
|
modCompileOnly("dev.latvian.mods:kubejs-forge:${kubejs_version}")
|
||||||
modRuntimeOnly("curse.maven:ferritecore-429235:4074294")
|
modCompileOnly("curse.maven:jeresources-240630:3545538")
|
||||||
|
modCompileOnly("curse.maven:jepb-437558:3172880")
|
||||||
|
modCompileOnly("curse.maven:babel-436964:3196072")
|
||||||
|
modCompileOnly("curse.maven:twforest-227639:3575220")
|
||||||
|
modRuntimeOnly("curse.maven:ferritecore-429235:4074330")
|
||||||
modCompileOnly("team.chisel.ctm:CTM:${ctm_version}")
|
modCompileOnly("team.chisel.ctm:CTM:${ctm_version}")
|
||||||
modCompileOnly("curse.maven:supermartijncore-454372:4455384")
|
modCompileOnly("curse.maven:supermartijncore-454372:4455378")
|
||||||
modCompileOnly("appeng:appliedenergistics2-forge:11.7.3")
|
modCompileOnly("curse.maven:valhesiastructures-347488:3476252")
|
||||||
modCompileOnly("vazkii.patchouli:Patchouli:1.18.2-71.1")
|
modCompileOnly files("deps/starlight-1.2.jar")
|
||||||
}
|
modCompileOnly("appeng:appliedenergistics2:8.4.7")
|
||||||
|
modCompileOnly("vazkii.patchouli:Patchouli:1.16.4-53.3")
|
||||||
|
*/
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
||||||
|
|
@ -110,7 +147,10 @@ tasks.withType(JavaCompile) {
|
||||||
// If Javadoc is generated, this must be specified in that task too.
|
// If Javadoc is generated, this must be specified in that task too.
|
||||||
options.encoding = "UTF-8"
|
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()) {
|
if (JavaVersion.current().isJava9Compatible()) {
|
||||||
options.release = targetVersion
|
options.release = targetVersion
|
||||||
|
|
@ -118,36 +158,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) {
|
task generateChangelog(type: se.bjurr.gitchangelog.plugin.gradle.GitChangelogTask) {
|
||||||
def details = versionDetails();
|
def details = versionDetails();
|
||||||
if(details.commitDistance > 0) {
|
if(details.commitDistance > 0) {
|
||||||
|
|
@ -164,46 +174,7 @@ task generateChangelog(type: se.bjurr.gitchangelog.plugin.gradle.GitChangelogTas
|
||||||
toCommit = "HEAD";
|
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 {
|
curseforge {
|
||||||
if (System.getenv("CURSEFORGE_TOKEN") != null) {
|
if (System.getenv("CURSEFORGE_TOKEN") != null) {
|
||||||
apiKey = System.getenv("CURSEFORGE_TOKEN")
|
apiKey = System.getenv("CURSEFORGE_TOKEN")
|
||||||
|
|
@ -247,3 +218,4 @@ tasks.register('publishToModSites') {
|
||||||
publishToModSites.dependsOn(tasks.modrinth)
|
publishToModSites.dependsOn(tasks.modrinth)
|
||||||
publishToModSites.dependsOn(tasks.curseforge)
|
publishToModSites.dependsOn(tasks.curseforge)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
42
common/build.gradle
Normal file
42
common/build.gradle
Normal 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.
|
||||||
|
}
|
||||||
|
}
|
||||||
73
common/src/main/java/org/embeddedt/modernfix/ModernFix.java
Normal file
73
common/src/main/java/org/embeddedt/modernfix/ModernFix.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package org.embeddedt.modernfix.blockstate;
|
package org.embeddedt.modernfix.blockstate;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
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.*;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +1,23 @@
|
||||||
package org.embeddedt.modernfix.core.config;
|
package org.embeddedt.modernfix.core.config;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.*;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
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.IModFile;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
|
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.tree.AnnotationNode;
|
import org.objectweb.asm.tree.AnnotationNode;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import org.objectweb.asm.tree.TypeAnnotationNode;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class ModernFixEarlyConfig {
|
public class ModernFixEarlyConfig {
|
||||||
private static final Logger LOGGER = LogManager.getLogger("ModernFixConfig");
|
private static final Logger LOGGER = LogManager.getLogger("ModernFixConfig");
|
||||||
|
|
@ -49,7 +42,7 @@ public class ModernFixEarlyConfig {
|
||||||
if(modId.equals("optifine"))
|
if(modId.equals("optifine"))
|
||||||
return OPTIFINE_PRESENT;
|
return OPTIFINE_PRESENT;
|
||||||
else
|
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_DESC = "Lorg/spongepowered/asm/mixin/Mixin;";
|
||||||
|
|
@ -64,73 +57,76 @@ public class ModernFixEarlyConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scanForAndBuildMixinOptions() {
|
private void scanForAndBuildMixinOptions() {
|
||||||
IModFile file = FMLLoader.getLoadingModList().getModFileById("modernfix").getFile();
|
List<String> configFiles = ImmutableList.of("modernfix-common.mixins.json", "modernfix-fabric.mixins.json", "modernfix-forge.mixins.json");
|
||||||
Path mixinFolder = file.findResource("org", "embeddedt", "modernfix", "mixin");
|
List<String> mixinPaths = new ArrayList<>();
|
||||||
try(Stream<Path> mixinFiles = Files.find(mixinFolder, Integer.MAX_VALUE, (p, a) -> true)) {
|
for(String configFile : configFiles) {
|
||||||
Splitter dotSplitter = Splitter.on('.');
|
InputStream stream = ModernFixEarlyConfig.class.getClassLoader().getResourceAsStream(configFile);
|
||||||
// filter via toString
|
if(stream == null)
|
||||||
mixinFiles
|
continue;
|
||||||
.filter(p -> {
|
try(Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
|
||||||
Path fileName = p.getFileName();
|
JsonObject configObject = (JsonObject)new JsonParser().parse(reader);
|
||||||
return fileName != null && fileName.toString().endsWith(".class");
|
JsonArray mixinList = configObject.getAsJsonArray("mixins");
|
||||||
})
|
for(JsonElement mixin : mixinList) {
|
||||||
.forEach(path -> {
|
mixinPaths.add("org/embeddedt/modernfix/mixin/" + mixin.getAsString().replace('.', '/') + ".class");
|
||||||
try(InputStream stream = Files.newInputStream(path)) {
|
}
|
||||||
ClassReader reader = new ClassReader(stream);
|
} catch(IOException | JsonParseException e) {
|
||||||
ClassNode node = new ClassNode();
|
LOGGER.error("Error loading config " + configFile, e);
|
||||||
reader.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
|
}
|
||||||
if(node.invisibleAnnotations == null)
|
}
|
||||||
return;
|
Splitter dotSplitter = Splitter.on('.');
|
||||||
boolean isMixin = false, isClientOnly = false, requiredModPresent = true;
|
for(String mixinPath : mixinPaths) {
|
||||||
String requiredModId = "";
|
try(InputStream stream = ModernFixEarlyConfig.class.getClassLoader().getResourceAsStream(mixinPath)) {
|
||||||
for(AnnotationNode annotation : node.invisibleAnnotations) {
|
ClassReader reader = new ClassReader(stream);
|
||||||
if(Objects.equals(annotation.desc, MIXIN_DESC)) {
|
ClassNode node = new ClassNode();
|
||||||
isMixin = true;
|
reader.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
|
||||||
} else if(Objects.equals(annotation.desc, MIXIN_CLIENT_ONLY_DESC)) {
|
if(node.invisibleAnnotations == null)
|
||||||
isClientOnly = true;
|
return;
|
||||||
} else if(Objects.equals(annotation.desc, MIXIN_REQUIRES_MOD_DESC)) {
|
boolean isMixin = false, isClientOnly = false, requiredModPresent = true;
|
||||||
for(int i = 0; i < annotation.values.size(); i += 2) {
|
String requiredModId = "";
|
||||||
if(annotation.values.get(i).equals("value")) {
|
for(AnnotationNode annotation : node.invisibleAnnotations) {
|
||||||
String modId = (String)annotation.values.get(i + 1);
|
if(Objects.equals(annotation.desc, MIXIN_DESC)) {
|
||||||
if(modId != null) {
|
isMixin = true;
|
||||||
requiredModPresent = modPresent(modId);
|
} else if(Objects.equals(annotation.desc, MIXIN_CLIENT_ONLY_DESC)) {
|
||||||
requiredModId = modId;
|
isClientOnly = true;
|
||||||
}
|
} else if(Objects.equals(annotation.desc, MIXIN_REQUIRES_MOD_DESC)) {
|
||||||
break;
|
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 = node.name.replace("org/embeddedt/modernfix/mixin/", "").replace('/', '.');
|
||||||
|
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 shouldReplaceSearchTrees;
|
||||||
private static final boolean isDevEnv = !FMLLoader.isProduction() && FMLLoader.getLoadingModList().getModFileById("modernfix").getFile().getLocator() instanceof ExplodedDirectoryLocator;;
|
private static final boolean isDevEnv = ModernFixPlatformHooks.isDevEnv();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Optional<ModInfo> jeiMod = FMLLoader.getLoadingModList().getMods().stream().filter(mod -> mod.getModId().equals("jei")).findFirst();
|
shouldReplaceSearchTrees = modPresent("jei");
|
||||||
shouldReplaceSearchTrees = (jeiMod.isPresent() && jeiMod.get().getVersion().getMajorVersion() >= 10) || FMLLoader.getLoadingModList().getModFileById("roughlyenoughitems") != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ImmutableMap<String, Boolean> DEFAULT_SETTING_OVERRIDES = ImmutableMap.<String, Boolean>builder()
|
private static final ImmutableMap<String, Boolean> DEFAULT_SETTING_OVERRIDES = ImmutableMap.<String, Boolean>builder()
|
||||||
|
|
@ -159,7 +155,6 @@ public class ModernFixEarlyConfig {
|
||||||
}
|
}
|
||||||
// Defines the default rules which can be configured by the user or other mods.
|
// 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.
|
// You must manually add a rule for any new mixins not covered by an existing package rule.
|
||||||
|
|
||||||
this.addMixinRule("launch.class_search_cache", true);
|
this.addMixinRule("launch.class_search_cache", true);
|
||||||
/*
|
/*
|
||||||
this.addMixinRule("perf.use_integrated_resources.jepb", modPresent("jepb"));
|
this.addMixinRule("perf.use_integrated_resources.jepb", modPresent("jepb"));
|
||||||
|
|
@ -12,7 +12,6 @@ import org.embeddedt.modernfix.ModernFix;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package org.embeddedt.modernfix.dfu;
|
package org.embeddedt.modernfix.dfu;
|
||||||
|
|
||||||
import com.mojang.datafixers.DSL;
|
import com.mojang.datafixers.DSL;
|
||||||
import com.mojang.datafixers.DataFix;
|
|
||||||
import com.mojang.datafixers.DataFixUtils;
|
import com.mojang.datafixers.DataFixUtils;
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
import com.mojang.datafixers.schemas.Schema;
|
import com.mojang.datafixers.schemas.Schema;
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package org.embeddedt.modernfix.duck;
|
package org.embeddedt.modernfix.duck;
|
||||||
|
|
||||||
import org.embeddedt.modernfix.util.BakeReason;
|
|
||||||
|
|
||||||
public interface IBlockState {
|
public interface IBlockState {
|
||||||
void clearCache();
|
void clearCache();
|
||||||
|
|
@ -2,7 +2,6 @@ package org.embeddedt.modernfix.dynamicresources;
|
||||||
|
|
||||||
import com.mojang.math.Transformation;
|
import com.mojang.math.Transformation;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
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.BakedModel;
|
||||||
import net.minecraft.client.resources.model.BlockModelRotation;
|
import net.minecraft.client.resources.model.BlockModelRotation;
|
||||||
import net.minecraft.client.resources.model.BuiltInModel;
|
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.apache.commons.lang3.tuple.Triple;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -75,7 +73,6 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public BakedModel put(ResourceLocation resourceLocation, BakedModel bakedModel) {
|
public BakedModel put(ResourceLocation resourceLocation, BakedModel bakedModel) {
|
||||||
BakedModel m = permanentOverrides.put(resourceLocation, bakedModel);
|
BakedModel m = permanentOverrides.put(resourceLocation, bakedModel);
|
||||||
|
|
@ -0,0 +1,307 @@
|
||||||
|
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.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.add(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");
|
||||||
|
try (Resource resource = frm.getResource(fileLocation)) {
|
||||||
|
knownLocations.add(blockstate);
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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", Integer.MAX_VALUE, p -> p.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", Integer.MAX_VALUE, p -> p.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.getResources(fileLocation);
|
||||||
|
for(Resource resource : resources) {
|
||||||
|
JsonParser parser = new JsonParser();
|
||||||
|
try {
|
||||||
|
blockStateLoadedFiles.add(Pair.of(blockstate, parser.parse(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))));
|
||||||
|
} catch(JsonParseException e) {
|
||||||
|
logOrSuppressError(blockstateErrors, "blockstate", blockstate, e);
|
||||||
|
} finally {
|
||||||
|
resource.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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(() -> {
|
||||||
|
try(Resource resource = manager.getResource(fileLocation)) {
|
||||||
|
JsonParser parser = new JsonParser();
|
||||||
|
return Pair.of(model, parser.parse(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)));
|
||||||
|
} catch(IOException | 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,22 +3,12 @@ package org.embeddedt.modernfix.dynamicresources;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
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.renderer.block.BlockModelShaper;
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.registries.IRegistryDelegate;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
public class ModelLocationCache {
|
public class ModelLocationCache {
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.bugfix.mc218112;
|
||||||
|
|
||||||
|
import net.minecraft.network.syncher.SynchedEntityData;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
|
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 java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
|
||||||
|
@Mixin(SynchedEntityData.class)
|
||||||
|
@ClientOnlyMixin
|
||||||
|
public abstract class SynchedEntityDataMixin_Client {
|
||||||
|
@Shadow @Final private ReadWriteLock lock;
|
||||||
|
|
||||||
|
@Shadow private boolean isDirty;
|
||||||
|
|
||||||
|
@Shadow protected abstract <T> void assignValue(SynchedEntityData.DataItem<T> target, SynchedEntityData.DataItem<?> source);
|
||||||
|
|
||||||
|
@Shadow @Final private Entity entity;
|
||||||
|
|
||||||
|
@Shadow @Final private Map<Integer, SynchedEntityData.DataItem<?>> itemsById;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author embeddedt
|
||||||
|
* @reason always unlock
|
||||||
|
*/
|
||||||
|
@Overwrite
|
||||||
|
public void assignValues(List<SynchedEntityData.DataItem<?>> entries) {
|
||||||
|
this.lock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
for(SynchedEntityData.DataItem<?> dataentry : entries) {
|
||||||
|
SynchedEntityData.DataItem<?> dataentry1 = this.itemsById.get(dataentry.getAccessor().getId());
|
||||||
|
if (dataentry1 != null) {
|
||||||
|
this.assignValue(dataentry1, dataentry);
|
||||||
|
this.entity.onSyncedDataUpdated(dataentry.getAccessor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.lock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
this.isDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,8 +9,8 @@ import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
|
||||||
import org.embeddedt.modernfix.duck.IPaperChunkHolder;
|
import org.embeddedt.modernfix.duck.IPaperChunkHolder;
|
||||||
|
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
@ -45,10 +45,10 @@ public abstract class ChunkMapMixin {
|
||||||
|
|
||||||
private Executor mainInvokingExecutor;
|
private Executor mainInvokingExecutor;
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"), cancellable = true)
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void setup(CallbackInfo ci) {
|
private void setup(CallbackInfo ci) {
|
||||||
this.mainInvokingExecutor = (runnable) -> {
|
this.mainInvokingExecutor = (runnable) -> {
|
||||||
if(ServerLifecycleHooks.getCurrentServer().isSameThread())
|
if(ModernFixPlatformHooks.getCurrentServer().isSameThread())
|
||||||
runnable.run();
|
runnable.run();
|
||||||
else
|
else
|
||||||
this.mainThreadExecutor.execute(runnable);
|
this.mainThreadExecutor.execute(runnable);
|
||||||
|
|
@ -9,12 +9,10 @@ import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.world.level.storage.WorldData;
|
import net.minecraft.world.level.storage.WorldData;
|
||||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
import org.embeddedt.modernfix.ModernFixClient;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
@ -34,9 +32,4 @@ public class MinecraftMixin {
|
||||||
float timeSpentReloading = ((float)(System.nanoTime() - datapackReloadStartTime) / 1000000000f);
|
float timeSpentReloading = ((float)(System.nanoTime() - datapackReloadStartTime) / 1000000000f);
|
||||||
ModernFix.LOGGER.warn("Datapack reload took " + timeSpentReloading + " seconds.");
|
ModernFix.LOGGER.warn("Datapack reload took " + timeSpentReloading + " seconds.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "doLoadLevel", at = @At("HEAD"), remap = false)
|
|
||||||
private void recordWorldLoadStart(CallbackInfo ci) {
|
|
||||||
ModernFixClient.worldLoadStartTime = System.nanoTime();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,6 @@ import net.minecraft.server.packs.resources.ProfiledReloadInstance;
|
||||||
import org.embeddedt.modernfix.util.NamedPreparableResourceListener;
|
import org.embeddedt.modernfix.util.NamedPreparableResourceListener;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
package org.embeddedt.modernfix.mixin.feature.measure_time;
|
package org.embeddedt.modernfix.mixin.feature.measure_time;
|
||||||
|
|
||||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
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.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
||||||
@Mixin(ReloadableResourceManager.class)
|
@Mixin(ReloadableResourceManager.class)
|
||||||
public class SimpleReloadableResourceManagerMixin {
|
public class SimpleReloadableResourceManagerMixin {
|
||||||
|
// TODO maybe expose as a mixin config
|
||||||
|
private static final boolean ENABLE_DEBUG_RELOADER = Boolean.getBoolean("modernfix.debugReloader");
|
||||||
/**
|
/**
|
||||||
* @author embeddedt
|
* @author embeddedt
|
||||||
* @reason add ability to use this feature in modpacks
|
* @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)
|
@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) {
|
private boolean enableDebugReloader(boolean bl) {
|
||||||
return bl || ModernFixConfig.ENABLE_DEBUG_RELOADER.get();
|
return bl || ENABLE_DEBUG_RELOADER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,10 +8,10 @@ import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||||
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
|
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
|
||||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
import org.embeddedt.modernfix.duck.IChunkGenerator;
|
import org.embeddedt.modernfix.duck.IChunkGenerator;
|
||||||
import org.embeddedt.modernfix.duck.IServerLevel;
|
import org.embeddedt.modernfix.duck.IServerLevel;
|
||||||
|
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||||
import org.embeddedt.modernfix.world.StrongholdLocationCache;
|
import org.embeddedt.modernfix.world.StrongholdLocationCache;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
@ -1,31 +1,16 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.dynamic_resources;
|
package org.embeddedt.modernfix.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.renderer.block.BlockModelShaper;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.client.resources.model.ModelManager;
|
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.BlockState;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
import org.spongepowered.asm.mixin.Overwrite;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
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)
|
@Mixin(BlockModelShaper.class)
|
||||||
@ClientOnlyMixin
|
@ClientOnlyMixin
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.embeddedt.modernfix.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() {}
|
||||||
|
}
|
||||||
|
|
@ -9,11 +9,9 @@ import net.minecraft.client.resources.metadata.animation.AnimationMetadataSectio
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.packs.resources.Resource;
|
import net.minecraft.server.packs.resources.Resource;
|
||||||
import net.minecraft.server.packs.resources.ResourceManager;
|
import net.minecraft.server.packs.resources.ResourceManager;
|
||||||
import net.minecraftforge.client.ForgeHooksClient;
|
|
||||||
import net.minecraftforge.fml.ModLoader;
|
|
||||||
import org.apache.commons.lang3.tuple.Triple;
|
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
|
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
@ -22,7 +20,6 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
@ -43,7 +40,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;"))
|
@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) {
|
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
|
// bail if Forge is erroring to avoid AT crashes
|
||||||
if(!usingFasterLoad) {
|
if(!usingFasterLoad) {
|
||||||
return getBasicSpriteInfos(manager, imageLocations);
|
return getBasicSpriteInfos(manager, imageLocations);
|
||||||
|
|
@ -94,9 +91,7 @@ public abstract class TextureAtlasMixin {
|
||||||
} else {
|
} else {
|
||||||
TextureAtlasSprite sprite = null;
|
TextureAtlasSprite sprite = null;
|
||||||
try {
|
try {
|
||||||
sprite = ForgeHooksClient.loadTextureAtlasSprite((TextureAtlas)(Object)this, resourceManager, spriteInfo, pair.getFirst(), storageX, storageY, x, y, mipLevel, pair.getSecond());
|
sprite = ModernFixPlatformHooks.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(RuntimeException e) {
|
} catch(RuntimeException e) {
|
||||||
ModernFix.LOGGER.error("Error loading texture {}: {}", spriteInfo.name(), e);
|
ModernFix.LOGGER.error("Error loading texture {}: {}", spriteInfo.name(), e);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -3,19 +3,17 @@ package org.embeddedt.modernfix.mixin.perf.faster_texture_stitching;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import net.minecraft.client.renderer.texture.Stitcher;
|
import net.minecraft.client.renderer.texture.Stitcher;
|
||||||
import net.minecraftforge.fml.ModLoader;
|
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
|
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||||
import org.embeddedt.modernfix.textures.StbStitcher;
|
import org.embeddedt.modernfix.textures.StbStitcher;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -38,7 +36,7 @@ public class StitcherMixin {
|
||||||
*/
|
*/
|
||||||
@Inject(method = "stitch", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "stitch", at = @At("HEAD"), cancellable = true)
|
||||||
private void stitchFast(CallbackInfo ci) {
|
private void stitchFast(CallbackInfo ci) {
|
||||||
if(!ModLoader.isLoadingStateValid()) {
|
if(!ModernFixPlatformHooks.isLoadingNormally()) {
|
||||||
ModernFix.LOGGER.error("Using vanilla stitcher implementation due to invalid loading state");
|
ModernFix.LOGGER.error("Using vanilla stitcher implementation due to invalid loading state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +57,7 @@ public class StitcherMixin {
|
||||||
*/
|
*/
|
||||||
@Inject(method = "gatherSprites", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "gatherSprites", at = @At("HEAD"), cancellable = true)
|
||||||
private void gatherSpritesFast(Stitcher.SpriteLoader spriteLoader, CallbackInfo ci) {
|
private void gatherSpritesFast(Stitcher.SpriteLoader spriteLoader, CallbackInfo ci) {
|
||||||
if(!ModLoader.isLoadingStateValid())
|
if(!ModernFixPlatformHooks.isLoadingNormally())
|
||||||
return;
|
return;
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
for(StbStitcher.LoadableSpriteInfo info : loadableSpriteInfos) {
|
for(StbStitcher.LoadableSpriteInfo info : loadableSpriteInfos) {
|
||||||
|
|
@ -4,7 +4,6 @@ import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import org.embeddedt.modernfix.dedup.IdentifierCaches;
|
import org.embeddedt.modernfix.dedup.IdentifierCaches;
|
||||||
import org.spongepowered.asm.mixin.*;
|
import org.spongepowered.asm.mixin.*;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
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.Redirect;
|
||||||
|
|
||||||
@Mixin(Property.class)
|
@Mixin(Property.class)
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.nbt_memory_usage;
|
package org.embeddedt.modernfix.mixin.perf.nbt_memory_usage;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import org.embeddedt.modernfix.util.CanonizingStringMap;
|
import org.embeddedt.modernfix.util.CanonizingStringMap;
|
||||||
import org.spongepowered.asm.mixin.*;
|
import org.spongepowered.asm.mixin.*;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
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.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.reduce_blockstate_cache_rebuilds;
|
package org.embeddedt.modernfix.mixin.perf.reduce_blockstate_cache_rebuilds;
|
||||||
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
|
||||||
import org.embeddedt.modernfix.duck.IBlockState;
|
import org.embeddedt.modernfix.duck.IBlockState;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
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.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
@Mixin(BlockBehaviour.BlockStateBase.class)
|
@Mixin(BlockBehaviour.BlockStateBase.class)
|
||||||
public abstract class BlockStateBaseMixin implements IBlockState {
|
public abstract class BlockStateBaseMixin implements IBlockState {
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.remove_spawn_chunks;
|
package org.embeddedt.modernfix.mixin.perf.remove_spawn_chunks;
|
||||||
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.DistanceManager;
|
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.TicketType;
|
import net.minecraft.server.level.TicketType;
|
||||||
import net.minecraft.util.Unit;
|
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.state_definition_construct;
|
package org.embeddedt.modernfix.mixin.perf.state_definition_construct;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSortedMap;
|
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.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.StateHolder;
|
import net.minecraft.world.level.block.state.StateHolder;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
|
import org.embeddedt.modernfix.annotation.RequiresMod;
|
||||||
import org.embeddedt.modernfix.blockstate.FakeStateMap;
|
import org.embeddedt.modernfix.blockstate.FakeStateMap;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
@ -15,6 +15,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Mixin(StateDefinition.class)
|
@Mixin(StateDefinition.class)
|
||||||
|
@RequiresMod("ferritecore")
|
||||||
public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
|
public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
|
||||||
@Shadow @Final private ImmutableSortedMap<String, Property<?>> propertiesByName;
|
@Shadow @Final private ImmutableSortedMap<String, Property<?>> propertiesByName;
|
||||||
|
|
||||||
|
|
@ -11,9 +11,7 @@ import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
|
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
|
||||||
import net.minecraft.world.level.storage.WorldData;
|
import net.minecraft.world.level.storage.WorldData;
|
||||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.embeddedt.modernfix.core.config.ModernFixConfig;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
|
@ -24,7 +22,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
public class IntegratedServerMixin {
|
public class IntegratedServerMixin {
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void adjustServerPriority(Thread thread, Minecraft arg, LevelStorageSource.LevelStorageAccess arg2, PackRepository arg3, WorldStem arg4, MinecraftSessionService minecraftSessionService, GameProfileRepository gameProfileRepository, GameProfileCache arg5, ChunkProgressListenerFactory arg6, CallbackInfo ci) {
|
private void adjustServerPriority(Thread thread, Minecraft arg, LevelStorageSource.LevelStorageAccess arg2, PackRepository arg3, WorldStem arg4, MinecraftSessionService minecraftSessionService, GameProfileRepository gameProfileRepository, GameProfileCache arg5, ChunkProgressListenerFactory arg6, CallbackInfo ci) {
|
||||||
int pri = ModernFixConfig.INTEGRATED_SERVER_PRIORITY.get();
|
int pri = 4;
|
||||||
thread.setPriority(pri);
|
thread.setPriority(pri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.thread_priorities;
|
package org.embeddedt.modernfix.mixin.perf.thread_priorities;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
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.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
package org.embeddedt.modernfix.mixin.safety;
|
package org.embeddedt.modernfix.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.BlockColors;
|
||||||
import net.minecraft.client.color.block.BlockColor;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
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.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) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExpectPlatform
|
||||||
|
public static Path getGameDirectory() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExpectPlatform
|
||||||
|
public static void sendPacket(ServerPlayer player, Object packet) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,6 @@ package org.embeddedt.modernfix.resources;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
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 it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.packs.PackType;
|
import net.minecraft.server.packs.PackType;
|
||||||
|
|
@ -4,18 +4,15 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.CommonComponents;
|
import net.minecraft.network.chat.CommonComponents;
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class ModernFixConfigScreen extends Screen {
|
public class ModernFixConfigScreen extends Screen {
|
||||||
private OptionList optionList;
|
private OptionList optionList;
|
||||||
private Screen lastScreen;
|
private Screen lastScreen;
|
||||||
|
|
||||||
public boolean madeChanges = false;
|
public boolean madeChanges = false;
|
||||||
private Button doneButton;
|
private Button doneButton;
|
||||||
public ModernFixConfigScreen(@Nullable Screen lastScreen) {
|
public ModernFixConfigScreen(Screen lastScreen) {
|
||||||
super(new TranslatableComponent("modernfix.config"));
|
super(new TranslatableComponent("modernfix.config"));
|
||||||
this.lastScreen = lastScreen;
|
this.lastScreen = lastScreen;
|
||||||
}
|
}
|
||||||
|
|
@ -3,12 +3,10 @@ package org.embeddedt.modernfix.screen;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.client.KeyMapping;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
||||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
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.client.gui.narration.NarratableEntry;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.MutableComponent;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
@ -22,14 +20,13 @@ import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
|
public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
|
||||||
private final int maxNameWidth;
|
private final int maxNameWidth;
|
||||||
|
|
||||||
private static final Component OPTION_ON = new TranslatableComponent("modernfix.option.on").withStyle(style -> style.withColor(ChatFormatting.GREEN));
|
private static final Component OPTION_ON = new TranslatableComponent("modernfix.option.on").withStyle(ChatFormatting.GREEN);
|
||||||
private static final Component OPTION_OFF = new TranslatableComponent("modernfix.option.off").withStyle(style -> style.withColor(ChatFormatting.RED));
|
private static final Component OPTION_OFF = new TranslatableComponent("modernfix.option.off").withStyle(ChatFormatting.RED);
|
||||||
|
|
||||||
private ModernFixConfigScreen mainScreen;
|
private ModernFixConfigScreen mainScreen;
|
||||||
|
|
||||||
|
|
@ -40,7 +37,7 @@ public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
|
||||||
this.mainScreen = arg;
|
this.mainScreen = arg;
|
||||||
|
|
||||||
int maxW = 0;
|
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());
|
List<String> sortedKeys = optionMap.keySet().stream().filter(key -> !key.equals("mixin.core")).sorted().collect(Collectors.toList());
|
||||||
for(String key : sortedKeys) {
|
for(String key : sortedKeys) {
|
||||||
Option option = optionMap.get(key);
|
Option option = optionMap.get(key);
|
||||||
|
|
@ -71,7 +68,7 @@ public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
|
||||||
this.toggleButton = new Button(0, 0, 95, 20, new TextComponent(""), (arg) -> {
|
this.toggleButton = new Button(0, 0, 95, 20, new TextComponent(""), (arg) -> {
|
||||||
this.option.setEnabled(!this.option.isEnabled(), !this.option.isUserDefined());
|
this.option.setEnabled(!this.option.isEnabled(), !this.option.isUserDefined());
|
||||||
try {
|
try {
|
||||||
ModernFixMixinPlugin.config.save();
|
ModernFixMixinPlugin.instance.config.save();
|
||||||
if(!OptionList.this.mainScreen.madeChanges) {
|
if(!OptionList.this.mainScreen.madeChanges) {
|
||||||
OptionList.this.mainScreen.madeChanges = true;
|
OptionList.this.mainScreen.madeChanges = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package org.embeddedt.modernfix.structure;
|
package org.embeddedt.modernfix.structure;
|
||||||
|
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
|
||||||
import net.minecraft.SharedConstants;
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtIo;
|
import net.minecraft.nbt.NbtIo;
|
||||||
|
|
@ -9,16 +8,23 @@ import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.datafix.DataFixTypes;
|
import net.minecraft.util.datafix.DataFixTypes;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
import net.minecraftforge.fml.loading.FMLPaths;
|
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
|
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||||
import org.embeddedt.modernfix.util.FileUtil;
|
import org.embeddedt.modernfix.util.FileUtil;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
public class CachingStructureManager {
|
public class CachingStructureManager {
|
||||||
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> LamdbaExceptionUtils.uncheck(() -> MessageDigest.getInstance("SHA-256")));
|
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
|
||||||
private static final File STRUCTURE_CACHE_FOLDER = FileUtil.childFile(FMLPaths.GAMEDIR.get().resolve("modernfix").resolve("structureCacheV1").toFile());
|
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 {
|
static {
|
||||||
STRUCTURE_CACHE_FOLDER.mkdirs();
|
STRUCTURE_CACHE_FOLDER.mkdirs();
|
||||||
|
|
@ -16,7 +16,6 @@ import static java.lang.invoke.MethodHandles.*;
|
||||||
import static java.lang.invoke.MethodType.*;
|
import static java.lang.invoke.MethodType.*;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.sql.Ref;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
package org.embeddedt.modernfix.util;
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
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.ModernFix;
|
||||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -41,6 +37,8 @@ public class ClassInfoManager {
|
||||||
|
|
||||||
// Clear manifest entries
|
// Clear manifest entries
|
||||||
int numManifestsCleared = 0;
|
int numManifestsCleared = 0;
|
||||||
|
// TODO port
|
||||||
|
/*
|
||||||
for(IModFileInfo mod : ModList.get().getModFiles()) {
|
for(IModFileInfo mod : ModList.get().getModFiles()) {
|
||||||
Manifest manifest = mod.getFile().getSecureJar().getManifest();
|
Manifest manifest = mod.getFile().getSecureJar().getManifest();
|
||||||
if(manifest.getEntries() instanceof HashMap<String, Attributes> entryMap) {
|
if(manifest.getEntries() instanceof HashMap<String, Attributes> entryMap) {
|
||||||
|
|
@ -56,6 +54,8 @@ public class ClassInfoManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
if(numManifestsCleared > 0)
|
if(numManifestsCleared > 0)
|
||||||
ModernFix.LOGGER.info("Cleared {} manifest attributes", numManifestsCleared);
|
ModernFix.LOGGER.info("Cleared {} manifest attributes", numManifestsCleared);
|
||||||
|
|
||||||
|
|
@ -68,6 +68,7 @@ public class ClassInfoManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void clearSecureJarStructs() throws Throwable {
|
private static void clearSecureJarStructs() throws Throwable {
|
||||||
|
/*
|
||||||
// Clear Jar signing data
|
// Clear Jar signing data
|
||||||
Unsafe unsafe;
|
Unsafe unsafe;
|
||||||
Field f = Unsafe.class.getDeclaredField("theUnsafe");
|
Field f = Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
|
|
@ -91,6 +92,8 @@ public class ClassInfoManager {
|
||||||
unsafe.putObject(secureJar, verifiedSignersOffset, EmptyCodeSignerTable.INSTANCE);
|
unsafe.putObject(secureJar, verifiedSignersOffset, EmptyCodeSignerTable.INSTANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EmptyCodeSignerTable extends Hashtable<String, CodeSigner[]> {
|
static class EmptyCodeSignerTable extends Hashtable<String, CodeSigner[]> {
|
||||||
|
|
@ -13,7 +13,6 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||||
import net.minecraft.world.level.storage.WorldData;
|
import net.minecraft.world.level.storage.WorldData;
|
||||||
import net.minecraft.world.level.storage.ServerLevelData;
|
import net.minecraft.world.level.storage.ServerLevelData;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class DummyServerConfiguration implements WorldData {
|
public class DummyServerConfiguration implements WorldData {
|
||||||
|
|
@ -42,14 +41,13 @@ public class DummyServerConfiguration implements WorldData {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getCustomBossEvents() {
|
public CompoundTag getCustomBossEvents() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCustomBossEvents(@Nullable CompoundTag nbt) {
|
public void setCustomBossEvents(CompoundTag nbt) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +62,7 @@ public class DummyServerConfiguration implements WorldData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag createTag(RegistryAccess registries, @Nullable CompoundTag hostPlayerNBT) {
|
public CompoundTag createTag(RegistryAccess registries, CompoundTag hostPlayerNBT) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package org.embeddedt.modernfix.util;
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class FileUtil {
|
public class FileUtil {
|
||||||
public static File childFile(File file) {
|
public static File childFile(File file) {
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user