mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
397ceac0b6 | ||
|
|
1b7665cdaa | ||
|
|
70f96ef64e | ||
|
|
0cf4446352 | ||
|
|
b8270cd9ff | ||
|
|
e1fa61080a | ||
|
|
381998c35c | ||
|
|
11ed2500a6 | ||
|
|
a647237db4 | ||
|
|
e0dccae041 | ||
|
|
e7a5c58907 | ||
|
|
e094eee54d | ||
|
|
a6adc58655 | ||
|
|
d31ea640f9 | ||
|
|
8e16765438 | ||
|
|
73b0088cb4 | ||
|
|
203fbbb742 | ||
|
|
46d78c8210 | ||
|
|
cfba4381b6 | ||
|
|
7113701322 | ||
|
|
73e02c6add | ||
|
|
7f2b85d2ff | ||
|
|
099d121c2c | ||
|
|
a6978eed68 | ||
|
|
309116520b | ||
|
|
3e358acbe1 | ||
|
|
c243adf6aa | ||
|
|
5d0047753d | ||
|
|
aa6f268c74 | ||
|
|
d21556a4da | ||
|
|
d4c998e311 | ||
|
|
25727a0e93 | ||
|
|
80286594c5 | ||
|
|
870e3ebcab | ||
|
|
a4c26c9b2b | ||
|
|
45b00b0004 | ||
|
|
4b1c5ddb2c | ||
|
|
0966109602 | ||
|
|
b31006534a | ||
|
|
740a5d5039 | ||
|
|
817e20821d | ||
|
|
fdb22d02cc | ||
|
|
f09fd1f05b | ||
|
|
ed2ba0f52c | ||
|
|
b04118982f | ||
|
|
d44d0b8edc | ||
|
|
6d7fda6a9b | ||
|
|
0303ca651e | ||
|
|
8445f73b2d | ||
|
|
c7446a5180 | ||
|
|
5c15aa3322 | ||
|
|
588466f5e4 | ||
|
|
470f03b2f9 | ||
|
|
d2367d81fc |
No files matched your search
+4
-4
@@ -3,7 +3,7 @@ Minecraft Forge: Credits/Thank You
|
||||
Forge is a set of tools and modifications to the Minecraft base game code to assist
|
||||
mod developers in creating new and exciting content. It has been in development for
|
||||
several years now, but I would like to take this time thank a few people who have
|
||||
helped it along it's way.
|
||||
helped it along its way.
|
||||
|
||||
First, the people who originally created the Forge projects way back in Minecraft
|
||||
alpha. Eloraam of RedPower, and SpaceToad of Buildcraft, without their acceptiance
|
||||
@@ -11,7 +11,7 @@ of me taking over the project, who knows what Minecraft modding would be today.
|
||||
|
||||
Secondly, someone who has worked with me, and developed some of the core features
|
||||
that allow modding to be as functional, and as simple as it is, cpw. For developing
|
||||
FML, which stabelized the client and server modding ecosystem. As well as the base
|
||||
FML, which stabilized the client and server modding ecosystem. As well as the base
|
||||
loading system that allows us to modify Minecraft's code as elegently as possible.
|
||||
|
||||
Mezz, who has stepped up as the issue and pull request manager. Helping to keep me
|
||||
@@ -45,11 +45,11 @@ and minecraft clients.
|
||||
The code is authored by cpw.
|
||||
|
||||
It began by partially implementing an API defined by the client side ModLoader, authored by Risugami.
|
||||
http://www.minecraftforum.net/topic/75440-
|
||||
https://www.minecraftforum.net/topic/75440-
|
||||
This support has been dropped as of Minecraft release 1.7, as Risugami no longer maintains ModLoader.
|
||||
|
||||
It also contains suggestions and hints and generous helpings of code from LexManos, author of MinecraftForge.
|
||||
http://www.minecraftforge.net/
|
||||
https://minecraftforge.net/
|
||||
|
||||
Additionally, it contains an implementation of topological sort based on that
|
||||
published at http://keithschwarz.com/interesting/code/?dir=topological-sort
|
||||
|
||||
+3
-7
@@ -2,7 +2,7 @@ import net.minecraftforge.forge.tasks.*
|
||||
import net.minecraftforge.gradleutils.PomUtils
|
||||
|
||||
plugins {
|
||||
id 'org.cadixdev.licenser' version '0.6.1'
|
||||
id 'net.minecraftforge.licenser' version '1.0.1'
|
||||
id 'com.github.ben-manes.versions' version '0.46.0'
|
||||
id 'net.minecraftforge.gradleutils' version '[2.3.0,2.4.0)'
|
||||
id 'eclipse'
|
||||
@@ -19,10 +19,6 @@ ext {
|
||||
GIT_INFO = gradleutils.gitInfo
|
||||
VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, '[0-9]', MC_VERSION)
|
||||
FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1)
|
||||
|
||||
BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.2.0:fatjar'
|
||||
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.4.0'
|
||||
FART = 'net.minecraftforge:ForgeAutoRenamingTool:1.0.6'
|
||||
}
|
||||
|
||||
changelog {
|
||||
@@ -50,10 +46,10 @@ project(':mcp') {
|
||||
|
||||
if (System.env.TEAMCITY_VERSION) {
|
||||
//Only setup the CI environment if and only if the environment variables are set.
|
||||
tasks.configureTeamCity {
|
||||
tasks.named('configureTeamCity').configure {
|
||||
doLast {
|
||||
println "##teamcity[buildNumber '${project(':forge').version}']"
|
||||
println "##teamcity[setParameter name='env.PUBLISHED_JAVA_ARTIFACT_VERSION' value='${project(':forge').version}']"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.ow2.asm:asm:9.5'
|
||||
implementation 'org.ow2.asm:asm-tree:9.5'
|
||||
implementation 'org.ow2.asm:asm:9.6'
|
||||
implementation 'org.ow2.asm:asm-tree:9.6'
|
||||
implementation 'net.minecraftforge:srgutils:0.5.+'
|
||||
implementation 'commons-io:commons-io:2.12.0'
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
implementation 'org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r'
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ import org.gradle.api.tasks.*
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
abstract class BundleList extends DefaultTask {
|
||||
@InputFiles abstract ConfigurableFileCollection getConfig()
|
||||
@@ -23,21 +26,24 @@ abstract class BundleList extends DefaultTask {
|
||||
void run() {
|
||||
def entries = [:] as TreeMap
|
||||
def resolved = project.configurations.installer.resolvedConfiguration.resolvedArtifacts
|
||||
for (var dep : resolved) {
|
||||
for (def dep : resolved) {
|
||||
def info = Util.getMavenInfoFromDep(dep)
|
||||
//println("$dep.file.sha1\t$info.name\t$info.path")
|
||||
entries.put("$info.art.group:$info.art.name", "$dep.file.sha256\t$info.name\t$info.path")
|
||||
}
|
||||
|
||||
var packed = (AbstractArchiveTask) project.tasks.universalJar
|
||||
var info = Util.getMavenInfoFromTask(packed)
|
||||
def file = packed.archiveFile.get().asFile
|
||||
entries.put("$info.art.group:$info.art.name:$info.art.classifier", "$file.sha256\t$info.name\t$info.path")
|
||||
|
||||
var classifier = 'server'
|
||||
var genned = project.tasks.applyServerBinPatches
|
||||
info = Util.getMavenInfoFromTask(genned, classifier)
|
||||
file = genned.output.get().asFile
|
||||
entries.put("$info.art.group:$info.art.name:$info.art.classifier", "$file.sha256\t$info.name\t$info.path")
|
||||
|
||||
[
|
||||
project.tasks.universalJar
|
||||
].forEach{ packed ->
|
||||
def info = Util.getMavenInfoFromTask(packed)
|
||||
def file = packed.archiveFile.get().asFile
|
||||
entries.put("$info.art.group:$info.art.name:$info.art.classifier", "$file.sha256\t$info.name\t$info.path")
|
||||
}
|
||||
|
||||
try (def zip = new java.util.zip.ZipFile(serverBundle.get().asFile)) {
|
||||
try (def zip = new ZipFile(serverBundle.get().asFile)) {
|
||||
def entry = zip.getEntry('META-INF/libraries.list')
|
||||
def data = zip.getInputStream(entry).text.split('\n')
|
||||
for (def line : data) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import groovy.transform.CompileStatic
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
@@ -10,6 +11,7 @@ import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.FieldNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
@CompileStatic
|
||||
abstract class BytecodeFinder extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getJar()
|
||||
// It should be fine to mark the output as internal as we want to control when we run it anyways.
|
||||
@@ -24,13 +26,13 @@ abstract class BytecodeFinder extends DefaultTask {
|
||||
protected void exec() {
|
||||
Util.init()
|
||||
|
||||
def outputFile = output.get().asFile
|
||||
var outputFile = output.get().asFile
|
||||
if (outputFile.exists())
|
||||
outputFile.delete()
|
||||
|
||||
pre()
|
||||
|
||||
Util.processClassNodes(jar.get().asFile, this::process)
|
||||
Util.processClassNodes(jar.get().asFile, this.&process)
|
||||
|
||||
post()
|
||||
outputFile.text = new JsonBuilder(getData()).toPrettyString()
|
||||
@@ -38,8 +40,8 @@ abstract class BytecodeFinder extends DefaultTask {
|
||||
|
||||
|
||||
protected process(ClassNode node) {
|
||||
if (node.fields != null) node.fields.each { process(node, it) }
|
||||
if (node.methods != null) node.methods.each { process(node, it) }
|
||||
if (node.fields !== null) node.fields.each { process(node, it) }
|
||||
if (node.methods !== null) node.methods.each { process(node, it) }
|
||||
}
|
||||
|
||||
protected pre() {}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ abstract class BytecodePredicateFinder extends BytecodeFinder {
|
||||
@Internal
|
||||
abstract Property<Closure<Boolean>> getPredicate()
|
||||
|
||||
private final Set<String> matches = new HashSet()
|
||||
private final Set<String> matches = new HashSet<>()
|
||||
|
||||
@Override
|
||||
protected process(ClassNode parent, MethodNode node) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package net.minecraftforge.forge.tasks;
|
||||
|
||||
import groovy.transform.CompileDynamic;
|
||||
import groovy.transform.CompileStatic;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
@@ -26,6 +29,7 @@ import java.util.Set;
|
||||
* This does the same thing, as well as sorting alphabetically.
|
||||
* It also ignores all comments. We can add them latter if someone cares.
|
||||
*/
|
||||
@CompileStatic
|
||||
public class CleanProperties extends Properties {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String LINE_SEP = System.getProperty("line.separator");
|
||||
@@ -58,6 +62,7 @@ public class CleanProperties extends Properties {
|
||||
return Collections.enumeration(ret);
|
||||
}
|
||||
|
||||
@CompileDynamic
|
||||
@Override
|
||||
public Set<Map.Entry<Object, Object>> entrySet() {
|
||||
Set<Map.Entry<Object, Object>> ret = new TreeSet<>((l, r) -> ((String)l.getKey()).compareTo((String)r.getKey()));
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.stc.FirstParam
|
||||
|
||||
import java.util.function.BiConsumer
|
||||
|
||||
public class ClosureHelper {
|
||||
@@ -22,7 +24,7 @@ public class ClosureHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static <T> T apply(T obj, Closure cl) {
|
||||
static <T> T apply(T obj, @DelegatesTo(value = FirstParam, strategy = Closure.DELEGATE_FIRST) Closure cl) {
|
||||
cl.delegate = obj
|
||||
cl.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
cl()
|
||||
|
||||
@@ -27,7 +27,7 @@ abstract class DownloadLibraries extends DefaultTask {
|
||||
def run() {
|
||||
Util.init()
|
||||
File outputDir = output.get().asFile
|
||||
def libraries = new ArrayList()
|
||||
var libraries = new ArrayList<String>()
|
||||
|
||||
def json = input.get().asFile.json().libraries.each { lib ->
|
||||
//TODO: Thread?
|
||||
@@ -35,7 +35,7 @@ abstract class DownloadLibraries extends DefaultTask {
|
||||
artifacts.each{ art ->
|
||||
def target = new File(outputDir, art.path)
|
||||
libraries.add(target.absolutePath)
|
||||
if (!target.exists() || !art.sha1.equals(target.sha1())) {
|
||||
if (!target.exists() || art.sha1 != target.sha1()) {
|
||||
project.logger.lifecycle("Downloading ${art.url}")
|
||||
if (!target.parentFile.exists()) {
|
||||
target.parentFile.mkdirs()
|
||||
@@ -43,7 +43,7 @@ abstract class DownloadLibraries extends DefaultTask {
|
||||
new URL(art.url).withInputStream { i ->
|
||||
target.withOutputStream { it << i }
|
||||
}
|
||||
if (!art.sha1.equals(target.sha1())) {
|
||||
if (art.sha1 != target.sha1()) {
|
||||
throw new IllegalStateException("Failed to download ${art.url} to ${target.canonicalPath} SHA Mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
@CompileStatic
|
||||
abstract class ExtractFile extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getInput()
|
||||
@Input abstract Property<String> getTarget()
|
||||
@@ -12,11 +16,11 @@ abstract class ExtractFile extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def zip = new java.util.zip.ZipFile(input.get().asFile);
|
||||
def entry = zip.getEntry(target.get())
|
||||
var zip = new ZipFile(input.get().asFile);
|
||||
var entry = zip.getEntry(target.get())
|
||||
if (entry == null)
|
||||
throw new IllegalStateException(input.get().asFile.absolutePath + " does not contain " + target.get())
|
||||
def stream = zip.getInputStream(entry)
|
||||
var stream = zip.getInputStream(entry)
|
||||
output.get().asFile.withOutputStream { out ->
|
||||
stream.transferTo(out)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
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.AbstractInsnNode
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.FieldNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*
|
||||
@@ -34,17 +25,17 @@ abstract class FieldCompareFinder extends BytecodeFinder {
|
||||
|
||||
@Override
|
||||
protected process(ClassNode parent, MethodNode node) {
|
||||
def last = null
|
||||
AbstractInsnNode last = null
|
||||
def parentInstance = new ObjectTarget(owner: parent.name, name: '', desc: '')
|
||||
for (int x = 0; x < node.instructions.size(); x++) {
|
||||
def current = node.instructions.get(x)
|
||||
if (current.opcode == IF_ACMPEQ || current.opcode == IF_ACMPNE) {
|
||||
if (last != null && (last.opcode == GETSTATIC || last.opcode == GETFIELD)) {
|
||||
if (current.opcode === IF_ACMPEQ || current.opcode === IF_ACMPNE) {
|
||||
if (last !== null && (last.opcode === GETSTATIC || last.opcode === GETFIELD)) {
|
||||
def target = new Search(cls: last.owner, name: last.name)
|
||||
def wanted = fieldsReverse.get(target)
|
||||
def original = fields.get(wanted)
|
||||
def instance = new ObjectTarget(owner: parent.name, name: node.name, desc: node.desc)
|
||||
if (wanted != null && (original.blacklist == null || (!original.blacklist.contains(instance) && !original.blacklist.contains(parentInstance)))) {
|
||||
if (wanted !== null && (original.blacklist === null || (!original.blacklist.contains(instance) && !original.blacklist.contains(parentInstance)))) {
|
||||
targets.computeIfAbsent(wanted, { k -> new TreeSet() }).add(instance)
|
||||
}
|
||||
}
|
||||
@@ -68,9 +59,10 @@ abstract class FieldCompareFinder extends BytecodeFinder {
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
@CompileStatic
|
||||
@EqualsAndHashCode(excludes = ['replacement', 'blacklist'])
|
||||
public static class Search {
|
||||
static class Search {
|
||||
@Input
|
||||
String cls
|
||||
|
||||
@@ -89,17 +81,17 @@ abstract class FieldCompareFinder extends BytecodeFinder {
|
||||
return cls + '.' + name
|
||||
}
|
||||
|
||||
def blacklist(def owner, def name, def desc) {
|
||||
if (blacklist == null)
|
||||
blacklist = new HashSet()
|
||||
def blacklist(String owner, String name, String desc) {
|
||||
if (blacklist === null)
|
||||
blacklist = new HashSet<>()
|
||||
blacklist.add(new ObjectTarget(owner: owner, name: name, desc: desc))
|
||||
}
|
||||
def blacklist(def owner) {
|
||||
def blacklist(String owner) {
|
||||
blacklist(owner, '', '')
|
||||
}
|
||||
}
|
||||
|
||||
def fields(Closure cl) {
|
||||
void fields(Closure cl) {
|
||||
new ClosureHelper(cl, {name, ccl ->
|
||||
def search = ClosureHelper.apply(new Search(), ccl)
|
||||
this.fields.put(name, search)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
import org.gradle.api.tasks.bundling.Zip
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.DefaultTask
|
||||
@@ -27,7 +29,7 @@ abstract class InstallerJar extends Zip {
|
||||
from(project.rootProject.file('/src/main/resources/url.png'))
|
||||
project.afterEvaluate {
|
||||
from(project.zipTree(downloadInstaller.output)) {
|
||||
duplicatesStrategy = 'exclude'
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
if (fat.get() || offline.get()) {
|
||||
@@ -42,7 +44,7 @@ abstract class InstallerJar extends Zip {
|
||||
// I should make it allow downloads but thats a spec break, and this is just a ~14KB jar
|
||||
[
|
||||
project.tasks.serverShimJar // Server bootstrap executable jar
|
||||
].forEach { packed ->
|
||||
].forEach { AbstractArchiveTask packed ->
|
||||
def path = Util.getMavenInfoFromTask(packed).path
|
||||
from(packed) {
|
||||
rename { "maven/$path" }
|
||||
@@ -67,8 +69,8 @@ abstract class InstallerJar extends Zip {
|
||||
].each { task ->
|
||||
def json = task.output.get().asFile.json
|
||||
json.libraries.each { lib ->
|
||||
deps.put(lib.name, lib.downloads.artifact)
|
||||
//println(lib.name)
|
||||
if (lib.downloads?.artifact?.url !== null && !lib.downloads.artifact.url.isEmpty())
|
||||
deps.put(lib.name, lib.downloads.artifact)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +78,10 @@ abstract class InstallerJar extends Zip {
|
||||
[
|
||||
project.tasks.universalJar, // Forge runtime code
|
||||
project.tasks.serverShimJar // Shim jar for dedicated server
|
||||
].forEach { packed ->
|
||||
].forEach { AbstractArchiveTask packed ->
|
||||
def name = Util.getMavenInfoFromTask(packed).name
|
||||
def info = deps.remove(name)
|
||||
if (info != null) {
|
||||
if (info !== null) {
|
||||
println("Adding: $packed.path $name")
|
||||
parent.from(packed) {
|
||||
rename { "maven/$info.path" }
|
||||
@@ -96,7 +98,7 @@ abstract class InstallerJar extends Zip {
|
||||
//println('')
|
||||
def resolved = cfg.resolvedConfiguration.resolvedArtifacts
|
||||
int found = 0
|
||||
for (var dep : resolved) {
|
||||
for (def dep : resolved) {
|
||||
def name = Util.getMavenInfoFromDep(dep).name
|
||||
def info = deps.remove(name)
|
||||
if (info == null) {
|
||||
@@ -132,13 +134,13 @@ abstract class InstallerJar extends Zip {
|
||||
}
|
||||
|
||||
void addFile(file, info) {
|
||||
def pack = parent.offline.get() || info.url.isEmpty()
|
||||
boolean pack = parent.offline.get() || info.url.isEmpty()
|
||||
|
||||
// If it's a offline jar just always pack
|
||||
if (!pack) {
|
||||
try {
|
||||
def remote = new URL("${info.url}.sha1").getText('UTF-8')
|
||||
pack = !info.sha1.equals(remote)
|
||||
var remote = new URL("${info.url}.sha1").getText('UTF-8')
|
||||
pack = info.sha1 != remote
|
||||
} catch (FileNotFoundException e) {
|
||||
pack = !info.url.startsWith('https://libraries.minecraft.net/')
|
||||
// Oh noes its not there!
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
@@ -45,7 +46,7 @@ abstract class InstallerJson extends DefaultTask {
|
||||
[
|
||||
project.tasks.universalJar,
|
||||
project.tasks.serverShimJar
|
||||
].forEach { packed ->
|
||||
].forEach { AbstractArchiveTask packed ->
|
||||
def info = Util.getMavenInfoFromTask(packed)
|
||||
libs.put(info.name, [
|
||||
name: info.name,
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
@@ -33,7 +34,7 @@ abstract class LauncherJson extends DefaultTask {
|
||||
"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/"
|
||||
],
|
||||
id: "$mc-$project.name$forge",
|
||||
id: "$mc-$project.name-$forge",
|
||||
time: timestamp,
|
||||
releaseTime: timestamp,
|
||||
inheritsFrom: mc,
|
||||
@@ -49,30 +50,45 @@ abstract class LauncherJson extends DefaultTask {
|
||||
dependsOn(packed)
|
||||
input.from packed.archiveFile
|
||||
}
|
||||
|
||||
def patched = project.tasks.applyClientBinPatches
|
||||
dependsOn(patched)
|
||||
input.from patched.output
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
[
|
||||
project.tasks.universalJar
|
||||
].forEach { packed ->
|
||||
def info = Util.getMavenInfoFromTask(packed)
|
||||
json.libraries.add([
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: "https://maven.minecraftforge.net/$info.path",
|
||||
sha1: packed.archiveFile.get().asFile.sha1(),
|
||||
size: packed.archiveFile.get().asFile.length()
|
||||
]
|
||||
var packed = (AbstractArchiveTask) project.tasks.universalJar
|
||||
def info = Util.getMavenInfoFromTask(packed)
|
||||
json.libraries.add([
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: "https://maven.minecraftforge.net/$info.path",
|
||||
sha1: packed.archiveFile.get().asFile.sha1(),
|
||||
size: packed.archiveFile.get().asFile.length()
|
||||
]
|
||||
])
|
||||
}
|
||||
getArtifacts(project, project.configurations.installer).each { key, lib ->
|
||||
json.libraries.add(lib)
|
||||
}
|
||||
]
|
||||
])
|
||||
|
||||
var classifier = 'client'
|
||||
var genned = project.tasks.applyClientBinPatches
|
||||
info = Util.getMavenInfoFromTask(genned, classifier)
|
||||
json.libraries.add([
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: "",
|
||||
sha1: genned.output.get().asFile.sha1(),
|
||||
size: genned.output.get().asFile.length()
|
||||
]
|
||||
]
|
||||
])
|
||||
|
||||
json.libraries.addAll(getArtifacts(project.configurations.installer).values())
|
||||
Files.writeString(output.get().asFile.toPath(), new JsonBuilder(json).toPrettyString())
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
@@ -12,6 +13,7 @@ import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
@CompileStatic
|
||||
abstract class MergeJars extends DefaultTask {
|
||||
MergeJars() {
|
||||
output.convention(project.layout.buildDirectory.dir(name).map { it.file('output.jar') })
|
||||
@@ -24,8 +26,8 @@ abstract class MergeJars extends DefaultTask {
|
||||
try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(output.get().asFile))) {
|
||||
for (def jar : jars) {
|
||||
try (ZipInputStream zin = new ZipInputStream(new FileInputStream(jar))) {
|
||||
def entry
|
||||
while ((entry = zin.getNextEntry()) != null) {
|
||||
ZipEntry entry
|
||||
while ((entry = zin.getNextEntry()) !== null) {
|
||||
ZipEntry _new = new ZipEntry(entry.getName())
|
||||
_new.setTime(0) //SHOULD be the same time as the main entry, but NOOOO _new.setTime(entry.getTime()) throws DateTimeException, so you get 0, screw you!
|
||||
zout.putNextEntry(_new)
|
||||
|
||||
@@ -27,6 +27,6 @@ public class ObjectTarget implements Comparable<ObjectTarget> {
|
||||
|
||||
@Override
|
||||
int compareTo(ObjectTarget o) {
|
||||
return toString().compareTo(o.toString())
|
||||
return toString() <=> o.toString()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ abstract class SetupCheckJarCompatibility extends DefaultTask {
|
||||
SetupCheckJarCompatibility() {
|
||||
group = 'jar compatibility'
|
||||
onlyIf {
|
||||
inputVersion.getOrNull() != null
|
||||
inputVersion.getOrNull() !== null
|
||||
}
|
||||
outputs.upToDateWhen { false } // Never up to date, because this setup task should always run
|
||||
|
||||
|
||||
@@ -2,35 +2,47 @@ package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import groovy.json.JsonSlurper
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.SimpleType
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
|
||||
import java.io.File
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpRequest
|
||||
import java.net.http.HttpResponse
|
||||
import java.security.MessageDigest
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.Semaphore
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
public class Util {
|
||||
static final ASM_LEVEL = Opcodes.ASM9
|
||||
final class Util {
|
||||
public static final int ASM_LEVEL = Opcodes.ASM9
|
||||
private static final HttpClient HTTP = HttpClient.newBuilder().build()
|
||||
|
||||
static void init() {
|
||||
File.metaClass.sha1 = { ->
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-1')
|
||||
delegate.eachByte 4096, {bytes, size ->
|
||||
delegate.eachByte(4096) { byte[] bytes, int size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect {String.format "%02x", it}.join()
|
||||
return md.digest().collect(this.&toHex).join('')
|
||||
}
|
||||
File.metaClass.getSha1 = { !delegate.exists() ? null : delegate.sha1() }
|
||||
File.metaClass.sha256 = { ->
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-256')
|
||||
delegate.eachByte 4096, {bytes, size ->
|
||||
delegate.eachByte(4096) { byte[] bytes, int size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect {String.format "%02x", it}.join()
|
||||
return md.digest().collect(this.&toHex).join('')
|
||||
}
|
||||
File.metaClass.getSha256 = { !delegate.exists() ? null : delegate.sha256() }
|
||||
|
||||
@@ -39,16 +51,17 @@ public class Util {
|
||||
File.metaClass.setJson = { json -> delegate.text = new JsonBuilder(json).toPrettyString() }
|
||||
|
||||
Date.metaClass.iso8601 = { ->
|
||||
def format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
def result = format.format(delegate)
|
||||
var format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
var result = format.format(delegate)
|
||||
return result[0..21] + ':' + result[22..-1]
|
||||
}
|
||||
|
||||
String.metaClass.rsplit = { String del, int limit = -1 ->
|
||||
def lst = new ArrayList()
|
||||
def x = 0, idx
|
||||
def tmp = delegate
|
||||
while ((idx = tmp.lastIndexOf(del)) != -1 && (limit == -1 || x++ < limit)) {
|
||||
var lst = new ArrayList<String>()
|
||||
int x = 0
|
||||
int idx
|
||||
String tmp = delegate
|
||||
while ((idx = tmp.lastIndexOf(del)) != -1 && (limit === -1 || x++ < limit)) {
|
||||
lst.add(0, tmp.substring(idx + del.length(), tmp.length()))
|
||||
tmp = tmp.substring(0, idx)
|
||||
}
|
||||
@@ -57,7 +70,7 @@ public class Util {
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getClasspath(project, libs, artifact) {
|
||||
static String[] getClasspath(Project project, Map libs, String artifact) {
|
||||
def ret = []
|
||||
artifactTree(project, artifact).each { key, lib ->
|
||||
libs[lib.name] = lib
|
||||
@@ -67,30 +80,38 @@ public class Util {
|
||||
return ret
|
||||
}
|
||||
|
||||
public static def getArtifacts(project, config) {
|
||||
def ret = [:]
|
||||
config.resolvedConfiguration.resolvedArtifacts.each { dep ->
|
||||
def info = getMavenInfoFromDep(dep)
|
||||
def url = "https://libraries.minecraft.net/$info.path"
|
||||
@CompileStatic
|
||||
static Map getArtifacts(Configuration config) {
|
||||
var ret = [:]
|
||||
var semaphore = new Semaphore(1, true)
|
||||
config.resolvedConfiguration.resolvedArtifacts.parallelStream().forEachOrdered(dep -> {
|
||||
var info = getMavenInfoFromDep(dep)
|
||||
var domain = 'libraries.minecraft.net'
|
||||
var url = "https://$domain/$info.path"
|
||||
if (!checkExists(url))
|
||||
url = "https://maven.minecraftforge.net/$info.path"
|
||||
|
||||
url.values[0] = 'maven.minecraftforge.net'
|
||||
|
||||
var sha1 = sha1(dep.file)
|
||||
|
||||
semaphore.acquire()
|
||||
ret[info.key] = [
|
||||
name: info.name,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: info.path,
|
||||
url: url,
|
||||
sha1: dep.file.sha1(),
|
||||
url: url.toString(),
|
||||
sha1: sha1,
|
||||
size: dep.file.length()
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
semaphore.release()
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
public static Map getMavenInfoFromDep(dep) {
|
||||
|
||||
@CompileStatic
|
||||
static Map getMavenInfoFromDep(ResolvedArtifact dep) {
|
||||
return getMavenInfoFromMap([
|
||||
group: dep.moduleVersion.id.group,
|
||||
name: dep.moduleVersion.id.name,
|
||||
@@ -99,49 +120,69 @@ public class Util {
|
||||
extension: dep.extension
|
||||
])
|
||||
}
|
||||
public static Map getMavenInfoFromTask(task) {
|
||||
|
||||
@CompileStatic
|
||||
static Map getMavenInfoFromTask(AbstractArchiveTask task) {
|
||||
return getMavenInfoFromMap([
|
||||
group: task.project.group,
|
||||
group: task.project.group.toString(),
|
||||
name: task.project.name,
|
||||
version: task.project.version,
|
||||
version: task.project.version.toString(),
|
||||
classifier: task.archiveClassifier.get(),
|
||||
extension: task.archiveExtension.get()
|
||||
])
|
||||
}
|
||||
|
||||
private static Map getMavenInfoFromMap(art) {
|
||||
def key = "$art.group:$art.name"
|
||||
def name = "$art.group:$art.name:$art.version"
|
||||
def path = "${art.group.replace('.', '/')}/$art.name/$art.version/$art.name-$art.version"
|
||||
if (art.classifier != null) {
|
||||
|
||||
@CompileStatic
|
||||
static Map getMavenInfoFromTask(Task task, String classifier) {
|
||||
return getMavenInfoFromMap([
|
||||
group: task.project.group.toString(),
|
||||
name: task.project.name,
|
||||
version: task.project.version.toString(),
|
||||
classifier: classifier,
|
||||
extension: 'jar'
|
||||
])
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
private static Map getMavenInfoFromMap(Map<String, String> art) {
|
||||
var key = "$art.group:$art.name"
|
||||
var name = "$art.group:$art.name:$art.version"
|
||||
var path = "${art.group.replace('.', '/')}/$art.name/$art.version/$art.name-$art.version"
|
||||
if (art.classifier !== null) {
|
||||
name += ":$art.classifier"
|
||||
path += "-$art.classifier"
|
||||
}
|
||||
if (!'jar'.equals(art.extension)) {
|
||||
if ('jar' != art.extension) {
|
||||
name += "@$art.extension"
|
||||
path += ".$art.extension"
|
||||
} else {
|
||||
path += ".jar"
|
||||
}
|
||||
return [
|
||||
key: key,
|
||||
name: name,
|
||||
path: path,
|
||||
key: key.toString(),
|
||||
name: name.toString(),
|
||||
path: path.toString(),
|
||||
art: art
|
||||
]
|
||||
}
|
||||
|
||||
public static def iso8601Now() { new Date().iso8601() }
|
||||
static String iso8601Now() { new Date().iso8601() }
|
||||
|
||||
public static def sha1(file) {
|
||||
@CompileStatic
|
||||
static String sha1(File file) {
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-1')
|
||||
file.eachByte 4096, {bytes, size ->
|
||||
file.eachByte(4096) { byte[] bytes, int size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect {String.format "%02x", it}.join()
|
||||
return md.digest().collect(this.&toHex).join('')
|
||||
}
|
||||
|
||||
private static def artifactTree(project, artifact, transitive = true) {
|
||||
@CompileStatic
|
||||
private static String toHex(byte bite) {
|
||||
return String.format('%02x', bite)
|
||||
}
|
||||
|
||||
private static Map artifactTree(Project project, String artifact, boolean transitive = true) {
|
||||
if (!project.ext.has('tree_resolver'))
|
||||
project.ext.tree_resolver = 1
|
||||
def cfg = project.configurations.create('tree_resolver_' + project.ext.tree_resolver++)
|
||||
@@ -149,37 +190,36 @@ public class Util {
|
||||
def dep = project.dependencies.create(artifact)
|
||||
cfg.dependencies.add(dep)
|
||||
def files = cfg.resolve()
|
||||
return getArtifacts(project, cfg)
|
||||
return getArtifacts(cfg)
|
||||
}
|
||||
|
||||
static boolean checkExists(url) {
|
||||
@CompileStatic
|
||||
static boolean checkExists(String url) {
|
||||
try {
|
||||
def code = new URL(url).openConnection().with {
|
||||
requestMethod = 'HEAD'
|
||||
connect()
|
||||
responseCode
|
||||
}
|
||||
return code == 200
|
||||
return HTTP.send(HttpRequest.newBuilder(new URI(url))
|
||||
.method('HEAD', HttpRequest.BodyPublishers.noBody()).build(), HttpResponse.BodyHandlers.discarding()
|
||||
).statusCode() === 200
|
||||
} catch (Exception e) {
|
||||
if (e.toString().contains('unable to find valid certification path to requested target'))
|
||||
throw new RuntimeException('Failed to connect to ' + url + ': Missing certificate root authority, try updating java')
|
||||
throw new RuntimeException("Failed to connect to $url: Missing certificate root authority, try updating Java")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
static String getLatestForgeVersion(mcVersion) {
|
||||
static String getLatestForgeVersion(String mcVersion) {
|
||||
final json = new JsonSlurper().parseText(new URL('https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json').getText('UTF-8'))
|
||||
final ver = json.promos["$mcVersion-latest"]
|
||||
ver === null ? null : (mcVersion + '-' + ver)
|
||||
}
|
||||
|
||||
static void processClassNodes(File file, Closure process) {
|
||||
@CompileStatic
|
||||
static void processClassNodes(File file, @ClosureParams(value = SimpleType, options = 'org.objectweb.asm.tree.ClassNode') Closure process) {
|
||||
file.withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) != null) {
|
||||
while ((zein = zin.nextEntry) !== null) {
|
||||
if (zein.name.endsWith('.class')) {
|
||||
def node = new ClassNode(ASM_LEVEL)
|
||||
var node = new ClassNode(ASM_LEVEL)
|
||||
new ClassReader(zin).accept(node, 0)
|
||||
process(node)
|
||||
}
|
||||
@@ -187,4 +227,4 @@ public class Util {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import net.minecraftforge.srgutils.MinecraftVersion
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
@@ -28,8 +29,8 @@ abstract class ValidateDeprecations extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def mcVer = MinecraftVersion.from(mcVersion.get())
|
||||
def errors = []
|
||||
var mcVer = MinecraftVersion.from(mcVersion.get())
|
||||
List<String> errors = []
|
||||
|
||||
Util.processClassNodes(input.get().asFile) {
|
||||
processNode(mcVer, errors, it)
|
||||
@@ -65,7 +66,7 @@ abstract class ValidateDeprecations extends DefaultTask {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processAnnotations(AnnotationNode annotation, MinecraftVersion mcVer, List<String> errors, Closure context) {
|
||||
private static void processAnnotations(AnnotationNode annotation, MinecraftVersion mcVer, List<String> errors, Closure<String> context) {
|
||||
def values = annotation.values
|
||||
if (values === null)
|
||||
return
|
||||
@@ -73,7 +74,7 @@ abstract class ValidateDeprecations extends DefaultTask {
|
||||
int since = values.indexOf('since')
|
||||
if (annotation.desc == 'Ljava/lang/Deprecated;' && forRemoval !== -1 && since !== -1 && values.size() >= 4 && values[forRemoval + 1] === true) {
|
||||
def oldVersion = MinecraftVersion.from(values[since + 1])
|
||||
def split = ValidateDeprecations.splitDots(oldVersion.toString())
|
||||
int[] split = ValidateDeprecations.splitDots(oldVersion.toString())
|
||||
if (split.length < 2)
|
||||
return
|
||||
def removeVersion = MinecraftVersion.from("${split[0]}.${split[1] + 1}")
|
||||
@@ -82,6 +83,7 @@ abstract class ValidateDeprecations extends DefaultTask {
|
||||
}
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
private static int[] splitDots(String version) {
|
||||
String[] pts = version.split('\\.')
|
||||
int[] values = new int[pts.length]
|
||||
|
||||
@@ -26,12 +26,12 @@ abstract class CheckExcs extends CheckTask {
|
||||
excs.each { f ->
|
||||
final lines = []
|
||||
f.eachLine { line ->
|
||||
def idx = line.indexOf('#')
|
||||
if (idx == 0 || line.isEmpty()) {
|
||||
int idx = line.indexOf('#')
|
||||
if (idx === 0 || line.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (idx != -1) line = line.substring(0, idx - 1)
|
||||
if (idx !== -1) line = line.substring(0, idx - 1)
|
||||
|
||||
if (!line.contains('=')) {
|
||||
reporter.report("Invalid: $line")
|
||||
@@ -58,6 +58,8 @@ abstract class CheckExcs extends CheckTask {
|
||||
return
|
||||
}
|
||||
lines.add(line)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (fix) f.text = lines.sort().join('\n')
|
||||
|
||||
@@ -6,4 +6,6 @@ import groovy.transform.CompileStatic
|
||||
enum CheckMode {
|
||||
CHECK,
|
||||
FIX
|
||||
|
||||
CheckMode() {}
|
||||
}
|
||||
@@ -36,13 +36,13 @@ abstract class CheckPatches extends CheckTask {
|
||||
}
|
||||
}
|
||||
|
||||
def accessChange(previous, current) {
|
||||
static boolean accessChange(String previous, String current) {
|
||||
//return ACCESS_MAP[previous] < ACCESS_MAP[current]
|
||||
return previous != current
|
||||
}
|
||||
|
||||
void verifyPatch(Path patch, Reporter reporter, boolean fix, String patchPath, boolean hasS2SArtifact) {
|
||||
final oldFixedErrors = reporter.fixed.size()
|
||||
int oldFixedErrors = reporter.fixed.size()
|
||||
|
||||
final lines = Files.readAllLines(patch)
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ abstract class CheckSAS extends CheckTask {
|
||||
}
|
||||
}
|
||||
|
||||
protected static isSided(Annotatable annotatable) {
|
||||
protected static boolean isSided(Annotatable annotatable) {
|
||||
if (annotatable === null) return false
|
||||
for (ann in annotatable.annotations) {
|
||||
if ('Lnet/minecraftforge/api/distmarker/OnlyIn;' == ann.desc)
|
||||
@@ -104,7 +104,7 @@ abstract class CheckSAS extends CheckTask {
|
||||
}
|
||||
|
||||
protected static findChildMethods(Map<String, InheritanceData> json, String cls, String desc) {
|
||||
return json.values().findAll{ it.methods != null && it.methods[desc] != null && it.methods[desc].override == cls && isSided(it.methods[desc]) }
|
||||
return json.values().findAll{ it.methods !== null && it.methods[desc] !== null && it.methods[desc].override == cls && isSided(it.methods[desc]) }
|
||||
.collect { it.name + ' ' + desc.replace(' ', '') } as TreeSet
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.minecraftforge.forge.tasks.checks
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.ThirdParam
|
||||
import net.minecraftforge.forge.tasks.Util
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
@@ -33,7 +35,7 @@ abstract class CheckTask extends DefaultTask implements VerificationTask {
|
||||
void run() {
|
||||
Util.init()
|
||||
|
||||
final doFix = getMode().get() === CheckMode.FIX
|
||||
boolean doFix = getMode().get() === CheckMode.FIX
|
||||
final Reporter reporter = new Reporter(doFix)
|
||||
check(reporter, doFix)
|
||||
|
||||
@@ -88,7 +90,8 @@ abstract class CheckTask extends DefaultTask implements VerificationTask {
|
||||
}
|
||||
|
||||
static <T extends CheckTask> void registerTask(TaskContainer tasks, String taskName, @DelegatesTo.Target('type') Class<T> clazz,
|
||||
@DelegatesTo(genericTypeIndex = 0, target = 'type') Closure configuration) {
|
||||
@DelegatesTo(genericTypeIndex = 0, target = 'type')
|
||||
@ClosureParams(ThirdParam.FirstGenericType) Closure configuration) {
|
||||
taskName = taskName.capitalize()
|
||||
tasks.register("check$taskName", clazz) { CheckTask task ->
|
||||
def castedTask = task as T
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.gradle.patcher'
|
||||
}
|
||||
|
||||
|
||||
+90
-30
@@ -1,11 +1,11 @@
|
||||
import de.undercouch.gradle.tasks.download.Download
|
||||
import net.minecraftforge.forge.tasks.checks.CheckATs
|
||||
import net.minecraftforge.forge.tasks.checks.CheckExcs
|
||||
import net.minecraftforge.forge.tasks.checks.CheckPatches
|
||||
import net.minecraftforge.forge.tasks.checks.CheckSAS
|
||||
import net.minecraftforge.forge.tasks.checks.CheckTask
|
||||
|
||||
import java.util.Date
|
||||
import java.util.LinkedHashMap
|
||||
import java.nio.file.Files
|
||||
import net.minecraftforge.forge.tasks.*
|
||||
import static net.minecraftforge.forge.tasks.Util.*
|
||||
import net.minecraftforge.gradle.common.tasks.ApplyBinPatches
|
||||
@@ -23,7 +23,7 @@ plugins {
|
||||
id 'eclipse'
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'de.undercouch.download'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
id 'net.minecraftforge.gradle.patcher'
|
||||
@@ -69,19 +69,27 @@ sourceSets {
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
SPEC_VERSION = gradleutils.gitInfo.tag
|
||||
// The new versioning sceme is <MCVersion>-<ForgeMC>.<RB>.<CommitsSinceRB>
|
||||
// ForgeMC is a unique identifier for every MC version we have supported.
|
||||
// Essentially, the same as the old, except dropping the first number, and the builds are no longer unique.
|
||||
MCP_ARTIFACT = project(':mcp').mcp.config.get()
|
||||
final String SPEC_VERSION = gradleutils.gitInfo.tag
|
||||
|
||||
EXTRA_TXTS = [
|
||||
// The new versioning sceme is <MCVersion>-<ForgeMC>.<RB>.<CommitsSinceRB>
|
||||
// ForgeMC is a unique identifier for every MC version we have supported.
|
||||
// Essentially, the same as the old, except dropping the first number, and the builds are no longer unique.
|
||||
final def MCP_ARTIFACT = project(':mcp').mcp.config.get()
|
||||
|
||||
final List<File> EXTRA_TXTS = [
|
||||
rootProject.file('CREDITS.txt'),
|
||||
rootProject.file('LICENSE.txt'),
|
||||
rootProject.tasks.createChangelog.outputFile
|
||||
]
|
||||
]
|
||||
|
||||
ext {
|
||||
MAVEN_PATH = "${group.toString().replace('.', '/')}/${project.name}/${VERSION}".toString()
|
||||
}
|
||||
final String MAVEN_PATH = ext.MAVEN_PATH
|
||||
|
||||
final String BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.2.0:fatjar'
|
||||
final String INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.4.0'
|
||||
final String FART = 'net.minecraftforge:ForgeAutoRenamingTool:1.0.6'
|
||||
|
||||
configurations {
|
||||
// Don't pull all libraries, if we're missing something, add it to the installer list so the installer knows to download it.
|
||||
@@ -128,6 +136,7 @@ dependencies {
|
||||
installer(project(':mclanguage'))
|
||||
|
||||
runtimeOnly(libs.bootstrap)
|
||||
runtimeOnly(libs.bootstrap.dev)
|
||||
}
|
||||
|
||||
patcher {
|
||||
@@ -277,7 +286,7 @@ tasks.userdevConfig.configure {
|
||||
}
|
||||
}
|
||||
|
||||
for (def run : patcher.runs + tasks.userdevConfig.runs) {
|
||||
for (def run in patcher.runs + tasks.userdevConfig.runs) {
|
||||
if (run.parents) continue // We already added this to the parent run config
|
||||
//run.property 'bsl.debug', 'true'
|
||||
run.args '--gameDir', '.'
|
||||
@@ -309,7 +318,7 @@ tasks.register('downloadVersionManifest', Download) {
|
||||
tasks.register('downloadJson', Download) {
|
||||
dependsOn downloadVersionManifest
|
||||
inputs.file downloadVersionManifest.dest
|
||||
src { downloadVersionManifest.dest.json.versions.find{ it.id == MC_VERSION }.url }
|
||||
src { downloadVersionManifest.dest.json.versions.find { it.id == MC_VERSION }.url }
|
||||
dest file("build/versions/$MC_VERSION/version.json")
|
||||
useETag 'all'
|
||||
onlyIfModified true
|
||||
@@ -349,8 +358,8 @@ tasks.register('extractInheritance', ExtractInheritance) {
|
||||
tool = INSTALLER_TOOLS + ':fatjar'
|
||||
args.add '--annotations'
|
||||
input = genJoinedBinPatches.cleanJar
|
||||
libraries.addAll downloadLibraries.librariesOutput.map { rf ->
|
||||
java.nio.file.Files.readAllLines(rf.asFile.toPath()).stream().map(File::new).collect(java.util.stream.Collectors.toList())
|
||||
libraries.addAll downloadLibraries.librariesOutput.map { rf ->
|
||||
Files.readAllLines(rf.asFile.toPath()).stream().map(File::new).toList()
|
||||
}
|
||||
}
|
||||
tasks.register("findFieldInstanceChecks", FieldCompareFinder) {
|
||||
@@ -377,16 +386,18 @@ tasks.register("findFinalizeSpawnTargets", BytecodePredicateFinder) {
|
||||
predicate = {
|
||||
parent, node, insn ->
|
||||
'net/minecraft/world/level/BaseSpawner' != parent.name // Ignore this class as we special case it.
|
||||
&& insn.getOpcode() == Opcodes.INVOKEVIRTUAL
|
||||
&& insn.name.equals('m_6518_')
|
||||
&& insn.desc.equals('(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/entity/SpawnGroupData;')
|
||||
&& insn.getOpcode() === Opcodes.INVOKEVIRTUAL
|
||||
&& insn.name == 'm_6518_'
|
||||
&& insn.desc == '(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/entity/SpawnGroupData;'
|
||||
}
|
||||
}
|
||||
tasks.register('validateDeprecations', ValidateDeprecations) {
|
||||
input = tasks.jar.archiveFile
|
||||
mcVersion = MC_VERSION
|
||||
}
|
||||
tasks.jar.finalizedBy 'validateDeprecations'
|
||||
tasks.named('jar', Jar).configure {
|
||||
finalizedBy 'validateDeprecations'
|
||||
}
|
||||
tasks.register("downloadInstaller", DownloadMavenArtifact) {
|
||||
artifact = "net.minecraftforge:installer:2.2.+:fatjar"
|
||||
changing = true
|
||||
@@ -536,7 +547,7 @@ CheckTask.registerTask(tasks, 'Excs', CheckExcs) {
|
||||
}
|
||||
|
||||
CheckTask.registerTask(tasks, 'Patches', CheckPatches) {
|
||||
dependsOn genPatches
|
||||
dependsOn 'genPatches'
|
||||
patchDir = file("$rootDir/patches")
|
||||
patchesWithS2SArtifact = [
|
||||
'minecraft/net/minecraft/client/renderer/ViewArea.java.patch',
|
||||
@@ -544,7 +555,7 @@ CheckTask.registerTask(tasks, 'Patches', CheckPatches) {
|
||||
]
|
||||
}
|
||||
|
||||
genPatches {
|
||||
tasks.named('genPatches', GeneratePatches).configure {
|
||||
finalizedBy checkAndFixPatches
|
||||
autoHeader true
|
||||
lineEnding = '\n'
|
||||
@@ -553,10 +564,10 @@ genPatches {
|
||||
def baseForgeVersionProperty = project.objects.property(String)
|
||||
baseForgeVersionProperty.set(project.provider { TeamcityRequests.attemptFindBase(rootDir) ?: getLatestForgeVersion(MC_VERSION) })
|
||||
baseForgeVersionProperty.finalizeValueOnRead()
|
||||
def jarCompatibilityTaskSetup = { task ->
|
||||
final jarCompatibilityTaskSetup = { Task task ->
|
||||
task.group = 'jar compatibility'
|
||||
task.onlyIf {
|
||||
baseForgeVersionProperty.getOrNull() != null
|
||||
baseForgeVersionProperty.getOrNull() !== null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,8 +651,8 @@ tasks.register('installerJson', InstallerJson) {
|
||||
input.from(applyClientBinPatches.output, applyServerBinPatches.output, genClientBinPatches.toolJar)
|
||||
|
||||
doFirst {
|
||||
def libs = libraries
|
||||
def INSTALLER_TOOLS_CLASSPATH = getClasspath(project, libs, INSTALLER_TOOLS)
|
||||
var libs = libraries
|
||||
String[] INSTALLER_TOOLS_CLASSPATH = getClasspath(project, libs, INSTALLER_TOOLS)
|
||||
json.putAll([
|
||||
_comment: launcherJson.json._comment,
|
||||
hideExtract: true,
|
||||
@@ -707,6 +718,34 @@ tasks.register('installerJson', InstallerJson) {
|
||||
],
|
||||
processors: [
|
||||
[
|
||||
sides: ['server'],
|
||||
jar: INSTALLER_TOOLS,
|
||||
classpath: INSTALLER_TOOLS_CLASSPATH,
|
||||
args: [
|
||||
'--task', 'EXTRACT_FILES',
|
||||
'--archive', '{INSTALLER}',
|
||||
|
||||
'--from', 'data/README.txt',
|
||||
'--to', '{ROOT}/README.txt',
|
||||
|
||||
'--from', 'data/run.sh',
|
||||
'--to', '{ROOT}/run.sh',
|
||||
'--exec', '{ROOT}/run.sh',
|
||||
|
||||
'--from', 'data/run.bat',
|
||||
'--to', '{ROOT}/run.bat',
|
||||
|
||||
'--from', 'data/user_jvm_args.txt',
|
||||
'--to', '{ROOT}/user_jvm_args.txt',
|
||||
'--optional', '{ROOT}/user_jvm_args.txt',
|
||||
|
||||
'--from', 'data/unix_args.txt',
|
||||
'--to', "{ROOT}/libraries/${MAVEN_PATH}/unix_args.txt",
|
||||
|
||||
'--from', 'data/win_args.txt',
|
||||
'--to', "{ROOT}/libraries/${MAVEN_PATH}/win_args.txt"
|
||||
]
|
||||
], [
|
||||
sides: ['server'],
|
||||
jar: INSTALLER_TOOLS,
|
||||
classpath: INSTALLER_TOOLS_CLASSPATH,
|
||||
@@ -814,12 +853,12 @@ tasks.register('installerJson', InstallerJson) {
|
||||
|
||||
tasks.named('universalJar').configure {
|
||||
dependsOn downloadCrowdin
|
||||
from zipTree(downloadCrowdin.dest).matching {
|
||||
from zipTree(downloadCrowdin.dest).matching {
|
||||
include 'assets/forge/lang/*.json'
|
||||
}
|
||||
|
||||
from(EXTRA_TXTS)
|
||||
duplicatesStrategy = 'exclude'
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
exclude '.cache'
|
||||
|
||||
manifest {
|
||||
@@ -856,6 +895,29 @@ tasks.register('installerJar', InstallerJar) {
|
||||
from(genServerBinPatches.output) {
|
||||
rename { 'data/server.lzma' }
|
||||
}
|
||||
|
||||
final var argsFile = rootProject.file('server_files/args.txt')
|
||||
final Map<String, Map<String, String>> tokens = [tokens: [
|
||||
SHIM_JAR_FILE: serverShimJar.archiveFileName.get(),
|
||||
MAVEN_PATH: MAVEN_PATH
|
||||
]]
|
||||
from(argsFile) {
|
||||
filter(tokens, ReplaceTokens)
|
||||
into 'data'
|
||||
rename { 'unix_args.txt' }
|
||||
}
|
||||
from(argsFile) {
|
||||
filter(tokens, ReplaceTokens)
|
||||
into 'data'
|
||||
rename { 'win_args.txt' }
|
||||
}
|
||||
|
||||
from(rootProject.file('server_files')) {
|
||||
filter(tokens, ReplaceTokens)
|
||||
into 'data'
|
||||
exclude 'args.txt'
|
||||
}
|
||||
|
||||
jarSigner.sign(it)
|
||||
}
|
||||
|
||||
@@ -1029,6 +1091,4 @@ publishing {
|
||||
|
||||
// Make sure we run bin compat checking during local testing.
|
||||
if (!System.env.MAVEN_USER || !System.env.MAVEN_PASSWORD)
|
||||
publish.dependsOn(':forge:checkJarCompatibility')
|
||||
|
||||
apply from: rootProject.file('build_forge_eclipse.gradle')
|
||||
tasks.named('publish').configure { dependsOn(':forge:checkJarCompatibility') }
|
||||
@@ -1,44 +0,0 @@
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
eclipse {
|
||||
classpath.file.whenMerged {
|
||||
def minecraft = entries.find { it.path == 'src/main/java' }
|
||||
if (minecraft == null) throw new IllegalStateException("You must run `setup` task before importing")
|
||||
// Disable optional warnings on the minecraft decompiled source code. It just muddies the warning window and hides warnings in our own codebase
|
||||
minecraft.entryAttributes['ignore_optional_problems'] = 'true'
|
||||
|
||||
def mods = [
|
||||
'src/main/java': 'minecraft',
|
||||
'src/main/resources': 'minecraft',
|
||||
'src/test/java': 'minecraft-test',
|
||||
'src/test/resources': 'minecraft-test',
|
||||
|
||||
'main-java': 'forge',
|
||||
'main-resources': 'forge',
|
||||
'generated': 'forge',
|
||||
|
||||
'test-java': 'forge-test',
|
||||
'test-resources': 'forge-test',
|
||||
'test-generated': 'forge-test',
|
||||
]
|
||||
|
||||
entries.forEach { e ->
|
||||
if ('src'.equals(e.kind) && e.hasProperty('output')) {
|
||||
if (mods.containsKey(e.path))
|
||||
e.output = 'bin/' + mods[e.path]
|
||||
//else
|
||||
// throw new IllegalStateException('Unknown path: ' + e.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out the run directory
|
||||
project.resourceFilter {
|
||||
appliesTo = 'FOLDERS'
|
||||
type = 'EXCLUDE_ALL'
|
||||
matcher {
|
||||
id = 'org.eclipse.ui.ide.multiFilter'
|
||||
arguments = '1.0-name-matches-false-true-run'
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -40,8 +40,8 @@ tasks.register('generateResources') {
|
||||
|
||||
// Make sure out manifests get written before compiling the code, IDEA calls this task if you tell it to use the gradle build.
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
dependsOn(generateResources)
|
||||
dependsOn(processResources) // Needed because we merge the output of this with the output of the compile task. And gradle detects downstream tasks using the output without a hard dep
|
||||
dependsOn 'generateResources'
|
||||
dependsOn 'processResources' // Needed because we merge the output of this with the output of the compile task. And gradle detects downstream tasks using the output without a hard dep
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
options.warnings = false // Shutup deprecated for removal warnings
|
||||
}
|
||||
@@ -61,7 +61,7 @@ tasks.register('copyEclipseSettings') {
|
||||
def temp = new CleanProperties().load(file)
|
||||
def exst = new CleanProperties().load(target)
|
||||
exst.put('eclipse.preferences.version', '1')
|
||||
temp.forEach(exst::put)
|
||||
exst.putAll(temp)
|
||||
exst.store(target)
|
||||
}
|
||||
}
|
||||
@@ -73,4 +73,4 @@ eclipse {
|
||||
//autoBuildTasks writeManifest
|
||||
// Run when importing the project
|
||||
synchronizationTasks generateResources, copyEclipseSettings, eclipseClasspath, eclipseProject
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
|
||||
MinecraftForge
|
||||
=============
|
||||
[][Download]
|
||||
[][Download]
|
||||
[][Download] [][Discord] [][Patreon]
|
||||
|
||||
Forge is a free, open-source modding API all of your favourite mods use!
|
||||
|
||||
@@ -3,7 +3,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ tasks.named('jar', Jar).configure {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:-unchecked'
|
||||
}
|
||||
|
||||
@@ -64,4 +64,4 @@ publishing {
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,5 +96,26 @@ public interface IExtensionPoint<T extends Record>
|
||||
@SuppressWarnings("JavadocReference") // reference to NetworkConstants, ForgeHooksClient
|
||||
record DisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) implements IExtensionPoint<DisplayTest> {
|
||||
public static final String IGNORESERVERONLY = "SERVER_ONLY";
|
||||
|
||||
/**
|
||||
* Ignores any version information coming from the server - use for server only mods
|
||||
*/
|
||||
public static final Supplier<DisplayTest> IGNORE_SERVER_VERSION = () -> new DisplayTest(IGNORESERVERONLY, (remoteVersion, isFromServer) -> true);
|
||||
|
||||
/**
|
||||
* Ignores all information and provides no information
|
||||
* <p>Note: If your mod is purely client-side and has no multiplayer functionality (be it dedicated servers or
|
||||
* Open to LAN), consider setting {@code clientSideOnly=true} in the root of your mods.toml.</p>
|
||||
*/
|
||||
public static final Supplier<DisplayTest> IGNORE_ALL_VERSION = () -> new DisplayTest("", (remoteVersion, isFromServer) -> true);
|
||||
|
||||
/**
|
||||
* An optional alternative to {@link #DisplayTest(Supplier, BiPredicate)} which accepts a constant version string
|
||||
* instead of a {@link Supplier}.
|
||||
* <p>Internally, the provided version string is wrapped in a Supplier for you.</p>
|
||||
*/
|
||||
public DisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
this(() -> version, remoteVersionTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -58,15 +59,16 @@ public abstract class ModContainer
|
||||
this.modInfo = info;
|
||||
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
|
||||
|
||||
final String displayTestString = info.getConfig().<String>getConfigElement("displayTest").orElse("MATCH_VERSION"); // missing defaults to DEFAULT type
|
||||
final String displayTestString = info.getConfig().<String>getConfigElement("displayTest")
|
||||
.orElseGet(() -> info.getOwningFile().isClientSideOnly() ? "IGNORE_ALL_VERSION" : "MATCH_VERSION");
|
||||
Supplier<IExtensionPoint.DisplayTest> displayTestSupplier = switch (displayTestString) {
|
||||
case "MATCH_VERSION" -> // default displaytest checks for version string match
|
||||
() -> new IExtensionPoint.DisplayTest(() -> this.modInfo.getVersion().toString(),
|
||||
(incoming, isNetwork) -> Objects.equals(incoming, this.modInfo.getVersion().toString()));
|
||||
case "IGNORE_SERVER_VERSION" -> // Ignores any version information coming from the server - use for server only mods
|
||||
() -> new IExtensionPoint.DisplayTest(() -> IExtensionPoint.DisplayTest.IGNORESERVERONLY, (incoming, isNetwork) -> true);
|
||||
IExtensionPoint.DisplayTest.IGNORE_SERVER_VERSION;
|
||||
case "IGNORE_ALL_VERSION" -> // Ignores all information and provides no information
|
||||
() -> new IExtensionPoint.DisplayTest(() -> "", (incoming, isNetwork) -> true);
|
||||
IExtensionPoint.DisplayTest.IGNORE_ALL_VERSION;
|
||||
case "NONE" -> null; // NO display test at all - use this if you're going to do your own display test
|
||||
default -> // any other value throws an exception
|
||||
throw new IllegalArgumentException("Invalid displayTest value supplied in mods.toml");
|
||||
@@ -145,6 +147,22 @@ public abstract class ModContainer
|
||||
extensionPoints.put(point, extension);
|
||||
}
|
||||
|
||||
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
|
||||
registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> displayTest);
|
||||
}
|
||||
|
||||
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
|
||||
registerExtensionPoint(IExtensionPoint.DisplayTest.class, displayTest);
|
||||
}
|
||||
|
||||
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
|
||||
}
|
||||
|
||||
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
|
||||
}
|
||||
|
||||
public void addConfig(final ModConfig modConfig) {
|
||||
configs.put(modConfig.getType(), modConfig);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
public class ModList
|
||||
{
|
||||
private static Logger LOGGER = LogManager.getLogger();
|
||||
//private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static ModList INSTANCE;
|
||||
private final List<IModFileInfo> modFiles;
|
||||
private final List<IModInfo> sortedList;
|
||||
@@ -120,14 +120,14 @@ public class ModList
|
||||
return executor -> gather(
|
||||
this.mods.stream()
|
||||
.map(mod -> ModContainer.buildTransitionHandler(mod, eventGenerator, progressBar, stateChange, executor))
|
||||
.collect(Collectors.toList()))
|
||||
.thenComposeAsync(ModList::completableFutureFromExceptionList, executor);
|
||||
.toList()
|
||||
).thenComposeAsync(ModList::completableFutureFromExceptionList, executor);
|
||||
}
|
||||
static CompletionStage<Void> completableFutureFromExceptionList(List<? extends Map.Entry<?, Throwable>> t) {
|
||||
if (t.stream().noneMatch(e->e.getValue()!=null)) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
final List<Throwable> throwables = t.stream().filter(e -> e.getValue() != null).map(Map.Entry::getValue).collect(Collectors.toList());
|
||||
final List<Throwable> throwables = t.stream().filter(e -> e.getValue() != null).map(Map.Entry::getValue).toList();
|
||||
CompletableFuture<Void> cf = new CompletableFuture<>();
|
||||
final RuntimeException accumulator = new RuntimeException();
|
||||
cf.completeExceptionally(accumulator);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
@@ -32,6 +33,7 @@ import java.util.function.BiConsumer;
|
||||
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.Logging.CORE;
|
||||
import static net.minecraftforge.fml.Logging.LOADING;
|
||||
@@ -91,13 +93,13 @@ public class ModLoader
|
||||
{
|
||||
INSTANCE = this;
|
||||
this.loadingModList = FMLLoader.getLoadingModList();
|
||||
this.loadingExceptions = FMLLoader.getLoadingModList().getErrors().stream()
|
||||
this.loadingExceptions = this.loadingModList.getErrors().stream()
|
||||
.flatMap(ModLoadingException::fromEarlyException)
|
||||
.collect(Collectors.toList());
|
||||
this.loadingWarnings = FMLLoader.getLoadingModList().getBrokenFiles().stream()
|
||||
this.loadingWarnings = this.loadingModList.getBrokenFiles().stream()
|
||||
.map(file -> new ModLoadingWarning(null, ModLoadingStage.VALIDATE, InvalidModIdentifier.identifyJarProblem(file.getFilePath()).orElse("fml.modloading.brokenfile"), file.getFileName()))
|
||||
.collect(Collectors.toList());
|
||||
FMLLoader.getLoadingModList().getModFiles().stream()
|
||||
this.loadingModList.getModFiles().stream()
|
||||
.filter(ModFileInfo::missingLicense)
|
||||
.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()))
|
||||
@@ -228,10 +230,9 @@ public class ModLoader
|
||||
} catch (CompletionException e) {
|
||||
loadingStateValid = false;
|
||||
Throwable t = e.getCause();
|
||||
final List<Throwable> notModLoading = Arrays.stream(t.getSuppressed())
|
||||
.filter(obj -> !(obj instanceof ModLoadingException))
|
||||
.collect(Collectors.toList());
|
||||
if (!notModLoading.isEmpty()) {
|
||||
boolean hasNotModLoadingEx = Arrays.stream(t.getSuppressed())
|
||||
.anyMatch(obj -> !(obj instanceof ModLoadingException));
|
||||
if (hasNotModLoadingEx) {
|
||||
LOGGER.fatal("Encountered non-modloading exceptions!", e);
|
||||
statusConsumer.ifPresent(c->c.accept("ERROR DURING MOD LOADING"));
|
||||
throw e;
|
||||
@@ -257,10 +258,10 @@ public class ModLoader
|
||||
.stream()
|
||||
.map(e -> buildModContainerFromTOML(modFile, modInfoMap, e))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
if (containers.size() != modInfoMap.size()) {
|
||||
var modIds = modInfoMap.values().stream().map(IModInfo::getModId).sorted().collect(Collectors.toList());
|
||||
var containerIds = containers.stream().map(c -> c != null ? c.getModId() : "(null)").sorted().collect(Collectors.toList());
|
||||
var modIds = modInfoMap.values().stream().map(IModInfo::getModId).sorted().toList();
|
||||
var containerIds = containers.stream().map(c -> c != null ? c.getModId() : "(null)").sorted().toList();
|
||||
|
||||
LOGGER.fatal(LOADING,"File {} constructed {} mods: {}, but had {} mods specified: {}",
|
||||
modFile.getFilePath(),
|
||||
@@ -278,7 +279,7 @@ public class ModLoader
|
||||
loadingExceptions.add(new ModLoadingException(null, ModLoadingStage.CONSTRUCT, "fml.modloading.missingclasses", null, modFile.getFilePath()));
|
||||
}
|
||||
// remove errored mod containers
|
||||
return containers.stream().filter(mc -> mc.modLoadingStage != ModLoadingStage.ERROR).collect(Collectors.toList());
|
||||
return containers.stream().filter(mc -> mc.modLoadingStage != ModLoadingStage.ERROR).toList();
|
||||
}
|
||||
|
||||
private ModContainer buildModContainerFromTOML(final IModFile modFile, final Map<String, IModInfo> modInfoMap, final Map.Entry<String, ? extends IModLanguageProvider.IModLanguageLoader> idToProviderEntry) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ModLoadingContext
|
||||
@@ -50,6 +51,44 @@ public class ModLoadingContext
|
||||
getActiveContainer().registerExtensionPoint(point, extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)}.</p>
|
||||
* @param displayTest The {@link IExtensionPoint.DisplayTest} to register
|
||||
*/
|
||||
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
|
||||
getActiveContainer().registerDisplayTest(() -> displayTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest supplier with {@link #registerExtensionPoint(Class, Supplier)}.</p>
|
||||
* @param displayTest The {@link Supplier<IExtensionPoint.DisplayTest>} to register
|
||||
*/
|
||||
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
|
||||
getActiveContainer().registerDisplayTest(displayTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
|
||||
* creates the DisplayTest instance for you using the provided parameters.</p>
|
||||
* @see IExtensionPoint.DisplayTest#DisplayTest(String, BiPredicate)
|
||||
*/
|
||||
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
getActiveContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
|
||||
* creates the DisplayTest instance for you using the provided parameters.</p>
|
||||
* @see IExtensionPoint.DisplayTest#DisplayTest(Supplier, BiPredicate)
|
||||
*/
|
||||
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
getActiveContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
|
||||
}
|
||||
|
||||
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
|
||||
if (spec.isEmpty())
|
||||
{
|
||||
|
||||
@@ -12,8 +12,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ModLoadingWarning
|
||||
{
|
||||
public class ModLoadingWarning {
|
||||
/**
|
||||
* Mod Info for mod with warning
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
}
|
||||
|
||||
@@ -44,11 +44,11 @@ dependencies {
|
||||
testRuntimeOnly("org.lwjgl:lwjgl-stb::$lwjglNatives")
|
||||
}
|
||||
|
||||
test {
|
||||
tasks.named('test', Test).configure {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
jar {
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': 'net.minecraftforge.earlydisplay',
|
||||
@@ -65,7 +65,7 @@ jar {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
@@ -89,4 +89,4 @@ publishing {
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
-39
@@ -14,9 +14,7 @@ import net.minecraftforge.fml.loading.ImmediateWindowProvider;
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.glfw.GLFWImage;
|
||||
import org.lwjgl.glfw.GLFWVidMode;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
||||
@@ -30,9 +28,8 @@ import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
@@ -50,7 +47,6 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
@@ -80,7 +76,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("EARLYDISPLAY");
|
||||
private final AtomicBoolean animationTimerTrigger = new AtomicBoolean(true);
|
||||
|
||||
private ColourScheme colourScheme;
|
||||
private ColourScheme colourScheme = ColourScheme.RED;
|
||||
private ElementShader elementShader;
|
||||
|
||||
private RenderElement.DisplayContext context;
|
||||
@@ -139,13 +135,17 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
this.colourScheme = ColourScheme.BLACK;
|
||||
} else {
|
||||
try {
|
||||
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Paths.get("options.txt")));
|
||||
var options = optionLines.stream().map(l -> l.split(":")).filter(a -> a.length == 2).collect(Collectors.toMap(a -> a[0], a -> a[1]));
|
||||
var colourScheme = Boolean.parseBoolean(options.getOrDefault("darkMojangStudiosBackground", "false"));
|
||||
this.colourScheme = colourScheme ? ColourScheme.BLACK : ColourScheme.RED;
|
||||
} catch (IOException ioe) {
|
||||
// No options
|
||||
this.colourScheme = ColourScheme.RED; // default to red colourscheme
|
||||
// check the options file for the colour scheme
|
||||
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Path.of("options.txt")));
|
||||
var keyName = "darkMojangStudiosBackground:";
|
||||
for (String line : optionLines) {
|
||||
if (line.startsWith(keyName)) {
|
||||
this.colourScheme = line.startsWith("true", keyName.length()) ? ColourScheme.BLACK : ColourScheme.RED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.colourScheme = ColourScheme.RED; // fallback to red colourScheme
|
||||
}
|
||||
}
|
||||
this.maximized = parsed.has(maximizedopt) || FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_MAXIMIZED);
|
||||
@@ -229,7 +229,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
LOGGER.error("Crash during font initialization", t);
|
||||
crashElegantly("An error occurred initializing a font for rendering. "+t.getMessage());
|
||||
}
|
||||
this.elements = new ArrayList<>(Arrays.asList(
|
||||
this.elements = new ArrayList<>(List.of(
|
||||
RenderElement.anvil(font),
|
||||
RenderElement.logMessageOverlay(font),
|
||||
RenderElement.forgeVersionOverlay(font, mcVersion + "-" + forgeVersion),
|
||||
@@ -364,14 +364,15 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||
if (mcVersion != null) {
|
||||
// this emulates what we would get without early progress window
|
||||
// as vanilla never sets these, so GLFW uses the first window title
|
||||
// set them explicitly to avoid it using "FML early loading progress" as the class
|
||||
String vanillaWindowTitle = "Minecraft* " + mcVersion;
|
||||
glfwWindowHintString(GLFW_X11_CLASS_NAME, vanillaWindowTitle);
|
||||
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, vanillaWindowTitle);
|
||||
}
|
||||
|
||||
String vanillaWindowTitle = "Minecraft* ";
|
||||
if (mcVersion != null) vanillaWindowTitle += mcVersion;
|
||||
|
||||
// this emulates what we would get without early progress window
|
||||
// as vanilla never sets these, so GLFW uses the first window title
|
||||
// set them explicitly to avoid it using "FML early loading progress" as the class
|
||||
glfwWindowHintString(GLFW_X11_CLASS_NAME, vanillaWindowTitle);
|
||||
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, vanillaWindowTitle);
|
||||
|
||||
long primaryMonitor = glfwGetPrimaryMonitor();
|
||||
if (primaryMonitor == 0) {
|
||||
@@ -393,7 +394,8 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
}, 10, TimeUnit.SECONDS);
|
||||
int versidx = 0;
|
||||
var skipVersions = FMLConfig.<String>getListConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SKIP_GL_VERSIONS);
|
||||
final String[] lastGLError=new String[GL_VERSIONS.length];
|
||||
boolean showHelpLog = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_LOG_HELP_MSG);
|
||||
final String[] lastGLError = new String[GL_VERSIONS.length];
|
||||
do {
|
||||
final var glVersionToTry = GL_VERSIONS[versidx][0] + "." + GL_VERSIONS[versidx][1];
|
||||
if (skipVersions.contains(glVersionToTry)) {
|
||||
@@ -402,11 +404,23 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
continue;
|
||||
}
|
||||
LOGGER.info("Trying GL version " + glVersionToTry);
|
||||
if (showHelpLog && versidx == 0) {
|
||||
LOGGER.info("""
|
||||
If this message is the only thing at the bottom of your log before a crash, you probably have a driver issue.
|
||||
|
||||
Possible solutions:
|
||||
A) Make sure Minecraft is set to prefer high performance graphics in the OS and/or driver control panel
|
||||
B) Check for driver updates on the graphics brand's website
|
||||
C) Try reinstalling your graphics drivers
|
||||
D) If still not working after trying all of the above, ask for further help on the Forge forums or Discord
|
||||
|
||||
You can safely ignore this message if the game starts up successfully.""");
|
||||
}
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_VERSIONS[versidx][0]); // we try our versions one at a time
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_VERSIONS[versidx][1]);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
window = glfwCreateWindow(winWidth, winHeight, "Minecraft: Forge Loading...", 0L, 0L);
|
||||
window = glfwCreateWindow(winWidth, winHeight, vanillaWindowTitle, 0L, 0L);
|
||||
var erridx = versidx;
|
||||
handleLastGLFWError((error, description) -> lastGLError[erridx] = String.format("Trying %d.%d: GLFW error: [0x%X]%s", GL_VERSIONS[erridx][0], GL_VERSIONS[erridx][1], error, description));
|
||||
if (lastGLError[versidx] != null) {
|
||||
@@ -434,6 +448,9 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
this.glVersion = gotVersion;
|
||||
this.window = window;
|
||||
|
||||
if (showHelpLog)
|
||||
FMLConfig.updateConfig(FMLConfig.ConfigValue.EARLY_WINDOW_LOG_HELP_MSG, false);
|
||||
|
||||
int[] x = new int[1];
|
||||
int[] y = new int[1];
|
||||
glfwGetMonitorPos(primaryMonitor, x, y);
|
||||
@@ -451,19 +468,19 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
glfwSetWindowPos(window, (vidmode.width() - this.winWidth) / 2 + monitorX, (vidmode.height() - this.winHeight) / 2 + monitorY);
|
||||
|
||||
// Attempt setting the icon
|
||||
int[] channels = new int[1];
|
||||
try (var glfwImgBuffer = GLFWImage.create(MemoryUtil.getAllocator().malloc(GLFWImage.SIZEOF), 1)) {
|
||||
final ByteBuffer imgBuffer;
|
||||
try (GLFWImage glfwImages = GLFWImage.malloc()) {
|
||||
imgBuffer = STBHelper.loadImageFromClasspath("forge_logo.png", 20000, x, y, channels);
|
||||
glfwImgBuffer.put(glfwImages.set(x[0], y[0], imgBuffer));
|
||||
glfwSetWindowIcon(window, glfwImgBuffer);
|
||||
STBImage.stbi_image_free(imgBuffer);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
System.err.println("Failed to load forge logo");
|
||||
}
|
||||
handleLastGLFWError((error, description) -> LOGGER.debug(String.format("Suppressing GLFW icon error: [0x%X]%s", error, description)));
|
||||
// int[] channels = new int[1];
|
||||
// try (var glfwImgBuffer = GLFWImage.create(MemoryUtil.getAllocator().malloc(GLFWImage.SIZEOF), 1)) {
|
||||
// final ByteBuffer imgBuffer;
|
||||
// try (GLFWImage glfwImages = GLFWImage.malloc()) {
|
||||
// imgBuffer = STBHelper.loadImageFromClasspath("forge_logo.png", 20000, x, y, channels);
|
||||
// glfwImgBuffer.put(glfwImages.set(x[0], y[0], imgBuffer));
|
||||
// glfwSetWindowIcon(window, glfwImgBuffer);
|
||||
// STBImage.stbi_image_free(imgBuffer);
|
||||
// }
|
||||
// } catch (NullPointerException e) {
|
||||
// System.err.println("Failed to load forge logo");
|
||||
// }
|
||||
// handleLastGLFWError((error, description) -> LOGGER.debug(String.format("Suppressing GLFW icon error: [0x%X]%s", error, description)));
|
||||
|
||||
glfwSetFramebufferSizeCallback(window, this::fbResize);
|
||||
glfwSetWindowPosCallback(window, this::winMove);
|
||||
@@ -598,8 +615,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
var fm = layer.findModule("forge").orElseThrow();
|
||||
getClass().getModule().addReads(fm);
|
||||
var clz = FMLLoader.getGameLayer().findModule("forge").map(l->Class.forName(l, "net.minecraftforge.client.loading.ForgeLoadingOverlay")).orElseThrow();
|
||||
var methods = Arrays.stream(clz.getMethods()).filter(m-> Modifier.isStatic(m.getModifiers())).collect(Collectors.toMap(Method::getName, Function.identity()));
|
||||
loadingOverlay = methods.get("newInstance");
|
||||
loadingOverlay = Arrays.stream(clz.getDeclaredMethods()).filter(m-> Modifier.isStatic(m.getModifiers()) && m.getName().equals("newInstance")).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public int getFramebufferTextureId() {
|
||||
|
||||
+15
-5
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.fml.earlydisplay;
|
||||
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
import net.minecraftforge.fml.loading.FMLConfig;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
@@ -13,28 +14,37 @@ import java.lang.management.MemoryUsage;
|
||||
|
||||
public class PerformanceInfo {
|
||||
|
||||
private final boolean showCPUUsage;
|
||||
private final OperatingSystemMXBean osBean;
|
||||
private final MemoryMXBean memoryBean;
|
||||
float memory;
|
||||
|
||||
private float memory;
|
||||
private String text;
|
||||
|
||||
PerformanceInfo() {
|
||||
osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
|
||||
showCPUUsage = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SHOW_CPU);
|
||||
osBean = showCPUUsage ? ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class) : null;
|
||||
memoryBean = ManagementFactory.getMemoryMXBean();
|
||||
}
|
||||
|
||||
void update() {
|
||||
final MemoryUsage heapusage = memoryBean.getHeapMemoryUsage();
|
||||
memory = (float) heapusage.getUsed() / heapusage.getMax();
|
||||
|
||||
if (!showCPUUsage) {
|
||||
text = "Heap: %d/%d MB (%.1f%%) OffHeap: %d MB".formatted(heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20);
|
||||
return;
|
||||
}
|
||||
|
||||
var cpuLoad = osBean.getProcessCpuLoad();
|
||||
String cpuText;
|
||||
if (cpuLoad == -1) {
|
||||
cpuText = String.format("*CPU: %.1f%%", osBean.getCpuLoad() * 100f);
|
||||
cpuText = "*CPU: %.1f%%".formatted(osBean.getCpuLoad() * 100f);
|
||||
} else {
|
||||
cpuText = String.format("CPU: %.1f%%", cpuLoad * 100f);
|
||||
cpuText = "CPU: %.1f%%".formatted(cpuLoad * 100f);
|
||||
}
|
||||
|
||||
text = String.format("Heap: %d/%d MB (%.1f%%) OffHeap: %d MB %s", heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20, cpuText);
|
||||
text = "Heap: %d/%d MB (%.1f%%) OffHeap: %d MB %s".formatted(heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20, cpuText);
|
||||
}
|
||||
|
||||
String text() {
|
||||
|
||||
+8
-2
@@ -34,11 +34,14 @@ public class RenderElement {
|
||||
};
|
||||
}
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface TextureRenderer {
|
||||
void accept(SimpleBufferBuilder bb, DisplayContext context, int[] size, int frame);
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface Initializer extends Supplier<Renderer> {}
|
||||
|
||||
@FunctionalInterface
|
||||
interface TextGenerator {
|
||||
void accept(SimpleBufferBuilder bb, SimpleFont fh, DisplayContext ctx);
|
||||
}
|
||||
@@ -201,14 +204,17 @@ public class RenderElement {
|
||||
bar.then(label).accept(buffer, context, frameNumber);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ColourFunction {
|
||||
int colour(int frame);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ProgressDisplay {
|
||||
float[] progress(int frame);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface BarPosition {
|
||||
int[] location(DisplayContext context);
|
||||
}
|
||||
@@ -280,7 +286,7 @@ public class RenderElement {
|
||||
if (num < min) {
|
||||
return min;
|
||||
} else {
|
||||
return num > max ? max : num;
|
||||
return Math.min(num, max);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +294,7 @@ public class RenderElement {
|
||||
if (num < min) {
|
||||
return min;
|
||||
} else {
|
||||
return num > max ? max : num;
|
||||
return Math.min(num, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ tasks.named('jar', Jar).configure {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ publishing {
|
||||
tasks.register('writeForgeVersionJson') {
|
||||
doLast {
|
||||
file('src/main/resources/forge_version.json').json = [
|
||||
'forge': FORGE_VERSION,
|
||||
'mc': MC_VERSION,
|
||||
'mcp': MCP_VERSION
|
||||
] as LinkedHashMap
|
||||
forge: FORGE_VERSION,
|
||||
mc: MC_VERSION,
|
||||
mcp: MCP_VERSION
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class BackgroundWaiter {
|
||||
private static ExecutorService runner = Executors.newSingleThreadExecutor();
|
||||
private static final ExecutorService runner = Executors.newSingleThreadExecutor();
|
||||
|
||||
public static void runAndTick(Runnable r, Runnable tick) {
|
||||
ImmediateWindowHandler.updateProgress("Loading bootstrap resources");
|
||||
|
||||
@@ -36,7 +36,10 @@ public class FMLConfig
|
||||
EARLY_WINDOW_FBSCALE("earlyWindowFBScale", 1, "Early window framebuffer scale"),
|
||||
EARLY_WINDOW_MAXIMIZED("earlyWindowMaximized", Boolean.FALSE, "Early window starts maximized"),
|
||||
EARLY_WINDOW_SKIP_GL_VERSIONS("earlyWindowSkipGLVersions", List.of(), "Skip specific GL versions, may help with buggy graphics card drivers"),
|
||||
EARLY_WINDOW_SQUIR("earlyWindowSquir", Boolean.FALSE, "Squir?")
|
||||
EARLY_WINDOW_SQUIR("earlyWindowSquir", Boolean.FALSE, "Squir?"),
|
||||
EARLY_WINDOW_SHOW_CPU("earlyWindowShowCPU", Boolean.FALSE, "Whether to show CPU usage stats in early window"),
|
||||
EARLY_WINDOW_LOG_HELP_MSG("earlyWindowLogHelpMessage", Boolean.TRUE, "Whether to log a help message on first attempt, to aid troubleshooting. This setting should automatically disable itself after a successful launch"),
|
||||
DETECT_NON_FORGE_MODS_TOML("detectNonForgeModsToml", Boolean.TRUE, "Attempt to detect non-Forge mods from their mods.toml to show a friendlier error message. This is a best-effort feature - disable if it causes issues."),
|
||||
;
|
||||
|
||||
private final String entry;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class FMLLoader {
|
||||
private static LoadingModList loadingModList;
|
||||
private static RuntimeDistCleaner runtimeDistCleaner;
|
||||
private static Path gamePath;
|
||||
private static VersionInfo versionInfo = VersionInfo.detect();
|
||||
private static final VersionInfo versionInfo = VersionInfo.detect();
|
||||
private static String launchHandlerName;
|
||||
private static CommonLaunchHandler commonLaunchHandler;
|
||||
public static Runnable progressWindowTick;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class LibraryFinder {
|
||||
private static Path libsPath;
|
||||
static Path findLibsPath() {
|
||||
if (libsPath == null) {
|
||||
libsPath = Path.of(System.getProperty("libraryDirectory", "libraries"));
|
||||
if (!Files.isDirectory(libsPath))
|
||||
throw new IllegalStateException("Library directory: `" + libsPath + "` does not exist. Set it via the `libraryDirectory` system property.");
|
||||
}
|
||||
return libsPath;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
+14
@@ -10,6 +10,8 @@ import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import cpw.mods.modlauncher.api.NamedPath;
|
||||
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -20,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Set<String> SERVICES = Set.of(
|
||||
@@ -76,4 +79,15 @@ public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService
|
||||
.filter(SERVICES::contains)
|
||||
.forEach(s -> found.add(new NamedPath(s, path)));
|
||||
}
|
||||
|
||||
public static boolean isServiceProvider(Path path) {
|
||||
var jar = SecureJar.from(path);
|
||||
|
||||
for (var providers : jar.moduleDataProvider().descriptor().provides()) {
|
||||
if (SERVICES.contains(providers.service()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,9 @@ public class ModSorter
|
||||
ms.buildUniqueList();
|
||||
} catch (EarlyLoadingException e) {
|
||||
// We cannot build any list with duped mods. We have to abort immediately and report it
|
||||
// Note this will never actually throw an error because the duplicate checks are done in ModDiscovererer before we get to this phase
|
||||
// So all this is really doing is wasting time.
|
||||
// But i'm leaving it here until I rewrite all of cpw's mod loading code because its such a clusterfuck.
|
||||
return LoadingModList.of(ms.systemMods, ms.systemMods.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), e);
|
||||
}
|
||||
// try and validate dependencies
|
||||
|
||||
@@ -25,7 +25,7 @@ public record VersionInfo(String forgeVersion, String mcVersion, String mcpVersi
|
||||
/*==========================================================================*
|
||||
* INTERNAL SHIT *
|
||||
*==========================================================================*/
|
||||
private static Gson GSON = new GsonBuilder().create();
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
private static <T> T readJson(String path, Class<T> type) {
|
||||
try (var is = VersionInfo.class.getResourceAsStream(path)) {
|
||||
if (is == null)
|
||||
|
||||
+9
-4
@@ -50,6 +50,10 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
if (sj.moduleDataProvider().findFile(MODS_TOML).isPresent()) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MODS_TOML, type, path);
|
||||
mod = new ModFile(sj, this, ModFileParser::modsTomlParser);
|
||||
if (ModFileInfo.DETECT_NON_FORGE_MODS_TOML && mod.getModFileInfo().getFileProperties().containsKey(ModFileInfo.NOT_A_FORGE_MOD_PROP)) {
|
||||
LOGGER.error(LogMarkers.SCAN, "Unable to load file \"{}\" because its mods.toml is requesting an invalid javafml loaderVersion (use \"*\" if you want to allow all versions) and is missing a forge modId dependency declaration (see the sample mods.toml in the MDK).", path);
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("File \"%s\" is not a Forge mod and cannot be loaded. Look for a Forge version of this mod or consider alternative mods.".formatted(mod.getFileName())));
|
||||
}
|
||||
} else if (type != null) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", JarFile.MANIFEST_NAME, type, path);
|
||||
mod = new ModFile(sj, this, this::manifestParser, type);
|
||||
@@ -109,20 +113,20 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
Files.walk(root)
|
||||
try (var files = Files.walk(root)) {
|
||||
files
|
||||
.filter(p -> p.toString().endsWith(".class"))
|
||||
.forEach(consumer);
|
||||
|
||||
file.setSecurityStatus(holder.value);
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
LOGGER.debug(LogMarkers.SCAN, "Scan finished: {}", file);
|
||||
}
|
||||
|
||||
private static class Holder<T> {
|
||||
private static final class Holder<T> {
|
||||
T value;
|
||||
}
|
||||
|
||||
@@ -132,6 +136,7 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
@Override public List<IModInfo> getMods() { return Collections.emptyList(); }
|
||||
@Override public List<LanguageSpec> requiredLanguageLoaders() { return Collections.emptyList(); }
|
||||
@Override public boolean showAsResourcePack() { return false; }
|
||||
@Override public boolean showAsDataPack() { return false; }
|
||||
@Override public Map<String, Object> getFileProperties() { return Collections.emptyMap(); }
|
||||
@Override public String getLicense() { return license; }
|
||||
@Override public IModFile getFile() { return mod; }
|
||||
|
||||
+6
-2
@@ -8,6 +8,7 @@ package net.minecraftforge.fml.loading.moddiscovery;
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer;
|
||||
import net.minecraftforge.forgespi.locating.IModLocator;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -71,8 +72,11 @@ public class ClasspathLocator extends AbstractModProvider implements IModLocator
|
||||
}
|
||||
|
||||
var ret = new ArrayList<ModFileOrException>();
|
||||
for (var path : claimed)
|
||||
ret.add(createMod(path));
|
||||
for (var path : claimed) {
|
||||
// Filter out anything found by the ServiceLoader
|
||||
if (!ModDirTransformerDiscoverer.isServiceProvider(path))
|
||||
ret.add(createMod(path));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -12,10 +12,12 @@ import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.*;
|
||||
|
||||
// TODO: [FML][Loader] By the time this is reached, most stuff this checks for is already filtered out - needs fixing.
|
||||
public enum InvalidModIdentifier {
|
||||
|
||||
OLDFORGE(filePresent("mcmod.info")),
|
||||
@@ -23,9 +25,9 @@ public enum InvalidModIdentifier {
|
||||
LITELOADER(filePresent("litemod.json")),
|
||||
OPTIFINE(filePresent("optifine/Installer.class")),
|
||||
BUKKIT(filePresent("plugin.yml")),
|
||||
INVALIDZIP((f,zf) -> !zf.isPresent());
|
||||
INVALIDZIP((f,zf) -> zf.isEmpty()); // note: only this one INVALIDZIP check is ran until the todo on this class is fixed
|
||||
|
||||
private BiPredicate<Path, Optional<ZipFile>> ident;
|
||||
private final BiPredicate<Path, Optional<ZipFile>> ident;
|
||||
|
||||
InvalidModIdentifier(BiPredicate<Path, Optional<ZipFile>> identifier)
|
||||
{
|
||||
@@ -40,7 +42,7 @@ public enum InvalidModIdentifier {
|
||||
public static Optional<String> identifyJarProblem(Path path)
|
||||
{
|
||||
Optional<ZipFile> zfo = optionalFromException(() -> new ZipFile(path.toFile()));
|
||||
Optional<String> result = Arrays.stream(values()).
|
||||
Optional<String> result = Stream.of(INVALIDZIP).
|
||||
filter(i -> i.ident.test(path, zfo)).
|
||||
map(InvalidModIdentifier::getReason).
|
||||
findAny();
|
||||
|
||||
+26
-3
@@ -12,6 +12,7 @@ import cpw.mods.modlauncher.Launcher;
|
||||
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
|
||||
import net.minecraftforge.fml.loading.EarlyLoadingException;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.ImmediateWindowHandler;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.UniqueModListBuilder;
|
||||
@@ -22,6 +23,7 @@ import net.minecraftforge.forgespi.locating.IDependencyLocator;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.forgespi.locating.IModLocator;
|
||||
|
||||
import net.minecraftforge.forgespi.locating.ModFileLoadingException;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -70,6 +72,8 @@ public class ModDiscoverer {
|
||||
List<EarlyLoadingException.ExceptionData> discoveryErrorData = new ArrayList<>();
|
||||
boolean successfullyLoadedMods = true;
|
||||
List<IModFileInfo> brokenFiles = new ArrayList<>();
|
||||
List<ModFileLoadingException> modFileLoadingExceptions = new ArrayList<>();
|
||||
boolean distIsDedicatedServer = FMLLoader.getDist().isDedicatedServer();
|
||||
ImmediateWindowHandler.updateProgress("Discovering mod files");
|
||||
//Loop all mod locators to get the prime mods to load from.
|
||||
for (IModLocator locator : modLocatorList) {
|
||||
@@ -80,7 +84,17 @@ public class ModDiscoverer {
|
||||
var exceptions = candidates.stream().map(IModLocator.ModFileOrException::ex).filter(Objects::nonNull).toList();
|
||||
if (!exceptions.isEmpty()) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Locator {} found {} invalid mod files", locator, exceptions.size());
|
||||
brokenFiles.addAll(exceptions.stream().map(e->e instanceof InvalidModFileException ime ? ime.getBrokenFile() : null).filter(Objects::nonNull).toList());
|
||||
for (ModFileLoadingException ex : exceptions) {
|
||||
// pipe exception messages through the discoveryErrorData to avoid swallowing some exceptions and improve error messages
|
||||
// (no longer a generic "Invalid mod file" for all InvalidModExceptions - it actually shows the exception message now)
|
||||
if (ex instanceof InvalidModFileException invalidModFileEx) {
|
||||
var modInfo = invalidModFileEx.getBrokenFile();
|
||||
brokenFiles.add(modInfo);
|
||||
discoveryErrorData.add(new EarlyLoadingException.ExceptionData(ex.getMessage(), modInfo));
|
||||
} else {
|
||||
discoveryErrorData.add(new EarlyLoadingException.ExceptionData(ex.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
var locatedFiles = candidates.stream().map(IModLocator.ModFileOrException::file).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
|
||||
@@ -88,8 +102,17 @@ public class ModDiscoverer {
|
||||
if (!badModFiles.isEmpty()) {
|
||||
LOGGER.error(LogMarkers.SCAN, "Locator {} returned {} files which is are not ModFile instances! They will be skipped!", locator, badModFiles.size());
|
||||
brokenFiles.addAll(badModFiles.stream().map(IModFile::getModFileInfo).toList());
|
||||
locatedFiles.removeAll(badModFiles);
|
||||
}
|
||||
locatedFiles.removeAll(badModFiles);
|
||||
|
||||
if (distIsDedicatedServer) {
|
||||
var clientOnlyModFiles = locatedFiles.stream().filter(file -> file.getModFileInfo().isClientSideOnly()).toList();
|
||||
if (!clientOnlyModFiles.isEmpty()) {
|
||||
LOGGER.warn(LogMarkers.SCAN, "Locator {} returned {} files which are client-side-only mods, but we're on a dedicated server. They will be skipped!", locator, clientOnlyModFiles.size());
|
||||
locatedFiles.removeAll(clientOnlyModFiles);
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.debug(LogMarkers.SCAN, "Locator {} found {} valid mod files", locator, locatedFiles.size());
|
||||
handleLocatedFiles(loadedFiles, locatedFiles);
|
||||
} catch (InvalidModFileException imfe) {
|
||||
@@ -162,7 +185,7 @@ public class ModDiscoverer {
|
||||
|
||||
//Validate the loading. With a deduplicated list, we can now successfully process the artifacts and load
|
||||
//transformer plugins.
|
||||
var validator = new ModValidator(modFilesMap, brokenFiles, discoveryErrorData);
|
||||
var validator = new ModValidator(modFilesMap, brokenFiles, discoveryErrorData, modFileLoadingExceptions);
|
||||
validator.stage1Validation();
|
||||
return validator;
|
||||
}
|
||||
|
||||
+55
-5
@@ -8,12 +8,14 @@ package net.minecraftforge.fml.loading.moddiscovery;
|
||||
import com.google.common.base.Strings;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import net.minecraftforge.fml.loading.FMLConfig;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.StringUtils;
|
||||
import net.minecraftforge.forgespi.language.IConfigurable;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.slf4j.Logger;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.net.URL;
|
||||
@@ -29,6 +31,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -40,11 +43,22 @@ import java.util.stream.Stream;
|
||||
public class ModFileInfo implements IModFileInfo, IConfigurable
|
||||
{
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final String MAYBE_NOT_JAVAFML_VER = "[2,)";
|
||||
private static final String JAVAFML = "javafml";
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static final String NOT_A_FORGE_MOD_PROP = "__FORGE__not_a_forge_mod";
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static final boolean DETECT_NON_FORGE_MODS_TOML = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.DETECT_NON_FORGE_MODS_TOML);
|
||||
|
||||
private final IConfigurable config;
|
||||
private final ModFile modFile;
|
||||
private final URL issueURL;
|
||||
private final List<LanguageSpec> languageSpecs;
|
||||
private final boolean showAsResourcePack;
|
||||
private final boolean clientSideOnly;
|
||||
private final boolean showAsDataPack;
|
||||
private final List<IModInfo> mods;
|
||||
private final Map<String,Object> properties;
|
||||
private final String license;
|
||||
@@ -59,23 +73,47 @@ public class ModFileInfo implements IModFileInfo, IConfigurable
|
||||
var modLoader = config.<String>getConfigElement("modLoader")
|
||||
.orElseThrow(()->new InvalidModFileException("Missing ModLoader in file", this));
|
||||
// as is modloader version
|
||||
var modLoaderVersion = config.<String>getConfigElement("loaderVersion")
|
||||
.map(MavenVersionAdapter::createFromVersionSpec)
|
||||
var modLoaderVerStr = config.<String>getConfigElement("loaderVersion")
|
||||
.orElseThrow(()->new InvalidModFileException("Missing ModLoader version in file", this));
|
||||
var modLoaderVersion = MavenVersionAdapter.createFromVersionSpec(modLoaderVerStr);
|
||||
this.languageSpecs = new ArrayList<>(List.of(new LanguageSpec(modLoader, modLoaderVersion)));
|
||||
|
||||
// if true, this might not be a Forge mod
|
||||
boolean maybeNotAForgeMod = DETECT_NON_FORGE_MODS_TOML
|
||||
&& modLoader.equals(JAVAFML)
|
||||
&& modLoaderVersion.hasRestrictions() // if loaderVersion is not "*"
|
||||
&& modLoaderVerStr.equals(MAYBE_NOT_JAVAFML_VER); // if loaderVersion is exactly "[2,)"
|
||||
|
||||
// the remaining properties are optional with sensible defaults
|
||||
this.license = config.<String>getConfigElement("license")
|
||||
.orElse("");
|
||||
this.showAsResourcePack = config.<Boolean>getConfigElement("showAsResourcePack")
|
||||
.orElse(false);
|
||||
this.clientSideOnly = config.<Boolean>getConfigElement("clientSideOnly")
|
||||
.orElse(false);
|
||||
if (this.clientSideOnly) {
|
||||
// if clientSideOnly, then this is definitely a Forge mod
|
||||
maybeNotAForgeMod = false;
|
||||
}
|
||||
this.showAsDataPack = config.<Boolean>getConfigElement("showAsDataPack")
|
||||
.orElse(false);
|
||||
this.usesServices = config.<List<String>>getConfigElement("services")
|
||||
.orElse(List.of());
|
||||
this.properties = config.<Map<String, Object>>getConfigElement("properties")
|
||||
.orElse(Collections.emptyMap());
|
||||
this.modFile.setFileProperties(this.properties);
|
||||
this.issueURL = config.<String>getConfigElement("issueTrackerURL")
|
||||
.map(StringUtils::toURL)
|
||||
.orElse(null);
|
||||
|
||||
if (maybeNotAForgeMod) {
|
||||
// mark this file as not a Forge mod. Note: this marker may be removed later based on the mod dependencies
|
||||
this.properties = config.<Map<String, Object>>getConfigElement("properties")
|
||||
.orElse(new LinkedHashMap<>());
|
||||
this.properties.put(NOT_A_FORGE_MOD_PROP, true);
|
||||
} else {
|
||||
this.properties = config.<Map<String, Object>>getConfigElement("properties")
|
||||
.orElse(Collections.emptyMap());
|
||||
}
|
||||
this.modFile.setFileProperties(this.properties);
|
||||
|
||||
final List<? extends IConfigurable> modConfigs = config.getConfigList("mods");
|
||||
if (modConfigs.isEmpty())
|
||||
{
|
||||
@@ -126,6 +164,18 @@ public class ModFileInfo implements IModFileInfo, IConfigurable
|
||||
return this.showAsResourcePack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClientSideOnly()
|
||||
{
|
||||
return this.clientSideOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showAsDataPack()
|
||||
{
|
||||
return this.showAsDataPack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Optional<T> getConfigElement(final String... key)
|
||||
{
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.forgespi.locating.ModFileFactory;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -30,7 +31,7 @@ public class ModFileParser {
|
||||
return parser.build(modFile);
|
||||
}
|
||||
|
||||
public static IModFileInfo modsTomlParser(final IModFile imodFile) {
|
||||
public static @Nullable IModFileInfo modsTomlParser(final IModFile imodFile) {
|
||||
ModFile modFile = (ModFile) imodFile;
|
||||
LOGGER.debug(LogMarkers.LOADING,"Considering mod file candidate {}", modFile.getFilePath());
|
||||
final Path modsjson = modFile.findResource("META-INF", "mods.toml");
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@@ -213,8 +214,23 @@ public class ModInfo implements IModInfo, IConfigurable {
|
||||
this.owner = owner;
|
||||
this.modId = config.<String>getConfigElement("modId")
|
||||
.orElseThrow(()->new InvalidModFileException("Missing required field modid in dependency", getOwningFile()));
|
||||
this.mandatory = config.<Boolean>getConfigElement("mandatory")
|
||||
.orElseThrow(()->new InvalidModFileException("Missing required field mandatory in dependency", getOwningFile()));
|
||||
if (ModFileInfo.DETECT_NON_FORGE_MODS_TOML && this.modId.equals("forge")) {
|
||||
var fileProps = owner.getOwningFile().getFileProperties();
|
||||
// Checking containsKey to avoid a possible exception if the property is not present (due to Collections.emptyMap())
|
||||
if (!fileProps.isEmpty() && fileProps.containsKey(ModFileInfo.NOT_A_FORGE_MOD_PROP)) {
|
||||
// if the mod has a dependency on Forge, but we thought it wasn't a Forge mod earlier, we were wrong
|
||||
// so remove the flag.
|
||||
fileProps.remove(ModFileInfo.NOT_A_FORGE_MOD_PROP);
|
||||
}
|
||||
}
|
||||
var mandatory = config.<Boolean>getConfigElement("mandatory");
|
||||
if (mandatory.isPresent()) {
|
||||
this.mandatory = mandatory.get();
|
||||
} else if (ModFileInfo.DETECT_NON_FORGE_MODS_TOML && owner.getOwningFile().getFileProperties().containsKey(ModFileInfo.NOT_A_FORGE_MOD_PROP)) {
|
||||
this.mandatory = true;
|
||||
} else {
|
||||
throw new InvalidModFileException("Missing required field mandatory in dependency", getOwningFile());
|
||||
}
|
||||
this.versionRange = config.<String>getConfigElement("versionRange")
|
||||
.map(MavenVersionAdapter::createFromVersionSpec)
|
||||
.orElse(UNBOUNDED);
|
||||
|
||||
+41
-11
@@ -6,11 +6,18 @@
|
||||
package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||
import cpw.mods.modlauncher.api.ITransformationService;
|
||||
import net.minecraftforge.fml.loading.*;
|
||||
import net.minecraftforge.fml.loading.EarlyLoadingException;
|
||||
import net.minecraftforge.fml.loading.ImmediateWindowHandler;
|
||||
import net.minecraftforge.fml.loading.LoadingModList;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.ModSorter;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.forgespi.locating.ModFileLoadingException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -18,25 +25,30 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ModValidator {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
//private final Map<IModFile.Type, List<ModFile>> modFiles;
|
||||
private final List<ModFile> candidatePlugins;
|
||||
private final List<ModFile> candidateMods;
|
||||
private final List<ModFile> gameLibraries;
|
||||
private LoadingModList loadingModList;
|
||||
private List<IModFile> brokenFiles;
|
||||
private final List<IModFile> brokenFiles = new ArrayList<>();
|
||||
private final List<EarlyLoadingException.ExceptionData> discoveryErrorData;
|
||||
private final List<ModFileLoadingException> modFileLoadingExceptions;
|
||||
|
||||
public ModValidator(final Map<IModFile.Type, List<ModFile>> modFiles, final List<IModFileInfo> brokenFiles, final List<EarlyLoadingException.ExceptionData> discoveryErrorData) {
|
||||
//this.modFiles = modFiles;
|
||||
public ModValidator(Map<IModFile.Type, List<ModFile>> modFiles, List<IModFileInfo> brokenFiles, List<EarlyLoadingException.ExceptionData> discoveryErrorData, List<ModFileLoadingException> modFileLoadingExceptions) {
|
||||
this.candidateMods = lst(modFiles.get(IModFile.Type.MOD));
|
||||
this.candidateMods.addAll(lst(modFiles.get(IModFile.Type.GAMELIBRARY)));
|
||||
this.gameLibraries = lst(modFiles.get(IModFile.Type.GAMELIBRARY));
|
||||
this.candidateMods.addAll(this.gameLibraries);
|
||||
this.candidatePlugins = lst(modFiles.get(IModFile.Type.LANGPROVIDER));
|
||||
this.candidatePlugins.addAll(lst(modFiles.get(IModFile.Type.LIBRARY)));
|
||||
this.discoveryErrorData = discoveryErrorData;
|
||||
this.brokenFiles = brokenFiles.stream().map(IModFileInfo::getFile).collect(Collectors.toList()); // mutable list
|
||||
this.brokenFiles.addAll(brokenFiles.stream().map(IModFileInfo::getFile).toList());
|
||||
this.modFileLoadingExceptions = modFileLoadingExceptions;
|
||||
}
|
||||
|
||||
public ModValidator(Map<IModFile.Type, List<ModFile>> modFiles, List<IModFileInfo> brokenFiles, List<EarlyLoadingException.ExceptionData> discoveryErrorData) {
|
||||
this(modFiles, brokenFiles, discoveryErrorData, List.of());
|
||||
}
|
||||
|
||||
private static List<ModFile> lst(List<ModFile> files) {
|
||||
@@ -54,8 +66,7 @@ public class ModValidator {
|
||||
@NotNull
|
||||
private List<ModFile> validateFiles(final List<ModFile> mods) {
|
||||
final List<ModFile> brokenFiles = new ArrayList<>();
|
||||
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext();) {
|
||||
ModFile modFile = iterator.next();
|
||||
if (!modFile.getProvider().isValid(modFile) || !modFile.identifyMods()) {
|
||||
LOGGER.warn(LogMarkers.SCAN, "File {} has been ignored - it is invalid", modFile.getFilePath());
|
||||
@@ -71,7 +82,26 @@ public class ModValidator {
|
||||
}
|
||||
|
||||
public ITransformationService.Resource getModResources() {
|
||||
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, this.candidateMods.stream().map(IModFile::getSecureJar).toList());
|
||||
var mods = new ArrayList<SecureJar>();
|
||||
// Add only the valid mods that we will be attempting to load.
|
||||
// If any detectable error happens during the sorting process {missing deps, duplicates,
|
||||
// This helps prevent coremods/mixins from screwing up us displaying the error screens that the sorting/validation is trying to display.
|
||||
// This won't fix them all as they are still loaded and will still apply but it might help
|
||||
for (var info : this.loadingModList.getModFiles())
|
||||
mods.add(info.getFile().getSecureJar());
|
||||
|
||||
// Add any game libraries, this *may* be duplicates, depending on the state of the sorting. But until I get around to re-writing
|
||||
// that clusterfuck of a system, have this simple de-duplication. Order of resource is important, but i'm unsure if duplication is
|
||||
// so might as well waste a few cycles on checking. Still faster then converting from a set to a list.
|
||||
// Ideally we would explicitly list out which mods to load {forge and MC being the only ones} but some coremods could require extra things.
|
||||
// So try game libraries as well
|
||||
for (var lib : this.gameLibraries) {
|
||||
var jar = lib.getSecureJar();
|
||||
if (!mods.contains(jar))
|
||||
mods.add(jar);
|
||||
}
|
||||
|
||||
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, mods);
|
||||
}
|
||||
|
||||
private List<EarlyLoadingException.ExceptionData> validateLanguages() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public final class ProgressMeter {
|
||||
private final String name;
|
||||
private final int steps;
|
||||
private AtomicInteger current;
|
||||
private final AtomicInteger current;
|
||||
private Message label;
|
||||
|
||||
public ProgressMeter(String name, int steps, int current, Message label) {
|
||||
|
||||
+21
@@ -19,6 +19,7 @@ import org.slf4j.Logger;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -89,4 +90,24 @@ public abstract class CommonLaunchHandler implements ILaunchHandlerService {
|
||||
if (mtd == null) throw new IllegalStateException("Class " + target + " in module " + module + " does not have a main(String[]) method");
|
||||
mtd.invoke(null, (Object)arguments);
|
||||
}
|
||||
|
||||
protected static Path getPathFromResource(String resource) {
|
||||
return getPathFromResource(resource, ForgeDevLaunchHandler.class.getClassLoader());
|
||||
}
|
||||
|
||||
protected static Path getPathFromResource(String resource, ClassLoader cl) {
|
||||
var url = cl.getResource(resource);
|
||||
if (url == null)
|
||||
throw new IllegalStateException("Could not find " + resource + " in classloader " + cl);
|
||||
|
||||
var str = url.toString();
|
||||
int len = resource.length();
|
||||
if ("jar".equalsIgnoreCase(url.getProtocol())) {
|
||||
str = url.getFile();
|
||||
len += 2;
|
||||
}
|
||||
str = str.substring(0, str.length() - len);
|
||||
var path = Paths.get(URI.create(str));
|
||||
return path;
|
||||
}
|
||||
}
|
||||
-19
@@ -4,9 +4,7 @@
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@@ -35,23 +33,6 @@ abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
return List.of(filtered);
|
||||
}
|
||||
|
||||
static Path getPathFromResource(String resource) {
|
||||
var cl = ForgeDevLaunchHandler.class.getClassLoader();
|
||||
var url = cl.getResource(resource);
|
||||
if (url == null)
|
||||
throw new IllegalStateException("Could not find " + resource + " in classloader " + cl);
|
||||
|
||||
var str = url.toString();
|
||||
int len = resource.length();
|
||||
if ("jar".equalsIgnoreCase(url.getProtocol())) {
|
||||
str = url.getFile();
|
||||
len += 2;
|
||||
}
|
||||
str = str.substring(0, str.length() - len);
|
||||
var path = Paths.get(URI.create(str));
|
||||
return path;
|
||||
}
|
||||
|
||||
public static class Client extends ForgeDevLaunchHandler {
|
||||
public Client() {
|
||||
super(CLIENT);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -71,7 +76,7 @@ public class ForgeDevLocator extends AbstractModProvider implements IModLocator
|
||||
if (!isTest)
|
||||
return ret;
|
||||
|
||||
var test = ForgeDevLaunchHandler.getPathFromResource("net/minecraftforge/test/BaseTestMod.class");
|
||||
var test = ForgeDevLaunchHandler.getPathFromResource("net/minecraftforge/test/BaseTestMod.class", ClassLoader.getSystemClassLoader());
|
||||
// Explode our test mods into a framework that treats them all as separate jars.
|
||||
var tests = explodeTestMods(test);
|
||||
ret.addAll(tests);
|
||||
|
||||
+10
-10
@@ -9,9 +9,6 @@ import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LibraryFinder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class ForgeProdLaunchHandler extends CommonLaunchHandler {
|
||||
protected ForgeProdLaunchHandler(LaunchType type) {
|
||||
@@ -21,22 +18,25 @@ abstract class ForgeProdLaunchHandler extends CommonLaunchHandler {
|
||||
@Override public String getNaming() { return "srg"; }
|
||||
@Override public boolean isProduction() { return true; }
|
||||
|
||||
@Override
|
||||
public List<Path> getMinecraftPaths() {
|
||||
var vers = FMLLoader.versionInfo();
|
||||
var mc = LibraryFinder.findPathForMaven(vers.forgeGroup(), "forge", "", this.type.name(), vers.mcAndForgeVersion());
|
||||
return List.of(mc);
|
||||
}
|
||||
|
||||
public static class Client extends ForgeProdLaunchHandler {
|
||||
public Client() {
|
||||
super(CLIENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Path> getMinecraftPaths() {
|
||||
return List.of(getPathFromResource("net/minecraft/client/Minecraft.class"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Server extends ForgeProdLaunchHandler {
|
||||
public Server() {
|
||||
super(SERVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Path> getMinecraftPaths() {
|
||||
return List.of(getPathFromResource("net/minecraft/server/MinecraftServer.class"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) Forge Development LLC and contributors
|
||||
SPDX-License-Identifier: LGPL-2.1-only
|
||||
-->
|
||||
|
||||
<Configuration status="warn" packages="net.minecrell.terminalconsole,net.minecrell.terminalconsole.util,com.mojang.util,cpw.mods.modlauncher.log,net.minecraftforge.fml.loading.log4j" shutdownHook="disable">
|
||||
<filters>
|
||||
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
|
||||
|
||||
+4
-3
@@ -2,10 +2,11 @@
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
org.gradle.parallel=true
|
||||
|
||||
JAVA_VERSION=17
|
||||
MC_VERSION=1.20.2
|
||||
MC_VERSION=1.20.4
|
||||
MC_NEXT_VERSION=1.21
|
||||
MCP_VERSION=20230921.100330
|
||||
MCP_VERSION=20231207.112700
|
||||
MAPPING_CHANNEL=official
|
||||
MAPPING_VERSION=1.20.2
|
||||
MAPPING_VERSION=1.20.4
|
||||
@@ -3,7 +3,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ tasks.named('jar', Jar).configure {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
@@ -61,4 +61,4 @@ publishing {
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ tasks.named('jar', Jar).configure {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
@@ -62,4 +62,4 @@ publishing {
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ tasks.named('jar', Jar).configure {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
}
|
||||
|
||||
@@ -61,4 +61,4 @@ publishing {
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,9 @@ loaderVersion="${loader_version_range}" #mandatory This is typically bumped ever
|
||||
license="${mod_license}"
|
||||
# A URL to refer people to when problems occur with this mod
|
||||
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
|
||||
# If your mod is purely client-side and has no multiplayer functionality (be it dedicated servers or Open to LAN),
|
||||
# set this to true, and Forge will set the correct displayTest for you and skip loading your mod on dedicated servers.
|
||||
#clientSideOnly=true #optional - defaults to false if absent
|
||||
# A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
# The modid of the mod
|
||||
@@ -36,7 +39,7 @@ authors="${mod_authors}" #optional
|
||||
# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component.
|
||||
# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value.
|
||||
# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself.
|
||||
#displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional)
|
||||
#displayTest="MATCH_VERSION" # if nothing is specified, MATCH_VERSION is the default when clientSideOnly=false, otherwise IGNORE_ALL_VERSION when clientSideOnly=true (#optional)
|
||||
|
||||
# The description text for the mod (multi line!) (#mandatory)
|
||||
description='''${mod_description}'''
|
||||
@@ -67,4 +70,4 @@ description='''${mod_description}'''
|
||||
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
|
||||
# stop your mod loading on the server for example.
|
||||
#[features.${mod_id}]
|
||||
#openGLVersion="[3.2,)"
|
||||
#openGLVersion="[3.2,)"
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/vertex/BufferBuilder.java
|
||||
+++ b/com/mojang/blaze3d/vertex/BufferBuilder.java
|
||||
@@ -459,4 +_,14 @@
|
||||
@@ -477,4 +_,14 @@
|
||||
this.sorting = p_277855_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/CrashReport.java
|
||||
+++ b/net/minecraft/CrashReport.java
|
||||
@@ -57,14 +_,9 @@
|
||||
@@ -59,14 +_,9 @@
|
||||
if (this.uncategorizedStackTrace != null && this.uncategorizedStackTrace.length > 0) {
|
||||
p_127520_.append("-- Head --\n");
|
||||
p_127520_.append("Thread: ").append(Thread.currentThread().getName()).append("\n");
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
for(CrashReportCategory crashreportcategory : this.details) {
|
||||
@@ -72,6 +_,7 @@
|
||||
@@ -74,6 +_,7 @@
|
||||
p_127520_.append("\n\n");
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
this.systemReport.appendToCrashReportString(p_127520_);
|
||||
}
|
||||
|
||||
@@ -91,18 +_,7 @@
|
||||
@@ -93,18 +_,7 @@
|
||||
throwable.setStackTrace(this.exception.getStackTrace());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/SharedConstants.java
|
||||
+++ b/net/minecraft/SharedConstants.java
|
||||
@@ -212,6 +_,7 @@
|
||||
@@ -215,6 +_,7 @@
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/Util.java
|
||||
+++ b/net/minecraft/Util.java
|
||||
@@ -172,6 +_,11 @@
|
||||
@@ -180,6 +_,11 @@
|
||||
return 255;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
public static ExecutorService backgroundExecutor() {
|
||||
return BACKGROUND_EXECUTOR;
|
||||
}
|
||||
@@ -240,7 +_,7 @@
|
||||
@@ -254,7 +_,7 @@
|
||||
try {
|
||||
type = DataFixers.getDataFixer().getSchema(DataFixUtils.makeKey(SharedConstants.getCurrentVersion().getDataVersion().getVersion())).getChoiceType(p_137552_, p_137553_);
|
||||
} catch (IllegalArgumentException illegalargumentexception) {
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
--- a/net/minecraft/advancements/Advancement.java
|
||||
+++ b/net/minecraft/advancements/Advancement.java
|
||||
@@ -62,7 +_,14 @@
|
||||
return jsonobject;
|
||||
}
|
||||
|
||||
+ /** @deprecated Forge: use {@linkplain #fromJson(JsonObject, DeserializationContext, net.minecraftforge.common.crafting.conditions.ICondition.IContext) overload with context}. */
|
||||
+ @Deprecated
|
||||
public static Advancement fromJson(JsonObject p_300691_, DeserializationContext p_300053_) {
|
||||
+ return fromJson(p_300691_, p_300053_, net.minecraftforge.common.crafting.conditions.ICondition.IContext.EMPTY);
|
||||
+ }
|
||||
+
|
||||
+ public static Advancement fromJson(JsonObject p_300691_, DeserializationContext p_300053_, net.minecraftforge.common.crafting.conditions.ICondition.IContext context) {
|
||||
+ if ((p_300691_ = net.minecraftforge.common.ForgeHooks.readConditionalAdvancement(context, p_300691_)) == null) return null;
|
||||
Optional<ResourceLocation> optional = p_300691_.has("parent") ? Optional.of(new ResourceLocation(GsonHelper.getAsString(p_300691_, "parent"))) : Optional.empty();
|
||||
Optional<DisplayInfo> optional1 = p_300691_.has("display") ? Optional.of(DisplayInfo.fromJson(GsonHelper.getAsJsonObject(p_300691_, "display"))) : Optional.empty();
|
||||
AdvancementRewards advancementrewards = p_300691_.has("rewards") ? AdvancementRewards.deserialize(GsonHelper.getAsJsonObject(p_300691_, "rewards")) : AdvancementRewards.EMPTY;
|
||||
@@ -182,7 +_,11 @@
|
||||
@@ -171,7 +_,11 @@
|
||||
}
|
||||
|
||||
public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, String p_138391_) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/advancements/AdvancementRewards.java
|
||||
+++ b/net/minecraft/advancements/AdvancementRewards.java
|
||||
@@ -43,7 +_,7 @@
|
||||
@@ -27,7 +_,7 @@
|
||||
|
||||
public void grant(ServerPlayer p_9990_) {
|
||||
p_9990_.giveExperiencePoints(this.experience);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/advancements/CriteriaTriggers.java
|
||||
+++ b/net/minecraft/advancements/CriteriaTriggers.java
|
||||
@@ -46,7 +_,7 @@
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class CriteriaTriggers {
|
||||
- private static final BiMap<ResourceLocation, CriterionTrigger<?>> CRITERIA = HashBiMap.create();
|
||||
+ private static final BiMap<ResourceLocation, CriterionTrigger<?>> CRITERIA = com.google.common.collect.Maps.synchronizedBiMap(HashBiMap.create());
|
||||
public static final ImpossibleTrigger IMPOSSIBLE = register("impossible", new ImpossibleTrigger());
|
||||
public static final KilledTrigger PLAYER_KILLED_ENTITY = register("player_killed_entity", new KilledTrigger());
|
||||
public static final KilledTrigger ENTITY_KILLED_PLAYER = register("entity_killed_player", new KilledTrigger());
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/advancements/critereon/ItemPredicate.java
|
||||
+++ b/net/minecraft/advancements/critereon/ItemPredicate.java
|
||||
@@ -50,7 +_,7 @@
|
||||
@@ -45,7 +_,7 @@
|
||||
return false;
|
||||
} else {
|
||||
if (!this.enchantments.isEmpty()) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/client/Camera.java
|
||||
+++ b/net/minecraft/client/Camera.java
|
||||
@@ -206,6 +_,18 @@
|
||||
this.initialized = false;
|
||||
@@ -212,6 +_,18 @@
|
||||
return this.partialTickTime;
|
||||
}
|
||||
|
||||
+ public void setAnglesInternal(float yaw, float pitch) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/KeyboardHandler.java
|
||||
+++ b/net/minecraft/client/KeyboardHandler.java
|
||||
@@ -380,11 +_,15 @@
|
||||
@@ -397,11 +_,15 @@
|
||||
Screen.wrapScreenError(() -> {
|
||||
if (p_90897_ != 1 && p_90897_ != 2) {
|
||||
if (p_90897_ == 0) {
|
||||
@@ -18,11 +18,10 @@
|
||||
}
|
||||
|
||||
}, "keyPressed event handler", screen.getClass().getCanonicalName());
|
||||
@@ -443,22 +_,26 @@
|
||||
this.minecraft.debugFpsMeterKeyPress(p_90895_ - 48);
|
||||
@@ -478,21 +_,26 @@
|
||||
}
|
||||
|
||||
}
|
||||
-
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onKeyInput(p_90895_, p_90896_, p_90897_, p_90898_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Minecraft.java
|
||||
+++ b/net/minecraft/client/Minecraft.java
|
||||
@@ -252,7 +_,7 @@
|
||||
@@ -254,7 +_,7 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -9,15 +9,15 @@
|
||||
static Minecraft instance;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final boolean ON_OSX = Util.getPlatform() == Util.OS.OSX;
|
||||
@@ -422,7 +_,6 @@
|
||||
}, Util.ioPool());
|
||||
this.userApiService = this.createUserApiService(this.authenticationService, p_91084_);
|
||||
@@ -438,7 +_,6 @@
|
||||
}
|
||||
}, Util.nonCriticalIoPool());
|
||||
LOGGER.info("Setting user: {}", (Object)this.user.getName());
|
||||
- LOGGER.debug("(Session ID is {})", (Object)this.user.getSessionId());
|
||||
this.demo = p_91084_.game.demo;
|
||||
this.allowsMultiplayer = !p_91084_.game.disableMultiplayer;
|
||||
this.allowsChat = !p_91084_.game.disableChat;
|
||||
@@ -458,15 +_,15 @@
|
||||
@@ -474,15 +_,15 @@
|
||||
}
|
||||
|
||||
this.window.setFramerateLimit(this.options.framerateLimit().get());
|
||||
@@ -35,7 +35,7 @@
|
||||
this.resourcePackRepository.reload();
|
||||
this.options.loadSelectedResourcePacks(this.resourcePackRepository);
|
||||
this.languageManager = new LanguageManager(this.options.languageCode);
|
||||
@@ -512,10 +_,13 @@
|
||||
@@ -538,10 +_,13 @@
|
||||
this.gameRenderer = new GameRenderer(this, this.entityRenderDispatcher.getItemInHandRenderer(), this.resourceManager, this.renderBuffers);
|
||||
this.resourceManager.registerReloadListener(this.gameRenderer.createReloadListener());
|
||||
this.levelRenderer = new LevelRenderer(this, this.entityRenderDispatcher, this.blockEntityRenderDispatcher, this.renderBuffers);
|
||||
@@ -50,7 +50,7 @@
|
||||
this.resourceManager.registerReloadListener(this.particleEngine);
|
||||
this.paintingTextures = new PaintingTextureManager(this.textureManager);
|
||||
this.resourceManager.registerReloadListener(this.paintingTextures);
|
||||
@@ -526,7 +_,10 @@
|
||||
@@ -552,7 +_,10 @@
|
||||
this.gpuWarnlistManager = new GpuWarnlistManager();
|
||||
this.resourceManager.registerReloadListener(this.gpuWarnlistManager);
|
||||
this.resourceManager.registerReloadListener(this.regionalCompliancies);
|
||||
@@ -62,7 +62,7 @@
|
||||
this.debugRenderer = new DebugRenderer(this);
|
||||
RealmsClient realmsclient = RealmsClient.create(this);
|
||||
this.realmsDataFetcher = new RealmsDataFetcher(realmsclient);
|
||||
@@ -546,6 +_,7 @@
|
||||
@@ -572,6 +_,7 @@
|
||||
TinyFileDialogs.tinyfd_messageBox("Minecraft", stringbuilder.toString(), "ok", "error", false);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
this.window.updateVsync(this.options.enableVsync().get());
|
||||
this.window.updateRawMouseInput(this.options.rawMouseInput().get());
|
||||
this.window.setDefaultErrorCallback();
|
||||
@@ -565,7 +_,7 @@
|
||||
@@ -592,7 +_,7 @@
|
||||
ReloadInstance reloadinstance = this.resourceManager.createReload(Util.backgroundExecutor(), this, RESOURCE_RELOAD_INITIAL_TASK, list);
|
||||
GameLoadTimesEvent.INSTANCE.beginStep(TelemetryProperty.LOAD_TIME_LOADING_OVERLAY_MS);
|
||||
Minecraft.GameLoadCookie minecraft$gameloadcookie = new Minecraft.GameLoadCookie(realmsclient, p_91084_.quickPlay);
|
||||
@@ -79,7 +79,7 @@
|
||||
Util.ifElse(p_296164_, (p_296162_) -> {
|
||||
this.rollbackResourcePacks(p_296162_, minecraft$gameloadcookie);
|
||||
}, () -> {
|
||||
@@ -575,8 +_,10 @@
|
||||
@@ -602,8 +_,10 @@
|
||||
|
||||
this.reloadStateTracker.finishReload();
|
||||
this.onResourceLoadFinished(minecraft$gameloadcookie);
|
||||
@@ -91,25 +91,25 @@
|
||||
this.quickPlayLog = QuickPlayLog.of(p_91084_.quickPlay.path());
|
||||
}
|
||||
|
||||
@@ -674,7 +_,7 @@
|
||||
@@ -701,7 +_,7 @@
|
||||
private String createTitle() {
|
||||
StringBuilder stringbuilder = new StringBuilder("Minecraft");
|
||||
if (checkModStatus().shouldReportAsModified()) {
|
||||
- stringbuilder.append("*");
|
||||
+ stringbuilder.append(" Forge").append('*');
|
||||
+ stringbuilder.append('*').append(" Forge");
|
||||
}
|
||||
|
||||
stringbuilder.append(" ");
|
||||
@@ -699,6 +_,8 @@
|
||||
@@ -725,6 +_,8 @@
|
||||
}
|
||||
|
||||
private UserApiService createUserApiService(YggdrasilAuthenticationService p_193586_, GameConfig p_193587_) {
|
||||
try {
|
||||
+ if ("0".equals(p_193587_.user.user.getAccessToken())) // Forge: We use "0" in dev. Short circuit to stop exception spam.
|
||||
+ return UserApiService.OFFLINE;
|
||||
return p_193586_.createUserApiService(p_193587_.user.user.getAccessToken());
|
||||
} catch (AuthenticationException authenticationexception) {
|
||||
LOGGER.error("Failed to verify authentication", (Throwable)authenticationexception);
|
||||
@@ -711,7 +_,7 @@
|
||||
+ if ("0".equals(p_193587_.user.user.getAccessToken())) // Forge: We use "0" in dev. Short circuit to stop exception spam.
|
||||
+ return UserApiService.OFFLINE;
|
||||
return p_193586_.createUserApiService(p_193587_.user.user.getAccessToken());
|
||||
}
|
||||
|
||||
@@ -733,7 +_,7 @@
|
||||
}
|
||||
|
||||
private void rollbackResourcePacks(Throwable p_91240_, @Nullable Minecraft.GameLoadCookie p_299515_) {
|
||||
@@ -118,7 +118,7 @@
|
||||
this.clearResourcePacksOnError(p_91240_, (Component)null, p_299515_);
|
||||
} else {
|
||||
Util.throwAsRuntime(p_91240_);
|
||||
@@ -803,7 +_,10 @@
|
||||
@@ -819,7 +_,10 @@
|
||||
}
|
||||
|
||||
public void createSearchTrees() {
|
||||
@@ -130,7 +130,7 @@
|
||||
return new FullTextSearchTree<>((p_210797_) -> {
|
||||
return p_210797_.getTooltipLines((Player)null, TooltipFlag.Default.NORMAL.asCreative()).stream().map((p_231455_) -> {
|
||||
return ChatFormatting.stripFormatting(p_231455_.getString()).trim();
|
||||
@@ -814,7 +_,8 @@
|
||||
@@ -830,7 +_,8 @@
|
||||
return Stream.of(BuiltInRegistries.ITEM.getKey(p_91317_.getItem()));
|
||||
}, p_231451_);
|
||||
});
|
||||
@@ -140,7 +140,7 @@
|
||||
return new IdSearchTree<>((p_231353_) -> {
|
||||
return p_231353_.getTags().map(TagKey::location);
|
||||
}, p_231430_);
|
||||
@@ -834,9 +_,12 @@
|
||||
@@ -850,9 +_,12 @@
|
||||
});
|
||||
}, p_301514_);
|
||||
});
|
||||
@@ -156,7 +156,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1019,10 +_,6 @@
|
||||
@@ -1054,10 +_,6 @@
|
||||
LOGGER.error("setScreen called from non-game thread");
|
||||
}
|
||||
|
||||
@@ -164,30 +164,30 @@
|
||||
- this.screen.removed();
|
||||
- }
|
||||
-
|
||||
if (p_91153_ == null && this.level == null) {
|
||||
p_91153_ = new TitleScreen();
|
||||
} else if (p_91153_ == null && this.player.isDeadOrDying()) {
|
||||
@@ -1033,6 +_,19 @@
|
||||
if (p_91153_ == null && this.clientLevelTeardownInProgress) {
|
||||
throw new IllegalStateException("Trying to return to in-game GUI during disconnection");
|
||||
} else {
|
||||
@@ -1071,6 +_,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ net.minecraftforge.client.ForgeHooksClient.clearGuiLayers(this);
|
||||
+ Screen old = this.screen;
|
||||
+ if (p_91153_ != null) {
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenOpening(old, p_91153_);
|
||||
+ if (event == null) return;
|
||||
+ p_91153_ = event;
|
||||
+ }
|
||||
+ net.minecraftforge.client.ForgeHooksClient.clearGuiLayers(this);
|
||||
+ Screen old = this.screen;
|
||||
+ if (p_91153_ != null) {
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenOpening(old, p_91153_);
|
||||
+ if (event == null) return;
|
||||
+ p_91153_ = event;
|
||||
+ }
|
||||
+
|
||||
+ if (old != null && p_91153_ != old) {
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenClose(old);
|
||||
+ old.removed();
|
||||
+ }
|
||||
+ if (old != null && p_91153_ != old) {
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenClose(old);
|
||||
+ old.removed();
|
||||
+ }
|
||||
+
|
||||
this.screen = p_91153_;
|
||||
if (this.screen != null) {
|
||||
this.screen.added();
|
||||
@@ -1179,9 +_,12 @@
|
||||
this.screen = p_91153_;
|
||||
if (this.screen != null) {
|
||||
this.screen.added();
|
||||
@@ -1218,9 +_,12 @@
|
||||
RenderSystem.enableCull();
|
||||
this.profiler.pop();
|
||||
if (!this.noRender) {
|
||||
@@ -200,15 +200,25 @@
|
||||
}
|
||||
|
||||
if (this.fpsPieResults != null) {
|
||||
@@ -1223,6 +_,7 @@
|
||||
@@ -1254,7 +_,8 @@
|
||||
this.window.setErrorSection("Post render");
|
||||
++this.frames;
|
||||
boolean flag1 = this.hasSingleplayerServer() && (this.screen != null && this.screen.isPauseScreen() || this.overlay != null && this.overlay.isPauseScreen()) && !this.singleplayerServer.isPublished();
|
||||
- if (this.pause != flag1) {
|
||||
+ if (this.pause != flag1 && !net.minecraftforge.client.ForgeHooksClient.onClientPauseChangePre(flag1)) {
|
||||
+
|
||||
if (flag1) {
|
||||
this.pausePartialTick = this.timer.partialTick;
|
||||
} else {
|
||||
@@ -1262,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.pause = flag1;
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onClientPauseUpdate(this.pause);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onClientPauseChangePost(flag1);
|
||||
}
|
||||
|
||||
long l = Util.getNanos();
|
||||
@@ -1302,10 +_,12 @@
|
||||
@@ -1341,10 +_,12 @@
|
||||
this.window.setGuiScale((double)i);
|
||||
if (this.screen != null) {
|
||||
this.screen.resize(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
@@ -221,7 +231,7 @@
|
||||
this.gameRenderer.resize(this.window.getWidth(), this.window.getHeight());
|
||||
this.mouseHandler.setIgnoreFirstMove();
|
||||
}
|
||||
@@ -1579,6 +_,7 @@
|
||||
@@ -1618,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -229,7 +239,7 @@
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@@ -1608,10 +_,18 @@
|
||||
@@ -1647,10 +_,18 @@
|
||||
if (p_91387_ && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
@@ -251,7 +261,7 @@
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
}
|
||||
@@ -1640,6 +_,8 @@
|
||||
@@ -1679,6 +_,8 @@
|
||||
return false;
|
||||
} else {
|
||||
boolean flag = false;
|
||||
@@ -260,7 +270,7 @@
|
||||
switch (this.hitResult.getType()) {
|
||||
case ENTITY:
|
||||
this.gameMode.attack(this.player, ((EntityHitResult)this.hitResult).getEntity());
|
||||
@@ -1647,7 +_,7 @@
|
||||
@@ -1686,7 +_,7 @@
|
||||
case BLOCK:
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
@@ -269,7 +279,7 @@
|
||||
this.gameMode.startDestroyBlock(blockpos, blockhitresult.getDirection());
|
||||
if (this.level.getBlockState(blockpos).isAir()) {
|
||||
flag = true;
|
||||
@@ -1660,8 +_,10 @@
|
||||
@@ -1699,8 +_,10 @@
|
||||
}
|
||||
|
||||
this.player.resetAttackStrengthTicker();
|
||||
@@ -280,7 +290,7 @@
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
return flag;
|
||||
}
|
||||
@@ -1677,6 +_,11 @@
|
||||
@@ -1716,6 +_,11 @@
|
||||
}
|
||||
|
||||
for(InteractionHand interactionhand : InteractionHand.values()) {
|
||||
@@ -292,7 +302,7 @@
|
||||
ItemStack itemstack = this.player.getItemInHand(interactionhand);
|
||||
if (!itemstack.isItemEnabled(this.level.enabledFeatures())) {
|
||||
return;
|
||||
@@ -1697,7 +_,7 @@
|
||||
@@ -1736,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (interactionresult.consumesAction()) {
|
||||
@@ -301,7 +311,7 @@
|
||||
this.player.swing(interactionhand);
|
||||
}
|
||||
|
||||
@@ -1709,7 +_,7 @@
|
||||
@@ -1748,7 +_,7 @@
|
||||
int i = itemstack.getCount();
|
||||
InteractionResult interactionresult1 = this.gameMode.useItemOn(this.player, interactionhand, blockhitresult);
|
||||
if (interactionresult1.consumesAction()) {
|
||||
@@ -310,7 +320,7 @@
|
||||
this.player.swing(interactionhand);
|
||||
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.gameMode.hasInfiniteItems())) {
|
||||
this.gameRenderer.itemInHandRenderer.itemUsed(interactionhand);
|
||||
@@ -1725,6 +_,9 @@
|
||||
@@ -1764,6 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +330,7 @@
|
||||
if (!itemstack.isEmpty()) {
|
||||
InteractionResult interactionresult2 = this.gameMode.useItem(this.player, interactionhand);
|
||||
if (interactionresult2.consumesAction()) {
|
||||
@@ -1751,6 +_,8 @@
|
||||
@@ -1795,6 +_,8 @@
|
||||
--this.rightClickDelay;
|
||||
}
|
||||
|
||||
@@ -329,7 +339,7 @@
|
||||
this.profiler.push("gui");
|
||||
this.chatListener.tick();
|
||||
this.gui.tick(this.pause);
|
||||
@@ -1839,6 +_,7 @@
|
||||
@@ -1887,6 +_,7 @@
|
||||
|
||||
this.tutorial.tick();
|
||||
|
||||
@@ -337,7 +347,7 @@
|
||||
try {
|
||||
this.level.tick(() -> {
|
||||
return true;
|
||||
@@ -1854,6 +_,7 @@
|
||||
@@ -1902,6 +_,7 @@
|
||||
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
@@ -345,7 +355,7 @@
|
||||
}
|
||||
|
||||
this.profiler.popPush("animateTick");
|
||||
@@ -1873,6 +_,8 @@
|
||||
@@ -1921,6 +_,8 @@
|
||||
this.profiler.popPush("keyboard");
|
||||
this.keyboardHandler.tick();
|
||||
this.profiler.pop();
|
||||
@@ -354,36 +364,39 @@
|
||||
}
|
||||
|
||||
private boolean isMultiplayerServer() {
|
||||
@@ -2069,6 +_,7 @@
|
||||
@@ -2112,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void setLevel(ClientLevel p_91157_) {
|
||||
+ if (this.level != null) net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.level.LevelEvent.Unload(this.level));
|
||||
+ if (this.level != null) net.minecraftforge.event.ForgeEventFactory.onLevelUnload(this.level);
|
||||
ProgressScreen progressscreen = new ProgressScreen(true);
|
||||
progressscreen.progressStartNoAbort(Component.translatable("connect.joining"));
|
||||
this.updateScreenAndTick(progressscreen);
|
||||
@@ -2102,10 +_,12 @@
|
||||
@@ -2146,6 +_,7 @@
|
||||
IntegratedServer integratedserver = this.singleplayerServer;
|
||||
this.singleplayerServer = null;
|
||||
this.gameRenderer.resetData();
|
||||
+ net.minecraftforge.client.ForgeHooksClient.firePlayerLogout(this.gameMode, this.player);
|
||||
this.gameMode = null;
|
||||
this.narrator.clear();
|
||||
this.updateScreenAndTick(p_91321_);
|
||||
if (this.level != null) {
|
||||
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.level.LevelEvent.Unload(this.level));
|
||||
if (integratedserver != null) {
|
||||
this.profiler.push("waitForServer");
|
||||
this.clientLevelTeardownInProgress = true;
|
||||
@@ -2153,6 +_,7 @@
|
||||
try {
|
||||
this.updateScreenAndTick(p_91321_);
|
||||
if (this.level != null) {
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onLevelUnload(this.level);
|
||||
if (integratedserver != null) {
|
||||
this.profiler.push("waitForServer");
|
||||
|
||||
@@ -2119,6 +_,7 @@
|
||||
this.downloadedPackSource.clearServerPack();
|
||||
this.gui.onDisconnected();
|
||||
this.isLocalServer = false;
|
||||
+ net.minecraftforge.client.ForgeHooksClient.handleClientLevelClosing(this.level);
|
||||
}
|
||||
@@ -2165,6 +_,7 @@
|
||||
|
||||
this.level = null;
|
||||
@@ -2243,6 +_,7 @@
|
||||
this.gui.onDisconnected();
|
||||
this.isLocalServer = false;
|
||||
+ net.minecraftforge.client.ForgeHooksClient.handleClientLevelClosing(this.level);
|
||||
}
|
||||
|
||||
this.level = null;
|
||||
@@ -2313,6 +_,7 @@
|
||||
|
||||
private void pickBlock() {
|
||||
if (this.hitResult != null && this.hitResult.getType() != HitResult.Type.MISS) {
|
||||
@@ -391,7 +404,7 @@
|
||||
boolean flag = this.player.getAbilities().instabuild;
|
||||
BlockEntity blockentity = null;
|
||||
HitResult.Type hitresult$type = this.hitResult.getType();
|
||||
@@ -2255,10 +_,7 @@
|
||||
@@ -2325,10 +_,7 @@
|
||||
}
|
||||
|
||||
Block block = blockstate.getBlock();
|
||||
@@ -403,7 +416,7 @@
|
||||
|
||||
if (flag && Screen.hasControlDown() && blockstate.hasBlockEntity()) {
|
||||
blockentity = this.level.getBlockEntity(blockpos);
|
||||
@@ -2269,7 +_,7 @@
|
||||
@@ -2339,7 +_,7 @@
|
||||
}
|
||||
|
||||
Entity entity = ((EntityHitResult)this.hitResult).getEntity();
|
||||
@@ -412,7 +425,7 @@
|
||||
if (itemstack == null) {
|
||||
return;
|
||||
}
|
||||
@@ -2808,6 +_,19 @@
|
||||
@@ -2904,6 +_,19 @@
|
||||
|
||||
public void updateMaxMipLevel(int p_91313_) {
|
||||
this.modelManager.updateMaxMipLevel(p_91313_);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Options.java
|
||||
+++ b/net/minecraft/client/Options.java
|
||||
@@ -507,7 +_,8 @@
|
||||
@@ -509,7 +_,8 @@
|
||||
}, new OptionInstance.LazyEnum<>(() -> {
|
||||
return Stream.concat(Stream.of(""), Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().stream()).toList();
|
||||
}, (p_232011_) -> {
|
||||
@@ -10,7 +10,7 @@
|
||||
}, Codec.STRING), "", (p_299350_) -> {
|
||||
SoundManager soundmanager = Minecraft.getInstance().getSoundManager();
|
||||
soundmanager.reload();
|
||||
@@ -835,6 +_,7 @@
|
||||
@@ -841,6 +_,7 @@
|
||||
}
|
||||
|
||||
public Options(Minecraft p_92138_, File p_92139_) {
|
||||
@@ -18,7 +18,7 @@
|
||||
this.minecraft = p_92138_;
|
||||
this.optionsFile = new File(p_92139_, "options.txt");
|
||||
boolean flag = p_92138_.is64Bit();
|
||||
@@ -957,11 +_,20 @@
|
||||
@@ -964,11 +_,20 @@
|
||||
p_168428_.process("telemetryOptInExtra", this.telemetryOptInExtra);
|
||||
this.onboardAccessibility = p_168428_.process("onboardAccessibility", this.onboardAccessibility);
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,6 +_,9 @@
|
||||
@@ -987,6 +_,9 @@
|
||||
}
|
||||
|
||||
public void load() {
|
||||
@@ -51,7 +51,7 @@
|
||||
try {
|
||||
if (!this.optionsFile.exists()) {
|
||||
return;
|
||||
@@ -1008,7 +_,8 @@
|
||||
@@ -1015,7 +_,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
@Nullable
|
||||
private String getValueOrNull(String p_168459_) {
|
||||
return compoundtag1.contains(p_168459_) ? compoundtag1.getString(p_168459_) : null;
|
||||
@@ -1181,6 +_,7 @@
|
||||
@@ -1188,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void broadcastOptions() {
|
||||
@@ -69,7 +69,7 @@
|
||||
if (this.minecraft.player != null) {
|
||||
this.minecraft.player.connection.send(new ServerboundClientInformationPacket(this.buildPlayerInformation()));
|
||||
}
|
||||
@@ -1239,6 +_,23 @@
|
||||
@@ -1246,6 +_,23 @@
|
||||
}
|
||||
|
||||
p_92146_.setSelected(set);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/Gui.java
|
||||
+++ b/net/minecraft/client/gui/Gui.java
|
||||
@@ -130,7 +_,7 @@
|
||||
@@ -131,7 +_,7 @@
|
||||
public float vignetteBrightness = 1.0F;
|
||||
protected int toolHighlightTimer;
|
||||
protected ItemStack lastToolHighlight = ItemStack.EMPTY;
|
||||
@@ -9,7 +9,7 @@
|
||||
protected final SubtitleOverlay subtitleOverlay;
|
||||
protected final SpectatorGui spectatorGui;
|
||||
protected final PlayerTabOverlay tabList;
|
||||
@@ -453,6 +_,8 @@
|
||||
@@ -454,6 +_,8 @@
|
||||
|
||||
for(MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
|
||||
MobEffect mobeffect = mobeffectinstance.getEffect();
|
||||
@@ -18,7 +18,7 @@
|
||||
if (mobeffectinstance.showIcon()) {
|
||||
int i = this.screenWidth;
|
||||
int j = 1;
|
||||
@@ -481,6 +_,7 @@
|
||||
@@ -482,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.get(mobeffect);
|
||||
int i1 = j;
|
||||
float f1 = f;
|
||||
@@ -601,16 +_,21 @@
|
||||
@@ -602,16 +_,21 @@
|
||||
}
|
||||
|
||||
public void renderSelectedItemName(GuiGraphics p_283501_) {
|
||||
@@ -51,7 +51,7 @@
|
||||
if (!this.minecraft.gameMode.canHurtPlayer()) {
|
||||
k += 14;
|
||||
}
|
||||
@@ -622,7 +_,13 @@
|
||||
@@ -623,7 +_,13 @@
|
||||
|
||||
if (l > 0) {
|
||||
p_283501_.fill(j - 2, k - 2, j + i + 2, k + 9 + 2, this.minecraft.options.getBackgroundColor(0));
|
||||
@@ -66,7 +66,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1069,7 +_,7 @@
|
||||
@@ -1080,7 +_,7 @@
|
||||
ItemStack itemstack = this.minecraft.player.getInventory().getSelected();
|
||||
if (itemstack.isEmpty()) {
|
||||
this.toolHighlightTimer = 0;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
int i = p_282636_.drawInBatch(p_281596_, (float)p_281586_, (float)p_282816_, p_281743_, p_282394_, this.pose.last().pose(), this.bufferSource, Font.DisplayMode.NORMAL, 0, 15728880);
|
||||
this.flushIfUnmanaged();
|
||||
return i;
|
||||
@@ -511,6 +_,7 @@
|
||||
@@ -515,6 +_,7 @@
|
||||
crashreportcategory.setDetail("Item Type", () -> {
|
||||
return String.valueOf((Object)p_281675_.getItem());
|
||||
});
|
||||
@@ -41,7 +41,7 @@
|
||||
crashreportcategory.setDetail("Item Damage", () -> {
|
||||
return String.valueOf(p_281675_.getDamageValue());
|
||||
});
|
||||
@@ -558,18 +_,26 @@
|
||||
@@ -562,18 +_,26 @@
|
||||
}
|
||||
|
||||
this.pose.popPose();
|
||||
@@ -72,7 +72,7 @@
|
||||
this.renderTooltipInternal(p_283128_, list, p_283678_, p_281696_, DefaultTooltipPositioner.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -578,7 +_,15 @@
|
||||
@@ -582,7 +_,15 @@
|
||||
}
|
||||
|
||||
public void renderComponentTooltip(Font p_282739_, List<Component> p_281832_, int p_282191_, int p_282446_) {
|
||||
@@ -89,7 +89,7 @@
|
||||
}
|
||||
|
||||
public void renderTooltip(Font p_282192_, List<? extends FormattedCharSequence> p_282297_, int p_281680_, int p_283325_) {
|
||||
@@ -591,11 +_,13 @@
|
||||
@@ -595,11 +_,13 @@
|
||||
|
||||
private void renderTooltipInternal(Font p_282675_, List<ClientTooltipComponent> p_282615_, int p_283230_, int p_283417_, ClientTooltipPositioner p_282442_) {
|
||||
if (!p_282615_.isEmpty()) {
|
||||
@@ -104,7 +104,7 @@
|
||||
if (k > i) {
|
||||
i = k;
|
||||
}
|
||||
@@ -605,20 +_,21 @@
|
||||
@@ -609,20 +_,21 @@
|
||||
|
||||
int i2 = i;
|
||||
int j2 = j;
|
||||
@@ -129,7 +129,7 @@
|
||||
k1 += clienttooltipcomponent1.getHeight() + (l1 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -626,7 +_,7 @@
|
||||
@@ -630,7 +_,7 @@
|
||||
|
||||
for(int k2 = 0; k2 < p_282615_.size(); ++k2) {
|
||||
ClientTooltipComponent clienttooltipcomponent2 = p_282615_.get(k2);
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
--- a/net/minecraft/client/gui/components/AbstractSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/components/AbstractSelectionList.java
|
||||
@@ -504,6 +_,13 @@
|
||||
return new ScreenRectangle(this.x0, this.y0, this.x1 - this.x0, this.y1 - this.y0);
|
||||
}
|
||||
|
||||
+ public int getWidth() { return this.width; }
|
||||
+ public int getHeight() { return this.height; }
|
||||
+ public int getTop() { return this.y0; }
|
||||
+ public int getBottom() { return this.y1; }
|
||||
+ public int getLeft() { return this.x0; }
|
||||
+ public int getRight() { return this.x1; }
|
||||
+
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
protected abstract static class Entry<E extends AbstractSelectionList.Entry<E>> implements GuiEventListener {
|
||||
/** @deprecated */
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/AbstractWidget.java
|
||||
+++ b/net/minecraft/client/gui/components/AbstractWidget.java
|
||||
@@ -259,6 +_,19 @@
|
||||
@@ -233,6 +_,19 @@
|
||||
this.focused = p_93693_;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/Button.java
|
||||
+++ b/net/minecraft/client/gui/components/Button.java
|
||||
@@ -29,6 +_,11 @@
|
||||
@@ -30,6 +_,11 @@
|
||||
this.createNarration = p_259552_;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
public void onPress() {
|
||||
this.onPress.onPress(this);
|
||||
}
|
||||
@@ -92,9 +_,11 @@
|
||||
@@ -93,9 +_,11 @@
|
||||
}
|
||||
|
||||
public Button build() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/DebugScreenOverlay.java
|
||||
+++ b/net/minecraft/client/gui/components/DebugScreenOverlay.java
|
||||
@@ -93,9 +_,9 @@
|
||||
@@ -95,9 +_,9 @@
|
||||
@Nullable
|
||||
private CompletableFuture<LevelChunk> serverChunk;
|
||||
private boolean renderDebug;
|
||||
@@ -13,7 +13,7 @@
|
||||
private final SampleLogger frameTimeLogger = new SampleLogger();
|
||||
private final SampleLogger tickTimeLogger = new SampleLogger();
|
||||
private final SampleLogger pingLogger = new SampleLogger();
|
||||
@@ -120,14 +_,18 @@
|
||||
@@ -124,14 +_,18 @@
|
||||
this.clientChunk = null;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
if (this.renderFpsCharts) {
|
||||
int i = p_281427_.guiWidth();
|
||||
int j = i / 2;
|
||||
@@ -137,7 +_,9 @@
|
||||
@@ -141,7 +_,9 @@
|
||||
this.tpsChart.drawChart(p_281427_, i - k, k);
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@
|
||||
if (this.renderNetworkCharts) {
|
||||
int l = p_281427_.guiWidth();
|
||||
int i1 = l / 2;
|
||||
@@ -148,17 +_,32 @@
|
||||
@@ -152,17 +_,32 @@
|
||||
int j1 = this.pingChart.getWidth(i1);
|
||||
this.pingChart.drawChart(p_281427_, l - j1, j1);
|
||||
}
|
||||
@@ -82,7 +82,7 @@
|
||||
this.renderLines(p_281525_, list, true);
|
||||
}
|
||||
|
||||
@@ -430,6 +_,7 @@
|
||||
@@ -451,6 +_,7 @@
|
||||
list.add("");
|
||||
list.add(ChatFormatting.UNDERLINE + "Targeted Entity");
|
||||
list.add(String.valueOf((Object)BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType())));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/ConnectScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/ConnectScreen.java
|
||||
@@ -84,6 +_,8 @@
|
||||
@@ -85,6 +_,8 @@
|
||||
}
|
||||
|
||||
if (optional.isEmpty()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/MenuScreens.java
|
||||
+++ b/net/minecraft/client/gui/screens/MenuScreens.java
|
||||
@@ -40,6 +_,10 @@
|
||||
@@ -41,6 +_,10 @@
|
||||
private static final Map<MenuType<?>, MenuScreens.ScreenConstructor<?, ?>> SCREENS = Maps.newHashMap();
|
||||
|
||||
public static <T extends AbstractContainerMenu> void create(@Nullable MenuType<T> p_96202_, Minecraft p_96203_, int p_96204_, Component p_96205_) {
|
||||
@@ -11,7 +11,7 @@
|
||||
if (p_96202_ == null) {
|
||||
LOGGER.warn("Trying to open invalid screen with name: {}", (Object)p_96205_.getString());
|
||||
} else {
|
||||
@@ -47,9 +_,10 @@
|
||||
@@ -48,9 +_,10 @@
|
||||
if (screenconstructor == null) {
|
||||
LOGGER.warn("Failed to create screen for menu type: {}", (Object)BuiltInRegistries.MENU.getKey(p_96202_));
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
@@ -88,6 +_,7 @@
|
||||
@@ -87,6 +_,7 @@
|
||||
} else {
|
||||
gridlayout$rowhelper.addChild(this.openScreenButton(PLAYER_REPORTING, SocialInteractionsScreen::new));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/TitleScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/TitleScreen.java
|
||||
@@ -64,6 +_,7 @@
|
||||
@@ -63,6 +_,7 @@
|
||||
@Nullable
|
||||
private TitleScreen.WarningLabel warningLabel;
|
||||
private final LogoRenderer logoRenderer;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public TitleScreen() {
|
||||
this(false);
|
||||
@@ -114,11 +_,15 @@
|
||||
@@ -113,11 +_,15 @@
|
||||
int j = this.width - i - 2;
|
||||
int k = 24;
|
||||
int l = this.height / 4 + 48;
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
SpriteIconButton spriteiconbutton = this.addRenderableWidget(CommonButtons.language(20, (p_280830_) -> {
|
||||
this.minecraft.setScreen(new LanguageSelectScreen(this, this.minecraft.options, this.minecraft.getLanguageManager()));
|
||||
@@ -164,7 +_,7 @@
|
||||
@@ -163,7 +_,7 @@
|
||||
}).bounds(this.width / 2 - 100, p_96764_ + p_96765_ * 1, 200, 20).tooltip(tooltip).build())).active = flag;
|
||||
(this.addRenderableWidget(Button.builder(Component.translatable("menu.online"), (p_210872_) -> {
|
||||
this.realmsButtonClicked();
|
||||
@@ -33,15 +33,15 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -248,6 +_,7 @@
|
||||
@@ -243,6 +_,7 @@
|
||||
this.warningLabel.render(p_282860_, i);
|
||||
}
|
||||
|
||||
+ net.minecraftforge.client.ForgeHooksClient.renderMainMenu(this, p_282860_, this.font, this.width, this.height, i);
|
||||
if (this.splash != null) {
|
||||
if (this.splash != null && !this.minecraft.options.hideSplashTexts().get()) {
|
||||
this.splash.render(p_282860_, this.width, this.font, i);
|
||||
}
|
||||
@@ -263,7 +_,14 @@
|
||||
@@ -258,7 +_,14 @@
|
||||
s = s + I18n.get("menu.modded");
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
for(GuiEventListener guieventlistener : this.children()) {
|
||||
if (guieventlistener instanceof AbstractWidget) {
|
||||
@@ -276,6 +_,7 @@
|
||||
@@ -271,6 +_,7 @@
|
||||
RenderSystem.enableDepthTest();
|
||||
this.realmsNotificationsScreen.render(p_282860_, p_281753_, p_283539_, p_282628_);
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
|
||||
@@ -38,6 +_,7 @@
|
||||
@@ -37,6 +_,7 @@
|
||||
private int maxY = Integer.MIN_VALUE;
|
||||
private float fade;
|
||||
private boolean centered;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public AdvancementTab(Minecraft p_97145_, AdvancementsScreen p_97146_, AdvancementTabType p_97147_, int p_97148_, AdvancementNode p_297568_, DisplayInfo p_97150_) {
|
||||
this.minecraft = p_97145_;
|
||||
@@ -52,6 +_,15 @@
|
||||
@@ -51,6 +_,15 @@
|
||||
this.addWidget(this.root, p_297568_.holder());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
public AdvancementTabType getType() {
|
||||
return this.type;
|
||||
}
|
||||
@@ -146,8 +_,8 @@
|
||||
@@ -145,8 +_,8 @@
|
||||
return null;
|
||||
} else {
|
||||
for(AdvancementTabType advancementtabtype : AdvancementTabType.values()) {
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/client/gui/screens/controls/KeyBindsScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/controls/KeyBindsScreen.java
|
||||
@@ -31,7 +_,7 @@
|
||||
this.addWidget(this.keyBindsList);
|
||||
@@ -30,7 +_,7 @@
|
||||
this.keyBindsList = this.addRenderableWidget(new KeyBindsList(this, this.minecraft));
|
||||
this.resetButton = this.addRenderableWidget(Button.builder(Component.translatable("controls.resetAll"), (p_269619_) -> {
|
||||
for(KeyMapping keymapping : this.options.keyMappings) {
|
||||
- keymapping.setKey(keymapping.getDefaultKey());
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
this.keyBindsList.resetMappingAndUpdateButtons();
|
||||
@@ -55,11 +_,13 @@
|
||||
@@ -54,11 +_,13 @@
|
||||
public boolean keyPressed(int p_193987_, int p_193988_, int p_193989_) {
|
||||
if (this.selectedKey != null) {
|
||||
if (p_193987_ == 256) {
|
||||
@@ -24,7 +24,7 @@
|
||||
this.selectedKey = null;
|
||||
this.lastKeySelection = Util.getMillis();
|
||||
this.keyBindsList.resetMappingAndUpdateButtons();
|
||||
@@ -67,6 +_,19 @@
|
||||
@@ -66,6 +_,19 @@
|
||||
} else {
|
||||
return super.keyPressed(p_193987_, p_193988_, p_193989_);
|
||||
}
|
||||
|
||||
+9
-9
@@ -52,7 +52,7 @@
|
||||
p_282567_.pose().popPose();
|
||||
}
|
||||
|
||||
@@ -274,7 +_,8 @@
|
||||
@@ -280,7 +_,8 @@
|
||||
if (super.mouseClicked(p_97748_, p_97749_, p_97750_)) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -62,7 +62,7 @@
|
||||
Slot slot = this.findSlot(p_97748_, p_97749_);
|
||||
long i = Util.getMillis();
|
||||
this.doubleclick = this.lastClickSlot == slot && i - this.lastClickTime < 250L && this.lastClickButton == p_97750_;
|
||||
@@ -285,6 +_,7 @@
|
||||
@@ -291,6 +_,7 @@
|
||||
int j = this.leftPos;
|
||||
int k = this.topPos;
|
||||
boolean flag1 = this.hasClickedOutside(p_97748_, p_97749_, j, k, p_97750_);
|
||||
@@ -70,7 +70,7 @@
|
||||
int l = -1;
|
||||
if (slot != null) {
|
||||
l = slot.index;
|
||||
@@ -310,7 +_,7 @@
|
||||
@@ -316,7 +_,7 @@
|
||||
}
|
||||
} else if (!this.isQuickCrafting) {
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
@@ -79,7 +79,7 @@
|
||||
this.slotClicked(slot, l, p_97750_, ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag2 = l != -999 && (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340) || InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344));
|
||||
@@ -334,7 +_,7 @@
|
||||
@@ -340,7 +_,7 @@
|
||||
this.quickCraftingType = 0;
|
||||
} else if (p_97750_ == 1) {
|
||||
this.quickCraftingType = 1;
|
||||
@@ -88,7 +88,7 @@
|
||||
this.quickCraftingType = 2;
|
||||
}
|
||||
}
|
||||
@@ -403,10 +_,13 @@
|
||||
@@ -409,10 +_,13 @@
|
||||
}
|
||||
|
||||
public boolean mouseReleased(double p_97812_, double p_97813_, int p_97814_) {
|
||||
@@ -102,7 +102,7 @@
|
||||
int k = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
@@ -420,7 +_,7 @@
|
||||
@@ -426,7 +_,7 @@
|
||||
if (hasShiftDown()) {
|
||||
if (!this.lastQuickMoved.isEmpty()) {
|
||||
for(Slot slot2 : this.menu.slots) {
|
||||
@@ -111,7 +111,7 @@
|
||||
this.slotClicked(slot2, slot2.index, p_97814_, ClickType.QUICK_MOVE);
|
||||
}
|
||||
}
|
||||
@@ -483,7 +_,7 @@
|
||||
@@ -489,7 +_,7 @@
|
||||
|
||||
this.slotClicked((Slot)null, -999, AbstractContainerMenu.getQuickcraftMask(2, this.quickCraftingType), ClickType.QUICK_CRAFT);
|
||||
} else if (!this.menu.getCarried().isEmpty()) {
|
||||
@@ -120,7 +120,7 @@
|
||||
this.slotClicked(slot, k, p_97814_, ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag1 = k != -999 && (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340) || InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344));
|
||||
@@ -530,34 +_,39 @@
|
||||
@@ -540,34 +_,39 @@
|
||||
}
|
||||
|
||||
public boolean keyPressed(int p_97765_, int p_97766_, int p_97767_) {
|
||||
@@ -167,7 +167,7 @@
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, i, ClickType.SWAP);
|
||||
return true;
|
||||
}
|
||||
@@ -592,6 +_,18 @@
|
||||
@@ -602,6 +_,18 @@
|
||||
|
||||
public T getMenu() {
|
||||
return this.menu;
|
||||
|
||||
+1
-1
@@ -42,4 +42,4 @@
|
||||
+ }
|
||||
Component component = this.getEffectName(mobeffectinstance);
|
||||
p_281462_.drawString(this.font, component, p_283484_ + 10 + 18, i + 6, 16777215);
|
||||
Component component1 = MobEffectUtil.formatDuration(mobeffectinstance, 1.0F);
|
||||
Component component1 = MobEffectUtil.formatDuration(mobeffectinstance, 1.0F, this.minecraft.level.tickRateManager().tickrate());
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
@@ -346,6 +_,8 @@
|
||||
@@ -342,6 +_,8 @@
|
||||
this.screen.setToolTip(list1);
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -1,16 +1,11 @@
|
||||
--- a/net/minecraft/client/gui/screens/packs/PackSelectionScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/packs/PackSelectionScreen.java
|
||||
@@ -138,10 +_,10 @@
|
||||
@@ -136,7 +_,7 @@
|
||||
TransferableSelectionList.PackEntry transferableselectionlist$packentry = p_100014_.getSelected();
|
||||
String s = transferableselectionlist$packentry == null ? "" : transferableselectionlist$packentry.getPackId();
|
||||
p_100014_.setSelected((TransferableSelectionList.PackEntry)null);
|
||||
- p_100015_.forEach((p_280875_) -> {
|
||||
- TransferableSelectionList.PackEntry transferableselectionlist$packentry1 = new TransferableSelectionList.PackEntry(this.minecraft, p_100014_, p_280875_);
|
||||
+ p_100015_.filter(PackSelectionModel.Entry::notHidden).forEach((p_264692_) -> {
|
||||
+ TransferableSelectionList.PackEntry transferableselectionlist$packentry1 = new TransferableSelectionList.PackEntry(this.minecraft, p_100014_, p_264692_);
|
||||
- p_100015_.forEach((p_308207_) -> {
|
||||
+ p_100015_.filter(PackSelectionModel.Entry::notHidden).forEach((p_308207_) -> {
|
||||
TransferableSelectionList.PackEntry transferableselectionlist$packentry1 = new TransferableSelectionList.PackEntry(this.minecraft, p_100014_, p_308207_);
|
||||
p_100014_.children().add(transferableselectionlist$packentry1);
|
||||
- if (p_280875_.getId().equals(s)) {
|
||||
+ if (p_264692_.getId().equals(s)) {
|
||||
p_100014_.setSelected(transferableselectionlist$packentry1);
|
||||
}
|
||||
|
||||
if (p_308207_.getId().equals(s)) {
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
if (path != null) {
|
||||
if (this.tempDataPackRepository == null) {
|
||||
this.tempDataPackRepository = ServerPacksSource.createPackRepository(path, this.packValidator);
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(this.tempDataPackRepository, net.minecraftforge.server.ServerLifecycleHooks::buildPackFinder);
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(this.tempDataPackRepository, false);
|
||||
this.tempDataPackRepository.reload();
|
||||
}
|
||||
|
||||
+40
-42
@@ -1,49 +1,47 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.java
|
||||
@@ -181,13 +_,23 @@
|
||||
@@ -280,12 +_,19 @@
|
||||
}
|
||||
|
||||
private void doLoadLevel(Screen p_233146_, String p_233147_, boolean p_233148_, boolean p_233149_) {
|
||||
+ // FORGE: Patch in overload to reduce further patching
|
||||
+ this.doLoadLevel(p_233146_, p_233147_, p_233148_, p_233149_, false);
|
||||
private void loadLevel(LevelStorageSource.LevelStorageAccess p_309733_, Dynamic<?> p_312455_, boolean p_310657_, boolean p_309504_, Runnable p_309915_) {
|
||||
+ loadLevel(p_309733_, p_312455_, p_310657_, p_309504_, p_309915_, false);
|
||||
+ }
|
||||
+
|
||||
+ // FORGE: Patch in confirmExperimentalWarning which confirms the experimental warning when true
|
||||
+ private void doLoadLevel(Screen p_233146_, String p_233147_, boolean p_233148_, boolean p_233149_, boolean confirmExperimentalWarning) {
|
||||
LevelStorageSource.LevelStorageAccess levelstoragesource$levelstorageaccess = this.createWorldAccess(p_233147_);
|
||||
if (levelstoragesource$levelstorageaccess != null) {
|
||||
PackRepository packrepository = ServerPacksSource.createPackRepository(levelstoragesource$levelstorageaccess);
|
||||
+ private void loadLevel(LevelStorageSource.LevelStorageAccess p_309733_, Dynamic<?> p_312455_, boolean p_310657_, boolean p_309504_, Runnable p_309915_, boolean confirmExperimentalWarning) {
|
||||
this.minecraft.forceSetScreen(new GenericDirtMessageScreen(Component.translatable("selectWorld.resource_load")));
|
||||
PackRepository packrepository = ServerPacksSource.createPackRepository(p_309733_);
|
||||
|
||||
WorldStem worldstem;
|
||||
try {
|
||||
+ levelstoragesource$levelstorageaccess.readAdditionalLevelSaveData(); // Read extra (e.g. modded) data from the world before creating it
|
||||
worldstem = this.loadWorldStem(levelstoragesource$levelstorageaccess, p_233148_, packrepository);
|
||||
+ if (confirmExperimentalWarning && worldstem.worldData() instanceof PrimaryLevelData pld) {
|
||||
+ pld.withConfirmedWarning(true);
|
||||
+ }
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Failed to load level data or datapacks, can't proceed with server load", (Throwable)exception);
|
||||
if (!p_233148_) {
|
||||
@@ -207,7 +_,9 @@
|
||||
WorldData worlddata = worldstem.worldData();
|
||||
boolean flag = worlddata.worldGenOptions().isOldCustomizedWorld();
|
||||
boolean flag1 = worlddata.worldGenSettingsLifecycle() != Lifecycle.stable();
|
||||
- if (!p_233149_ || !flag && !flag1) {
|
||||
+ // Forge: Skip confirmation if it has been done already for this world
|
||||
+ boolean skipConfirmation = worlddata instanceof PrimaryLevelData pld && pld.hasConfirmedExperimentalWarning();
|
||||
+ if (skipConfirmation || !p_233149_ || !flag && !flag1) {
|
||||
this.minecraft.getDownloadedPackSource().loadBundledResourcePack(levelstoragesource$levelstorageaccess).thenApply((p_233177_) -> {
|
||||
return true;
|
||||
}).exceptionallyComposeAsync((p_233183_) -> {
|
||||
@@ -229,9 +_,11 @@
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
+ if (flag) // Forge: For legacy world options, let vanilla handle it.
|
||||
this.askForBackup(p_233146_, p_233147_, flag, () -> {
|
||||
this.doLoadLevel(p_233146_, p_233147_, p_233148_, false);
|
||||
});
|
||||
+ else net.minecraftforge.client.ForgeHooksClient.createWorldConfirmationScreen(() -> this.doLoadLevel(p_233146_, p_233147_, p_233148_, false, true));
|
||||
worldstem.close();
|
||||
safeCloseAccess(levelstoragesource$levelstorageaccess, p_233147_);
|
||||
}
|
||||
+ net.minecraftforge.common.ForgeHooks.readAdditionalLevelSaveData(p_309733_, p_309733_.getLevelDirectory());
|
||||
+
|
||||
WorldStem worldstem;
|
||||
try {
|
||||
worldstem = this.loadWorldStem(p_312455_, p_310657_, packrepository);
|
||||
+ if (confirmExperimentalWarning && worldstem.worldData() instanceof PrimaryLevelData pld) pld.withConfirmedWarning(true);
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Failed to load level data or datapacks, can't proceed with server load", (Throwable)exception);
|
||||
if (!p_310657_) {
|
||||
@@ -305,7 +_,8 @@
|
||||
|
||||
WorldData worlddata = worldstem.worldData();
|
||||
boolean flag = worlddata.worldGenOptions().isOldCustomizedWorld();
|
||||
- boolean flag1 = worlddata.worldGenSettingsLifecycle() != Lifecycle.stable();
|
||||
+ boolean skipConfirmation = worlddata instanceof PrimaryLevelData pld && pld.hasConfirmedExperimentalWarning();
|
||||
+ boolean flag1 = worlddata.worldGenSettingsLifecycle() != Lifecycle.stable() && !skipConfirmation;
|
||||
if (!p_309504_ || !flag && !flag1) {
|
||||
DownloadedPackSource downloadedpacksource = this.minecraft.getDownloadedPackSource();
|
||||
this.loadBundledResourcePack(downloadedpacksource, p_309733_).thenApply((p_233177_) -> {
|
||||
@@ -328,12 +_,14 @@
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
+ if (flag) // Forge: For legacy world options, let vanilla handle it.
|
||||
this.askForBackup(p_309733_, flag, () -> {
|
||||
this.loadLevel(p_309733_, p_312455_, p_310657_, false, p_309915_);
|
||||
}, () -> {
|
||||
p_309733_.safeClose();
|
||||
p_309915_.run();
|
||||
});
|
||||
+ else net.minecraftforge.client.ForgeHooksClient.createWorldConfirmationScreen(() -> this.loadLevel(p_309733_, p_312455_, p_310657_, false, p_309915_, true));
|
||||
worldstem.close();
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/WorldSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/WorldSelectionList.java
|
||||
@@ -74,6 +_,7 @@
|
||||
@@ -76,6 +_,7 @@
|
||||
static final ResourceLocation JOIN_SPRITE = new ResourceLocation("world_list/join");
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
static final DateFormat DATE_FORMAT = new SimpleDateFormat();
|
||||
private static final ResourceLocation ICON_MISSING = new ResourceLocation("textures/misc/unknown_server.png");
|
||||
+ private static final ResourceLocation FORGE_EXPERIMENTAL_WARNING_ICON = new ResourceLocation("forge","textures/gui/experimental_warning.png");
|
||||
static final Component FROM_NEWER_TOOLTIP_1 = Component.translatable("selectWorld.tooltip.fromNewerVersion1").withStyle(ChatFormatting.RED);
|
||||
static final Component FROM_NEWER_TOOLTIP_2 = Component.translatable("selectWorld.tooltip.fromNewerVersion2").withStyle(ChatFormatting.RED);
|
||||
static final Component SNAPSHOT_TOOLTIP_1 = Component.translatable("selectWorld.tooltip.snapshot1").withStyle(ChatFormatting.GOLD);
|
||||
@@ -362,6 +_,7 @@
|
||||
@@ -372,6 +_,7 @@
|
||||
RenderSystem.enableBlend();
|
||||
p_281612_.blit(this.icon.textureLocation(), p_282820_, p_283181_, 0.0F, 0.0F, 32, 32, 32, 32);
|
||||
RenderSystem.disableBlend();
|
||||
@@ -16,10 +16,10 @@
|
||||
if (this.minecraft.options.touchscreen().get() || p_283396_) {
|
||||
p_281612_.fill(p_282820_, p_283181_, p_282820_ + 32, p_283181_ + 32, -1601138544);
|
||||
int j = p_283204_ - p_282820_;
|
||||
@@ -608,6 +_,19 @@
|
||||
@@ -579,6 +_,19 @@
|
||||
|
||||
public boolean isSelectable() {
|
||||
return !this.summary.isDisabled();
|
||||
public String getLevelName() {
|
||||
return this.summary.getLevelName();
|
||||
+ }
|
||||
+
|
||||
+ // FORGE: Patch in experimental warning icon for worlds in the world selection screen
|
||||
|
||||
Loaded 100 of 580 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user