mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-13 16:54:22 +00:00
Update to 1.17
Update to Official classnames Patchwork Make the game compile and run Merge in the new HUD overlay API Merge in the new render properties API PEEL Use Gradle 7.2 snapshot to fix eclipse integration bug in 7.1, Would use 7.0 but FG needs 7.1 for some reason. New FML installer Update to 1.17.1 Co-authored-by: LexManos <[email protected]> Co-authored-by: SizableShrimp <[email protected]> Co-authored-by: cpw <[email protected]> Co-authored-by: Curle <[email protected]> Co-authored-by: Unnoen <[email protected]> Co-authored-by: covers1624 <[email protected]> Co-authored-by: DaemonUmbra <[email protected]> Co-authored-by: gigaherz <[email protected]> Signed-off-by: SizableShrimp <[email protected]>
This commit is contained in:
1 parent
064ae6961b
commit
be5446b91c
1990 files changed
+35661
-37544
No files matched your search
+10
-10
@@ -9,19 +9,24 @@
|
|||||||
|
|
||||||
#idea
|
#idea
|
||||||
/.idea
|
/.idea
|
||||||
|
/*/out
|
||||||
/classes
|
/classes
|
||||||
*.iml
|
*.iml
|
||||||
|
|
||||||
#gradle
|
#gradle
|
||||||
/build
|
/build
|
||||||
/.gradle
|
/.gradle
|
||||||
/mdk/.gradle
|
/*/build
|
||||||
/mdk/build
|
/*/.gradle
|
||||||
|
|
||||||
#occupational hazards
|
# Projects repo, either ignore it, or ignore patches.
|
||||||
/projects/mcp/
|
/projects/mcp/
|
||||||
/projects/clean/
|
/projects/clean/
|
||||||
/projects/forge/
|
/projects/forge/
|
||||||
|
/projects/fmlonly/
|
||||||
|
#/patches/
|
||||||
|
|
||||||
|
#occupational hazards
|
||||||
/projects/**/build/
|
/projects/**/build/
|
||||||
/projects/**/out/
|
/projects/**/out/
|
||||||
/projects/**/run/
|
/projects/**/run/
|
||||||
@@ -31,16 +36,11 @@ src/generated/resources/.cache/
|
|||||||
|
|
||||||
#Patch rejects
|
#Patch rejects
|
||||||
/patches-/
|
/patches-/
|
||||||
*.patch.rej
|
#*.patch.rej
|
||||||
|
/projects/*/rejects/
|
||||||
|
|
||||||
# FML changelog
|
# FML changelog
|
||||||
changelog.txt
|
changelog.txt
|
||||||
*.py
|
*.py
|
||||||
*.7z
|
*.7z
|
||||||
/logs/
|
/logs/
|
||||||
|
|
||||||
/projects/forge/rejects/
|
|
||||||
|
|
||||||
# Srg2Source causes import bugs on these patches. If you intentionnally change these, remove the ignore.
|
|
||||||
/patches/minecraft/net/minecraft/client/renderer/ViewFrustum.java.patch
|
|
||||||
/patches/minecraft/net/minecraft/data/BlockModelDefinition.java.patch
|
|
||||||
Vendored
+3
-3
@@ -6,7 +6,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'gradle:jdk8'
|
image 'gradle:7-jdk16'
|
||||||
args '-v forgegc:/home/gradle/.gradle/'
|
args '-v forgegc:/home/gradle/.gradle/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
withCredentials([usernamePassword(credentialsId: 'maven-forge-user', usernameVariable: 'MAVEN_USER', passwordVariable: 'MAVEN_PASSWORD')]) {
|
withCredentials([usernamePassword(credentialsId: 'maven-forge-user', usernameVariable: 'MAVEN_USER', passwordVariable: 'MAVEN_PASSWORD')]) {
|
||||||
withGradle {
|
withGradle {
|
||||||
sh './gradlew ${GRADLE_ARGS} :forge:publish -PkeystoreKeyPass=${KEYSTORE_KEYPASS} -PkeystoreStorePass=${KEYSTORE_STOREPASS} -Pkeystore=${KEYSTORE} -PcrowdinKey=${CROWDIN}'
|
sh './gradlew ${GRADLE_ARGS} publish -PkeystoreKeyPass=${KEYSTORE_KEYPASS} -PkeystoreStorePass=${KEYSTORE_STOREPASS} -Pkeystore=${KEYSTORE} -PcrowdinKey=${CROWDIN}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
withGradle {
|
withGradle {
|
||||||
sh './gradlew ${GRADLE_ARGS} :forge:publish -PcrowdinKey=${CROWDIN}'
|
sh './gradlew ${GRADLE_ARGS} publish -PcrowdinKey=${CROWDIN}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+887
-614
File diff suppressed because it is too large.
Load diff
@@ -1,2 +1,3 @@
|
|||||||
/.gradle/
|
/.gradle/
|
||||||
/build/
|
/build/
|
||||||
|
/out/
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
repositories {
|
repositories {
|
||||||
maven { url = 'https://maven.minecraftforge.net/' }
|
maven { url = 'https://maven.minecraftforge.net/' }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.ow2.asm:asm:9.1'
|
implementation 'org.ow2.asm:asm:9.1'
|
||||||
implementation 'org.ow2.asm:asm-tree:9.1'
|
implementation 'org.ow2.asm:asm-tree:9.1'
|
||||||
implementation 'net.minecraftforge:srgutils:0.4.+'
|
implementation 'net.minecraftforge:srgutils:0.4.+'
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package net.minecraftforge.forge.tasks
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
import net.minecraftforge.srgutils.IMappingFile
|
import net.minecraftforge.srgutils.IMappingFile
|
||||||
import org.gradle.api.DefaultTask
|
|
||||||
import org.gradle.api.file.ConfigurableFileCollection
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.tasks.InputFile
|
import org.gradle.api.tasks.InputFile
|
||||||
import org.gradle.api.tasks.InputFiles
|
import org.gradle.api.tasks.InputFiles
|
||||||
import org.gradle.api.tasks.Optional
|
import org.gradle.api.tasks.Optional
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
package net.minecraftforge.forge.tasks
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
|
||||||
import org.gradle.api.file.ConfigurableFileCollection
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.tasks.InputFile
|
import org.gradle.api.tasks.InputFile
|
||||||
import org.gradle.api.tasks.InputFiles
|
import org.gradle.api.tasks.InputFiles
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import org.objectweb.asm.*
|
|
||||||
|
import org.objectweb.asm.ClassReader
|
||||||
|
import org.objectweb.asm.ClassVisitor
|
||||||
|
import org.objectweb.asm.MethodVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
import org.objectweb.asm.Type
|
||||||
|
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ abstract class CheckPatches extends DefaultTask {
|
|||||||
@TaskAction
|
@TaskAction
|
||||||
protected void exec() {
|
protected void exec() {
|
||||||
def hasS2SArtifact = [
|
def hasS2SArtifact = [
|
||||||
Paths.get("patches/minecraft/net/minecraft/client/renderer/ViewFrustum.java.patch"),
|
Paths.get("patches/minecraft/net/minecraft/client/renderer/ViewArea.java.patch"),
|
||||||
Paths.get("patches/minecraft/net/minecraft/data/BlockModelDefinition.java.patch")
|
Paths.get("patches/minecraft/net/minecraft/data/models/blockstates/Variant.java.patch")
|
||||||
]
|
]
|
||||||
|
|
||||||
def verified = true;
|
def verified = true;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package net.minecraftforge.forge.tasks
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
|
||||||
import org.gradle.api.file.ConfigurableFileCollection
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.tasks.InputFile
|
import org.gradle.api.tasks.InputFile
|
||||||
import org.gradle.api.tasks.InputFiles
|
import org.gradle.api.tasks.InputFiles
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package net.minecraftforge.forge.tasks
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
import org.gradle.api.tasks.InputFile
|
import org.gradle.api.tasks.InputFile
|
||||||
import org.gradle.api.tasks.OutputDirectory
|
import org.gradle.api.tasks.Internal
|
||||||
import org.gradle.api.tasks.OutputFile
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.OutputFiles
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
package net.minecraftforge.forge.tasks
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
import groovy.transform.EqualsAndHashCode
|
import groovy.transform.EqualsAndHashCode
|
||||||
import org.gradle.api.tasks.Input
|
|
||||||
import org.gradle.api.tasks.Internal
|
import java.util.ArrayList
|
||||||
import org.gradle.api.tasks.Nested
|
import java.util.HashMap
|
||||||
import org.gradle.api.tasks.Optional
|
import java.util.TreeMap
|
||||||
|
import java.util.TreeSet
|
||||||
|
import java.util.function.BiConsumer
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
import org.objectweb.asm.Type
|
||||||
import org.objectweb.asm.tree.ClassNode
|
import org.objectweb.asm.tree.ClassNode
|
||||||
|
import org.objectweb.asm.tree.FieldNode
|
||||||
import org.objectweb.asm.tree.MethodNode
|
import org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*
|
import static org.objectweb.asm.Opcodes.*
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.tasks.bundling.Zip
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.api.provider.SetProperty
|
||||||
|
|
||||||
|
abstract class InstallerJar extends Zip {
|
||||||
|
@Input @Optional abstract SetProperty<String> getPackedDependencies()
|
||||||
|
|
||||||
|
InstallerJar() {
|
||||||
|
archiveClassifier.set('installer')
|
||||||
|
archiveExtension.set('jar') // Needs to be Zip task to not override Manifest, so set extension
|
||||||
|
destinationDirectory.set(project.layout.buildDirectory.dir('libs'))
|
||||||
|
|
||||||
|
def installerJson = project.tasks.installerJson
|
||||||
|
def launcherJson = project.tasks.launcherJson
|
||||||
|
def downloadInstaller = project.tasks.downloadInstaller
|
||||||
|
|
||||||
|
dependsOn(installerJson, launcherJson, downloadInstaller)
|
||||||
|
from(installerJson, launcherJson)
|
||||||
|
|
||||||
|
from(project.rootProject.file('/src/main/resources/url.png'))
|
||||||
|
project.afterEvaluate {
|
||||||
|
from(project.zipTree(downloadInstaller.output)) {
|
||||||
|
duplicatesStrategy = 'exclude'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!System.env.MAVEN_USER) {
|
||||||
|
dependsOn(project.universalJar)
|
||||||
|
from(project.universalJar) {
|
||||||
|
into '/maven/' + project.group.replace('.', '/') + '/' + project.universalJar.archiveBaseName.get() + '/' + project.version + '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
packedDependencies.get().forEach {
|
||||||
|
def jarTask = project.rootProject.getTasks().findByPath(it)
|
||||||
|
dependsOn(jarTask)
|
||||||
|
from(jarTask) {
|
||||||
|
into '/maven/' + jarTask.project.group.replace('.', '/') + '/' + jarTask.archiveBaseName.get() + '/' + jarTask.project.version + '/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
|
import groovy.json.JsonBuilder
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.SetProperty
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
abstract class InstallerJson extends DefaultTask {
|
||||||
|
@OutputFile abstract RegularFileProperty getOutput()
|
||||||
|
@InputFiles abstract ConfigurableFileCollection getInput()
|
||||||
|
@Input @Optional abstract SetProperty<String> getPackedDependencies()
|
||||||
|
@Input @Optional final Map<String, Object> libraries = new LinkedHashMap<>()
|
||||||
|
@Input Map<String, Object> json = new LinkedHashMap<>()
|
||||||
|
@InputFile abstract RegularFileProperty getIcon()
|
||||||
|
@Input abstract Property<String> getLauncherJsonName()
|
||||||
|
@Input abstract Property<String> getLogo()
|
||||||
|
@Input abstract Property<String> getMirrors()
|
||||||
|
@Input abstract Property<String> getWelcome()
|
||||||
|
|
||||||
|
InstallerJson() {
|
||||||
|
getLauncherJsonName().convention('/version.json')
|
||||||
|
getLogo().convention('/big_logo.png')
|
||||||
|
getMirrors().convention('https://files.minecraftforge.net/mirrors-2.0.json')
|
||||||
|
getWelcome().convention("Welcome to the simple ${project.name.capitalize()} installer.")
|
||||||
|
|
||||||
|
getOutput().convention(project.layout.buildDirectory.file('install_profile.json'))
|
||||||
|
|
||||||
|
['client', 'server'].each { side ->
|
||||||
|
['slim', 'extra'].each { type ->
|
||||||
|
def tsk = project.tasks.getByName("download${side.capitalize()}${type.capitalize()}")
|
||||||
|
dependsOn(tsk)
|
||||||
|
input.from(tsk.output)
|
||||||
|
}
|
||||||
|
def tsk = project.tasks.getByName("create${side.capitalize()}SRG")
|
||||||
|
dependsOn(tsk)
|
||||||
|
input.from(tsk.output)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
(packedDependencies.get().collect{ project.rootProject.tasks.findByPath(it) } + [project.universalJar]).forEach {
|
||||||
|
dependsOn(it)
|
||||||
|
input.from it.archiveFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
protected void exec() {
|
||||||
|
def libs = libraries
|
||||||
|
for (def child : packedDependencies.get().collect{ project.rootProject.tasks.findByPath(it) } + [project.universalJar]) {
|
||||||
|
def dep = Util.getMavenDep(child)
|
||||||
|
def path = Util.getMavenPath(child)
|
||||||
|
libs.put(dep.toString(), [
|
||||||
|
name: dep,
|
||||||
|
downloads: [
|
||||||
|
artifact: [
|
||||||
|
path: path,
|
||||||
|
url: "https://maven.minecraftforge.net/${path}",
|
||||||
|
sha1: child.archiveFile.get().asFile.sha1(),
|
||||||
|
size: child.archiveFile.get().asFile.length()
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
}
|
||||||
|
json.libraries = libs.values().sort{a,b -> a.name.compareTo(b.name)}
|
||||||
|
json.icon = "data:image/png;base64," + new String(Base64.getEncoder().encode(Files.readAllBytes(icon.get().asFile.toPath())))
|
||||||
|
json.json = launcherJsonName.get()
|
||||||
|
json.logo = logo.get()
|
||||||
|
if (!mirrors.get().isEmpty())
|
||||||
|
json.mirrorList = mirrors.get()
|
||||||
|
json.welcome = welcome.get()
|
||||||
|
|
||||||
|
Files.writeString(output.get().getAsFile().toPath(), new JsonBuilder(json).toPrettyString())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package net.minecraftforge.forge.tasks
|
||||||
|
|
||||||
|
import groovy.json.JsonBuilder
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.SetProperty
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
import static net.minecraftforge.forge.tasks.Util.getArtifacts
|
||||||
|
import static net.minecraftforge.forge.tasks.Util.iso8601Now
|
||||||
|
|
||||||
|
abstract class LauncherJson extends DefaultTask {
|
||||||
|
@OutputFile abstract RegularFileProperty getOutput()
|
||||||
|
@InputFiles abstract ConfigurableFileCollection getInput()
|
||||||
|
@Input Map<String, Object> json = new LinkedHashMap<>()
|
||||||
|
@Input @Optional abstract SetProperty<String> getPackedDependencies()
|
||||||
|
|
||||||
|
@Internal final vanilla = project.project(':mcp').file('build/mcp/downloadJson/version.json')
|
||||||
|
@Internal final timestamp = iso8601Now()
|
||||||
|
@Internal final comment = [
|
||||||
|
"Please do not automate the download and installation of Forge.",
|
||||||
|
"Our efforts are supported by ads from the download page.",
|
||||||
|
"If you MUST automate this, please consider supporting the project through https://www.patreon.com/LexManos/"
|
||||||
|
]
|
||||||
|
@Internal final id = "${project.rootProject.ext.MC_VERSION}-${project.name}${project.version.substring(project.rootProject.ext.MC_VERSION.length())}"
|
||||||
|
|
||||||
|
LauncherJson() {
|
||||||
|
getOutput().convention(project.layout.buildDirectory.file('version.json'))
|
||||||
|
|
||||||
|
dependsOn(':fmlloader:jar', 'universalJar')
|
||||||
|
getInput().from(project.tasks.universalJar.archiveFile,
|
||||||
|
project.project(':fmlloader').jar.archiveFile,
|
||||||
|
vanilla)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
packedDependencies.get().forEach {
|
||||||
|
def jarTask = project.rootProject.tasks.findByPath(it)
|
||||||
|
dependsOn(jarTask)
|
||||||
|
input.from jarTask.archiveFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
protected void exec() {
|
||||||
|
if (!json.libraries)
|
||||||
|
json.libraries = []
|
||||||
|
getArtifacts(project, project.configurations.installer, false).each { key, lib -> json.libraries.add(lib) }
|
||||||
|
getArtifacts(project, project.configurations.moduleonly, false).each { key, lib -> json.libraries.add(lib) }
|
||||||
|
|
||||||
|
packedDependencies.get().collect{ project.rootProject.tasks.findByPath(it) }.forEach {
|
||||||
|
def path = Util.getMavenPath(it)
|
||||||
|
|
||||||
|
json.libraries.add([
|
||||||
|
name: Util.getMavenDep(it),
|
||||||
|
downloads: [
|
||||||
|
artifact: [
|
||||||
|
path: path,
|
||||||
|
url: "https://maven.minecraftforge.net/${path}",
|
||||||
|
sha1: it.archiveFile.get().asFile.sha1(),
|
||||||
|
size: it.archiveFile.get().asFile.length()
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
}
|
||||||
|
Files.writeString(output.get().asFile.toPath(), new JsonBuilder(json).toPrettyString())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,10 @@ package net.minecraftforge.forge.tasks
|
|||||||
|
|
||||||
import groovy.json.JsonSlurper
|
import groovy.json.JsonSlurper
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
static void init() {
|
static void init() {
|
||||||
@@ -90,6 +92,17 @@ public class Util {
|
|||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static def getMavenPath(task) {
|
||||||
|
def classifier = task.archiveClassifier.get()
|
||||||
|
def dep = "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
|
||||||
|
return "${task.project.group.replace('.', '/')}/${task.project.name}/${task.project.version}/${task.project.name}-${task.project.version}".toString() + (classifier == '' ? '' : '-' + classifier) + '.jar'
|
||||||
|
}
|
||||||
|
|
||||||
|
public static def getMavenDep(task) {
|
||||||
|
def classifier = task.archiveClassifier.get()
|
||||||
|
return "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
|
||||||
|
}
|
||||||
|
|
||||||
public static def iso8601Now() { new Date().iso8601() }
|
public static def iso8601Now() { new Date().iso8601() }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
plugins {
|
||||||
|
id 'com.github.ben-manes.versions'
|
||||||
|
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||||
|
}
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
apply plugin: 'jacoco'
|
||||||
|
apply plugin: 'org.javamodularity.moduleplugin'
|
||||||
|
|
||||||
|
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly('org.jetbrains:annotations:21.0.1')
|
||||||
|
implementation(project(':fmlloader'))
|
||||||
|
api('net.minecraftforge:eventbus:5.0.+')
|
||||||
|
implementation('commons-io:commons-io:2.5')
|
||||||
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar) {
|
||||||
|
archiveClassifier = 'sources'
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
MANIFESTS = [
|
||||||
|
'': [
|
||||||
|
'FMLModType': 'LIBRARY',
|
||||||
|
'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||||
|
'Git-Commit': GIT_INFO.abbreviatedId,
|
||||||
|
'Git-Branch': GIT_INFO.branch,
|
||||||
|
'Build-Number': "${System.getenv('BUILD_NUMBER')?:0}"
|
||||||
|
] as LinkedHashMap,
|
||||||
|
'net/minecraftforge/fml/loading/': [
|
||||||
|
'Specification-Title': 'FMLLoader',
|
||||||
|
'Specification-Vendor': 'Forge Development LLC',
|
||||||
|
'Specification-Version': '1',
|
||||||
|
'Implementation-Title': 'FML Loader',
|
||||||
|
'Implementation-Version': '1.0',
|
||||||
|
'Implementation-Vendor': 'Forge'
|
||||||
|
] as LinkedHashMap
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.doFirst {
|
||||||
|
MANIFESTS.each { pkg, values ->
|
||||||
|
if (pkg == '')
|
||||||
|
manifest.attributes(values)
|
||||||
|
else
|
||||||
|
manifest.attributes(values, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs << '-Xlint:unchecked'
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives jar
|
||||||
|
archives sourcesJar
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing.publications.mavenJava(MavenPublication) {
|
||||||
|
from components.java
|
||||||
|
artifact sourcesJar
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
|
||||||
|
import net.minecraftforge.eventbus.api.BusBuilder;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
import net.minecraftforge.fml.config.IConfigEvent;
|
||||||
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
|
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class Bindings {
|
||||||
|
private static final Bindings INSTANCE = new Bindings();
|
||||||
|
|
||||||
|
private final IBindingsProvider provider;
|
||||||
|
|
||||||
|
private Bindings() {
|
||||||
|
final var providers = ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class), sce->{}).toList();
|
||||||
|
if (providers.size() != 1) {
|
||||||
|
throw new IllegalStateException("Could not find bindings provider");
|
||||||
|
}
|
||||||
|
this.provider = providers.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Supplier<IEventBus> getForgeBus() {
|
||||||
|
return INSTANCE.provider.getForgeBusSupplier();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Supplier<I18NParser> getMessageParser() {
|
||||||
|
return INSTANCE.provider.getMessageParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration() {
|
||||||
|
return INSTANCE.provider.getConfigConfiguration();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class CrashReportCallables {
|
||||||
|
private static final List<ISystemReportExtender> crashCallables = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
public static void registerCrashCallable(ISystemReportExtender callable)
|
||||||
|
{
|
||||||
|
crashCallables.add(callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerCrashCallable(String headerName, Supplier<String> reportGenerator) {
|
||||||
|
registerCrashCallable(new ISystemReportExtender() {
|
||||||
|
@Override
|
||||||
|
public String getLabel() {
|
||||||
|
return headerName;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return reportGenerator.get();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ISystemReportExtender> allCrashCallables() {
|
||||||
|
return List.copyOf(crashCallables);
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-38
@@ -21,20 +21,19 @@ package net.minecraftforge.fml;
|
|||||||
|
|
||||||
import static net.minecraftforge.fml.Logging.LOADING;
|
import static net.minecraftforge.fml.Logging.LOADING;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import net.minecraftforge.fml.event.lifecycle.ParallelDispatchEvent;
|
import com.google.common.base.Stopwatch;
|
||||||
import org.apache.commons.lang3.time.StopWatch;
|
|
||||||
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 com.google.common.base.Stopwatch;
|
|
||||||
|
|
||||||
import net.minecraftforge.forgespi.language.IModInfo;
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,26 +51,28 @@ public class DeferredWorkQueue
|
|||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
private static Map<Class<? extends ParallelDispatchEvent>, DeferredWorkQueue> workQueues = new HashMap<>();
|
private static final Map<ModLoadingStage, DeferredWorkQueue> workQueues = new HashMap<>();
|
||||||
|
|
||||||
private final ModLoadingStage modLoadingStage;
|
|
||||||
private final ConcurrentLinkedDeque<TaskInfo> tasks = new ConcurrentLinkedDeque<>();
|
private final ConcurrentLinkedDeque<TaskInfo> tasks = new ConcurrentLinkedDeque<>();
|
||||||
|
private final ModLoadingStage modLoadingStage;
|
||||||
|
|
||||||
public DeferredWorkQueue(final ModLoadingStage modLoadingStage, Class<? extends ParallelDispatchEvent> eventClass) {
|
public DeferredWorkQueue(ModLoadingStage modLoadingStage) {
|
||||||
this.modLoadingStage = modLoadingStage;
|
this.modLoadingStage = modLoadingStage;
|
||||||
workQueues.put(eventClass, this);
|
workQueues.put(modLoadingStage, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<DeferredWorkQueue> lookup(Optional<Class<? extends ParallelDispatchEvent>> parallelClass) {
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
|
public static Optional<DeferredWorkQueue> lookup(Optional<ModLoadingStage> parallelClass) {
|
||||||
return Optional.ofNullable(workQueues.get(parallelClass.orElse(null)));
|
return Optional.ofNullable(workQueues.get(parallelClass.orElse(null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void runTasks() {
|
public void runTasks() {
|
||||||
if (tasks.isEmpty()) return;
|
if (tasks.isEmpty()) return;
|
||||||
LOGGER.debug(LOADING, "Dispatching synchronous work after {}: {} jobs", modLoadingStage, tasks.size());
|
LOGGER.debug(LOADING, "Dispatching synchronous work for work queue {}: {} jobs", modLoadingStage, tasks.size());
|
||||||
StopWatch globalTimer = StopWatch.createStarted();
|
Stopwatch timer = Stopwatch.createStarted();
|
||||||
tasks.forEach(t->makeRunnable(t, Runnable::run));
|
tasks.forEach(t->makeRunnable(t, Runnable::run));
|
||||||
LOGGER.debug(LOADING, "Synchronous work queue completed in {}", globalTimer);
|
timer.stop();
|
||||||
|
LOGGER.debug(LOADING, "Synchronous work queue completed in {}", timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void makeRunnable(TaskInfo ti, Executor executor) {
|
private static void makeRunnable(TaskInfo ti, Executor executor) {
|
||||||
@@ -93,28 +94,5 @@ public class DeferredWorkQueue
|
|||||||
return CompletableFuture.supplyAsync(work, r->tasks.add(new TaskInfo(modInfo, r)));
|
return CompletableFuture.supplyAsync(work, r->tasks.add(new TaskInfo(modInfo, r)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
record TaskInfo(IModInfo owner, Runnable task) {}
|
||||||
* DEPRECATED FOR REMOVAL. Use {@link ParallelDispatchEvent#enqueueWork(Runnable)} or {@link ParallelDispatchEvent#enqueueWork(Supplier)}
|
|
||||||
*
|
|
||||||
* @param workToEnqueue Runnable to execute later
|
|
||||||
* @return a completable future
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static CompletableFuture<Void> runLater(Runnable workToEnqueue) {
|
|
||||||
return
|
|
||||||
Optional.ofNullable(ModLoadingContext.get().getActiveContainer().modLoadingStage.getDeferredWorkQueue())
|
|
||||||
.map(wq->wq.enqueueWork(ModLoadingContext.get().getActiveContainer().modInfo, workToEnqueue))
|
|
||||||
.orElseGet(()->CompletableFuture.completedFuture(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TaskInfo
|
|
||||||
{
|
|
||||||
public final IModInfo owner;
|
|
||||||
public final Runnable task;
|
|
||||||
|
|
||||||
private TaskInfo(IModInfo owner, Runnable task) {
|
|
||||||
this.owner = owner;
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
File renamed without changes.
@@ -0,0 +1,6 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
public interface I18NParser {
|
||||||
|
String parseMessage(String i18nMessage, Object... args);
|
||||||
|
String stripControlCodes(String toStrip);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
import net.minecraftforge.fml.config.IConfigEvent;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public interface IBindingsProvider {
|
||||||
|
Supplier<IEventBus> getForgeBusSupplier();
|
||||||
|
Supplier<I18NParser> getMessageParser();
|
||||||
|
Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration();
|
||||||
|
}
|
||||||
Whitespace-only changes.
+2
-18
@@ -19,21 +19,11 @@
|
|||||||
|
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
public interface IExtensionPoint<T extends Record>
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.resources.IResourcePack;
|
|
||||||
import net.minecraftforge.fml.packs.ModFileResourcePack;
|
|
||||||
|
|
||||||
public class ExtensionPoint<T>
|
|
||||||
{
|
{
|
||||||
public static final ExtensionPoint<BiFunction<Minecraft, Screen, Screen>> CONFIGGUIFACTORY = new ExtensionPoint<>();
|
|
||||||
public static final ExtensionPoint<BiFunction<Minecraft, ModFileResourcePack, IResourcePack>> RESOURCEPACK = new ExtensionPoint<>();
|
|
||||||
/**
|
/**
|
||||||
* Compatibility display test for the mod.
|
* Compatibility display test for the mod.
|
||||||
* Used for displaying compatibility with remote servers with the same mod, and on disk saves.
|
* Used for displaying compatibility with remote servers with the same mod, and on disk saves.
|
||||||
@@ -68,11 +58,5 @@ public class ExtensionPoint<T>
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static final ExtensionPoint<Pair<Supplier<String>, BiPredicate<String, Boolean>>> DISPLAYTEST = new ExtensionPoint<>();
|
record DisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) implements IExtensionPoint<DisplayTest> {}
|
||||||
|
|
||||||
private Class<T> type;
|
|
||||||
|
|
||||||
private ExtensionPoint() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
import net.minecraftforge.fml.event.IModBusEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface IModLoadingState {
|
||||||
|
String name();
|
||||||
|
String previous();
|
||||||
|
ModLoadingPhase phase();
|
||||||
|
Function<ModList, String> message();
|
||||||
|
Optional<Consumer<ModList>> inlineRunnable();
|
||||||
|
|
||||||
|
default <T extends Event & IModBusEvent> Optional<CompletableFuture<List<Throwable>>> buildTransition(final Executor syncExecutor, final Executor parallelExecutor) {
|
||||||
|
return buildTransition(syncExecutor, parallelExecutor, e->CompletableFuture.runAsync(()->{}, e), e->CompletableFuture.runAsync(()->{}, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends Event & IModBusEvent> Optional<CompletableFuture<List<Throwable>>> buildTransition(Executor syncExecutor, Executor parallelExecutor, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IModStateProvider {
|
||||||
|
List<IModLoadingState> getAllStates();
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
import net.minecraftforge.fml.event.IModBusEvent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public interface IModStateTransition {
|
||||||
|
static IModStateTransition buildNoopTransition() {
|
||||||
|
return new NoopTransition();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T extends Event & IModBusEvent> CompletableFuture<List<Throwable>> build(Executor syncExecutor, Executor parallelExecutor, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
|
||||||
|
List<CompletableFuture<List<Throwable>>> cfs = new ArrayList<>();
|
||||||
|
this.eventFunctionStream().get()
|
||||||
|
.map(f->(EventGenerator<T>)f)
|
||||||
|
.reduce((head, tail)-> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, cfs, head, ModLoadingStage::currentState, tail))
|
||||||
|
.ifPresent(last-> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, cfs, last, nextModLoadingStage(), null));
|
||||||
|
final CompletableFuture<Void> preSyncTaskCF = preSyncTask.apply(syncExecutor);
|
||||||
|
final CompletableFuture<List<Throwable>> eventDispatchCF = ModList.gather(cfs).thenCompose(ModList::completableFutureFromExceptionList);
|
||||||
|
final CompletableFuture<List<Throwable>> postEventDispatchCF = preSyncTaskCF.thenComposeAsync(n -> eventDispatchCF, parallelExecutor).thenApply(r -> {
|
||||||
|
postSyncTask.apply(syncExecutor);
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
return this.finalActivityGenerator().apply(syncExecutor, postEventDispatchCF);
|
||||||
|
}
|
||||||
|
|
||||||
|
default BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextModLoadingStage() {
|
||||||
|
return ModLoadingStage::nextState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends Event & IModBusEvent> EventGenerator<T> addCompletableFutureTaskForModDispatch(final Executor syncExecutor, final Executor parallelExecutor, final List<CompletableFuture<List<Throwable>>> completeableFutures, final EventGenerator<T> eventGenerator, BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextState, final EventGenerator<T> nextGenerator) {
|
||||||
|
completeableFutures.add(((BiFunction<Executor, EventGenerator<T>, CompletableFuture<List<Throwable>>>)preDispatchHook()).apply(threadSelector().apply(syncExecutor, parallelExecutor), eventGenerator));
|
||||||
|
completeableFutures.add(ModList.get().futureVisitor(eventGenerator, nextState).apply(threadSelector().apply(syncExecutor, parallelExecutor)));
|
||||||
|
completeableFutures.add(((BiFunction<Executor, EventGenerator<T>, CompletableFuture<List<Throwable>>>)postDispatchHook()).apply(threadSelector().apply(syncExecutor, parallelExecutor), eventGenerator));
|
||||||
|
return nextGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
Supplier<Stream<EventGenerator<?>>> eventFunctionStream();
|
||||||
|
ThreadSelector threadSelector();
|
||||||
|
BiFunction<Executor, CompletableFuture<List<Throwable>>, CompletableFuture<List<Throwable>>> finalActivityGenerator();
|
||||||
|
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> preDispatchHook();
|
||||||
|
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> postDispatchHook();
|
||||||
|
|
||||||
|
interface EventGenerator<T extends Event & IModBusEvent> extends Function<ModContainer, T> {
|
||||||
|
static <FN extends Event & IModBusEvent> EventGenerator<FN> fromFunction(Function<ModContainer, FN> fn) {
|
||||||
|
return fn::apply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record NoopTransition() implements IModStateTransition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<Stream<EventGenerator<?>>> eventFunctionStream() {
|
||||||
|
return Stream::of;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ThreadSelector threadSelector() {
|
||||||
|
return ThreadSelector.SYNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiFunction<Executor, CompletableFuture<List<Throwable>>, CompletableFuture<List<Throwable>>> finalActivityGenerator() {
|
||||||
|
return (e, t) -> t.thenApplyAsync(Function.identity(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> preDispatchHook() {
|
||||||
|
return (t, f)-> CompletableFuture.completedFuture(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> postDispatchHook() {
|
||||||
|
return (t, f)-> CompletableFuture.completedFuture(Collections.emptyList());
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -17,11 +17,11 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraft.crash.ICrashReportDetail;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public interface ICrashCallable extends ICrashReportDetail<String>
|
public interface ISystemReportExtender extends Supplier<String>
|
||||||
{
|
{
|
||||||
String getLabel();
|
String getLabel();
|
||||||
}
|
}
|
||||||
+10
-14
@@ -33,38 +33,32 @@ import java.util.stream.StreamSupport;
|
|||||||
|
|
||||||
public class InterModComms
|
public class InterModComms
|
||||||
{
|
{
|
||||||
public static final class IMCMessage {
|
public record IMCMessage(String senderModId, String modId, String method, Supplier<?> messageSupplier) {
|
||||||
private final String modId;
|
|
||||||
private final String method;
|
|
||||||
private final String senderModId;
|
|
||||||
private final Supplier<?> thing;
|
|
||||||
|
|
||||||
IMCMessage(String senderModId, String modId, String method, Supplier<?> thing)
|
|
||||||
{
|
|
||||||
this.senderModId = senderModId;
|
|
||||||
this.modId = modId;
|
|
||||||
this.method = method;
|
|
||||||
this.thing = thing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Deprecated: use {@link #senderModId()}
|
||||||
* @return The modid of the sender. This is supplied by the caller, or by the active mod container context.
|
* @return The modid of the sender. This is supplied by the caller, or by the active mod container context.
|
||||||
* Consider it unreliable.
|
* Consider it unreliable.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final String getSenderModId() {
|
public final String getSenderModId() {
|
||||||
return this.senderModId;
|
return this.senderModId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Deprecated: use {@link #modId()}
|
||||||
* @return The modid being sent to.
|
* @return The modid being sent to.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final String getModId() {
|
public final String getModId() {
|
||||||
return this.modId;
|
return this.modId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Deprecated: use {@link #method()}
|
||||||
* @return The method being sent to.
|
* @return The method being sent to.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final String getMethod() {
|
public final String getMethod() {
|
||||||
return this.method;
|
return this.method;
|
||||||
}
|
}
|
||||||
@@ -72,10 +66,12 @@ public class InterModComms
|
|||||||
/**
|
/**
|
||||||
* @param <T> The type of the message.
|
* @param <T> The type of the message.
|
||||||
* @return A {@link Supplier} of the message.
|
* @return A {@link Supplier} of the message.
|
||||||
|
* Use {@link #messageSupplier()}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@Deprecated
|
||||||
public final <T> Supplier<T> getMessageSupplier() {
|
public final <T> Supplier<T> getMessageSupplier() {
|
||||||
return (Supplier<T>)this.thing;
|
return (Supplier<T>) this.messageSupplier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File renamed without changes.
+1
@@ -31,6 +31,7 @@ public class Logging
|
|||||||
public static final Marker SPLASH = MarkerManager.getMarker("SPLASH");
|
public static final Marker SPLASH = MarkerManager.getMarker("SPLASH");
|
||||||
public static final Marker CAPABILITIES = MarkerManager.getMarker("CAPABILITIES");
|
public static final Marker CAPABILITIES = MarkerManager.getMarker("CAPABILITIES");
|
||||||
public static final Marker MODELLOADING = MarkerManager.getMarker("MODELLOADING");
|
public static final Marker MODELLOADING = MarkerManager.getMarker("MODELLOADING");
|
||||||
|
public static final Marker FORGEMOD = MarkerManager.getMarker("FORGEMOD").addParents(LOADING);
|
||||||
|
|
||||||
// --log CORE:+DEBUG,SCAN:-OFF
|
// --log CORE:+DEBUG,SCAN:-OFF
|
||||||
// forge log debug 5
|
// forge log debug 5
|
||||||
File renamed without changes.
+9
-12
@@ -20,10 +20,10 @@
|
|||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
import net.minecraftforge.fml.config.IConfigEvent;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.fml.event.lifecycle.IModBusEvent;
|
import net.minecraftforge.fml.event.IModBusEvent;
|
||||||
import net.minecraftforge.forgespi.language.IModInfo;
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -58,10 +58,10 @@ public abstract class ModContainer
|
|||||||
protected ModLoadingStage modLoadingStage;
|
protected ModLoadingStage modLoadingStage;
|
||||||
protected Supplier<?> contextExtension;
|
protected Supplier<?> contextExtension;
|
||||||
protected final Map<ModLoadingStage, Runnable> activityMap = new HashMap<>();
|
protected final Map<ModLoadingStage, Runnable> activityMap = new HashMap<>();
|
||||||
protected final Map<ExtensionPoint, Supplier<?>> extensionPoints = new IdentityHashMap<>();
|
protected final Map<Class<? extends IExtensionPoint<?>>, Supplier<?>> extensionPoints = new IdentityHashMap<>();
|
||||||
protected final EnumMap<ModConfig.Type, ModConfig> configs = new EnumMap<>(ModConfig.Type.class);
|
protected final EnumMap<ModConfig.Type, ModConfig> configs = new EnumMap<>(ModConfig.Type.class);
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
protected Optional<Consumer<ModConfig.ModConfigEvent>> configHandler = Optional.empty();
|
protected Optional<Consumer<IConfigEvent>> configHandler = Optional.empty();
|
||||||
|
|
||||||
public ModContainer(IModInfo info)
|
public ModContainer(IModInfo info)
|
||||||
{
|
{
|
||||||
@@ -71,7 +71,7 @@ public abstract class ModContainer
|
|||||||
this.modInfo = info;
|
this.modInfo = info;
|
||||||
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
|
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
|
||||||
// default displaytest extension checks for version string match
|
// default displaytest extension checks for version string match
|
||||||
registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(()->this.modInfo.getVersion().toString(),
|
registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(()->this.modInfo.getVersion().toString(),
|
||||||
(incoming, isNetwork)->Objects.equals(incoming, this.modInfo.getVersion().toString())));
|
(incoming, isNetwork)->Objects.equals(incoming, this.modInfo.getVersion().toString())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ public abstract class ModContainer
|
|||||||
|
|
||||||
public static <T extends Event & IModBusEvent> CompletableFuture<Void> buildTransitionHandler(
|
public static <T extends Event & IModBusEvent> CompletableFuture<Void> buildTransitionHandler(
|
||||||
final ModContainer target,
|
final ModContainer target,
|
||||||
final ModLoadingStage.EventGenerator<T> eventGenerator,
|
final IModStateTransition.EventGenerator<T> eventGenerator,
|
||||||
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChangeHandler,
|
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChangeHandler,
|
||||||
final Executor executor) {
|
final Executor executor) {
|
||||||
return CompletableFuture
|
return CompletableFuture
|
||||||
@@ -126,20 +126,17 @@ public abstract class ModContainer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the modinfo used to create this mod instance
|
|
||||||
*/
|
|
||||||
public IModInfo getModInfo()
|
public IModInfo getModInfo()
|
||||||
{
|
{
|
||||||
return modInfo;
|
return modInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> Optional<T> getCustomExtension(ExtensionPoint<T> point) {
|
public <T extends Record> Optional<T> getCustomExtension(Class<? extends IExtensionPoint<T>> point) {
|
||||||
return Optional.ofNullable((T)extensionPoints.getOrDefault(point,()-> null).get());
|
return Optional.ofNullable((T)extensionPoints.getOrDefault(point,()-> null).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void registerExtensionPoint(ExtensionPoint<T> point, Supplier<T> extension)
|
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension)
|
||||||
{
|
{
|
||||||
extensionPoints.put(point, extension);
|
extensionPoints.put(point, extension);
|
||||||
}
|
}
|
||||||
@@ -148,7 +145,7 @@ public abstract class ModContainer
|
|||||||
configs.put(modConfig.getType(), modConfig);
|
configs.put(modConfig.getType(), modConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchConfigEvent(ModConfig.ModConfigEvent event) {
|
public void dispatchConfigEvent(IConfigEvent event) {
|
||||||
configHandler.ifPresent(configHandler->configHandler.accept(event));
|
configHandler.ifPresent(configHandler->configHandler.accept(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
+20
-17
@@ -20,11 +20,14 @@
|
|||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
import net.minecraftforge.fml.event.lifecycle.IModBusEvent;
|
import net.minecraftforge.fml.event.IModBusEvent;
|
||||||
|
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||||
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -58,8 +61,8 @@ public class ModList
|
|||||||
{
|
{
|
||||||
private static Logger LOGGER = LogManager.getLogger();
|
private static Logger LOGGER = LogManager.getLogger();
|
||||||
private static ModList INSTANCE;
|
private static ModList INSTANCE;
|
||||||
private final List<ModFileInfo> modFiles;
|
private final List<IModFileInfo> modFiles;
|
||||||
private final List<ModInfo> sortedList;
|
private final List<IModInfo> sortedList;
|
||||||
private final Map<String, ModFileInfo> fileById;
|
private final Map<String, ModFileInfo> fileById;
|
||||||
private List<ModContainer> mods;
|
private List<ModContainer> mods;
|
||||||
private Map<String, ModContainer> indexedMods;
|
private Map<String, ModContainer> indexedMods;
|
||||||
@@ -71,17 +74,17 @@ public class ModList
|
|||||||
this.sortedList = sortedList.stream().
|
this.sortedList = sortedList.stream().
|
||||||
map(ModInfo.class::cast).
|
map(ModInfo.class::cast).
|
||||||
collect(Collectors.toList());
|
collect(Collectors.toList());
|
||||||
this.fileById = this.modFiles.stream().map(ModFileInfo::getMods).flatMap(Collection::stream).
|
this.fileById = this.modFiles.stream().map(IModFileInfo::getMods).flatMap(Collection::stream).
|
||||||
map(ModInfo.class::cast).
|
map(ModInfo.class::cast).
|
||||||
collect(Collectors.toMap(ModInfo::getModId, ModInfo::getOwningFile));
|
collect(Collectors.toMap(ModInfo::getModId, ModInfo::getOwningFile));
|
||||||
CrashReportExtender.registerCrashCallable("Mod List", this::crashReport);
|
CrashReportCallables.registerCrashCallable("Mod List", this::crashReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getModContainerState(String modId) {
|
private String getModContainerState(String modId) {
|
||||||
return getModContainerById(modId).map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE");
|
return getModContainerById(modId).map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String fileToLine(ModFile mf) {
|
private String fileToLine(IModFile mf) {
|
||||||
return String.format("%-50.50s|%-30.30s|%-30.30s|%-20.20s|%-10.10s|Manifest: %s", mf.getFileName(),
|
return String.format("%-50.50s|%-30.30s|%-30.30s|%-20.20s|%-10.10s|Manifest: %s", mf.getFileName(),
|
||||||
mf.getModInfos().get(0).getDisplayName(),
|
mf.getModInfos().get(0).getDisplayName(),
|
||||||
mf.getModInfos().get(0).getModId(),
|
mf.getModInfos().get(0).getModId(),
|
||||||
@@ -111,18 +114,18 @@ public class ModList
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ModFileInfo> getModFiles()
|
public List<IModFileInfo> getModFiles()
|
||||||
{
|
{
|
||||||
return modFiles;
|
return modFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModFileInfo getModFileById(String modid)
|
public IModFileInfo getModFileById(String modid)
|
||||||
{
|
{
|
||||||
return this.fileById.get(modid);
|
return this.fileById.get(modid);
|
||||||
}
|
}
|
||||||
|
|
||||||
<T extends Event & IModBusEvent> Function<Executor, CompletableFuture<List<Throwable>>> futureVisitor(
|
<T extends Event & IModBusEvent> Function<Executor, CompletableFuture<List<Throwable>>> futureVisitor(
|
||||||
final ModLoadingStage.EventGenerator<T> eventGenerator,
|
final IModStateTransition.EventGenerator<T> eventGenerator,
|
||||||
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChange) {
|
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChange) {
|
||||||
return executor -> gather(
|
return executor -> gather(
|
||||||
this.mods.stream()
|
this.mods.stream()
|
||||||
@@ -185,7 +188,7 @@ public class ModList
|
|||||||
return mods.stream().filter(mc -> mc.getMod() == obj).findFirst();
|
return mods.stream().filter(mc -> mc.getMod() == obj).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ModInfo> getMods()
|
public List<IModInfo> getMods()
|
||||||
{
|
{
|
||||||
return this.sortedList;
|
return this.sortedList;
|
||||||
}
|
}
|
||||||
@@ -205,24 +208,24 @@ public class ModList
|
|||||||
if (modFileScanData == null)
|
if (modFileScanData == null)
|
||||||
{
|
{
|
||||||
modFileScanData = this.sortedList.stream().
|
modFileScanData = this.sortedList.stream().
|
||||||
map(ModInfo::getOwningFile).
|
map(IModInfo::getOwningFile).
|
||||||
filter(Objects::nonNull).
|
filter(Objects::nonNull).
|
||||||
map(ModFileInfo::getFile).
|
map(IModFileInfo::getFile).
|
||||||
distinct().
|
distinct().
|
||||||
map(ModFile::getScanResult).
|
map(IModFile::getScanResult).
|
||||||
collect(Collectors.toList());
|
collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
return modFileScanData;
|
return modFileScanData;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forEachModFile(Consumer<ModFile> fileConsumer)
|
public void forEachModFile(Consumer<IModFile> fileConsumer)
|
||||||
{
|
{
|
||||||
modFiles.stream().map(ModFileInfo::getFile).forEach(fileConsumer);
|
modFiles.stream().map(IModFileInfo::getFile).forEach(fileConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> Stream<T> applyForEachModFile(Function<ModFile, T> function) {
|
public <T> Stream<T> applyForEachModFile(Function<IModFile, T> function) {
|
||||||
return modFiles.stream().map(ModFileInfo::getFile).map(function);
|
return modFiles.stream().map(IModFileInfo::getFile).map(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forEachModContainer(BiConsumer<String, ModContainer> modContainerConsumer) {
|
public void forEachModContainer(BiConsumer<String, ModContainer> modContainerConsumer) {
|
||||||
+48
-81
@@ -20,28 +20,16 @@
|
|||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import cpw.mods.modlauncher.TransformingClassLoader;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
import net.minecraftforge.fml.config.ConfigTracker;
|
import net.minecraftforge.fml.event.IModBusEvent;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
|
||||||
import net.minecraftforge.fml.event.lifecycle.IModBusEvent;
|
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
import net.minecraftforge.fml.loading.FMLPaths;
|
|
||||||
import net.minecraftforge.fml.loading.LoadingModList;
|
import net.minecraftforge.fml.loading.LoadingModList;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.InvalidModIdentifier;
|
import net.minecraftforge.fml.loading.moddiscovery.InvalidModIdentifier;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
|
||||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||||
import net.minecraftforge.fml.network.FMLNetworkConstants;
|
|
||||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
|
||||||
import net.minecraftforge.forgespi.language.IModInfo;
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
||||||
import net.minecraftforge.registries.GameData;
|
|
||||||
import net.minecraftforge.registries.ObjectHolderRegistry;
|
|
||||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@@ -102,38 +90,37 @@ public class ModLoader
|
|||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static ModLoader INSTANCE;
|
private static ModLoader INSTANCE;
|
||||||
private final TransformingClassLoader launchClassLoader;
|
|
||||||
private final LoadingModList loadingModList;
|
private final LoadingModList loadingModList;
|
||||||
|
|
||||||
private final List<ModLoadingException> loadingExceptions;
|
private final List<ModLoadingException> loadingExceptions;
|
||||||
private final List<ModLoadingWarning> loadingWarnings;
|
private final List<ModLoadingWarning> loadingWarnings;
|
||||||
|
private final ModStateManager stateManager;
|
||||||
private boolean loadingStateValid;
|
private boolean loadingStateValid;
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
private final Optional<Consumer<String>> statusConsumer = StartupMessageManager.modLoaderConsumer();
|
private final Optional<Consumer<String>> statusConsumer = StartupMessageManager.modLoaderConsumer();
|
||||||
|
private ModList modList;
|
||||||
|
|
||||||
private ModLoader()
|
private ModLoader()
|
||||||
{
|
{
|
||||||
INSTANCE = this;
|
INSTANCE = this;
|
||||||
this.launchClassLoader = FMLLoader.getLaunchClassLoader();
|
|
||||||
this.loadingModList = FMLLoader.getLoadingModList();
|
this.loadingModList = FMLLoader.getLoadingModList();
|
||||||
this.loadingExceptions = FMLLoader.getLoadingModList().
|
this.loadingExceptions = FMLLoader.getLoadingModList().getErrors().stream()
|
||||||
getErrors().stream().flatMap(ModLoadingException::fromEarlyException).collect(Collectors.toList());
|
.flatMap(ModLoadingException::fromEarlyException)
|
||||||
this.loadingWarnings = FMLLoader.getLoadingModList().
|
.collect(Collectors.toList());
|
||||||
getBrokenFiles().stream().map(file -> new ModLoadingWarning(null, ModLoadingStage.VALIDATE,
|
this.loadingWarnings = FMLLoader.getLoadingModList().getBrokenFiles().stream()
|
||||||
InvalidModIdentifier.identifyJarProblem(file.getFilePath()).orElse("fml.modloading.brokenfile"), file.getFileName())).collect(Collectors.toList());
|
.map(file -> new ModLoadingWarning(null, ModLoadingStage.VALIDATE, InvalidModIdentifier.identifyJarProblem(file.getFilePath()).orElse("fml.modloading.brokenfile"), file.getFileName()))
|
||||||
FMLLoader.getLoadingModList()
|
.collect(Collectors.toList());
|
||||||
.getModFiles().stream().filter(ModFileInfo::missingLicense) //Search for files with missing licenses
|
FMLLoader.getLoadingModList().getModFiles().stream()
|
||||||
|
.filter(ModFileInfo::missingLicense) //Search for files with missing licenses
|
||||||
.filter(modFileInfo -> modFileInfo.getMods().stream().noneMatch(thisModInfo -> this.loadingExceptions.stream().map(ModLoadingException::getModInfo).anyMatch(otherInfo -> otherInfo == thisModInfo))) //Ignore files where any other mod already encountered an error
|
.filter(modFileInfo -> modFileInfo.getMods().stream().noneMatch(thisModInfo -> this.loadingExceptions.stream().map(ModLoadingException::getModInfo).anyMatch(otherInfo -> otherInfo == thisModInfo))) //Ignore files where any other mod already encountered an error
|
||||||
.map(modFileInfo -> new ModLoadingException(null, ModLoadingStage.VALIDATE, "fml.modloading.missinglicense", null, modFileInfo.getFile()))
|
.map(modFileInfo -> new ModLoadingException(null, ModLoadingStage.VALIDATE, "fml.modloading.missinglicense", null, modFileInfo.getFile()))
|
||||||
.forEach(this.loadingExceptions::add);
|
.forEach(this.loadingExceptions::add);
|
||||||
LOGGER.debug(CORE, "Loading Network data for FML net version: {}", FMLNetworkConstants.init());
|
this.stateManager = new ModStateManager();
|
||||||
CrashReportExtender.registerCrashCallable("ModLauncher", FMLLoader::getLauncherInfo);
|
CrashReportCallables.registerCrashCallable("ModLauncher", FMLLoader::getLauncherInfo);
|
||||||
CrashReportExtender.registerCrashCallable("ModLauncher launch target", FMLLoader::launcherHandlerName);
|
CrashReportCallables.registerCrashCallable("ModLauncher launch target", FMLLoader::launcherHandlerName);
|
||||||
CrashReportExtender.registerCrashCallable("ModLauncher naming", FMLLoader::getNaming);
|
CrashReportCallables.registerCrashCallable("ModLauncher naming", FMLLoader::getNaming);
|
||||||
CrashReportExtender.registerCrashCallable("ModLauncher services", this::computeModLauncherServiceList);
|
CrashReportCallables.registerCrashCallable("ModLauncher services", this::computeModLauncherServiceList);
|
||||||
CrashReportExtender.registerCrashCallable("FML", ForgeVersion::getSpec);
|
CrashReportCallables.registerCrashCallable("FML Language Providers", this::computeLanguageList);
|
||||||
CrashReportExtender.registerCrashCallable("Forge", ()->ForgeVersion.getGroup()+":"+ForgeVersion.getVersion());
|
|
||||||
CrashReportExtender.registerCrashCallable("FML Language Providers", this::computeLanguageList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String computeLanguageList() {
|
private String computeLanguageList() {
|
||||||
@@ -165,11 +152,7 @@ public class ModLoader
|
|||||||
statusConsumer.ifPresent(c->c.accept("Waiting for scan to complete"));
|
statusConsumer.ifPresent(c->c.accept("Waiting for scan to complete"));
|
||||||
FMLLoader.backgroundScanHandler.waitForScanToComplete(periodicTask);
|
FMLLoader.backgroundScanHandler.waitForScanToComplete(periodicTask);
|
||||||
statusConsumer.ifPresent(c->c.accept("Loading mods"));
|
statusConsumer.ifPresent(c->c.accept("Loading mods"));
|
||||||
final ModList modList = ModList.of(loadingModList
|
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).toList(),
|
||||||
.getModFiles()
|
|
||||||
.stream()
|
|
||||||
.map(ModFileInfo::getFile)
|
|
||||||
.collect(Collectors.toList()),
|
|
||||||
loadingModList.getMods());
|
loadingModList.getMods());
|
||||||
if (!this.loadingExceptions.isEmpty()) {
|
if (!this.loadingExceptions.isEmpty()) {
|
||||||
LOGGER.fatal(CORE, "Error during pre-loading phase", loadingExceptions.get(0));
|
LOGGER.fatal(CORE, "Error during pre-loading phase", loadingExceptions.get(0));
|
||||||
@@ -178,11 +161,11 @@ public class ModLoader
|
|||||||
throw new LoadingFailedException(loadingExceptions);
|
throw new LoadingFailedException(loadingExceptions);
|
||||||
}
|
}
|
||||||
statusConsumer.ifPresent(c->c.accept("Building Mod List"));
|
statusConsumer.ifPresent(c->c.accept("Building Mod List"));
|
||||||
final List<ModContainer> modContainers = loadingModList.getModFiles().stream().
|
final List<ModContainer> modContainers = loadingModList.getModFiles().stream()
|
||||||
map(ModFileInfo::getFile).
|
.map(ModFileInfo::getFile)
|
||||||
map(mf -> buildMods(mf, launchClassLoader)).
|
.map(this::buildMods)
|
||||||
flatMap(Collection::stream).
|
.<ModContainer>mapMulti(Iterable::forEach)
|
||||||
collect(Collectors.toList());
|
.toList();
|
||||||
if (!loadingExceptions.isEmpty()) {
|
if (!loadingExceptions.isEmpty()) {
|
||||||
LOGGER.fatal(CORE, "Failed to initialize mod containers", loadingExceptions.get(0));
|
LOGGER.fatal(CORE, "Failed to initialize mod containers", loadingExceptions.get(0));
|
||||||
modList.setLoadedMods(Collections.emptyList());
|
modList.setLoadedMods(Collections.emptyList());
|
||||||
@@ -190,61 +173,45 @@ public class ModLoader
|
|||||||
throw new LoadingFailedException(loadingExceptions);
|
throw new LoadingFailedException(loadingExceptions);
|
||||||
}
|
}
|
||||||
modList.setLoadedMods(modContainers);
|
modList.setLoadedMods(modContainers);
|
||||||
statusConsumer.ifPresent(c->c.accept(String.format("Constructing %d mods", modList.size())));
|
this.modList = modList;
|
||||||
dispatchAndHandleError(ModLoadingStage.CONSTRUCT, syncExecutor, parallelExecutor, periodicTask);
|
statusConsumer.ifPresent(c->c.accept("Dispatching gathering events"));
|
||||||
statusConsumer.ifPresent(c->c.accept("Creating registries"));
|
stateManager.getStates(ModLoadingPhase.GATHER).forEach(mls->dispatchAndHandleError(mls, syncExecutor, parallelExecutor, periodicTask));
|
||||||
dispatchAndHandleError(ModLoadingStage.CREATE_REGISTRIES, syncExecutor, parallelExecutor, periodicTask);
|
statusConsumer.ifPresent(c->c.accept("Gathering phase complete"));
|
||||||
ObjectHolderRegistry.findObjectHolders();
|
|
||||||
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Adding custom tag types"));
|
|
||||||
GameData.setCustomTagTypesFromRegistries();
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Populating registries"));
|
|
||||||
dispatchAndHandleError(ModLoadingStage.LOAD_REGISTRIES, syncExecutor, parallelExecutor, periodicTask);
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Early mod loading complete"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMods(final ModWorkManager.DrivenExecutor syncExecutor, final Executor parallelExecutor, final Function<Executor, CompletableFuture<Void>> beforeSidedEvent, final Function<Executor, CompletableFuture<Void>> afterSidedEvent, final Runnable periodicTask) {
|
public void loadMods(final ModWorkManager.DrivenExecutor syncExecutor, final Executor parallelExecutor, final Runnable periodicTask) {
|
||||||
statusConsumer.ifPresent(c->c.accept("Loading mod config"));
|
statusConsumer.ifPresent(c->c.accept("Performing load phase"));
|
||||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, ()->()-> ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get()));
|
stateManager.getStates(ModLoadingPhase.LOAD).forEach(mls->dispatchAndHandleError(mls, syncExecutor, parallelExecutor, periodicTask));
|
||||||
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, FMLPaths.CONFIGDIR.get());
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: SETUP"));
|
|
||||||
dispatchAndHandleError(ModLoadingStage.COMMON_SETUP, syncExecutor, parallelExecutor, periodicTask);
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: SIDED SETUP"));
|
|
||||||
dispatchAndHandleError(ModLoadingStage.SIDED_SETUP, syncExecutor, parallelExecutor, periodicTask, beforeSidedEvent, afterSidedEvent);
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup complete"));
|
statusConsumer.ifPresent(c->c.accept("Mod setup complete"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finishMods(final ModWorkManager.DrivenExecutor syncExecutor, final Executor parallelExecutor, final Runnable periodicTask)
|
public void finishMods(final ModWorkManager.DrivenExecutor syncExecutor, final Executor parallelExecutor, final Runnable periodicTask) {
|
||||||
{
|
statusConsumer.ifPresent(c->c.accept("Performing completion phase"));
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC"));
|
stateManager.getStates(ModLoadingPhase.COMPLETE).forEach(mls->dispatchAndHandleError(mls, syncExecutor, parallelExecutor, periodicTask));
|
||||||
dispatchAndHandleError(ModLoadingStage.ENQUEUE_IMC, syncExecutor, parallelExecutor, periodicTask);
|
statusConsumer.ifPresent(c->c.accept(String.format("Mod loading complete - %d mods loaded", this.modList.size())));
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: PROCESS IMC"));
|
|
||||||
dispatchAndHandleError(ModLoadingStage.PROCESS_IMC, syncExecutor, parallelExecutor, periodicTask);
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: Final completion"));
|
|
||||||
dispatchAndHandleError(ModLoadingStage.COMPLETE, syncExecutor, parallelExecutor, periodicTask);
|
|
||||||
statusConsumer.ifPresent(c->c.accept("Freezing data"));
|
|
||||||
GameData.freezeData();
|
|
||||||
NetworkRegistry.lock();
|
|
||||||
statusConsumer.ifPresent(c->c.accept(String.format("Mod loading complete - %d mods loaded", ModList.get().size())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchAndHandleError(ModLoadingStage state, ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor, final Runnable ticker) {
|
private void dispatchAndHandleError(IModLoadingState state, ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor, final Runnable ticker) {
|
||||||
if (!isLoadingStateValid()) {
|
if (!isLoadingStateValid()) {
|
||||||
LOGGER.error("Cowardly refusing to process mod state change request from {}", state);
|
LOGGER.error("Cowardly refusing to process mod state change request from {}", state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
waitForTransition(state, syncExecutor, ticker, state.buildTransition(syncExecutor, parallelExecutor));
|
statusConsumer.ifPresent(c->c.accept(state.message().apply(this.modList)));
|
||||||
|
state.inlineRunnable().ifPresent(a->a.accept(this.modList));
|
||||||
|
state.buildTransition(syncExecutor, parallelExecutor).ifPresent(t->waitForTransition(state, syncExecutor, ticker, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchAndHandleError(ModLoadingStage state, ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor, final Runnable ticker, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
|
private void dispatchAndHandleError(IModLoadingState state, ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor, final Runnable ticker, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
|
||||||
if (!isLoadingStateValid()) {
|
if (!isLoadingStateValid()) {
|
||||||
LOGGER.error("Cowardly refusing to process mod state change request from {}", state);
|
LOGGER.error("Cowardly refusing to process mod state change request from {}", state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
waitForTransition(state, syncExecutor, ticker, state.buildTransition(syncExecutor, parallelExecutor, preSyncTask, postSyncTask));
|
statusConsumer.ifPresent(c->c.accept(state.message().apply(this.modList)));
|
||||||
|
state.inlineRunnable().ifPresent(a->a.accept(this.modList));
|
||||||
|
state.buildTransition(syncExecutor, parallelExecutor, preSyncTask, postSyncTask).ifPresent(t->waitForTransition(state, syncExecutor, ticker, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForTransition(final ModLoadingStage state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker, final CompletableFuture<List<Throwable>> transition) {
|
private void waitForTransition(final IModLoadingState state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker, final CompletableFuture<List<Throwable>> transition) {
|
||||||
while (!transition.isDone()) {
|
while (!transition.isDone()) {
|
||||||
syncExecutor.drive(ticker);
|
syncExecutor.drive(ticker);
|
||||||
}
|
}
|
||||||
@@ -265,12 +232,12 @@ public class ModLoader
|
|||||||
.filter(ModLoadingException.class::isInstance)
|
.filter(ModLoadingException.class::isInstance)
|
||||||
.map(ModLoadingException.class::cast)
|
.map(ModLoadingException.class::cast)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
LOGGER.fatal(LOADING,"Failed to complete lifecycle event {}, {} errors found", state, modLoadingExceptions.size());
|
LOGGER.fatal(LOADING,"Failed to complete lifecycle event {}, {} errors found", state.name(), modLoadingExceptions.size());
|
||||||
throw new LoadingFailedException(modLoadingExceptions);
|
throw new LoadingFailedException(modLoadingExceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ModContainer> buildMods(final ModFile modFile, final TransformingClassLoader modClassLoader)
|
private List<ModContainer> buildMods(final ModFile modFile)
|
||||||
{
|
{
|
||||||
final Map<String, IModInfo> modInfoMap = modFile.getModFileInfo().getMods().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
|
final Map<String, IModInfo> modInfoMap = modFile.getModFileInfo().getMods().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
|
||||||
|
|
||||||
@@ -278,7 +245,7 @@ public class ModLoader
|
|||||||
final List<ModContainer> containers = modFile.getScanResult().getTargets()
|
final List<ModContainer> containers = modFile.getScanResult().getTargets()
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.map(e -> buildModContainerFromTOML(modFile, modClassLoader, modInfoMap, e))
|
.map(e -> buildModContainerFromTOML(modFile, modInfoMap, e))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (containers.size() != modInfoMap.size()) {
|
if (containers.size() != modInfoMap.size()) {
|
||||||
@@ -292,14 +259,14 @@ public class ModLoader
|
|||||||
return containers.stream().filter(mc -> mc.modLoadingStage != ModLoadingStage.ERROR).collect(Collectors.toList());
|
return containers.stream().filter(mc -> mc.modLoadingStage != ModLoadingStage.ERROR).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModContainer buildModContainerFromTOML(final ModFile modFile, final TransformingClassLoader modClassLoader, final Map<String, IModInfo> modInfoMap, final Map.Entry<String, ? extends IModLanguageProvider.IModLanguageLoader> idToProviderEntry) {
|
private ModContainer buildModContainerFromTOML(final ModFile modFile, final Map<String, IModInfo> modInfoMap, final Map.Entry<String, ? extends IModLanguageProvider.IModLanguageLoader> idToProviderEntry) {
|
||||||
try {
|
try {
|
||||||
final String modId = idToProviderEntry.getKey();
|
final String modId = idToProviderEntry.getKey();
|
||||||
final IModLanguageProvider.IModLanguageLoader languageLoader = idToProviderEntry.getValue();
|
final IModLanguageProvider.IModLanguageLoader languageLoader = idToProviderEntry.getValue();
|
||||||
IModInfo info = Optional.ofNullable(modInfoMap.get(modId)).
|
IModInfo info = Optional.ofNullable(modInfoMap.get(modId)).
|
||||||
// throw a missing metadata error if there is no matching modid in the modInfoMap from the mods.toml file
|
// throw a missing metadata error if there is no matching modid in the modInfoMap from the mods.toml file
|
||||||
orElseThrow(()->new ModLoadingException(null, ModLoadingStage.CONSTRUCT, "fml.modloading.missingmetadata", null, modId));
|
orElseThrow(()->new ModLoadingException(null, ModLoadingStage.CONSTRUCT, "fml.modloading.missingmetadata", null, modId));
|
||||||
return languageLoader.loadMod(info, modClassLoader, modFile.getScanResult());
|
return languageLoader.loadMod(info, modFile.getScanResult(), FMLLoader.getGameLayer());
|
||||||
} catch (ModLoadingException mle) {
|
} catch (ModLoadingException mle) {
|
||||||
// exceptions are caught and added to the error list for later handling
|
// exceptions are caught and added to the error list for later handling
|
||||||
loadingExceptions.add(mle);
|
loadingExceptions.add(mle);
|
||||||
+6
-6
@@ -19,14 +19,14 @@
|
|||||||
|
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.fml.config.IConfigSpec;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ModLoadingContext
|
public class ModLoadingContext
|
||||||
{
|
{
|
||||||
private static ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
|
private static final ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
|
||||||
private Object languageExtension;
|
private Object languageExtension;
|
||||||
private ModLoadingStage stage;
|
private ModLoadingStage stage;
|
||||||
|
|
||||||
@@ -50,20 +50,20 @@ public class ModLoadingContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an {@link ExtensionPoint} with the mod container.
|
* Register an {@link IExtensionPoint} with the mod container.
|
||||||
* @param point The extension point to register
|
* @param point The extension point to register
|
||||||
* @param extension An extension operator
|
* @param extension An extension operator
|
||||||
* @param <T> The type signature of the extension operator
|
* @param <T> The type signature of the extension operator
|
||||||
*/
|
*/
|
||||||
public <T> void registerExtensionPoint(ExtensionPoint<T> point, Supplier<T> extension) {
|
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension) {
|
||||||
getActiveContainer().registerExtensionPoint(point, extension);
|
getActiveContainer().registerExtensionPoint(point, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerConfig(ModConfig.Type type, ForgeConfigSpec spec) {
|
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
|
||||||
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer()));
|
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerConfig(ModConfig.Type type, ForgeConfigSpec spec, String fileName) {
|
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec, String fileName) {
|
||||||
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer(), fileName));
|
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer(), fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-2
@@ -73,7 +73,7 @@ public class ModLoadingException extends RuntimeException
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String formatToString() {
|
public String formatToString() {
|
||||||
return ForgeI18n.parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, errorStage, getCause()), context.stream()).toArray());
|
return Bindings.getMessageParser().get().parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, errorStage, getCause()), context.stream()).toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,6 +85,6 @@ public class ModLoadingException extends RuntimeException
|
|||||||
return modInfo;
|
return modInfo;
|
||||||
}
|
}
|
||||||
public String getCleanMessage() {
|
public String getCleanMessage() {
|
||||||
return ForgeI18n.stripControlCodes(formatToString());
|
return Bindings.getMessageParser().get().stripControlCodes(formatToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
public enum ModLoadingPhase {
|
||||||
|
ERROR, // Special state for error handling
|
||||||
|
GATHER,
|
||||||
|
LOAD,
|
||||||
|
COMPLETE,
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016-2021.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
public enum ModLoadingStage
|
||||||
|
{
|
||||||
|
ERROR,
|
||||||
|
VALIDATE,
|
||||||
|
CONSTRUCT,
|
||||||
|
COMMON_SETUP,
|
||||||
|
SIDED_SETUP,
|
||||||
|
ENQUEUE_IMC,
|
||||||
|
PROCESS_IMC,
|
||||||
|
COMPLETE,
|
||||||
|
DONE;
|
||||||
|
|
||||||
|
private final DeferredWorkQueue deferredWorkQueue;
|
||||||
|
|
||||||
|
ModLoadingStage() {
|
||||||
|
deferredWorkQueue = new DeferredWorkQueue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModLoadingStage nextState(Throwable exception) {
|
||||||
|
return exception != null ? ERROR : values()[this.ordinal()+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModLoadingStage currentState(Throwable exception) {
|
||||||
|
return exception != null ? ERROR : this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeferredWorkQueue getDeferredWorkQueue() {
|
||||||
|
return deferredWorkQueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
import net.minecraftforge.fml.event.IModBusEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public record ModLoadingState(String name, String previous, Function<ModList, String> message, ModLoadingPhase phase, Optional<Consumer<ModList>> inlineRunnable, Optional<IModStateTransition> transition) implements IModLoadingState {
|
||||||
|
@Override
|
||||||
|
public <T extends Event & IModBusEvent> Optional<CompletableFuture<List<Throwable>>> buildTransition(final Executor syncExecutor, final Executor parallelExecutor, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
|
||||||
|
return transition.map(t->t.build(syncExecutor, parallelExecutor, preSyncTask, postSyncTask));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ModLoadingState empty(final String name, final String previous, final ModLoadingPhase phase) {
|
||||||
|
return new ModLoadingState(name, previous, ml->"", phase, Optional.empty(), Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ModLoadingState withTransition(final String name, final String previous, final ModLoadingPhase phase, IModStateTransition transition) {
|
||||||
|
return new ModLoadingState(name, previous, ml->"Processing transition "+name, phase, Optional.empty(), Optional.of(transition));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ModLoadingState withTransition(final String name, final String previous, final Function<ModList, String> message, final ModLoadingPhase phase, IModStateTransition transition) {
|
||||||
|
return new ModLoadingState(name, previous, message, phase, Optional.empty(), Optional.of(transition));
|
||||||
|
}
|
||||||
|
public static ModLoadingState withInline(final String name, final String previous, final ModLoadingPhase phase, Consumer<ModList> inline) {
|
||||||
|
return new ModLoadingState(name, previous, ml->"Processing work "+name, phase, Optional.of(inline), Optional.empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -55,6 +55,6 @@ public class ModLoadingWarning
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String formatToString() {
|
public String formatToString() {
|
||||||
return ForgeI18n.parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, warningStage), context.stream()).toArray());
|
return Bindings.getMessageParser().get().parseMessage(i18nMessage, Streams.concat(Stream.of(modInfo, warningStage), context.stream()).toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import com.google.common.graph.GraphBuilder;
|
||||||
|
import com.google.common.graph.MutableGraph;
|
||||||
|
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
|
||||||
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
|
import net.minecraftforge.fml.loading.toposort.TopologicalSort;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
public class ModStateManager {
|
||||||
|
static ModStateManager INSTANCE;
|
||||||
|
private final EnumMap<ModLoadingPhase, List<IModLoadingState>> stateMap;
|
||||||
|
|
||||||
|
public ModStateManager() {
|
||||||
|
INSTANCE = this;
|
||||||
|
final var sp = ServiceLoader.load(FMLLoader.getGameLayer(), IModStateProvider.class);
|
||||||
|
this.stateMap = ServiceLoaderUtils.streamWithErrorHandling(sp, sce->{})
|
||||||
|
.map(IModStateProvider::getAllStates)
|
||||||
|
.<IModLoadingState>mapMulti(Iterable::forEach)
|
||||||
|
.collect(Collectors.groupingBy(IModLoadingState::phase, ()->new EnumMap<>(ModLoadingPhase.class), Collectors.toUnmodifiableList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IModLoadingState> getStates(final ModLoadingPhase phase) {
|
||||||
|
var nodes = stateMap.get(phase);
|
||||||
|
var lookup = nodes.stream().collect(Collectors.toMap(IModLoadingState::name, Function.identity()));
|
||||||
|
|
||||||
|
var graph = GraphBuilder.directed().allowsSelfLoops(false).<IModLoadingState>build();
|
||||||
|
var dummy = ModLoadingState.empty("", "", phase);
|
||||||
|
nodes.forEach(graph::addNode);
|
||||||
|
graph.addNode(dummy);
|
||||||
|
nodes.forEach(n->graph.putEdge(lookup.getOrDefault(n.previous(), dummy), n));
|
||||||
|
return TopologicalSort.topologicalSort(graph, Comparator.comparingInt(nodes::indexOf)).stream().filter(st->st!=dummy).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
+11
@@ -19,8 +19,19 @@
|
|||||||
|
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class StartupMessageManager {
|
public class StartupMessageManager {
|
||||||
public static void addModMessage(final String message) {
|
public static void addModMessage(final String message) {
|
||||||
net.minecraftforge.fml.loading.progress.StartupMessageManager.addModMessage(message);
|
net.minecraftforge.fml.loading.progress.StartupMessageManager.addModMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Optional<Consumer<String>> modLoaderConsumer() {
|
||||||
|
return net.minecraftforge.fml.loading.progress.StartupMessageManager.modLoaderConsumer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<Consumer<String>> mcLoaderConsumer() {
|
||||||
|
return net.minecraftforge.fml.loading.progress.StartupMessageManager.mcLoaderConsumer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.BinaryOperator;
|
||||||
|
|
||||||
|
public enum ThreadSelector implements BinaryOperator<Executor> {
|
||||||
|
SYNC((sync, parallel) -> sync),
|
||||||
|
PARALLEL((sync, parallel) -> parallel);
|
||||||
|
|
||||||
|
private final BinaryOperator<Executor> selector;
|
||||||
|
|
||||||
|
ThreadSelector(final BinaryOperator<Executor> selector) {
|
||||||
|
this.selector = selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor apply(final Executor sync, final Executor parallel) {
|
||||||
|
return this.selector.apply(sync, parallel);
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-27
@@ -24,15 +24,16 @@ import com.google.gson.Gson;
|
|||||||
import net.minecraftforge.fml.loading.FMLConfig;
|
import net.minecraftforge.fml.loading.FMLConfig;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
import net.minecraftforge.forgespi.language.IModInfo;
|
import net.minecraftforge.forgespi.language.IModInfo;
|
||||||
import net.minecraftforge.versions.mcp.MCPVersion;
|
|
||||||
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.apache.maven.artifact.versioning.ComparableVersion;
|
import org.apache.maven.artifact.versioning.ComparableVersion;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -41,8 +42,6 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static net.minecraftforge.fml.VersionChecker.Status.*;
|
import static net.minecraftforge.fml.VersionChecker.Status.*;
|
||||||
|
|
||||||
@@ -103,25 +102,7 @@ public class VersionChecker
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CheckResult
|
public record CheckResult(VersionChecker.Status status, ComparableVersion target, Map<ComparableVersion, String> changes, String url) {}
|
||||||
{
|
|
||||||
@Nonnull
|
|
||||||
public final Status status;
|
|
||||||
@Nullable
|
|
||||||
public final ComparableVersion target;
|
|
||||||
@Nullable
|
|
||||||
public final Map<ComparableVersion, String> changes;
|
|
||||||
@Nullable
|
|
||||||
public final String url;
|
|
||||||
|
|
||||||
private CheckResult(@Nonnull Status status, @Nullable ComparableVersion target, @Nullable Map<ComparableVersion, String> changes, @Nullable String url)
|
|
||||||
{
|
|
||||||
this.status = status;
|
|
||||||
this.target = target;
|
|
||||||
this.changes = changes == null ? Collections.<ComparableVersion, String>emptyMap() : Collections.unmodifiableMap(changes);
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startVersionCheck()
|
public static void startVersionCheck()
|
||||||
{
|
{
|
||||||
@@ -175,13 +156,15 @@ public class VersionChecker
|
|||||||
|
|
||||||
private void process(IModInfo mod)
|
private void process(IModInfo mod)
|
||||||
{
|
{
|
||||||
|
// HttpClient.newBuilder().build();
|
||||||
Status status = PENDING;
|
Status status = PENDING;
|
||||||
ComparableVersion target = null;
|
ComparableVersion target = null;
|
||||||
Map<ComparableVersion, String> changes = null;
|
Map<ComparableVersion, String> changes = null;
|
||||||
String display_url = null;
|
String display_url = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
URL url = mod.getUpdateURL();
|
if (mod.getUpdateURL().isEmpty()) return;
|
||||||
|
URL url = mod.getUpdateURL().get();
|
||||||
LOGGER.info("[{}] Starting version check at {}", mod.getModId(), url.toString());
|
LOGGER.info("[{}] Starting version check at {}", mod.getModId(), url.toString());
|
||||||
|
|
||||||
InputStream con = openUrlStream(url);
|
InputStream con = openUrlStream(url);
|
||||||
@@ -197,7 +180,8 @@ public class VersionChecker
|
|||||||
Map<String, String> promos = (Map<String, String>)json.get("promos");
|
Map<String, String> promos = (Map<String, String>)json.get("promos");
|
||||||
display_url = (String)json.get("homepage");
|
display_url = (String)json.get("homepage");
|
||||||
|
|
||||||
String mcVersion = MCPVersion.getMCVersion();
|
// String mcVersion = MCPVersion.getMCVersion();
|
||||||
|
var mcVersion = "1.17";
|
||||||
String rec = promos.get(mcVersion + "-recommended");
|
String rec = promos.get(mcVersion + "-recommended");
|
||||||
String lat = promos.get(mcVersion + "-latest");
|
String lat = promos.get(mcVersion + "-latest");
|
||||||
ComparableVersion current = new ComparableVersion(mod.getVersion().toString());
|
ComparableVersion current = new ComparableVersion(mod.getVersion().toString());
|
||||||
@@ -278,9 +262,8 @@ public class VersionChecker
|
|||||||
private static List<IModInfo> gatherMods()
|
private static List<IModInfo> gatherMods()
|
||||||
{
|
{
|
||||||
List<IModInfo> ret = new LinkedList<>();
|
List<IModInfo> ret = new LinkedList<>();
|
||||||
for (ModInfo info : ModList.get().getMods()) {
|
for (IModInfo info : ModList.get().getMods()) {
|
||||||
URL url = info.getUpdateURL();
|
if (info.getUpdateURL().isPresent())
|
||||||
if (url != null)
|
|
||||||
ret.add(info);
|
ret.add(info);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
+1
-1
@@ -157,7 +157,7 @@ public class ConfigFileTypeHandler {
|
|||||||
}
|
}
|
||||||
LOGGER.debug(CONFIG, "Config file {} changed, sending notifies", this.modConfig.getFileName());
|
LOGGER.debug(CONFIG, "Config file {} changed, sending notifies", this.modConfig.getFileName());
|
||||||
this.modConfig.getSpec().afterReload();
|
this.modConfig.getSpec().afterReload();
|
||||||
this.modConfig.fireEvent(new ModConfig.Reloading(this.modConfig));
|
this.modConfig.fireEvent(IConfigEvent.reloading(this.modConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+12
-43
@@ -21,33 +21,14 @@ package net.minecraftforge.fml.config;
|
|||||||
|
|
||||||
import com.electronwill.nightconfig.core.CommentedConfig;
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
import com.electronwill.nightconfig.toml.TomlFormat;
|
|
||||||
import it.unimi.dsi.fastutil.bytes.Byte2ByteOpenCustomHashMap;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraftforge.fml.network.FMLHandshakeMessages;
|
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
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.apache.logging.log4j.Marker;
|
import org.apache.logging.log4j.Marker;
|
||||||
import org.apache.logging.log4j.MarkerManager;
|
import org.apache.logging.log4j.MarkerManager;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.rethrowFunction;
|
|
||||||
|
|
||||||
public class ConfigTracker {
|
public class ConfigTracker {
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
@@ -55,7 +36,7 @@ public class ConfigTracker {
|
|||||||
public static final ConfigTracker INSTANCE = new ConfigTracker();
|
public static final ConfigTracker INSTANCE = new ConfigTracker();
|
||||||
private final ConcurrentHashMap<String, ModConfig> fileMap;
|
private final ConcurrentHashMap<String, ModConfig> fileMap;
|
||||||
private final EnumMap<ModConfig.Type, Set<ModConfig>> configSets;
|
private final EnumMap<ModConfig.Type, Set<ModConfig>> configSets;
|
||||||
private ConcurrentHashMap<String, Map<ModConfig.Type, ModConfig>> configsByMod;
|
private final ConcurrentHashMap<String, Map<ModConfig.Type, ModConfig>> configsByMod;
|
||||||
|
|
||||||
private ConfigTracker() {
|
private ConfigTracker() {
|
||||||
this.fileMap = new ConcurrentHashMap<>();
|
this.fileMap = new ConcurrentHashMap<>();
|
||||||
@@ -88,22 +69,11 @@ public class ConfigTracker {
|
|||||||
this.configSets.get(type).forEach(config -> closeConfig(config, configBasePath));
|
this.configSets.get(type).forEach(config -> closeConfig(config, configBasePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pair<String, FMLHandshakeMessages.S2CConfigData>> syncConfigs(boolean isLocal) {
|
|
||||||
final Map<String, byte[]> configData = configSets.get(ModConfig.Type.SERVER).stream().collect(Collectors.toMap(ModConfig::getFileName, mc -> { //TODO: Test cpw's LambdaExceptionUtils on Oracle javac.
|
|
||||||
try {
|
|
||||||
return Files.readAllBytes(mc.getFullPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return configData.entrySet().stream().map(e->Pair.of("Config "+e.getKey(), new FMLHandshakeMessages.S2CConfigData(e.getKey(), e.getValue()))).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openConfig(final ModConfig config, final Path configBasePath) {
|
private void openConfig(final ModConfig config, final Path configBasePath) {
|
||||||
LOGGER.trace(CONFIG, "Loading config file type {} at {} for {}", config.getType(), config.getFileName(), config.getModId());
|
LOGGER.trace(CONFIG, "Loading config file type {} at {} for {}", config.getType(), config.getFileName(), config.getModId());
|
||||||
final CommentedFileConfig configData = config.getHandler().reader(configBasePath).apply(config);
|
final CommentedFileConfig configData = config.getHandler().reader(configBasePath).apply(config);
|
||||||
config.setConfigData(configData);
|
config.setConfigData(configData);
|
||||||
config.fireEvent(new ModConfig.Loading(config));
|
config.fireEvent(IConfigEvent.loading(config));
|
||||||
config.save();
|
config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,21 +86,12 @@ public class ConfigTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receiveSyncedConfig(final FMLHandshakeMessages.S2CConfigData s2CConfigData, final Supplier<NetworkEvent.Context> contextSupplier) {
|
|
||||||
if (!Minecraft.getInstance().isLocalServer()) {
|
|
||||||
Optional.ofNullable(fileMap.get(s2CConfigData.getFileName())).ifPresent(mc-> {
|
|
||||||
mc.setConfigData(TomlFormat.instance().createParser().parse(new ByteArrayInputStream(s2CConfigData.getBytes())));
|
|
||||||
mc.fireEvent(new ModConfig.Reloading(mc));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadDefaultServerConfigs() {
|
public void loadDefaultServerConfigs() {
|
||||||
configSets.get(ModConfig.Type.SERVER).forEach(modConfig -> {
|
configSets.get(ModConfig.Type.SERVER).forEach(modConfig -> {
|
||||||
final CommentedConfig commentedConfig = CommentedConfig.inMemory();
|
final CommentedConfig commentedConfig = CommentedConfig.inMemory();
|
||||||
modConfig.getSpec().correct(commentedConfig);
|
modConfig.getSpec().correct(commentedConfig);
|
||||||
modConfig.setConfigData(commentedConfig);
|
modConfig.setConfigData(commentedConfig);
|
||||||
modConfig.fireEvent(new ModConfig.Loading(modConfig));
|
modConfig.fireEvent(IConfigEvent.loading(modConfig));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,4 +99,12 @@ public class ConfigTracker {
|
|||||||
return Optional.ofNullable(configsByMod.getOrDefault(modId, Collections.emptyMap()).getOrDefault(type, null)).
|
return Optional.ofNullable(configsByMod.getOrDefault(modId, Collections.emptyMap()).getOrDefault(type, null)).
|
||||||
map(ModConfig::getFullPath).map(Object::toString).orElse(null);
|
map(ModConfig::getFullPath).map(Object::toString).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<ModConfig.Type, Set<ModConfig>> configSets() {
|
||||||
|
return configSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<String, ModConfig> fileMap() {
|
||||||
|
return fileMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net.minecraftforge.fml.config;
|
||||||
|
|
||||||
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
import net.minecraftforge.fml.Bindings;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface IConfigEvent {
|
||||||
|
record ConfigConfig(Function<ModConfig, IConfigEvent> loading, Function<ModConfig, IConfigEvent> reloading) {}
|
||||||
|
ConfigConfig CONFIGCONFIG = Bindings.getConfigConfiguration().get();
|
||||||
|
|
||||||
|
static IConfigEvent reloading(ModConfig modConfig) {
|
||||||
|
return CONFIGCONFIG.reloading().apply(modConfig);
|
||||||
|
}
|
||||||
|
static IConfigEvent loading(ModConfig modConfig) {
|
||||||
|
return CONFIGCONFIG.loading().apply(modConfig);
|
||||||
|
}
|
||||||
|
ModConfig getConfig();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default <T extends Event & IConfigEvent> T self() {
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package net.minecraftforge.fml.config;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
|
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||||
|
|
||||||
|
public interface IConfigSpec<T extends IConfigSpec<T>> extends UnmodifiableConfig {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default T self() {
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acceptConfig(CommentedConfig data);
|
||||||
|
|
||||||
|
boolean isCorrecting();
|
||||||
|
|
||||||
|
boolean isCorrect(CommentedConfig commentedFileConfig);
|
||||||
|
|
||||||
|
int correct(CommentedConfig commentedFileConfig);
|
||||||
|
|
||||||
|
void afterReload();
|
||||||
|
}
|
||||||
+15
-34
@@ -21,26 +21,25 @@ package net.minecraftforge.fml.config;
|
|||||||
|
|
||||||
import com.electronwill.nightconfig.core.CommentedConfig;
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import com.electronwill.nightconfig.toml.TomlFormat;
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
import net.minecraftforge.fml.ModContainer;
|
||||||
import net.minecraftforge.fml.event.lifecycle.IModBusEvent;
|
|
||||||
import net.minecraftforge.fml.loading.StringUtils;
|
import net.minecraftforge.fml.loading.StringUtils;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class ModConfig
|
public class ModConfig
|
||||||
{
|
{
|
||||||
private final Type type;
|
private final Type type;
|
||||||
private final ForgeConfigSpec spec;
|
private final IConfigSpec<?> spec;
|
||||||
private final String fileName;
|
private final String fileName;
|
||||||
private final ModContainer container;
|
private final ModContainer container;
|
||||||
private final ConfigFileTypeHandler configHandler;
|
private final ConfigFileTypeHandler configHandler;
|
||||||
private CommentedConfig configData;
|
private CommentedConfig configData;
|
||||||
private Callable<Void> saveHandler;
|
private Callable<Void> saveHandler;
|
||||||
|
|
||||||
public ModConfig(final Type type, final ForgeConfigSpec spec, final ModContainer container, final String fileName) {
|
public ModConfig(final Type type, final IConfigSpec<?> spec, final ModContainer container, final String fileName) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.spec = spec;
|
this.spec = spec;
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
@@ -49,7 +48,7 @@ public class ModConfig
|
|||||||
ConfigTracker.INSTANCE.trackConfig(this);
|
ConfigTracker.INSTANCE.trackConfig(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModConfig(final Type type, final ForgeConfigSpec spec, final ModContainer activeContainer) {
|
public ModConfig(final Type type, final IConfigSpec<?> spec, final ModContainer activeContainer) {
|
||||||
this(type, spec, activeContainer, defaultConfigName(type, activeContainer.getModId()));
|
this(type, spec, activeContainer, defaultConfigName(type, activeContainer.getModId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,8 +68,9 @@ public class ModConfig
|
|||||||
return configHandler;
|
return configHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ForgeConfigSpec getSpec() {
|
@SuppressWarnings("unchecked")
|
||||||
return spec;
|
public <T extends IConfigSpec<T>> IConfigSpec<T> getSpec() {
|
||||||
|
return (IConfigSpec<T>) spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getModId() {
|
public String getModId() {
|
||||||
@@ -83,10 +83,10 @@ public class ModConfig
|
|||||||
|
|
||||||
void setConfigData(final CommentedConfig configData) {
|
void setConfigData(final CommentedConfig configData) {
|
||||||
this.configData = configData;
|
this.configData = configData;
|
||||||
this.spec.setConfig(this.configData);
|
this.spec.acceptConfig(this.configData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fireEvent(final ModConfigEvent configEvent) {
|
void fireEvent(final IConfigEvent configEvent) {
|
||||||
this.container.dispatchConfigEvent(configEvent);
|
this.container.dispatchConfigEvent(configEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +98,11 @@ public class ModConfig
|
|||||||
return ((CommentedFileConfig)this.configData).getNioPath();
|
return ((CommentedFileConfig)this.configData).getNioPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void acceptSyncedConfig(byte[] bytes) {
|
||||||
|
setConfigData(TomlFormat.instance().createParser().parse(new ByteArrayInputStream(bytes)));
|
||||||
|
fireEvent(IConfigEvent.reloading(this));
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
/**
|
/**
|
||||||
* Common mod config for configuration that needs to be loaded on both environments.
|
* Common mod config for configuration that needs to be loaded on both environments.
|
||||||
@@ -133,28 +138,4 @@ public class ModConfig
|
|||||||
return StringUtils.toLowerCase(name());
|
return StringUtils.toLowerCase(name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ModConfigEvent extends Event implements IModBusEvent {
|
|
||||||
private final ModConfig config;
|
|
||||||
|
|
||||||
ModConfigEvent(final ModConfig config) {
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModConfig getConfig() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Loading extends ModConfigEvent {
|
|
||||||
Loading(final ModConfig config) {
|
|
||||||
super(config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Reloading extends ModConfigEvent {
|
|
||||||
Reloading(final ModConfig config) {
|
|
||||||
super(config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.event.lifecycle;
|
package net.minecraftforge.fml.event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marker interface for events dispatched on the ModLifecycle event bus instead of the primary event bus
|
* Marker interface for events dispatched on the ModLifecycle event bus instead of the primary event bus
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
package net.minecraftforge.fml.util;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
package net.minecraftforge.fml.util;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
+1
-2
@@ -17,8 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
package net.minecraftforge.fml.util;
|
||||||
import net.minecraftforge.fml.common.EnhancedRuntimeException.WrappedPrintStream;
|
|
||||||
|
|
||||||
|
|
||||||
public class LoaderException extends EnhancedRuntimeException
|
public class LoaderException extends EnhancedRuntimeException
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
package net.minecraftforge.fml.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevent LoaderException from adding its own stack trace to the wrapped throwable's stack trace.
|
* Prevent LoaderException from adding its own stack trace to the wrapped throwable's stack trace.
|
||||||
+14
-15
@@ -17,15 +17,12 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
package net.minecraftforge.fml.util;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import cpw.mods.modlauncher.api.INameMappingService;
|
import cpw.mods.modlauncher.api.INameMappingService;
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -34,6 +31,8 @@ import org.apache.logging.log4j.Marker;
|
|||||||
import org.apache.logging.log4j.MarkerManager;
|
import org.apache.logging.log4j.MarkerManager;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some reflection helper code.
|
* Some reflection helper code.
|
||||||
@@ -58,7 +57,7 @@ public class ObfuscationReflectionHelper
|
|||||||
* @param name The name to try and remap.
|
* @param name The name to try and remap.
|
||||||
* @return The remapped name, or the original name if it couldn't be remapped.
|
* @return The remapped name, or the original name if it couldn't be remapped.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@NotNull
|
||||||
public static String remapName(INameMappingService.Domain domain, String name)
|
public static String remapName(INameMappingService.Domain domain, String name)
|
||||||
{
|
{
|
||||||
return FMLLoader.getNameFunction("srg").map(f->f.apply(domain, name)).orElse(name);
|
return FMLLoader.getNameFunction("srg").map(f->f.apply(domain, name)).orElse(name);
|
||||||
@@ -72,7 +71,7 @@ public class ObfuscationReflectionHelper
|
|||||||
*
|
*
|
||||||
* @param classToAccess The class to find the field on.
|
* @param classToAccess The class to find the field on.
|
||||||
* @param instance The instance of the {@code classToAccess}.
|
* @param instance The instance of the {@code classToAccess}.
|
||||||
* @param fieldName The SRG (unmapped) name of the field to find (e.g. "field_181725_a").
|
* @param fieldName The SRG (unmapped) name of the field to find (e.g. "f_46443_").
|
||||||
* @param <T> The type of the value.
|
* @param <T> The type of the value.
|
||||||
* @param <E> The type of the {@code classToAccess}.
|
* @param <E> The type of the {@code classToAccess}.
|
||||||
* @return The value of the field with the specified name in the {@code classToAccess}.
|
* @return The value of the field with the specified name in the {@code classToAccess}.
|
||||||
@@ -113,7 +112,7 @@ public class ObfuscationReflectionHelper
|
|||||||
* @throws UnableToFindFieldException If there was a problem getting the field.
|
* @throws UnableToFindFieldException If there was a problem getting the field.
|
||||||
* @throws UnableToAccessFieldException If there was a problem setting the value of the field.
|
* @throws UnableToAccessFieldException If there was a problem setting the value of the field.
|
||||||
*/
|
*/
|
||||||
public static <T, E> void setPrivateValue(@Nonnull final Class<? super T> classToAccess, @Nonnull final T instance, @Nullable final E value, @Nonnull final String fieldName)
|
public static <T, E> void setPrivateValue(@NotNull final Class<? super T> classToAccess, @NotNull final T instance, @Nullable final E value, @NotNull final String fieldName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -138,7 +137,7 @@ public class ObfuscationReflectionHelper
|
|||||||
* Throws an exception if the method is not found.
|
* Throws an exception if the method is not found.
|
||||||
*
|
*
|
||||||
* @param clazz The class to find the method on.
|
* @param clazz The class to find the method on.
|
||||||
* @param methodName The SRG (unmapped) name of the method to find (e.g. "func_12820_D").
|
* @param methodName The SRG (unmapped) name of the method to find (e.g. "m_5776_").
|
||||||
* @param parameterTypes The parameter types of the method to find.
|
* @param parameterTypes The parameter types of the method to find.
|
||||||
* @return The method with the specified name and parameters in the given class.
|
* @return The method with the specified name and parameters in the given class.
|
||||||
* @throws NullPointerException If {@code clazz} is null.
|
* @throws NullPointerException If {@code clazz} is null.
|
||||||
@@ -147,8 +146,8 @@ public class ObfuscationReflectionHelper
|
|||||||
* @throws NullPointerException If {@code parameterTypes} is null.
|
* @throws NullPointerException If {@code parameterTypes} is null.
|
||||||
* @throws UnableToFindMethodException If the method could not be found.
|
* @throws UnableToFindMethodException If the method could not be found.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@NotNull
|
||||||
public static Method findMethod(@Nonnull final Class<?> clazz, @Nonnull final String methodName, @Nonnull final Class<?>... parameterTypes)
|
public static Method findMethod(@NotNull final Class<?> clazz, @NotNull final String methodName, @NotNull final Class<?>... parameterTypes)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(clazz, "Class to find method on cannot be null.");
|
Preconditions.checkNotNull(clazz, "Class to find method on cannot be null.");
|
||||||
Preconditions.checkNotNull(methodName, "Name of method to find cannot be null.");
|
Preconditions.checkNotNull(methodName, "Name of method to find cannot be null.");
|
||||||
@@ -181,8 +180,8 @@ public class ObfuscationReflectionHelper
|
|||||||
* @throws NullPointerException If {@code parameterTypes} is null.
|
* @throws NullPointerException If {@code parameterTypes} is null.
|
||||||
* @throws UnknownConstructorException If the constructor could not be found.
|
* @throws UnknownConstructorException If the constructor could not be found.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@NotNull
|
||||||
public static <T> Constructor<T> findConstructor(@Nonnull final Class<T> clazz, @Nonnull final Class<?>... parameterTypes)
|
public static <T> Constructor<T> findConstructor(@NotNull final Class<T> clazz, @NotNull final Class<?>... parameterTypes)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(clazz, "Class to find constructor on cannot be null.");
|
Preconditions.checkNotNull(clazz, "Class to find constructor on cannot be null.");
|
||||||
Preconditions.checkNotNull(parameterTypes, "Parameter types of constructor to find cannot be null.");
|
Preconditions.checkNotNull(parameterTypes, "Parameter types of constructor to find cannot be null.");
|
||||||
@@ -216,7 +215,7 @@ public class ObfuscationReflectionHelper
|
|||||||
* Throws an exception if the field is not found.
|
* Throws an exception if the field is not found.
|
||||||
*
|
*
|
||||||
* @param clazz The class to find the field on.
|
* @param clazz The class to find the field on.
|
||||||
* @param fieldName The SRG (unmapped) name of the field to find (e.g. "field_181725_a").
|
* @param fieldName The SRG (unmapped) name of the field to find (e.g. "f_46443_").
|
||||||
* @param <T> The type.
|
* @param <T> The type.
|
||||||
* @return The constructor with the specified parameters in the given class.
|
* @return The constructor with the specified parameters in the given class.
|
||||||
* @throws NullPointerException If {@code clazz} is null.
|
* @throws NullPointerException If {@code clazz} is null.
|
||||||
@@ -224,8 +223,8 @@ public class ObfuscationReflectionHelper
|
|||||||
* @throws IllegalArgumentException If {@code fieldName} is empty.
|
* @throws IllegalArgumentException If {@code fieldName} is empty.
|
||||||
* @throws UnableToFindFieldException If the field could not be found.
|
* @throws UnableToFindFieldException If the field could not be found.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@NotNull
|
||||||
public static <T> Field findField(@Nonnull final Class<? super T> clazz, @Nonnull final String fieldName)
|
public static <T> Field findField(@NotNull final Class<? super T> clazz, @NotNull final String fieldName)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(clazz, "Class to find field on cannot be null.");
|
Preconditions.checkNotNull(clazz, "Class to find field on cannot be null.");
|
||||||
Preconditions.checkNotNull(fieldName, "Name of field to find cannot be null.");
|
Preconditions.checkNotNull(fieldName, "Name of field to find cannot be null.");
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.thread;
|
package net.minecraftforge.fml.util.thread;
|
||||||
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
import net.minecraftforge.fml.LogicalSide;
|
||||||
|
|
||||||
+3
-4
@@ -17,14 +17,13 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.thread;
|
package net.minecraftforge.fml.util.thread;
|
||||||
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
import net.minecraftforge.fml.LogicalSide;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread group and factory combination which belongs to a {@link LogicalSide}.
|
* A thread group and factory combination which belongs to a {@link LogicalSide}.
|
||||||
*/
|
*/
|
||||||
@@ -49,7 +48,7 @@ public final class SidedThreadGroup extends ThreadGroup implements ThreadFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(@Nonnull final Runnable runnable)
|
public Thread newThread(@NotNull final Runnable runnable)
|
||||||
{
|
{
|
||||||
return new Thread(this, runnable);
|
return new Thread(this, runnable);
|
||||||
}
|
}
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.thread;
|
package net.minecraftforge.fml.util.thread;
|
||||||
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
import net.minecraftforge.fml.LogicalSide;
|
||||||
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
plugins {
|
||||||
|
id 'com.github.ben-manes.versions'
|
||||||
|
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||||
|
}
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
apply plugin: 'jacoco'
|
||||||
|
apply plugin: 'org.javamodularity.moduleplugin'
|
||||||
|
|
||||||
|
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||||
|
configurations.forEach{ it.transitive = false }
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation('net.sf.jopt-simple:jopt-simple:5.0.4')
|
||||||
|
compileOnly('org.jetbrains:annotations:21.0.0')
|
||||||
|
api("org.ow2.asm:asm:${ASM_VERSION}")
|
||||||
|
api("org.ow2.asm:asm-tree:${ASM_VERSION}")
|
||||||
|
api("org.ow2.asm:asm-commons:${ASM_VERSION}")
|
||||||
|
api('net.minecraftforge:forgespi:4.0.+')
|
||||||
|
api('org.apache.logging.log4j:log4j-api:2.14.1')
|
||||||
|
api('com.google.guava:guava:21.0')
|
||||||
|
api('com.google.code.gson:gson:2.8.0')
|
||||||
|
api('org.apache.maven:maven-artifact:3.8.1')
|
||||||
|
api('org.apache.commons:commons-lang3:3.8.1')
|
||||||
|
api('com.electronwill.night-config:core:3.6.3')
|
||||||
|
api('com.electronwill.night-config:toml:3.6.3')
|
||||||
|
api('cpw.mods:modlauncher:9.0.+')
|
||||||
|
api('net.minecraftforge:coremods:5.0.+')
|
||||||
|
implementation("cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}")
|
||||||
|
implementation('org.apache.logging.log4j:log4j-core:2.14.1')
|
||||||
|
annotationProcessor('org.apache.logging.log4j:log4j-core:2.14.1')
|
||||||
|
implementation('net.minecraftforge:accesstransformers:8.0.4')
|
||||||
|
implementation('net.minecrell:terminalconsoleappender:1.2.0')
|
||||||
|
// implementation('org.jline:jline:3.12.+')
|
||||||
|
testCompileOnly('org.jetbrains:annotations:21.0.0')
|
||||||
|
testRuntimeOnly("cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}")
|
||||||
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar) {
|
||||||
|
archiveClassifier = 'sources'
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
MANIFESTS = [
|
||||||
|
'/': [
|
||||||
|
'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||||
|
'Git-Commit': GIT_INFO.abbreviatedId,
|
||||||
|
'Git-Branch': GIT_INFO.branch,
|
||||||
|
'Build-Number': "${System.getenv('BUILD_NUMBER')?:0}",
|
||||||
|
] as LinkedHashMap,
|
||||||
|
'net/minecraftforge/fml/loading/': [
|
||||||
|
'Specification-Title': 'FMLLoader',
|
||||||
|
'Specification-Vendor': 'Forge Development LLC',
|
||||||
|
'Specification-Version': '1',
|
||||||
|
'Implementation-Title': 'FML Loader',
|
||||||
|
'Implementation-Version': '1.0',
|
||||||
|
'Implementation-Vendor': 'Forge'
|
||||||
|
] as LinkedHashMap
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.doFirst {
|
||||||
|
MANIFESTS.each { pkg, values ->
|
||||||
|
manifest.attributes(values, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs << '-Xlint:unchecked'
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives jar
|
||||||
|
archives sourcesJar
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing.publications.mavenJava(MavenPublication) {
|
||||||
|
from components.java
|
||||||
|
artifact sourcesJar
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+7
-5
@@ -21,6 +21,7 @@ package net.minecraftforge.fml.loading;
|
|||||||
|
|
||||||
import com.electronwill.nightconfig.core.ConfigSpec;
|
import com.electronwill.nightconfig.core.ConfigSpec;
|
||||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
|
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
|
||||||
import com.electronwill.nightconfig.core.io.ParsingException;
|
import com.electronwill.nightconfig.core.io.ParsingException;
|
||||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
@@ -30,6 +31,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
||||||
@@ -50,11 +52,11 @@ public class FMLConfig
|
|||||||
|
|
||||||
private void loadFrom(final Path configFile)
|
private void loadFrom(final Path configFile)
|
||||||
{
|
{
|
||||||
configData = CommentedFileConfig.builder(configFile).sync().
|
configData = CommentedFileConfig.builder(configFile).sync()
|
||||||
defaultResource("/META-INF/defaultfmlconfig.toml").
|
.onFileNotFound(FileNotFoundAction.copyData(Objects.requireNonNull(getClass().getResourceAsStream("/META-INF/defaultfmlconfig.toml"))))
|
||||||
autosave().autoreload().
|
.autosave().autoreload()
|
||||||
writingMode(WritingMode.REPLACE).
|
.writingMode(WritingMode.REPLACE)
|
||||||
build();
|
.build();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
configData.load();
|
configData.load();
|
||||||
File renamed without changes.
+43
-86
@@ -20,42 +20,25 @@
|
|||||||
package net.minecraftforge.fml.loading;
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.Launcher;
|
import cpw.mods.modlauncher.Launcher;
|
||||||
import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
|
import cpw.mods.modlauncher.api.*;
|
||||||
import cpw.mods.modlauncher.TransformingClassLoader;
|
|
||||||
import cpw.mods.modlauncher.api.IEnvironment;
|
|
||||||
import cpw.mods.modlauncher.api.ILaunchHandlerService;
|
|
||||||
import cpw.mods.modlauncher.api.INameMappingService;
|
|
||||||
import cpw.mods.modlauncher.api.ITransformationService;
|
|
||||||
import cpw.mods.modlauncher.api.ITransformingClassLoader;
|
|
||||||
import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
|
|
||||||
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
|
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
|
||||||
|
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
|
||||||
import net.minecraftforge.accesstransformer.service.AccessTransformerService;
|
import net.minecraftforge.accesstransformer.service.AccessTransformerService;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
|
import net.minecraftforge.fml.loading.moddiscovery.*;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer;
|
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
|
||||||
import net.minecraftforge.fml.loading.progress.EarlyProgressVisualization;
|
import net.minecraftforge.fml.loading.progress.EarlyProgressVisualization;
|
||||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||||
|
import net.minecraftforge.fml.loading.targets.CommonLaunchHandler;
|
||||||
import net.minecraftforge.forgespi.Environment;
|
import net.minecraftforge.forgespi.Environment;
|
||||||
import net.minecraftforge.forgespi.coremod.ICoreModProvider;
|
import net.minecraftforge.forgespi.coremod.ICoreModProvider;
|
||||||
import net.minecraftforge.forgespi.locating.IModFile;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
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 java.net.URL;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
||||||
@@ -72,21 +55,16 @@ public class FMLLoader
|
|||||||
private static Dist dist;
|
private static Dist dist;
|
||||||
private static String naming;
|
private static String naming;
|
||||||
private static LoadingModList loadingModList;
|
private static LoadingModList loadingModList;
|
||||||
private static TransformingClassLoader launchClassLoader;
|
|
||||||
private static RuntimeDistCleaner runtimeDistCleaner;
|
private static RuntimeDistCleaner runtimeDistCleaner;
|
||||||
private static Path gamePath;
|
private static Path gamePath;
|
||||||
private static Path forgePath;
|
private static VersionInfo versionInfo;
|
||||||
private static Path[] mcPaths;
|
|
||||||
static String mcVersion;
|
|
||||||
private static String mcpVersion;
|
|
||||||
static String forgeVersion;
|
|
||||||
private static String forgeGroup;
|
|
||||||
private static Predicate<String> classLoaderExclusions;
|
|
||||||
private static String launchHandlerName;
|
private static String launchHandlerName;
|
||||||
private static FMLCommonLaunchHandler commonLaunchHandler;
|
private static CommonLaunchHandler commonLaunchHandler;
|
||||||
public static Runnable progressWindowTick;
|
public static Runnable progressWindowTick;
|
||||||
|
private static ModValidator modValidator;
|
||||||
public static BackgroundScanHandler backgroundScanHandler;
|
public static BackgroundScanHandler backgroundScanHandler;
|
||||||
private static boolean production;
|
private static boolean production;
|
||||||
|
private static IModuleLayerManager moduleLayerManager;
|
||||||
|
|
||||||
static void onInitialLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException
|
static void onInitialLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException
|
||||||
{
|
{
|
||||||
@@ -98,8 +76,6 @@ public class FMLLoader
|
|||||||
LOGGER.fatal(CORE,"Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor());
|
LOGGER.fatal(CORE,"Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor());
|
||||||
throw new IncompatibleEnvironmentException("Incompatible modlauncher found "+modLauncherPackage.getSpecificationVersion());
|
throw new IncompatibleEnvironmentException("Incompatible modlauncher found "+modLauncherPackage.getSpecificationVersion());
|
||||||
}
|
}
|
||||||
LOGGER.debug(CORE, "Initializing modjar URL handler");
|
|
||||||
URL.setURLStreamHandlerFactory(p->p.equals("modjar") ? new ModJarURLHandler() : null);
|
|
||||||
|
|
||||||
accessTransformer = (AccessTransformerService) environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> {
|
accessTransformer = (AccessTransformerService) environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> {
|
||||||
LOGGER.fatal(CORE,"Access Transformer library is missing, we need this to run");
|
LOGGER.fatal(CORE,"Access Transformer library is missing, we need this to run");
|
||||||
@@ -131,8 +107,7 @@ public class FMLLoader
|
|||||||
});
|
});
|
||||||
LOGGER.debug(CORE, "Found Runtime Dist Cleaner");
|
LOGGER.debug(CORE, "Found Runtime Dist Cleaner");
|
||||||
|
|
||||||
final ArrayList<ICoreModProvider> coreModProviders = new ArrayList<>();
|
var coreModProviders = ServiceLoaderUtils.streamWithErrorHandling(ServiceLoader.load(FMLLoader.class.getModule().getLayer(), ICoreModProvider.class), sce -> LOGGER.fatal(CORE, "Failed to load a coremod library, expect problems", sce)).toList();
|
||||||
ServiceLoaderStreamUtils.errorHandlingServiceLoader(ICoreModProvider.class, serviceConfigurationError -> LOGGER.fatal(CORE, "Failed to load a coremod library, expect problems", serviceConfigurationError)).forEach(coreModProviders::add);
|
|
||||||
|
|
||||||
if (coreModProviders.isEmpty()) {
|
if (coreModProviders.isEmpty()) {
|
||||||
LOGGER.fatal(CORE, "Found no coremod provider. Cannot run");
|
LOGGER.fatal(CORE, "Found no coremod provider. Cannot run");
|
||||||
@@ -161,7 +136,6 @@ public class FMLLoader
|
|||||||
LOGGER.fatal(CORE, "Failed to load NightConfig");
|
LOGGER.fatal(CORE, "Failed to load NightConfig");
|
||||||
throw new IncompatibleEnvironmentException("Missing NightConfig");
|
throw new IncompatibleEnvironmentException("Missing NightConfig");
|
||||||
}
|
}
|
||||||
FixSSL.fixup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setupLaunchHandler(final IEnvironment environment, final Map<String, ?> arguments)
|
static void setupLaunchHandler(final IEnvironment environment, final Map<String, ?> arguments)
|
||||||
@@ -169,55 +143,48 @@ public class FMLLoader
|
|||||||
final String launchTarget = environment.getProperty(IEnvironment.Keys.LAUNCHTARGET.get()).orElse("MISSING");
|
final String launchTarget = environment.getProperty(IEnvironment.Keys.LAUNCHTARGET.get()).orElse("MISSING");
|
||||||
final Optional<ILaunchHandlerService> launchHandler = environment.findLaunchHandler(launchTarget);
|
final Optional<ILaunchHandlerService> launchHandler = environment.findLaunchHandler(launchTarget);
|
||||||
LOGGER.debug(CORE, "Using {} as launch service", launchTarget);
|
LOGGER.debug(CORE, "Using {} as launch service", launchTarget);
|
||||||
if (!launchHandler.isPresent()) {
|
if (launchHandler.isEmpty()) {
|
||||||
LOGGER.fatal(CORE,"Missing LaunchHandler {}, cannot continue", launchTarget);
|
LOGGER.fatal(CORE,"Missing LaunchHandler {}, cannot continue", launchTarget);
|
||||||
throw new RuntimeException("Missing launch handler");
|
throw new RuntimeException("Missing launch handler: " + launchTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(launchHandler.get() instanceof FMLCommonLaunchHandler)) {
|
if (!(launchHandler.get() instanceof CommonLaunchHandler)) {
|
||||||
LOGGER.fatal(CORE, "Incompatible Launch handler found - type {}, cannot continue", launchHandler.get().getClass().getName());
|
LOGGER.fatal(CORE, "Incompatible Launch handler found - type {}, cannot continue", launchHandler.get().getClass().getName());
|
||||||
throw new RuntimeException("Incompatible launch handler found");
|
throw new RuntimeException("Incompatible launch handler found");
|
||||||
}
|
}
|
||||||
|
commonLaunchHandler = (CommonLaunchHandler)launchHandler.get();
|
||||||
launchHandlerName = launchHandler.get().name();
|
launchHandlerName = launchHandler.get().name();
|
||||||
gamePath = environment.getProperty(IEnvironment.Keys.GAMEDIR.get()).orElse(Paths.get(".").toAbsolutePath());
|
gamePath = environment.getProperty(IEnvironment.Keys.GAMEDIR.get()).orElse(Paths.get(".").toAbsolutePath());
|
||||||
|
|
||||||
commonLaunchHandler = (FMLCommonLaunchHandler)launchHandler.get();
|
|
||||||
naming = commonLaunchHandler.getNaming();
|
naming = commonLaunchHandler.getNaming();
|
||||||
dist = commonLaunchHandler.getDist();
|
dist = commonLaunchHandler.getDist();
|
||||||
production = commonLaunchHandler.isProduction();
|
production = commonLaunchHandler.isProduction();
|
||||||
|
|
||||||
mcVersion = (String) arguments.get("mcVersion");
|
versionInfo = new VersionInfo(arguments);
|
||||||
progressWindowTick = EarlyProgressVisualization.INSTANCE.accept(dist, commonLaunchHandler.isData(), mcVersion);
|
|
||||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Early Loading!"));
|
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Early Loading!"));
|
||||||
accessTransformer.getExtension().accept(Pair.of(naming, "srg"));
|
accessTransformer.getExtension().accept(Pair.of(naming, "srg"));
|
||||||
|
|
||||||
mcpVersion = (String) arguments.get("mcpVersion");
|
LOGGER.debug(CORE,"Received command line version data : {}", versionInfo);
|
||||||
forgeVersion = (String) arguments.get("forgeVersion");
|
|
||||||
forgeGroup = (String) arguments.get("forgeGroup");
|
|
||||||
|
|
||||||
LOGGER.debug(CORE,"Received command line version data : MC Version: '{}' MCP Version: '{}' Forge Version: '{}' Forge group: '{}'", mcVersion, mcpVersion, forgeVersion, forgeGroup);
|
|
||||||
forgePath = commonLaunchHandler.getForgePath(mcVersion, forgeVersion, forgeGroup);
|
|
||||||
mcPaths = commonLaunchHandler.getMCPaths(mcVersion, mcpVersion, forgeVersion, forgeGroup);
|
|
||||||
|
|
||||||
commonLaunchHandler.validatePaths(forgePath, mcPaths, forgeVersion, mcVersion, mcpVersion);
|
|
||||||
commonLaunchHandler.setup(environment, arguments);
|
|
||||||
classLoaderExclusions = commonLaunchHandler.getPackagePredicate();
|
|
||||||
|
|
||||||
languageLoadingProvider = new LanguageLoadingProvider();
|
|
||||||
languageLoadingProvider.addForgeLanguage(forgePath);
|
|
||||||
|
|
||||||
runtimeDistCleaner.getExtension().accept(dist);
|
runtimeDistCleaner.getExtension().accept(dist);
|
||||||
progressWindowTick.run();
|
|
||||||
}
|
}
|
||||||
public static Map<IModFile.Type, List<ModFile>> beginModScan(final Map<String,?> arguments)
|
public static List<ITransformationService.Resource> beginModScan(final Map<String,?> arguments)
|
||||||
{
|
{
|
||||||
LOGGER.debug(SCAN,"Scanning for Mod Locators");
|
LOGGER.debug(SCAN,"Scanning for Mod Locators");
|
||||||
modDiscoverer = new ModDiscoverer(arguments);
|
modDiscoverer = new ModDiscoverer(arguments);
|
||||||
backgroundScanHandler = modDiscoverer.discoverMods();
|
modValidator = modDiscoverer.discoverMods();
|
||||||
|
var pluginResources = modValidator.getPluginResources();
|
||||||
|
return List.of(pluginResources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ITransformationService.Resource> completeScan(IModuleLayerManager layerManager) {
|
||||||
|
progressWindowTick = EarlyProgressVisualization.INSTANCE.accept(dist, commonLaunchHandler.isData(), versionInfo.mcVersion());
|
||||||
|
moduleLayerManager = layerManager;
|
||||||
|
languageLoadingProvider = new LanguageLoadingProvider();
|
||||||
|
backgroundScanHandler = modValidator.stage2Validation();
|
||||||
loadingModList = backgroundScanHandler.getLoadingModList();
|
loadingModList = backgroundScanHandler.getLoadingModList();
|
||||||
commonLaunchHandler.addLibraries(backgroundScanHandler.getModFiles().getOrDefault(IModFile.Type.LIBRARY, Collections.emptyList()));
|
return List.of(modValidator.getModResources());
|
||||||
progressWindowTick.run();
|
|
||||||
return loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.groupingBy(ModFile::getType));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICoreModProvider getCoreModProvider() {
|
public static ICoreModProvider getCoreModProvider() {
|
||||||
@@ -233,6 +200,10 @@ public class FMLLoader
|
|||||||
return modDiscoverer;
|
return modDiscoverer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CommonLaunchHandler getLaunchHandler() {
|
||||||
|
return commonLaunchHandler;
|
||||||
|
}
|
||||||
|
|
||||||
public static void addAccessTransformer(Path atPath, ModFile modName)
|
public static void addAccessTransformer(Path atPath, ModFile modName)
|
||||||
{
|
{
|
||||||
LOGGER.debug(SCAN, "Adding Access Transformer in {}", modName.getFilePath());
|
LOGGER.debug(SCAN, "Adding Access Transformer in {}", modName.getFilePath());
|
||||||
@@ -244,9 +215,8 @@ public class FMLLoader
|
|||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void beforeStart(ITransformingClassLoader launchClassLoader)
|
public static void beforeStart(ClassLoader launchClassLoader)
|
||||||
{
|
{
|
||||||
FMLLoader.launchClassLoader = (TransformingClassLoader) launchClassLoader.getInstance();
|
|
||||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Launching minecraft"));
|
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Launching minecraft"));
|
||||||
progressWindowTick.run();
|
progressWindowTick.run();
|
||||||
}
|
}
|
||||||
@@ -256,28 +226,11 @@ public class FMLLoader
|
|||||||
return loadingModList;
|
return loadingModList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransformingClassLoader getLaunchClassLoader()
|
|
||||||
{
|
|
||||||
return launchClassLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Path getGamePath()
|
public static Path getGamePath()
|
||||||
{
|
{
|
||||||
return gamePath;
|
return gamePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path getForgePath() {
|
|
||||||
return forgePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Path[] getMCPaths() {
|
|
||||||
return mcPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<String> getClassLoaderExclusions() {
|
|
||||||
return classLoaderExclusions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getNaming() {
|
public static String getNaming() {
|
||||||
return naming;
|
return naming;
|
||||||
}
|
}
|
||||||
@@ -286,10 +239,6 @@ public class FMLLoader
|
|||||||
return Launcher.INSTANCE.environment().findNameMapping(naming);
|
return Launcher.INSTANCE.environment().findNameMapping(naming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getMcpVersion() {
|
|
||||||
return mcpVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getLauncherInfo() {
|
public static String getLauncherInfo() {
|
||||||
return Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.MLIMPL_VERSION.get()).orElse("MISSING");
|
return Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.MLIMPL_VERSION.get()).orElse("MISSING");
|
||||||
}
|
}
|
||||||
@@ -307,6 +256,14 @@ public class FMLLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSecureJarEnabled() {
|
public static boolean isSecureJarEnabled() {
|
||||||
return Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.SECURED_JARS_ENABLED.get()).orElse(false);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ModuleLayer getGameLayer() {
|
||||||
|
return moduleLayerManager.getLayer(IModuleLayerManager.Layer.GAME).orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VersionInfo versionInfo() {
|
||||||
|
return versionInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File renamed without changes.
+20
-22
@@ -19,10 +19,8 @@
|
|||||||
|
|
||||||
package net.minecraftforge.fml.loading;
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.api.IEnvironment;
|
import cpw.mods.jarhandling.SecureJar;
|
||||||
import cpw.mods.modlauncher.api.ITransformationService;
|
import cpw.mods.modlauncher.api.*;
|
||||||
import cpw.mods.modlauncher.api.ITransformer;
|
|
||||||
import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
|
|
||||||
import joptsimple.ArgumentAcceptingOptionSpec;
|
import joptsimple.ArgumentAcceptingOptionSpec;
|
||||||
import joptsimple.OptionSpecBuilder;
|
import joptsimple.OptionSpecBuilder;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
@@ -30,14 +28,16 @@ import net.minecraftforge.forgespi.Environment;
|
|||||||
import net.minecraftforge.forgespi.locating.IModFile;
|
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.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
@@ -47,7 +47,6 @@ import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
|||||||
|
|
||||||
public class FMLServiceProvider implements ITransformationService
|
public class FMLServiceProvider implements ITransformationService
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private ArgumentAcceptingOptionSpec<String> modsOption;
|
private ArgumentAcceptingOptionSpec<String> modsOption;
|
||||||
private ArgumentAcceptingOptionSpec<String> modListsOption;
|
private ArgumentAcceptingOptionSpec<String> modListsOption;
|
||||||
@@ -67,6 +66,12 @@ public class FMLServiceProvider implements ITransformationService
|
|||||||
private String targetForgeGroup;
|
private String targetForgeGroup;
|
||||||
private Map<String, Object> arguments;
|
private Map<String, Object> arguments;
|
||||||
|
|
||||||
|
public FMLServiceProvider()
|
||||||
|
{
|
||||||
|
final String markerselection = System.getProperty("forge.logging.markers", "");
|
||||||
|
Arrays.stream(markerselection.split(",")).forEach(marker -> System.setProperty("forge.logging.marker." + marker.toLowerCase(Locale.ROOT), "ACCEPT"));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name()
|
public String name()
|
||||||
{
|
{
|
||||||
@@ -97,28 +102,22 @@ public class FMLServiceProvider implements ITransformationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginScanning(final IEnvironment environment) {
|
public List<Resource> beginScanning(final IEnvironment environment) {
|
||||||
throw new IllegalStateException("WHY ARE YOU HERE??????");
|
LOGGER.debug(CORE,"Initiating mod scan");
|
||||||
|
return FMLLoader.beginModScan(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Map.Entry<String, Path>> runScan(final IEnvironment environment) {
|
public List<Resource> completeScan(final IModuleLayerManager layerManager) {
|
||||||
LOGGER.debug(CORE,"Initiating mod scan");
|
return FMLLoader.completeScan(layerManager);
|
||||||
final Map<IModFile.Type, List<ModFile>> foundFiles = FMLLoader.beginModScan(arguments);
|
|
||||||
return foundFiles
|
|
||||||
.values()
|
|
||||||
.stream()
|
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.map(modFile -> new AbstractMap.SimpleImmutableEntry<>(modFile.getFileName(), modFile.getFilePath()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException
|
public void onLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException
|
||||||
{
|
{
|
||||||
LOGGER.debug("Injecting tracing printstreams for STDOUT/STDERR.");
|
// LOGGER.debug("Injecting tracing printstreams for STDOUT/STDERR.");
|
||||||
System.setOut(new TracingPrintStream(LogManager.getLogger("STDOUT"), System.out));
|
// System.setOut(new TracingPrintStream(LogManager.getLogger("STDOUT"), System.out));
|
||||||
System.setErr(new TracingPrintStream(LogManager.getLogger("STDERR"), System.err));
|
// System.setErr(new TracingPrintStream(LogManager.getLogger("STDERR"), System.err));
|
||||||
FMLLoader.onInitialLoad(environment, otherServices);
|
FMLLoader.onInitialLoad(environment, otherServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,9 +147,8 @@ public class FMLServiceProvider implements ITransformationService
|
|||||||
targetMcpMappings = option.value(mappingsOption);
|
targetMcpMappings = option.value(mappingsOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
@Override
|
||||||
public List<ITransformer> transformers()
|
public @NotNull List<ITransformer> transformers()
|
||||||
{
|
{
|
||||||
LOGGER.debug(CORE, "Loading coremod transformers");
|
LOGGER.debug(CORE, "Loading coremod transformers");
|
||||||
return new ArrayList<>(FMLLoader.getCoreModProvider().getCoreModTransformers());
|
return new ArrayList<>(FMLLoader.getCoreModProvider().getCoreModTransformers());
|
||||||
File renamed without changes.
File renamed without changes.
+11
-23
@@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
package net.minecraftforge.fml.loading;
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
|
import cpw.mods.modlauncher.Launcher;
|
||||||
|
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||||
|
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
|
||||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||||
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
|
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
|
||||||
@@ -49,13 +51,12 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.rethrowFunction;
|
|
||||||
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
||||||
|
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||||
|
|
||||||
public class LanguageLoadingProvider
|
public class LanguageLoadingProvider
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private final LanguageClassLoader languageClassLoader;
|
|
||||||
private final List<IModLanguageProvider> languageProviders = new ArrayList<>();
|
private final List<IModLanguageProvider> languageProviders = new ArrayList<>();
|
||||||
private final ServiceLoader<IModLanguageProvider> serviceLoader;
|
private final ServiceLoader<IModLanguageProvider> serviceLoader;
|
||||||
private final Map<String, ModLanguageWrapper> languageProviderMap = new HashMap<>();
|
private final Map<String, ModLanguageWrapper> languageProviderMap = new HashMap<>();
|
||||||
@@ -71,7 +72,6 @@ public class LanguageLoadingProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class ModLanguageWrapper {
|
private static class ModLanguageWrapper {
|
||||||
|
|
||||||
private final IModLanguageProvider modLanguageProvider;
|
private final IModLanguageProvider modLanguageProvider;
|
||||||
|
|
||||||
private final ArtifactVersion version;
|
private final ArtifactVersion version;
|
||||||
@@ -92,26 +92,14 @@ public class LanguageLoadingProvider
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
private static class LanguageClassLoader extends URLClassLoader
|
|
||||||
{
|
|
||||||
public LanguageClassLoader() {
|
|
||||||
super(new URL[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addURL(final URL url) {
|
|
||||||
LOGGER.debug(CORE, "Adding {} to languageloader classloader", url);
|
|
||||||
super.addURL(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
LanguageLoadingProvider() {
|
LanguageLoadingProvider() {
|
||||||
languageClassLoader = new LanguageClassLoader();
|
var sl = Launcher.INSTANCE.environment().findModuleLayerManager().flatMap(lm->lm.getLayer(IModuleLayerManager.Layer.PLUGIN)).orElseThrow();
|
||||||
serviceLoader = ServiceLoader.load(IModLanguageProvider.class, languageClassLoader);
|
serviceLoader = ServiceLoader.load(sl, IModLanguageProvider.class);
|
||||||
loadLanguageProviders();
|
loadLanguageProviders();
|
||||||
}
|
}
|
||||||
private void loadLanguageProviders() {
|
private void loadLanguageProviders() {
|
||||||
LOGGER.debug(CORE, "Found {} language providers", ServiceLoaderStreamUtils.toList(serviceLoader).size());
|
LOGGER.debug(CORE, "Found {} language providers", ServiceLoaderUtils.streamServiceLoader(()->serviceLoader, sce->LOGGER.fatal("Problem with language loaders")).count());
|
||||||
serviceLoader.forEach(languageProviders::add);
|
serviceLoader.forEach(languageProviders::add);
|
||||||
|
|
||||||
languageProviders.forEach(lp -> {
|
languageProviders.forEach(lp -> {
|
||||||
@@ -122,7 +110,7 @@ public class LanguageLoadingProvider
|
|||||||
throw new RuntimeException("Huh?", e);
|
throw new RuntimeException("Huh?", e);
|
||||||
}
|
}
|
||||||
Optional<String> implementationVersion = JarVersionLookupHandler.getImplementationVersion(lp.getClass());
|
Optional<String> implementationVersion = JarVersionLookupHandler.getImplementationVersion(lp.getClass());
|
||||||
String impl = implementationVersion.orElse(Files.isDirectory(lpPath) ? FMLLoader.forgeVersion.split("\\.")[0] : null);
|
String impl = implementationVersion.orElse(Files.isDirectory(lpPath) ? FMLLoader.versionInfo().forgeVersion().split("\\.")[0] : null);
|
||||||
if (impl == null) {
|
if (impl == null) {
|
||||||
LOGGER.fatal(CORE, "Found unversioned language provider {}", lp.name());
|
LOGGER.fatal(CORE, "Found unversioned language provider {}", lp.name());
|
||||||
throw new RuntimeException("Failed to find implementation version for language provider "+ lp.name());
|
throw new RuntimeException("Failed to find implementation version for language provider "+ lp.name());
|
||||||
@@ -147,7 +135,7 @@ public class LanguageLoadingProvider
|
|||||||
private void addLanguagePaths(final Stream<Path> langPaths) {
|
private void addLanguagePaths(final Stream<Path> langPaths) {
|
||||||
languageProviders.clear();
|
languageProviders.clear();
|
||||||
languageProviderMap.clear();
|
languageProviderMap.clear();
|
||||||
langPaths.peek(languagePaths::add).map(Path::toFile).map(File::toURI).map(rethrowFunction(URI::toURL)).forEach(languageClassLoader::addURL);
|
// langPaths.peek(languagePaths::add).map(Path::toFile).map(File::toURI).map(rethrowFunction(URI::toURL)).forEach(languageClassLoader::addURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAdditionalLanguages(List<ModFile> modFiles)
|
public void addAdditionalLanguages(List<ModFile> modFiles)
|
||||||
@@ -167,11 +155,11 @@ public class LanguageLoadingProvider
|
|||||||
final String languageFileName = mf.getLocator() instanceof ExplodedDirectoryLocator ? "in-development" : mf.getFileName();
|
final String languageFileName = mf.getLocator() instanceof ExplodedDirectoryLocator ? "in-development" : mf.getFileName();
|
||||||
final ModLanguageWrapper mlw = languageProviderMap.get(modLoader);
|
final ModLanguageWrapper mlw = languageProviderMap.get(modLoader);
|
||||||
if (mlw == null) {
|
if (mlw == null) {
|
||||||
LOGGER.error("Missing language {} version {} wanted by {}", modLoader, modLoaderVersion, languageFileName);
|
LOGGER.error(LOADING,"Missing language {} version {} wanted by {}", modLoader, modLoaderVersion, languageFileName);
|
||||||
throw new EarlyLoadingException("Missing language "+modLoader, null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, "null")));
|
throw new EarlyLoadingException("Missing language "+modLoader, null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, "null")));
|
||||||
}
|
}
|
||||||
if (!VersionSupportMatrix.testVersionSupportMatrix(modLoaderVersion, modLoader, "languageloader", (llid, range) -> range.containsVersion(mlw.getVersion()))) {
|
if (!VersionSupportMatrix.testVersionSupportMatrix(modLoaderVersion, modLoader, "languageloader", (llid, range) -> range.containsVersion(mlw.getVersion()))) {
|
||||||
LOGGER.error("Missing language {} version {} wanted by {}, found {}", modLoader, modLoaderVersion, languageFileName, mlw.getVersion());
|
LOGGER.error(LOADING,"Missing language {} version {} wanted by {}, found {}", modLoader, modLoaderVersion, languageFileName, mlw.getVersion());
|
||||||
throw new EarlyLoadingException("Missing language "+ modLoader + " matching range "+modLoaderVersion + " found "+mlw.getVersion(), null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, mlw.getVersion())));
|
throw new EarlyLoadingException("Missing language "+ modLoader + " matching range "+modLoaderVersion + " found "+mlw.getVersion(), null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, mlw.getVersion())));
|
||||||
}
|
}
|
||||||
|
|
||||||
File renamed without changes.
+14
-5
@@ -36,11 +36,10 @@ public class LibraryFinder {
|
|||||||
private static Path libsPath;
|
private static Path libsPath;
|
||||||
static Path findLibsPath() {
|
static Path findLibsPath() {
|
||||||
if (libsPath == null) {
|
if (libsPath == null) {
|
||||||
final Path asm = findJarPathFor("org/objectweb/asm/Opcodes.class", "asm");
|
libsPath = Path.of(System.getProperty("libraryDirectory","crazysnowmannonsense/cheezwhizz"));
|
||||||
// go up SIX parents to find the libs dir
|
if (!Files.isDirectory(libsPath)) {
|
||||||
final Path libs = asm.getParent().getParent().getParent().getParent().getParent().getParent();
|
throw new IllegalStateException("Missing libraryDirectory system property, cannot continue");
|
||||||
LOGGER.debug(CORE, "Found probable library path {}", libs);
|
}
|
||||||
libsPath = libs;
|
|
||||||
}
|
}
|
||||||
return libsPath;
|
return libsPath;
|
||||||
}
|
}
|
||||||
@@ -87,4 +86,14 @@ public class LibraryFinder {
|
|||||||
LOGGER.debug(CORE,"Forge patches at {} is {}", patchedBinariesPath.toString(), pathStatus(patchedBinariesPath));
|
LOGGER.debug(CORE,"Forge patches at {} is {}", patchedBinariesPath.toString(), pathStatus(patchedBinariesPath));
|
||||||
return new Path[] { patchedBinariesPath, mcExtrasPath, srgMcPath };
|
return new Path[] { patchedBinariesPath, mcExtrasPath, srgMcPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Path findPathForMaven(final String group, final String artifact, final String extension, final String classifier, final String version) {
|
||||||
|
return findLibsPath().resolve(MavenCoordinateResolver.get(group, artifact, extension, classifier, version));
|
||||||
|
}
|
||||||
|
public static Path findPathForMaven(final String maven) {
|
||||||
|
return findLibsPath().resolve(MavenCoordinateResolver.get(maven));
|
||||||
|
}
|
||||||
|
public static Path getFMLCorePath() {
|
||||||
|
return findLibsPath().resolve(MavenCoordinateResolver.get("net.minecraftforge:fmlcore:1.0"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
-3
@@ -41,8 +41,6 @@ public class LoadingModList
|
|||||||
private final List<ModFileInfo> modFiles;
|
private final List<ModFileInfo> modFiles;
|
||||||
private final List<ModInfo> sortedList;
|
private final List<ModInfo> sortedList;
|
||||||
private final Map<String, ModFileInfo> fileById;
|
private final Map<String, ModFileInfo> fileById;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private BackgroundScanHandler scanner;
|
|
||||||
private final List<EarlyLoadingException> preLoadErrors;
|
private final List<EarlyLoadingException> preLoadErrors;
|
||||||
private List<ModFile> brokenFiles;
|
private List<ModFile> brokenFiles;
|
||||||
|
|
||||||
@@ -94,7 +92,6 @@ public class LoadingModList
|
|||||||
|
|
||||||
public void addForScanning(BackgroundScanHandler backgroundScanHandler)
|
public void addForScanning(BackgroundScanHandler backgroundScanHandler)
|
||||||
{
|
{
|
||||||
this.scanner = backgroundScanHandler;
|
|
||||||
backgroundScanHandler.setLoadingModList(this);
|
backgroundScanHandler.setLoadingModList(this);
|
||||||
modFiles.stream()
|
modFiles.stream()
|
||||||
.map(ModFileInfo::getFile)
|
.map(ModFileInfo::getFile)
|
||||||
-1
@@ -27,5 +27,4 @@ public class LogMarkers {
|
|||||||
public static final Marker LOADING = MarkerManager.getMarker("LOADING");
|
public static final Marker LOADING = MarkerManager.getMarker("LOADING");
|
||||||
public static final Marker SCAN = MarkerManager.getMarker("SCAN");
|
public static final Marker SCAN = MarkerManager.getMarker("SCAN");
|
||||||
public static final Marker SPLASH = MarkerManager.getMarker("SPLASH");
|
public static final Marker SPLASH = MarkerManager.getMarker("SPLASH");
|
||||||
public static final Marker FORGEMOD = MarkerManager.getMarker("FORGEMOD").addParents(LOADING);
|
|
||||||
}
|
}
|
||||||
+6
-30
@@ -1,23 +1,4 @@
|
|||||||
/*
|
package net.minecraftforge.fml.loading;
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2021.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.userdev;
|
|
||||||
|
|
||||||
import cpw.mods.modlauncher.api.INameMappingService;
|
import cpw.mods.modlauncher.api.INameMappingService;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
@@ -47,7 +28,7 @@ public class MCPNamingService implements INameMappingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String mappingVersion() {
|
public String mappingVersion() {
|
||||||
return "1234";
|
return "1234"; //TODO: Minecraft Version?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -92,19 +73,14 @@ public class MCPNamingService implements INameMappingService {
|
|||||||
return fields.getOrDefault(origin, origin);
|
return fields.getOrDefault(origin, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void loadMappings(final String mappingFileName, BiConsumer<String, String> mapStore) {
|
||||||
private static void loadMappings(final String mappingFileName, BiConsumer<String, String> mapStore)
|
URL path = ClassLoader.getSystemResource(mappingFileName); //We EXPLICITLY go through the SystemClassLoader here because this is dev-time only. And will be on the root classpath.
|
||||||
{
|
|
||||||
URL path = ClassLoader.getSystemResource(mappingFileName); //We EXPLICITLY go throught the SystemClassLoader here because this is dev-time only. And will be on the root classpath.
|
|
||||||
if (path == null)
|
if (path == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(path.openStream())))
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(path.openStream()))) {
|
||||||
{
|
|
||||||
reader.lines().skip(1).map(e -> e.split(",")).forEach(e -> mapStore.accept(e[0], e[1]));
|
reader.lines().skip(1).map(e -> e.split(",")).forEach(e -> mapStore.accept(e[0], e[1]));
|
||||||
}
|
} catch (IOException e1) {
|
||||||
catch (IOException e1)
|
|
||||||
{
|
|
||||||
LOGGER.error(CORE, "Error reading mappings", e1);
|
LOGGER.error(CORE, "Error reading mappings", e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File renamed without changes.
+10
-19
@@ -20,6 +20,7 @@
|
|||||||
package net.minecraftforge.fml.loading;
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||||
|
import cpw.mods.modlauncher.api.NamedPath;
|
||||||
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
|
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
@@ -29,40 +30,30 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService {
|
public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService {
|
||||||
@Override
|
@Override
|
||||||
public List<Path> candidates(final Path gameDirectory) {
|
public List<NamedPath> candidates(final Path gameDirectory) {
|
||||||
ModDirTransformerDiscoverer.scan(gameDirectory);
|
ModDirTransformerDiscoverer.scan(gameDirectory);
|
||||||
return ModDirTransformerDiscoverer.transformers;
|
return List.copyOf(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Path> transformers = new ArrayList<>();
|
private final static List<NamedPath> found = new ArrayList<>();
|
||||||
private static List<Path> locators = new ArrayList<>();
|
|
||||||
|
|
||||||
public static List<Path> allExcluded() {
|
public static List<Path> allExcluded() {
|
||||||
ArrayList<Path> paths = new ArrayList<>();
|
return found.stream().map(np->np.paths()[0]).toList();
|
||||||
paths.addAll(transformers);
|
|
||||||
paths.addAll(locators);
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Path> getExtraLocators() {
|
|
||||||
return locators;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scan(final Path gameDirectory) {
|
private static void scan(final Path gameDirectory) {
|
||||||
final Path modsDir = gameDirectory.resolve(FMLPaths.MODSDIR.relative()).toAbsolutePath().normalize();
|
final Path modsDir = gameDirectory.resolve(FMLPaths.MODSDIR.relative()).toAbsolutePath().normalize();
|
||||||
transformers = new ArrayList<>();
|
|
||||||
locators = new ArrayList<>();
|
|
||||||
if (!Files.exists(modsDir)) {
|
if (!Files.exists(modsDir)) {
|
||||||
// Skip if the mods dir doesn't exist yet.
|
// Skip if the mods dir doesn't exist yet.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try (var walk = Files.walk(modsDir, 1)){
|
||||||
Files.createDirectories(modsDir);
|
walk.forEach(ModDirTransformerDiscoverer::visitFile);
|
||||||
Files.walk(modsDir, 1).forEach(ModDirTransformerDiscoverer::visitFile);
|
|
||||||
} catch (IOException | IllegalStateException ioe) {
|
} catch (IOException | IllegalStateException ioe) {
|
||||||
LogManager.getLogger().error("Error during early discovery", ioe);
|
LogManager.getLogger().error("Error during early discovery", ioe);
|
||||||
}
|
}
|
||||||
@@ -74,9 +65,9 @@ public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService
|
|||||||
if (LamdbaExceptionUtils.uncheck(() -> Files.size(path)) == 0) return;
|
if (LamdbaExceptionUtils.uncheck(() -> Files.size(path)) == 0) return;
|
||||||
try (ZipFile zf = new ZipFile(new File(path.toUri()))) {
|
try (ZipFile zf = new ZipFile(new File(path.toUri()))) {
|
||||||
if (zf.getEntry("META-INF/services/cpw.mods.modlauncher.api.ITransformationService") != null) {
|
if (zf.getEntry("META-INF/services/cpw.mods.modlauncher.api.ITransformationService") != null) {
|
||||||
transformers.add(path);
|
found.add(new NamedPath(zf.getName(), path));
|
||||||
} else if (zf.getEntry("META-INF/services/net.minecraftforge.forgespi.locating.IModLocator") != null) {
|
} else if (zf.getEntry("META-INF/services/net.minecraftforge.forgespi.locating.IModLocator") != null) {
|
||||||
locators.add(path);
|
found.add(new NamedPath(zf.getName(), path));
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
LogManager.getLogger().error("Zip Error when loading jar file {}", path, ioe);
|
LogManager.getLogger().error("Zip Error when loading jar file {}", path, ioe);
|
||||||
+7
-7
@@ -70,13 +70,13 @@ public class ModJarURLHandler extends URLStreamHandler
|
|||||||
@Override
|
@Override
|
||||||
public void connect()
|
public void connect()
|
||||||
{
|
{
|
||||||
if (resource == null) {
|
// if (resource == null) {
|
||||||
modid = url.getHost();
|
// modid = url.getHost();
|
||||||
// trim first char
|
// // trim first char
|
||||||
modpath = url.getPath().substring(1);
|
// modpath = url.getPath().substring(1);
|
||||||
resource = FMLLoader.getLoadingModList().getModFileById(modid).getFile().findResource(modpath);
|
// resource = FMLLoader.getLoadingModList().getModFileById(modid).getFile().findResource(modpath);
|
||||||
manifest = FMLLoader.getLoadingModList().getModFileById(modid).getManifest();
|
// manifest = FMLLoader.getLoadingModList().getModFileById(modid).getManifest();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
+60
-95
@@ -42,6 +42,7 @@ import java.util.function.Function;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.*;
|
||||||
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||||
|
|
||||||
public class ModSorter
|
public class ModSorter
|
||||||
@@ -57,22 +58,20 @@ public class ModSorter
|
|||||||
this.modFiles = modFiles;
|
this.modFiles = modFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoadingModList sort(List<ModFile> mods)
|
public static LoadingModList sort(List<ModFile> mods, final List<ExceptionData> errors)
|
||||||
{
|
{
|
||||||
final ModSorter ms = new ModSorter(mods);
|
final ModSorter ms = new ModSorter(mods);
|
||||||
try {
|
try {
|
||||||
ms.buildUniqueList();
|
ms.buildUniqueList();
|
||||||
} catch (EarlyLoadingException e) {
|
} catch (EarlyLoadingException e) {
|
||||||
// We cannot build any list with duped mods. We have to abort immediately and report it
|
// We cannot build any list with duped mods. We have to abort immediately and report it
|
||||||
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(Collectors.toList()), e);
|
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), e);
|
||||||
}
|
}
|
||||||
// try and locate languages and validate dependencies
|
// try and validate dependencies
|
||||||
List<EarlyLoadingException.ExceptionData> missingLangs = ms.findLanguages();
|
final List<ExceptionData> failedList = Stream.concat(ms.verifyDependencyVersions().stream(), errors.stream()).toList();
|
||||||
List<EarlyLoadingException.ExceptionData> missingDeps = ms.verifyDependencyVersions();
|
|
||||||
final List<ExceptionData> failedList = Stream.concat(missingLangs.stream(), missingDeps.stream()).collect(Collectors.toList());
|
|
||||||
// if we miss one or the other, we abort now
|
// if we miss one or the other, we abort now
|
||||||
if (!failedList.isEmpty()) {
|
if (!failedList.isEmpty()) {
|
||||||
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(Collectors.toList()), new EarlyLoadingException("failure to validate mod list", null, failedList));
|
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), new EarlyLoadingException("failure to validate mod list", null, failedList));
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, lets try and sort the modlist and proceed
|
// Otherwise, lets try and sort the modlist and proceed
|
||||||
EarlyLoadingException earlyLoadingException = null;
|
EarlyLoadingException earlyLoadingException = null;
|
||||||
@@ -85,35 +84,21 @@ public class ModSorter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<EarlyLoadingException.ExceptionData> findLanguages() {
|
|
||||||
List<EarlyLoadingException.ExceptionData> errorData = new ArrayList<>();
|
|
||||||
modFiles.forEach(modFile -> {
|
|
||||||
try {
|
|
||||||
modFile.identifyLanguage();
|
|
||||||
} catch (EarlyLoadingException e) {
|
|
||||||
errorData.addAll(e.getAllData());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return errorData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
private void sort()
|
private void sort()
|
||||||
{
|
{
|
||||||
// lambdas are identity based, so sorting them is impossible unless you hold reference to them
|
// lambdas are identity based, so sorting them is impossible unless you hold reference to them
|
||||||
final MutableGraph<ModFileInfo> graph = GraphBuilder.directed().build();
|
final MutableGraph<ModFileInfo> graph = GraphBuilder.directed().build();
|
||||||
AtomicInteger counter = new AtomicInteger();
|
AtomicInteger counter = new AtomicInteger();
|
||||||
Map<IModFileInfo, Integer> infos = modFiles
|
Map<IModFileInfo, Integer> infos = modFiles.stream()
|
||||||
.stream()
|
|
||||||
.map(ModFile::getModFileInfo)
|
.map(ModFile::getModFileInfo)
|
||||||
.collect(Collectors.toMap(Function.identity(), e -> counter.incrementAndGet()));
|
.collect(toMap(Function.identity(), e -> counter.incrementAndGet()));
|
||||||
infos.keySet().forEach(i -> graph.addNode((ModFileInfo) i));
|
infos.keySet().forEach(i -> graph.addNode((ModFileInfo) i));
|
||||||
modFiles
|
modFiles.stream()
|
||||||
.stream()
|
|
||||||
.map(ModFile::getModInfos)
|
.map(ModFile::getModInfos)
|
||||||
.flatMap(Collection::stream)
|
.<IModInfo>mapMulti(Iterable::forEach)
|
||||||
.map(IModInfo::getDependencies)
|
.map(IModInfo::getDependencies)
|
||||||
.flatMap(Collection::stream)
|
.<IModInfo.ModVersion>mapMulti(Iterable::forEach)
|
||||||
.forEach(dep -> addDependency(graph, dep));
|
.forEach(dep -> addDependency(graph, dep));
|
||||||
|
|
||||||
final List<ModFileInfo> sorted;
|
final List<ModFileInfo> sorted;
|
||||||
@@ -124,33 +109,27 @@ public class ModSorter
|
|||||||
catch (CyclePresentException e)
|
catch (CyclePresentException e)
|
||||||
{
|
{
|
||||||
Set<Set<ModFileInfo>> cycles = e.getCycles();
|
Set<Set<ModFileInfo>> cycles = e.getCycles();
|
||||||
LOGGER.error(LOADING, () -> ((StringBuilderFormattable) (buffer -> {
|
LOGGER.error(LOADING, () -> new AdvancedLogMessageAdapter(buffer ->
|
||||||
buffer.append("Mod Sorting failed.\n");
|
buffer.append("Mod Sorting failed.\n")
|
||||||
buffer.append("Detected Cycles: ");
|
.append("Detected Cycles: ")
|
||||||
buffer.append(cycles);
|
.append(cycles)
|
||||||
buffer.append('\n');
|
.append('\n')));
|
||||||
})));
|
var dataList = cycles.stream()
|
||||||
List<ExceptionData> dataList = cycles.stream()
|
.<ModFileInfo>mapMulti(Iterable::forEach)
|
||||||
.map(Set::stream)
|
.<IModInfo>mapMulti((mf,c)->mf.getMods().forEach(c))
|
||||||
.map(stream -> stream
|
.map(IModInfo::getModId)
|
||||||
.flatMap(modFileInfo -> modFileInfo.getMods()
|
|
||||||
.stream()
|
|
||||||
.map(IModInfo::getModId))
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.map(list -> new ExceptionData("fml.modloading.cycle", list))
|
.map(list -> new ExceptionData("fml.modloading.cycle", list))
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
throw new EarlyLoadingException("Sorting error", e, dataList);
|
throw new EarlyLoadingException("Sorting error", e, dataList);
|
||||||
}
|
}
|
||||||
this.sortedList = sorted
|
this.sortedList = sorted.stream()
|
||||||
.stream()
|
|
||||||
.map(ModFileInfo::getMods)
|
.map(ModFileInfo::getMods)
|
||||||
.flatMap(Collection::stream)
|
.<IModInfo>mapMulti(Iterable::forEach)
|
||||||
.map(ModInfo.class::cast)
|
.map(ModInfo.class::cast)
|
||||||
.collect(Collectors.toList());
|
.collect(toList());
|
||||||
this.modFiles = sorted
|
this.modFiles = sorted.stream()
|
||||||
.stream()
|
|
||||||
.map(ModFileInfo::getFile)
|
.map(ModFileInfo::getFile)
|
||||||
.collect(Collectors.toList());
|
.collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
@@ -164,63 +143,55 @@ public class ModSorter
|
|||||||
if (self == target)
|
if (self == target)
|
||||||
return; // in case a jar has two mods that have dependencies between
|
return; // in case a jar has two mods that have dependencies between
|
||||||
switch (dep.getOrdering()) {
|
switch (dep.getOrdering()) {
|
||||||
case BEFORE:
|
case BEFORE -> topoGraph.putEdge(self, target);
|
||||||
topoGraph.putEdge(self, target);
|
case AFTER -> topoGraph.putEdge(target, self);
|
||||||
break;
|
|
||||||
case AFTER:
|
|
||||||
topoGraph.putEdge(target, self);
|
|
||||||
break;
|
|
||||||
case NONE:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildUniqueList()
|
private void buildUniqueList()
|
||||||
{
|
{
|
||||||
// Collect mod files by first modid in the file. This will be used for deduping purposes
|
// Collect mod files by first modid in the file. This will be used for deduping purposes
|
||||||
final Map<String, List<IModFile>> modFilesByFirstId = modFiles
|
final Map<String, List<IModFile>> modFilesByFirstId = modFiles.stream()
|
||||||
.stream()
|
.collect(groupingBy(mf -> mf.getModInfos().get(0).getModId()));
|
||||||
.collect(Collectors.groupingBy(mf -> mf.getModInfos().get(0).getModId()));
|
|
||||||
|
|
||||||
// Capture forge and MC here, so we can keep them for later
|
// Capture forge and MC here, so we can keep them for later
|
||||||
forgeAndMC = new ArrayList<>();
|
forgeAndMC = new ArrayList<>();
|
||||||
forgeAndMC.add((ModFile)modFilesByFirstId.get("minecraft").get(0));
|
var mc = modFilesByFirstId.get("minecraft");
|
||||||
forgeAndMC.add((ModFile)modFilesByFirstId.get("forge").get(0));
|
if (mc != null && !mc.isEmpty())
|
||||||
|
forgeAndMC.add((ModFile) mc.get(0));
|
||||||
|
else
|
||||||
|
throw new IllegalStateException("Failed to find minecraft somehow?");
|
||||||
|
|
||||||
// Select the newest by artifact version sorting of non-unique files thus identified
|
// Select the newest by artifact version sorting of non-unique files thus identified
|
||||||
this.modFiles = modFilesByFirstId.entrySet().stream()
|
this.modFiles = modFilesByFirstId.entrySet().stream()
|
||||||
.map(this::selectNewestModInfo)
|
.map(this::selectNewestModInfo)
|
||||||
.map(Map.Entry::getValue)
|
.map(Map.Entry::getValue)
|
||||||
.map(ModFile.class::cast)
|
.map(ModFile.class::cast)
|
||||||
.collect(Collectors.toList());
|
.collect(toList());
|
||||||
|
|
||||||
// Transform to the full mod id list
|
// Transform to the full mod id list
|
||||||
final Map<String, List<ModInfo>> modIds = modFiles.stream()
|
final Map<String, List<ModInfo>> modIds = modFiles.stream()
|
||||||
.map(ModFile::getModInfos)
|
.map(ModFile::getModInfos)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.map(ModInfo.class::cast)
|
.map(ModInfo.class::cast)
|
||||||
.collect(Collectors.groupingBy(IModInfo::getModId));
|
.collect(groupingBy(IModInfo::getModId));
|
||||||
|
|
||||||
// Its theoretically possible that some mod has somehow moved an id to a secondary place, thus causing a dupe.
|
// Its theoretically possible that some mod has somehow moved an id to a secondary place, thus causing a dupe.
|
||||||
// We can't handle this
|
// We can't handle this
|
||||||
final List<Map.Entry<String, List<ModInfo>>> dupedMods = modIds
|
final List<ModInfo> dupedMods = modIds.values().stream()
|
||||||
.entrySet()
|
.filter(modInfos -> modInfos.size() > 1)
|
||||||
.stream()
|
.map(modInfos -> modInfos.get(0))
|
||||||
.filter(e -> e.getValue().size() > 1)
|
.toList();
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (!dupedMods.isEmpty()) {
|
if (!dupedMods.isEmpty()) {
|
||||||
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods
|
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods.stream()
|
||||||
.stream()
|
.map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod",
|
||||||
.map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod", dm.getValue().get(0), Objects.toString(dm.getValue().get(0))))
|
dm, Objects.toString(dm))).toList();
|
||||||
.collect(Collectors.toList());
|
|
||||||
throw new EarlyLoadingException("Duplicate mods found", null, duplicateModErrors);
|
throw new EarlyLoadingException("Duplicate mods found", null, duplicateModErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
modIdNameLookup = modIds
|
modIdNameLookup = modIds.entrySet().stream()
|
||||||
.entrySet()
|
.collect(toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
||||||
.stream()
|
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map.Entry<String, IModFile> selectNewestModInfo(Map.Entry<String, List<IModFile>> fullList) {
|
private Map.Entry<String, IModFile> selectNewestModInfo(Map.Entry<String, List<IModFile>> fullList) {
|
||||||
@@ -230,46 +201,40 @@ public class ModSorter
|
|||||||
modInfoList.sort(Comparator.<IModFile, ArtifactVersion>comparing(mf -> mf.getModInfos().get(0).getVersion()).reversed());
|
modInfoList.sort(Comparator.<IModFile, ArtifactVersion>comparing(mf -> mf.getModInfos().get(0).getVersion()).reversed());
|
||||||
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.get(0).getFileName(), fullList.getKey(), modInfoList.get(0).getModInfos().get(0).getVersion());
|
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.get(0).getFileName(), fullList.getKey(), modInfoList.get(0).getModInfos().get(0).getVersion());
|
||||||
}
|
}
|
||||||
return new AbstractMap.SimpleImmutableEntry<>(fullList.getKey(), modInfoList.get(0));
|
return Map.entry(fullList.getKey(), modInfoList.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<EarlyLoadingException.ExceptionData> verifyDependencyVersions()
|
private List<EarlyLoadingException.ExceptionData> verifyDependencyVersions()
|
||||||
{
|
{
|
||||||
final Map<String, ArtifactVersion> modVersions = modFiles
|
final var modVersions = modFiles.stream()
|
||||||
.stream()
|
|
||||||
.map(ModFile::getModInfos)
|
.map(ModFile::getModInfos)
|
||||||
.flatMap(Collection::stream)
|
.<IModInfo>mapMulti(Iterable::forEach)
|
||||||
.collect(Collectors.toMap(IModInfo::getModId, IModInfo::getVersion));
|
.collect(toMap(IModInfo::getModId, IModInfo::getVersion));
|
||||||
|
|
||||||
final Map<IModInfo, List<IModInfo.ModVersion>> modVersionDependencies = modFiles
|
final var modVersionDependencies = modFiles.stream()
|
||||||
.stream()
|
|
||||||
.map(ModFile::getModInfos)
|
.map(ModFile::getModInfos)
|
||||||
.flatMap(Collection::stream)
|
.<IModInfo>mapMulti(Iterable::forEach)
|
||||||
.collect(Collectors.groupingBy(Function.identity(), Java9BackportUtils.flatMapping(e -> e.getDependencies().stream(), Collectors.toList())));
|
.collect(groupingBy(Function.identity(), flatMapping(e -> e.getDependencies().stream(), toList())));
|
||||||
|
|
||||||
final Set<IModInfo.ModVersion> modRequirements = modVersionDependencies
|
final var modRequirements = modVersionDependencies.values().stream()
|
||||||
.values()
|
.<IModInfo.ModVersion>mapMulti(Iterable::forEach)
|
||||||
.stream()
|
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.filter(mv -> mv.getSide().isCorrectSide())
|
.filter(mv -> mv.getSide().isCorrectSide())
|
||||||
.collect(Collectors.toSet());
|
.collect(toSet());
|
||||||
|
|
||||||
final long mandatoryRequired = modRequirements.stream().filter(IModInfo.ModVersion::isMandatory).count();
|
final long mandatoryRequired = modRequirements.stream().filter(IModInfo.ModVersion::isMandatory).count();
|
||||||
LOGGER.debug(LOADING, "Found {} mod requirements ({} mandatory, {} optional)", modRequirements.size(), mandatoryRequired, modRequirements.size() - mandatoryRequired);
|
LOGGER.debug(LOADING, "Found {} mod requirements ({} mandatory, {} optional)", modRequirements.size(), mandatoryRequired, modRequirements.size() - mandatoryRequired);
|
||||||
final Set<IModInfo.ModVersion> missingVersions = modRequirements
|
final var missingVersions = modRequirements.stream()
|
||||||
.stream()
|
|
||||||
.filter(mv -> (mv.isMandatory() || modVersions.containsKey(mv.getModId())) && this.modVersionNotContained(mv, modVersions))
|
.filter(mv -> (mv.isMandatory() || modVersions.containsKey(mv.getModId())) && this.modVersionNotContained(mv, modVersions))
|
||||||
.collect(Collectors.toSet());
|
.collect(toSet());
|
||||||
final long mandatoryMissing = missingVersions.stream().filter(IModInfo.ModVersion::isMandatory).count();
|
final long mandatoryMissing = missingVersions.stream().filter(IModInfo.ModVersion::isMandatory).count();
|
||||||
LOGGER.debug(LOADING, "Found {} mod requirements missing ({} mandatory, {} optional)", missingVersions.size(), mandatoryMissing, missingVersions.size() - mandatoryMissing);
|
LOGGER.debug(LOADING, "Found {} mod requirements missing ({} mandatory, {} optional)", missingVersions.size(), mandatoryMissing, missingVersions.size() - mandatoryMissing);
|
||||||
|
|
||||||
if (!missingVersions.isEmpty()) {
|
if (!missingVersions.isEmpty()) {
|
||||||
return missingVersions
|
return missingVersions.stream()
|
||||||
.stream()
|
|
||||||
.map(mv -> new ExceptionData(mv.isMandatory() ? "fml.modloading.missingdependency" : "fml.modloading.missingdependency.optional",
|
.map(mv -> new ExceptionData(mv.isMandatory() ? "fml.modloading.missingdependency" : "fml.modloading.missingdependency.optional",
|
||||||
mv.getOwner(), mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
|
mv.getOwner(), mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
|
||||||
modVersions.getOrDefault(mv.getModId(), new DefaultArtifactVersion("null"))))
|
modVersions.getOrDefault(mv.getModId(), new DefaultArtifactVersion("null"))))
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
File renamed without changes.
+2
-2
@@ -30,8 +30,8 @@ import java.util.Map;
|
|||||||
public class StringSubstitutor
|
public class StringSubstitutor
|
||||||
{
|
{
|
||||||
private static final Map<String,String> globals = ImmutableMap.of(
|
private static final Map<String,String> globals = ImmutableMap.of(
|
||||||
"mcVersion", FMLLoader.mcVersion,
|
"mcVersion", FMLLoader.versionInfo().mcVersion(),
|
||||||
"forgeVersion", FMLLoader.forgeVersion
|
"forgeVersion", FMLLoader.versionInfo().forgeVersion()
|
||||||
);
|
);
|
||||||
|
|
||||||
public static String replace(final String in, final ModFile file) {
|
public static String replace(final String in, final ModFile file) {
|
||||||
+1
-2
@@ -26,8 +26,7 @@ import java.net.URL;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class StringUtils
|
public class StringUtils {
|
||||||
{
|
|
||||||
public static String toLowerCase(final String str) {
|
public static String toLowerCase(final String str) {
|
||||||
return str.toLowerCase(Locale.ROOT);
|
return str.toLowerCase(Locale.ROOT);
|
||||||
}
|
}
|
||||||
File renamed without changes.
@@ -0,0 +1,17 @@
|
|||||||
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public record VersionInfo(String forgeVersion, String mcVersion, String mcpVersion, String forgeGroup) {
|
||||||
|
VersionInfo(Map<String, ?> arguments) {
|
||||||
|
this((String) arguments.get("forgeVersion"), (String) arguments.get("mcVersion"), (String) arguments.get("mcpVersion"), (String) arguments.get("forgeGroup"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String mcAndForgeVersion() {
|
||||||
|
return mcVersion+"-"+forgeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String mcAndMCPVersion() {
|
||||||
|
return mcVersion + "-" + mcpVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-11
@@ -32,17 +32,17 @@ import java.util.function.BiPredicate;
|
|||||||
public class VersionSupportMatrix {
|
public class VersionSupportMatrix {
|
||||||
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
|
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.mcVersion);
|
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
|
||||||
if (MavenVersionAdapter.createFromVersionSpec("[1.16.4,1.16.5]").containsVersion(version)) {
|
// if (MavenVersionAdapter.createFromVersionSpec("[1.16.4,1.16.5]").containsVersion(version)) {
|
||||||
// 1.16.4 is Compatible with 1.16.3
|
// // 1.16.4 is Compatible with 1.16.3
|
||||||
add("languageloader.javafml", "34");
|
// add("languageloader.javafml", "34");
|
||||||
add("mod.minecraft", "1.16.3");
|
// add("mod.minecraft", "1.16.3");
|
||||||
add("mod.forge", "34.1.42");
|
// add("mod.forge", "34.1.42");
|
||||||
// 1.16.5 is Compatible with 1.16.4, and thus 1.16.3
|
// // 1.16.5 is Compatible with 1.16.4, and thus 1.16.3
|
||||||
add("languageloader.javafml", "35");
|
// add("languageloader.javafml", "35");
|
||||||
add("mod.minecraft", "1.16.4");
|
// add("mod.minecraft", "1.16.4");
|
||||||
add("mod.forge", "35.1.37");
|
// add("mod.forge", "35.1.37");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
private static void add(String key, String value) {
|
private static void add(String key, String value) {
|
||||||
overrideVersions.computeIfAbsent(key, k -> new ArrayList<>()).add(new DefaultArtifactVersion(value));
|
overrideVersions.computeIfAbsent(key, k -> new ArrayList<>()).add(new DefaultArtifactVersion(value));
|
||||||
+1
-1
@@ -29,8 +29,8 @@ import org.apache.logging.log4j.core.pattern.HighlightConverter;
|
|||||||
import org.apache.logging.log4j.core.pattern.PatternConverter;
|
import org.apache.logging.log4j.core.pattern.PatternConverter;
|
||||||
import org.apache.logging.log4j.status.StatusLogger;
|
import org.apache.logging.log4j.status.StatusLogger;
|
||||||
import org.apache.logging.log4j.util.PerformanceSensitive;
|
import org.apache.logging.log4j.util.PerformanceSensitive;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016-2021.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.minecraftforge.fml.loading.moddiscovery;
|
||||||
|
|
||||||
|
import cpw.mods.jarhandling.SecureJar;
|
||||||
|
import net.minecraftforge.forgespi.locating.IModFile;
|
||||||
|
import net.minecraftforge.forgespi.locating.IModLocator;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
|
||||||
|
|
||||||
|
public abstract class AbstractJarFileLocator implements IModLocator {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scanFile(final IModFile file, final Consumer<Path> pathConsumer) {
|
||||||
|
LOGGER.debug(SCAN,"Scan started: {}", file);
|
||||||
|
final Function<Path, SecureJar.Status> status = p->file.getSecureJar().verifyPath(p);
|
||||||
|
try (Stream<Path> files = Files.find(file.getSecureJar().getRootPath(), Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) {
|
||||||
|
file.setSecurityStatus(files.peek(pathConsumer).map(status).reduce((s1, s2)-> SecureJar.Status.values()[Math.min(s1.ordinal(), s2.ordinal())]).orElse(SecureJar.Status.INVALID));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
LOGGER.debug(SCAN,"Scan finished: {}", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IModFile> scanMods() {
|
||||||
|
return scanCandidates()
|
||||||
|
.map(mc -> ModFile.newFMLInstance(this, mc))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Stream<Path> scanCandidates();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final IModFile modFile) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-11
@@ -21,17 +21,12 @@ package net.minecraftforge.fml.loading.moddiscovery;
|
|||||||
|
|
||||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||||
import net.minecraftforge.fml.loading.LoadingModList;
|
import net.minecraftforge.fml.loading.LoadingModList;
|
||||||
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 java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
|
import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
|
||||||
|
|
||||||
@@ -42,10 +37,11 @@ public class BackgroundScanHandler
|
|||||||
private final List<ModFile> pendingFiles;
|
private final List<ModFile> pendingFiles;
|
||||||
private final List<ModFile> scannedFiles;
|
private final List<ModFile> scannedFiles;
|
||||||
private final List<ModFile> allFiles;
|
private final List<ModFile> allFiles;
|
||||||
private final Map<IModFile.Type, List<ModFile>> modFiles;
|
private final List<ModFile> modFiles;
|
||||||
private LoadingModList loadingModList;
|
private LoadingModList loadingModList;
|
||||||
|
|
||||||
public BackgroundScanHandler(final Map<IModFile.Type, List<ModFile>> modFiles) {
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
public BackgroundScanHandler(final List<ModFile> modFiles) {
|
||||||
this.modFiles = modFiles;
|
this.modFiles = modFiles;
|
||||||
modContentScanner = Executors.newSingleThreadExecutor(r -> {
|
modContentScanner = Executors.newSingleThreadExecutor(r -> {
|
||||||
final Thread thread = Executors.defaultThreadFactory().newThread(r);
|
final Thread thread = Executors.defaultThreadFactory().newThread(r);
|
||||||
@@ -57,7 +53,7 @@ public class BackgroundScanHandler
|
|||||||
allFiles = new ArrayList<>();
|
allFiles = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<IModFile.Type, List<ModFile>> getModFiles() {
|
public List<ModFile> getModFiles() {
|
||||||
return modFiles;
|
return modFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,14 +88,18 @@ public class BackgroundScanHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void waitForScanToComplete(final Runnable ticker) {
|
public void waitForScanToComplete(final Runnable ticker) {
|
||||||
|
boolean interrupted = false;
|
||||||
|
boolean succeeded = false;
|
||||||
modContentScanner.shutdown();
|
modContentScanner.shutdown();
|
||||||
do {
|
do {
|
||||||
ticker.run();
|
ticker.run();
|
||||||
try {
|
try {
|
||||||
modContentScanner.awaitTermination(50, TimeUnit.MILLISECONDS);
|
succeeded = modContentScanner.awaitTermination(50, TimeUnit.MILLISECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.interrupted();
|
interrupted = true;
|
||||||
}
|
}
|
||||||
} while (!modContentScanner.isShutdown());
|
} while (!modContentScanner.isShutdown());
|
||||||
|
if (interrupted) Thread.currentThread().interrupt();
|
||||||
|
if (!succeeded) throw new IllegalStateException("Failed to complete mod scan");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File renamed without changes.
+90
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016-2021.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.minecraftforge.fml.loading.moddiscovery;
|
||||||
|
|
||||||
|
import net.minecraftforge.forgespi.locating.IModFile;
|
||||||
|
import net.minecraftforge.forgespi.locating.IModLocator;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||||
|
import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
|
||||||
|
|
||||||
|
public class ExplodedDirectoryLocator implements IModLocator {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
|
public record ExplodedMod(String modid, List<Path> paths) {}
|
||||||
|
|
||||||
|
private final List<ExplodedMod> explodedMods = new ArrayList<>();
|
||||||
|
private final Map<ExplodedMod, IModFile> mods = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IModFile> scanMods() {
|
||||||
|
explodedMods.forEach(explodedMod -> ModJarMetadata.buildFile(this, jar ->jar.findFile("/META-INF/mods.toml").isPresent(), explodedMod.paths().toArray(Path[]::new))
|
||||||
|
.ifPresentOrElse(f->mods.put(explodedMod, f), () -> LOGGER.warn(LOADING, "Failed to find exploded resource mods.toml in directory {}", explodedMod.paths().get(0).toString())));
|
||||||
|
return List.copyOf(mods.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "exploded directory";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scanFile(final IModFile file, final Consumer<Path> pathConsumer) {
|
||||||
|
LOGGER.debug(SCAN,"Scanning exploded directory {}", file.getFilePath().toString());
|
||||||
|
try (Stream<Path> files = Files.find(file.getSecureJar().getRootPath(), Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) {
|
||||||
|
files.forEach(pathConsumer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
LOGGER.debug(SCAN,"Exploded directory scan complete {}", file.getFilePath().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "{ExplodedDir locator}";
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void initArguments(final Map<String, ?> arguments) {
|
||||||
|
final var explodedTargets = ((Map<String, List<ExplodedMod>>) arguments).get("explodedTargets");
|
||||||
|
if (explodedTargets != null && !explodedTargets.isEmpty()) {
|
||||||
|
explodedMods.addAll(explodedTargets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final IModFile modFile) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
+2
-6
@@ -21,7 +21,6 @@ package net.minecraftforge.fml.loading.moddiscovery;
|
|||||||
|
|
||||||
import net.minecraftforge.fml.loading.FMLPaths;
|
import net.minecraftforge.fml.loading.FMLPaths;
|
||||||
import net.minecraftforge.fml.loading.MavenCoordinateResolver;
|
import net.minecraftforge.fml.loading.MavenCoordinateResolver;
|
||||||
import net.minecraftforge.forgespi.locating.IModFile;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -34,11 +33,8 @@ public class MavenDirectoryLocator extends AbstractJarFileLocator {
|
|||||||
private List<Path> modCoords;
|
private List<Path> modCoords;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IModFile> scanMods() {
|
public Stream<Path> scanCandidates() {
|
||||||
return modCoords.stream()
|
return modCoords.stream();
|
||||||
.map(mc -> ModFile.newFMLInstance(mc, this))
|
|
||||||
.peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf)))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
package net.minecraftforge.fml.loading.moddiscovery;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.Config;
|
||||||
|
import com.electronwill.nightconfig.core.file.FileConfig;
|
||||||
|
import cpw.mods.jarhandling.SecureJar;
|
||||||
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
|
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||||
|
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
|
||||||
|
import net.minecraftforge.forgespi.locating.IModFile;
|
||||||
|
import net.minecraftforge.forgespi.locating.IModLocator;
|
||||||
|
import net.minecraftforge.forgespi.locating.ModFileFactory;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||||
|
import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
|
||||||
|
|
||||||
|
public class MinecraftLocator implements IModLocator {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IModFile> scanMods() {
|
||||||
|
final var launchHandler = FMLLoader.getLaunchHandler();
|
||||||
|
var baseMC = launchHandler.getMinecraftPaths();
|
||||||
|
var mcjar = ModJarMetadata.buildFile(j->ModFileFactory.FACTORY.build(j, this, this::buildMinecraftTOML), j->true, baseMC.minecraftFilter(), baseMC.minecraftPaths().toArray(Path[]::new)).orElseThrow();
|
||||||
|
var artifacts = baseMC.otherArtifacts().stream().map(SecureJar::from).map(sj->ModFile.newFMLInstance(this, sj)).collect(Collectors.<IModFile>toList());
|
||||||
|
var othermods = baseMC.otherModPaths().stream().map(p->ModJarMetadata.buildFile(this, p.toArray(Path[]::new))).toList();
|
||||||
|
artifacts.add(mcjar);
|
||||||
|
artifacts.addAll(othermods);
|
||||||
|
return artifacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IModFileInfo buildMinecraftTOML(final IModFile iModFile) {
|
||||||
|
final ModFile modFile = (ModFile) iModFile;
|
||||||
|
/*
|
||||||
|
final Path mcmodtoml = modFile.findResource("META-INF", "minecraftmod.toml");
|
||||||
|
if (Files.notExists(mcmodtoml)) {
|
||||||
|
LOGGER.fatal(LOADING, "Mod file {} is missing minecraftmod.toml file", modFile.getFilePath());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FileConfig mcmodstomlfile = FileConfig.builder(mcmodtoml).build();
|
||||||
|
mcmodstomlfile.load();
|
||||||
|
mcmodstomlfile.close();
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// We haven't changed this in years, and I can't be asked right now to special case this one file in the path.
|
||||||
|
final var conf = Config.inMemory();
|
||||||
|
conf.set("modLoader", "minecraft");
|
||||||
|
conf.set("loaderVersion", "1");
|
||||||
|
conf.set("license", "Mojang Studios, All Rights Reserved");
|
||||||
|
final var mods = Config.inMemory();
|
||||||
|
mods.set("modId", "minecraft");
|
||||||
|
mods.set("version", FMLLoader.versionInfo().mcVersion());
|
||||||
|
mods.set("displayName", "Minecraft");
|
||||||
|
mods.set("logoFile", "mcplogo.png");
|
||||||
|
mods.set("credits", "Mojang, deobfuscated by MCP");
|
||||||
|
mods.set("authors", "MCP: Searge,ProfMobius,IngisKahn,Fesh0r,ZeuX,R4wk,LexManos,Bspkrs");
|
||||||
|
mods.set("description", "Minecraft, decompiled and deobfuscated with MCP technology");
|
||||||
|
conf.set("mods", List.of(mods));
|
||||||
|
/*
|
||||||
|
conf.putAll(mcmodstomlfile);
|
||||||
|
|
||||||
|
final var extralangs = Stream.<IModFileInfo.LanguageSpec>builder();
|
||||||
|
final Path forgemodtoml = modFile.findResource("META-INF", "mods.toml");
|
||||||
|
if (Files.notExists(forgemodtoml)) {
|
||||||
|
LOGGER.info("No forge mods.toml file found, not loading forge mod");
|
||||||
|
} else {
|
||||||
|
final FileConfig forgemodstomlfile = FileConfig.builder(forgemodtoml).build();
|
||||||
|
forgemodstomlfile.load();
|
||||||
|
forgemodstomlfile.close();
|
||||||
|
conf.putAll(forgemodstomlfile);
|
||||||
|
conf.<List<Object>>get("mods").add(0, mcmodstomlfile.<List<Object>>get("mods").get(0)); // Add MC as a sub-mod
|
||||||
|
extralangs.add(new IModFileInfo.LanguageSpec(mcmodstomlfile.get("modLoader"), MavenVersionAdapter.createFromVersionSpec(mcmodstomlfile.get("loaderVersion"))));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
final NightConfigWrapper configWrapper = new NightConfigWrapper(conf);
|
||||||
|
//final ModFileInfo modFileInfo = new ModFileInfo(modFile, configWrapper, extralangs.build().toList());
|
||||||
|
final ModFileInfo modFileInfo = new ModFileInfo(modFile, configWrapper, List.of());
|
||||||
|
configWrapper.setFile(modFileInfo);
|
||||||
|
return modFileInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "minecraft";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scanFile(final IModFile modFile, final Consumer<Path> pathConsumer) {
|
||||||
|
LOGGER.debug(SCAN, "Scan started: {}", modFile);
|
||||||
|
try (Stream<Path> files = Files.find(modFile.getSecureJar().getRootPath(), Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) {
|
||||||
|
files.forEach(pathConsumer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
LOGGER.debug(SCAN, "Scan finished: {}", modFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initArguments(final Map<String, ?> arguments) {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final IModFile modFile) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loaded 100 of 1990 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user