mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 09:05:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16defac82e | ||
|
|
16483d4ea1 | ||
|
|
28909812bb | ||
|
|
e5580b84b7 | ||
|
|
607ca5beea | ||
|
|
744906e33a | ||
|
|
c1557ec3c2 | ||
|
|
4ac1a3dedf | ||
|
|
a26f952212 | ||
|
|
83ee68c0b0 | ||
|
|
a5ff932125 | ||
|
|
0d820eddd4 | ||
|
|
83c651ce39 | ||
|
|
7cd88944d4 | ||
|
|
dff52ecd71 | ||
|
|
da34d97d9d | ||
|
|
a27405b8d1 | ||
|
|
7a443276a5 | ||
|
|
e34090c809 | ||
|
|
72e8ae252c | ||
|
|
347c480bdc | ||
|
|
e0b9474621 | ||
|
|
8ad1e899a3 | ||
|
|
3b6bb5edbc | ||
|
|
c4e7d694c1 | ||
|
|
e00de1a326 | ||
|
|
e9ee999558 | ||
|
|
a1aacf25fe | ||
|
|
0c2f3e5523 | ||
|
|
a6978cffbf | ||
|
|
2332ecf984 | ||
|
|
9cd73c84a6 | ||
|
|
ab544a78d3 | ||
|
|
5b0abf97c8 | ||
|
|
587b684035 | ||
|
|
90dafb0df0 | ||
|
|
aff05a4cf3 | ||
|
|
1ddac54256 | ||
|
|
fcf9088aa5 | ||
|
|
374dbc7a4b | ||
|
|
d25ba7adc8 | ||
|
|
05c88ae33a | ||
|
|
e2d564d32a | ||
|
|
225092130e | ||
|
|
eefca22aa3 | ||
|
|
19bbb88e52 | ||
|
|
18886e5128 | ||
|
|
47dfa83cff | ||
|
|
0940c532f2 | ||
|
|
d80f106140 | ||
|
|
516b35ce57 | ||
|
|
be60ddbfca | ||
|
|
af6e848227 | ||
|
|
dd139115ed | ||
|
|
145df60bec | ||
|
|
f7cca8fb88 | ||
|
|
1f59b3f9fe | ||
|
|
084effdadf | ||
|
|
40a7998281 | ||
|
|
4786fa6f89 | ||
|
|
9291b865c7 | ||
|
|
52eca96fdc | ||
|
|
4649f7af36 |
No files matched your search
@@ -21,3 +21,6 @@ src/generated/**/*.json text eol=lf
|
||||
src/generated_test/**/.cache/cache text eol=lf
|
||||
src/generated_test/**/*.json text eol=lf
|
||||
|
||||
# We force eclipse to use unix line endings
|
||||
ide/eclipse/template/.settings/*.prefs text eol=lf
|
||||
|
||||
+6
-3
@@ -13,6 +13,9 @@
|
||||
/classes
|
||||
*.iml
|
||||
|
||||
# We however WANT the ide folder as it has tempaltes/configs for developing Forge.
|
||||
!ide/**
|
||||
|
||||
#gradle
|
||||
/build
|
||||
/.gradle
|
||||
@@ -31,9 +34,9 @@
|
||||
/projects/**/run/
|
||||
/projects/**/*.launch
|
||||
/repo/
|
||||
src/generated/resources/.cache/
|
||||
src/generated_test/resources/.cache/
|
||||
src/generated_mdk/resources/.cache/
|
||||
src/generated/resources/**/.cache/
|
||||
src/generated_test/resources/**/.cache/
|
||||
src/generated_mdk/resources/**/.cache/
|
||||
|
||||
#Patch rejects
|
||||
#/patches-/
|
||||
|
||||
Vendored
-15
@@ -47,8 +47,6 @@ project {
|
||||
""".trimIndent(), label = "The branch specification of the repository", description = "By default all main branches are build by the configuration. Modify this value to adapt the branches build.", display = ParameterDisplay.HIDDEN, allowEmpty = true)
|
||||
text("github_repository_name", "MinecraftForge", label = "The github repository name. Used to connect to it in VCS Roots.", description = "This is the repository slug on github. So for example `MinecraftForge` or `MinecraftForge`. It is interpolated into the global VCS Roots.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("env.PUBLISHED_JAVA_ARTIFACT_ID", "forge", label = "Published artifact id", description = "The maven coordinate artifact id that has been published by this build. Can not be empty.", allowEmpty = false)
|
||||
text("env.PUBLISHED_JAVA_FML_ARTIFACT_ID", "fmlonly", label = "Published fmlonly artifact id", description = "The maven coordinate artifact id for fml only that has been published by this build. Can not be empty.", allowEmpty = false)
|
||||
text("env.PUBLISHED_JAVA_FML_ARTIFACT_VERSION", "0.0.0-SNAPSHOT", label = "Published fmlonly artifact version", description = "The version for fml only that has been published by this build. Can not be empty.", allowEmpty = false)
|
||||
text("env.PUBLISHED_JAVA_GROUP", "net.minecraftforge", label = "Published group", description = "The maven coordinate group that has been published by this build. Can not be empty.", allowEmpty = false)
|
||||
//These are references and not actually keys
|
||||
password("env.CROWDIN_KEY", "credentialsJSON:a3102dbe-805d-4177-9f54-3d2c2eb08fd5", display = ParameterDisplay.HIDDEN)
|
||||
@@ -76,19 +74,6 @@ object Build : BuildType({
|
||||
id("MinecraftForge_MinecraftForge__Build")
|
||||
name = "Build"
|
||||
description = "Builds and Publishes the main branches of the project."
|
||||
|
||||
features {
|
||||
feature {
|
||||
id = "trigger_fml_only_files_generator"
|
||||
type = "triggerBuildFeature"
|
||||
param("triggers", "MinecraftForge_FilesGenerator_GeneratePages")
|
||||
param("parameters", """
|
||||
env.PUBLISHED_JAVA_FML_ARTIFACT_ID~env.PUBLISHED_JAVA_ARTIFACT_ID
|
||||
env.PUBLISHED_JAVA_FML_ARTIFACT_VERSION~env.PUBLISHED_JAVA_ARTIFACT_VERSION
|
||||
env.PUBLISHED_JAVA_GROUP
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
object BuildSecondaryBranches : BuildType({
|
||||
|
||||
+294
-462
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,92 @@
|
||||
package net.minecraftforge.forge.tasks;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Eclipse config files are literally just java properties, with the header cleaned up.
|
||||
* https://github.com/eclipse/buildship/blob/5b2c7fca7fa86cd74d71b3c099c7b1559eba038e/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/PreferenceStore.java#L238
|
||||
*
|
||||
* This does the same thing, as well as sorting alphabetically.
|
||||
* It also ignores all comments. We can add them latter if someone cares.
|
||||
*/
|
||||
public class CleanProperties extends Properties {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String LINE_SEP = System.getProperty("line.separator");
|
||||
private static final String UNIX_LINE_SEP = "\n";
|
||||
private static final Charset ENCODING = StandardCharsets.UTF_8;
|
||||
|
||||
public CleanProperties load(File input) throws IOException {
|
||||
if (input.exists()) {
|
||||
try (Reader is = new InputStreamReader(new FileInputStream(input), ENCODING)) {
|
||||
super.load(is);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void store(File out) throws IOException {
|
||||
if (!out.getParentFile().exists())
|
||||
out.getParentFile().mkdirs();
|
||||
|
||||
try (OutputStream os = new FileOutputStream(out)) {
|
||||
store(os, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Enumeration<Object> keys() {
|
||||
Set<Object> ret = new TreeSet<>();
|
||||
for (Enumeration<?> e = super.keys(); e.hasMoreElements();)
|
||||
ret.add(e.nextElement());
|
||||
return Collections.enumeration(ret);
|
||||
}
|
||||
|
||||
@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()));
|
||||
ret.addAll(super.entrySet());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(OutputStream out, String comments) throws IOException {
|
||||
out.write(clean().getBytes(ENCODING));
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Writer out, String comments) throws IOException {
|
||||
out.write(clean());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private String clean() throws IOException {
|
||||
ByteArrayOutputStream tmp = new ByteArrayOutputStream();
|
||||
try {
|
||||
super.store(tmp, null);
|
||||
} finally {
|
||||
tmp.close();
|
||||
}
|
||||
|
||||
String ret = tmp.toString(ENCODING).replace(LINE_SEP, UNIX_LINE_SEP);
|
||||
ret = ret.substring(ret.indexOf(UNIX_LINE_SEP) + 1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
abstract class Crowdin extends DefaultTask {
|
||||
@Input abstract Property<String> getId()
|
||||
@Input @Optional abstract Property<String> getKey()
|
||||
@Input boolean json = true
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@OutputFile abstract RegularFileProperty getExport()
|
||||
|
||||
Crowdin() {
|
||||
outputs.upToDateWhen{ false }
|
||||
id.convention('minecraft-forge')
|
||||
output.convention(project.layout.buildDirectory.dir(name).map {it.file("output.zip") })
|
||||
export.convention(project.layout.buildDirectory.dir(name).map {it.file("export.json") })
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
def run() {
|
||||
File outputFile = output.get().asFile
|
||||
File exportFile = export.get().asFile
|
||||
if (outputFile.exists())
|
||||
outputFile.delete()
|
||||
|
||||
if (!key.isPresent())
|
||||
return
|
||||
String key = this.key.get()
|
||||
String id = this.id.get()
|
||||
|
||||
// Force an export
|
||||
new URL("https://api.crowdin.com/api/project/${id}/export?key=${key}").withInputStream { i ->
|
||||
exportFile.withOutputStream { it << i }
|
||||
}
|
||||
|
||||
if (!exportFile.text.contains('success')) {
|
||||
throw new RuntimeException("Crowdin export failed, see ${exportFile} for more info")
|
||||
}
|
||||
|
||||
new URL("https://api.crowdin.com/api/project/${id}/download/all.zip?key=${key}").withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
outputFile.withOutputStream { out ->
|
||||
new ZipOutputStream(out).withCloseable { zout ->
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) != null) {
|
||||
if (zein.isDirectory()) {
|
||||
zout.putNextEntry(new ZipEntry(zein.name))
|
||||
} else {
|
||||
// 1.13+ uses json
|
||||
if (zein.name.endsWith('.json') == json) {
|
||||
ZipEntry zeout = new ZipEntry(json ? zein.name.toLowerCase() : zein.name)
|
||||
zeout.time = 1
|
||||
zout.putNextEntry(zeout)
|
||||
zout << zin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import groovy.json.JsonSlurper
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipFile
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
abstract class DevInstallerJar extends DefaultTask {
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@InputFile abstract RegularFileProperty getInput()
|
||||
|
||||
DevInstallerJar() {
|
||||
output.convention(project.layout.buildDirectory.file('libs/' + project.name + '-' + project.version + '-installer-dev.jar'))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
try (def zos = new ZipOutputStream(output.get().asFile.newDataOutputStream())) {
|
||||
def seen = [] as Set
|
||||
def deps = [:] as java.util.TreeMap
|
||||
try (def base = new ZipFile(input.get().asFile)) {
|
||||
base.entries().each { entry ->
|
||||
zos.putNextEntry(entry)
|
||||
def data = base.getInputStream(entry).bytes
|
||||
zos.write(data)
|
||||
|
||||
if (entry.name == 'install_profile.json' || entry.name == 'version.json') {
|
||||
def json = new JsonSlurper().parse(data)
|
||||
json.libraries.each { lib ->
|
||||
deps.put(lib.name, lib.downloads.artifact)
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.name.startsWith('maven/'))
|
||||
seen.add(entry.name.substring(6))
|
||||
}
|
||||
}
|
||||
|
||||
def resolved = project.configurations.installer.resolvedConfiguration.resolvedArtifacts
|
||||
|
||||
deps.each { name, info ->
|
||||
if (seen.contains(info.path))
|
||||
return
|
||||
|
||||
def art = resolved.find { "${it.moduleVersion.id.group}:${it.moduleVersion.id.name}:${it.moduleVersion.id.version}" == name }
|
||||
|
||||
def file = null
|
||||
if (art != null) {
|
||||
if (!Util.checkExists(info.url))
|
||||
file = art.file
|
||||
} else {
|
||||
// TODO download missing things
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
//println('maven/' + info.path)
|
||||
zos.putNextEntry(new ZipEntry('maven/' + info.path))
|
||||
zos.write(file.bytes)
|
||||
seen.add(info.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
abstract class FixPatchImports extends DefaultTask {
|
||||
|
||||
@InputDirectory abstract DirectoryProperty getClean()
|
||||
@InputDirectory abstract DirectoryProperty getPatched()
|
||||
|
||||
@TaskAction
|
||||
void run() {
|
||||
final patchedPath = getPatched().get().asFile.toPath()
|
||||
final cleanPath = getClean().get().asFile.toPath()
|
||||
|
||||
try (final var stream = Files.find(patchedPath, Integer.MAX_VALUE, (path, attr) -> path.toString().endsWith('.java'))) {
|
||||
final itr = stream.iterator()
|
||||
while (itr.hasNext()) {
|
||||
final next = itr.next()
|
||||
final clean = cleanPath.resolve(patchedPath.relativize(next).toString())
|
||||
|
||||
final patchedLines = Files.readAllLines(next)
|
||||
final cleanLines = Files.readAllLines(clean)
|
||||
|
||||
final patchedImport = patchedLines.findLastIndexOf(2) { it.startsWith('import ') }
|
||||
final cleanImport = cleanLines.findLastIndexOf(2) { it.startsWith('import ') }
|
||||
|
||||
if (cleanImport !== patchedImport) {
|
||||
patchedLines.removeIf { it.startsWith('import ') }
|
||||
patchedLines.addAll(2, cleanLines.subList(2, cleanImport + 1))
|
||||
Files.write(next, patchedLines)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ public class Util {
|
||||
return getArtifacts(project, cfg, true)
|
||||
}
|
||||
|
||||
private static boolean checkExists(url) {
|
||||
static boolean checkExists(url) {
|
||||
try {
|
||||
def code = new URL(url).openConnection().with {
|
||||
requestMethod = 'HEAD'
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'eclipse'
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.16,6.2)'
|
||||
}
|
||||
|
||||
evaluationDependsOn(':mcp')
|
||||
|
||||
dependencies {
|
||||
implementation(libs.forgespi)
|
||||
}
|
||||
|
||||
patcher {
|
||||
parent = project(':mcp')
|
||||
mcVersion = MC_VERSION
|
||||
patchedSrc = file('src/main/java')
|
||||
|
||||
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
|
||||
|
||||
runs {
|
||||
clean_client {
|
||||
client true
|
||||
taskName 'clean_client'
|
||||
ideaModule "${rootProject.name}.${project.name}.main"
|
||||
|
||||
main 'net.minecraft.client.main.Main'
|
||||
workingDirectory project.file('run/client')
|
||||
|
||||
args '--gameDir', '.'
|
||||
args '--version', MC_VERSION
|
||||
args '--assetsDir', downloadAssets.output
|
||||
args '--assetIndex', '{asset_index}'
|
||||
args '--accessToken', '0'
|
||||
}
|
||||
|
||||
clean_server {
|
||||
client false
|
||||
taskName 'clean_server'
|
||||
ideaModule "${rootProject.name}.${project.name}.main"
|
||||
|
||||
main 'net.minecraft.server.Main'
|
||||
workingDirectory project.file('run/server')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eclipse.classpath.file.whenMerged {
|
||||
// Disable optional warnings on the minecraft decompiled source code. It just muddies the warning window and hides warnings in our own codebase
|
||||
def src = entries.find { it.path == 'src/main/java' }
|
||||
src.entryAttributes['ignore_optional_problems'] = 'true'
|
||||
}
|
||||
+3
-3
@@ -2,8 +2,8 @@
|
||||
|
||||
MinecraftForge
|
||||
=============
|
||||
[][Download]
|
||||
[][Download]
|
||||
[][Download] [][Discord] [][Patreon]
|
||||
|
||||
Forge is a free, open-source modding API all of your favourite mods use!
|
||||
@@ -73,4 +73,4 @@ Please ensure you have a valid email address associated with your GitHub account
|
||||
[ForgeDev]: https://docs.minecraftforge.net/en/latest/forgedev/
|
||||
[Pull-Requests]: https://docs.minecraftforge.net/en/latest/forgedev/#making-changes-and-pull-requests
|
||||
|
||||
[Patreon]: https://www.patreon.com/MinecraftForge
|
||||
[Patreon]: https://www.patreon.com/LexManos
|
||||
@@ -2,20 +2,19 @@ plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'java-library'
|
||||
id 'jacoco'
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
|
||||
compileOnly(libs.nulls)
|
||||
|
||||
api("net.minecraftforge:eventbus:${EVENTBUS_VERSION}")
|
||||
api(libs.eventbus)
|
||||
|
||||
implementation(project(':fmlloader'))
|
||||
implementation("commons-io:commons-io:${COMMONS_IO_VERSION}")
|
||||
implementation(libs.commons.io)
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.function.Supplier;
|
||||
* @param <T> the type of the record which is held by the extension point
|
||||
*/
|
||||
@SuppressWarnings("unused") // Type parameter T
|
||||
// TODO: Complete re-write, this hasnt actually be used in a generic way by mods and we could make it a lot simpler.
|
||||
public interface IExtensionPoint<T extends Record>
|
||||
{
|
||||
/**
|
||||
@@ -40,7 +41,7 @@ public interface IExtensionPoint<T extends Record>
|
||||
* where {@code true} means it is from the server and {@code false} means it is from the world save. The return
|
||||
* value of the predicate determines whether the remote version is "compatible" for the purposes of the display test.</p>
|
||||
*
|
||||
* <p>The local compatibility version may be of the value {@link net.minecraftforge.network.NetworkConstants#IGNORESERVERONLY},
|
||||
* <p>The local compatibility version may be of the value {@link DisplayTest#IGNORESERVERONLY},
|
||||
* in which case clients will ignore the mod's presence if it is present on the server but not on the client.
|
||||
* However, the remote version test predicate must still accept this value as a remote version in order to display
|
||||
* as compatible if the mod is present on the client.</p>
|
||||
@@ -94,6 +95,6 @@ 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 = "OHNOES\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31";
|
||||
public static final String IGNORESERVERONLY = "SERVER_ONLY";
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.7' apply false
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'java-library'
|
||||
id 'jacoco'
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
switch (OperatingSystem.current()) {
|
||||
case OperatingSystem.LINUX:
|
||||
project.ext.lwjglNatives = "natives-linux"
|
||||
@@ -21,22 +18,15 @@ switch (OperatingSystem.current()) {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
|
||||
java.withSourcesJar()
|
||||
|
||||
dependencies {
|
||||
compileOnly('org.jetbrains:annotations:23.0.0')
|
||||
compileOnly(libs.nulls)
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
implementation('org.lwjgl:lwjgl:3.3.1')
|
||||
implementation('org.lwjgl:lwjgl-glfw:3.3.1')
|
||||
implementation('org.lwjgl:lwjgl-opengl:3.3.1')
|
||||
implementation('org.lwjgl:lwjgl-stb:3.3.1')
|
||||
implementation('org.lwjgl:lwjgl-tinyfd:3.3.1')
|
||||
implementation(libs.bundles.lwjgl)
|
||||
implementation('org.slf4j:slf4j-api:1.8.0-beta4')
|
||||
implementation("net.sf.jopt-simple:jopt-simple:${JOPT_SIMPLE_VERSION}")
|
||||
implementation(libs.jopt.simple)
|
||||
testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.2')
|
||||
testImplementation('org.powermock:powermock-core:2.0.9')
|
||||
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.8.2')
|
||||
@@ -51,31 +41,16 @@ test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
ext {
|
||||
MANIFESTS = [
|
||||
'': [
|
||||
'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
'Git-Commit': GIT_INFO.abbreviatedId,
|
||||
'Git-Branch': GIT_INFO.branch,
|
||||
'Build-Number': "${System.getenv('BUILD_NUMBER')?:0}",
|
||||
] as LinkedHashMap,
|
||||
'net/minecraftforge/fml/earlydisplay/': [
|
||||
jar {
|
||||
manifest {
|
||||
attributes([
|
||||
'Specification-Title': 'FMLEarlyDisplay',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'FML Early Display',
|
||||
'Implementation-Version': '1.0',
|
||||
'Implementation-Vendor': 'Forge'
|
||||
] as LinkedHashMap
|
||||
]
|
||||
}
|
||||
|
||||
jar.doFirst {
|
||||
MANIFESTS.each { pkg, values ->
|
||||
if (pkg == '')
|
||||
manifest.attributes(values)
|
||||
else
|
||||
manifest.attributes(values, pkg)
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/earlydisplay/')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-2
@@ -40,11 +40,13 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
@@ -86,6 +88,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
private int framecount;
|
||||
private EarlyFramebuffer framebuffer;
|
||||
private ScheduledFuture<?> windowTick;
|
||||
private ScheduledFuture<?> initializationFuture;
|
||||
|
||||
private PerformanceInfo performanceInfo;
|
||||
private ScheduledFuture<?> performanceTick;
|
||||
@@ -264,7 +267,6 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
public void render(int alpha) {
|
||||
var currentVAO = glGetInteger(GL_VERTEX_ARRAY_BINDING);
|
||||
var currentFB = glGetInteger(GL_READ_FRAMEBUFFER_BINDING);
|
||||
glfwSwapInterval(0);
|
||||
glViewport(0, 0, this.context.scaledWidth(), this.context.scaledHeight());
|
||||
RenderElement.globalAlpha = alpha;
|
||||
framebuffer.activate();
|
||||
@@ -287,7 +289,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
return thread;
|
||||
});
|
||||
initWindow(mcVersion);
|
||||
renderScheduler.schedule(() -> initRender(mcVersion, forgeVersion), 1, TimeUnit.MILLISECONDS);
|
||||
this.initializationFuture = renderScheduler.schedule(() -> initRender(mcVersion, forgeVersion), 1, TimeUnit.MILLISECONDS);
|
||||
return this::periodicTick;
|
||||
}
|
||||
|
||||
@@ -518,6 +520,16 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
* @return the Window we own.
|
||||
*/
|
||||
public long setupMinecraftWindow(final IntSupplier width, final IntSupplier height, final Supplier<String> title, final LongSupplier monitorSupplier) {
|
||||
// wait for the window to actually be initialized
|
||||
try {
|
||||
this.initializationFuture.get(30, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (TimeoutException e) {
|
||||
Thread.dumpStack();
|
||||
crashElegantly("We seem to be having trouble initializing the window, waited for 30 seconds");
|
||||
}
|
||||
|
||||
// we have to spin wait for the window ticker
|
||||
ImmediateWindowHandler.updateProgress("Initializing Game Graphics");
|
||||
while (!this.windowTick.isDone()) {
|
||||
|
||||
+27
-37
@@ -2,47 +2,43 @@ plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'java-library'
|
||||
id 'jacoco'
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
configurations.forEach{ it.transitive = false }
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
|
||||
compileOnly(libs.nulls)
|
||||
|
||||
api("org.ow2.asm:asm:${ASM_VERSION}")
|
||||
api("org.ow2.asm:asm-tree:${ASM_VERSION}")
|
||||
api("org.ow2.asm:asm-commons:${ASM_VERSION}")
|
||||
api("net.minecraftforge:forgespi:${SPI_VERSION}")
|
||||
api("net.minecraftforge:mergetool:${MERGETOOL_VERSION}:api")
|
||||
api("org.apache.logging.log4j:log4j-api:${LOG4J_VERSION}")
|
||||
api("org.slf4j:slf4j-api:${SLF4J_API_VERSION}")
|
||||
api("com.google.guava:guava:${GUAVA_VERSION}")
|
||||
api("com.google.code.gson:gson:${GSON_VERSION}")
|
||||
api("org.apache.maven:maven-artifact:${APACHE_MAVEN_ARTIFACT_VERSION}")
|
||||
api("org.apache.commons:commons-lang3:${APACHE_COMMONS_LANG3_VERSION}")
|
||||
api("com.electronwill.night-config:core:${NIGHTCONFIG_VERSION}")
|
||||
api("com.electronwill.night-config:toml:${NIGHTCONFIG_VERSION}")
|
||||
api("cpw.mods:modlauncher:${MODLAUNCHER_VERSION}")
|
||||
api("net.minecraftforge:coremods:${COREMODS_VERSION}")
|
||||
api("com.mojang:logging:${MOJANG_LOGGING_VERSION}")
|
||||
api "net.minecraftforge:JarJarSelector:${JARJAR_VERSION}"
|
||||
api "net.minecraftforge:JarJarMetadata:${JARJAR_VERSION}"
|
||||
api(libs.bundles.asm) // Needed by all the black magic
|
||||
api(libs.forgespi)
|
||||
api(libs.mergetool.api)
|
||||
api(libs.log4j.api)
|
||||
api(libs.slf4j.api)
|
||||
api(libs.guava)
|
||||
api(libs.gson)
|
||||
api(libs.maven.artifact)
|
||||
api(libs.apache.commons)
|
||||
api(libs.bundles.night.config)
|
||||
api(libs.modlauncher)
|
||||
api(libs.coremods)
|
||||
api(libs.mojang.logging)
|
||||
api(libs.jarjar.selector)
|
||||
api(libs.jarjar.meta)
|
||||
|
||||
implementation("net.sf.jopt-simple:jopt-simple:${JOPT_SIMPLE_VERSION}")
|
||||
implementation("cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}")
|
||||
implementation("net.minecraftforge:accesstransformers:${ACCESSTRANSFORMERS_VERSION}")
|
||||
implementation("net.minecrell:terminalconsoleappender:${TERMINALCONSOLEAPPENDER_VERSION}")
|
||||
// implementation("org.jline:jline:${JLINE_VERSION}")
|
||||
implementation(libs.jopt.simple)
|
||||
implementation(libs.securemodules)
|
||||
implementation(libs.accesstransformers)
|
||||
implementation(libs.terminalconsoleappender)
|
||||
implementation(libs.jimfs)
|
||||
|
||||
implementation("org.apache.logging.log4j:log4j-core:${LOG4J_VERSION}")
|
||||
annotationProcessor("org.apache.logging.log4j:log4j-core:${LOG4J_VERSION}")
|
||||
implementation(libs.log4j.core)
|
||||
annotationProcessor(libs.log4j.core)
|
||||
|
||||
testCompileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
|
||||
testRuntimeOnly("cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}")
|
||||
testCompileOnly(libs.nulls)
|
||||
testRuntimeOnly(libs.bootstrap)
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
@@ -52,12 +48,6 @@ task sourcesJar(type: Jar) {
|
||||
|
||||
ext {
|
||||
MANIFESTS = [
|
||||
'/': [
|
||||
'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
'Git-Commit': GIT_INFO.abbreviatedId,
|
||||
'Git-Branch': GIT_INFO.branch,
|
||||
'Build-Number': "${System.getenv('BUILD_NUMBER')?:0}",
|
||||
] as LinkedHashMap,
|
||||
'net/minecraftforge/fml/loading/': [
|
||||
'Specification-Title': 'FMLLoader',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
|
||||
@@ -56,6 +56,7 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
|
||||
return lst != null && lst.stream().anyMatch(n -> n.desc.equals(OBJECT_HOLDER));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String getValue(List<AnnotationNode> lst)
|
||||
{
|
||||
AnnotationNode ann = lst.stream().filter(n -> n.desc.equals(OBJECT_HOLDER)).findFirst().get();
|
||||
|
||||
@@ -20,8 +20,6 @@ import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
/**
|
||||
* Modifies specified enums to allow runtime extension by making the $VALUES field non-final and
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -14,6 +14,8 @@ import java.util.List;
|
||||
* or server.
|
||||
*/
|
||||
public class EarlyLoadingException extends RuntimeException {
|
||||
private static final long serialVersionUID = 2302192216172508006L;
|
||||
|
||||
public static class ExceptionData {
|
||||
private final IModInfo modInfo;
|
||||
private final String i18message;
|
||||
|
||||
@@ -42,7 +42,6 @@ public class FMLConfig
|
||||
private final String entry;
|
||||
private final Object defaultValue;
|
||||
private final String comment;
|
||||
private final Class<?> valueType;
|
||||
private final Function<Object, Object> entryFunction;
|
||||
|
||||
ConfigValue(final String entry, final Object defaultValue, final String comment) {
|
||||
@@ -52,7 +51,6 @@ public class FMLConfig
|
||||
this.entry = entry;
|
||||
this.defaultValue = defaultValue;
|
||||
this.comment = comment;
|
||||
this.valueType = defaultValue.getClass();
|
||||
this.entryFunction = entryFunction;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModValidator;
|
||||
import net.minecraftforge.accesstransformer.service.AccessTransformerService;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
import net.minecraftforge.fml.loading.targets.CommonLaunchHandler;
|
||||
import net.minecraftforge.forgespi.Environment;
|
||||
import net.minecraftforge.forgespi.coremod.ICoreModProvider;
|
||||
@@ -137,6 +136,7 @@ public class FMLLoader
|
||||
throw new RuntimeException("Missing launch handler: " + launchTarget);
|
||||
}
|
||||
|
||||
// TODO: What the fuck is the point of using a service if you require a specific concrete class
|
||||
if (!(launchHandler.get() instanceof CommonLaunchHandler)) {
|
||||
LOGGER.error(CORE, "Incompatible Launch handler found - type {}, cannot continue", launchHandler.get().getClass().getName());
|
||||
throw new RuntimeException("Incompatible launch handler found");
|
||||
|
||||
@@ -126,6 +126,7 @@ public class FMLServiceProvider implements ITransformationService
|
||||
targetMcpMappings = option.value(mappingsOption);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public @NotNull List<ITransformer> transformers()
|
||||
{
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class FileUtils
|
||||
{
|
||||
|
||||
public static String fileExtension(final Path path) {
|
||||
String fileName = path.getFileName().toString();
|
||||
int idx = fileName.lastIndexOf('.');
|
||||
if (idx > -1) {
|
||||
return fileName.substring(idx+1);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean matchFileName(String path, String... matches) {
|
||||
// Extract file name from path
|
||||
String name = path.substring(Math.min(path.lastIndexOf(File.separatorChar) + 1, path.length()));
|
||||
// Check if it contains any of the desired keywords
|
||||
for (String match : matches) {
|
||||
if (name.contains(match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class ImmediateWindowHandler {
|
||||
|
||||
private static ProgressMeter earlyProgress;
|
||||
public static void load(final String launchTarget, final String[] arguments) {
|
||||
if (!List.of("forgeclient", "forgeclientuserdev", "forgeclientdev").contains(launchTarget)) {
|
||||
if (!launchTarget.contains("client")) {
|
||||
provider = new DummyProvider();
|
||||
LOGGER.info("ImmediateWindowProvider not loading because launch target is {}", launchTarget);
|
||||
} else if (!FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_CONTROL)) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.Optional;
|
||||
* Finds Version data from a package, with possible default values
|
||||
*/
|
||||
public class JarVersionLookupHandler {
|
||||
|
||||
public static Optional<String> getImplementationVersion(final String pkgName) {
|
||||
// Note that with Java 9, you'll probably want the module's version data, hence pulling this out
|
||||
final String pkgVersion = Package.getPackage(pkgName).getImplementationVersion();
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
|
||||
-3
@@ -7,7 +7,6 @@ package net.minecraftforge.fml.loading;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import cpw.mods.modlauncher.api.NamedPath;
|
||||
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
|
||||
@@ -19,8 +18,6 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.Set;
|
||||
|
||||
public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService {
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
||||
|
||||
public class ModJarURLHandler extends URLStreamHandler
|
||||
{
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
// modjar://modid/path/to/file
|
||||
@Override
|
||||
protected URLConnection openConnection(URL url) {
|
||||
return new ModJarURLConnection(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int hashCode(final URL u) {
|
||||
return Objects.hash(u.getHost(), u.getFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean equals(final URL u1, final URL u2) {
|
||||
return Objects.equals(u1.getProtocol(), u2.getProtocol())
|
||||
&& Objects.equals(u1.getHost(), u2.getHost())
|
||||
&& Objects.equals(u1.getFile(), u2.getFile());
|
||||
}
|
||||
|
||||
static class ModJarURLConnection extends URLConnection {
|
||||
private Path resource;
|
||||
private String modpath;
|
||||
private String modid;
|
||||
private Optional<Manifest> manifest;
|
||||
|
||||
public ModJarURLConnection(final URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect()
|
||||
{
|
||||
// if (resource == null) {
|
||||
// modid = url.getHost();
|
||||
// // trim first char
|
||||
// modpath = url.getPath().substring(1);
|
||||
// resource = FMLLoader.getLoadingModList().getModFileById(modid).getFile().findResource(modpath);
|
||||
// manifest = FMLLoader.getLoadingModList().getModFileById(modid).getManifest();
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
connect();
|
||||
LOGGER.trace(CORE, "Loading modjar URL {} got resource {} {}", url, resource, resource != null ? Files.exists(resource) : "missing");
|
||||
return Files.newInputStream(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentLengthLong() {
|
||||
try {
|
||||
connect();
|
||||
return Files.size(resource);
|
||||
} catch (IOException e) {
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
|
||||
// Used to cache protectiondomains by "top level object" aka the modid
|
||||
@Override
|
||||
public URL getURL() {
|
||||
return LamdbaExceptionUtils.uncheck(()->new URL("modjar://"+modid));
|
||||
}
|
||||
|
||||
public Optional<Manifest> getManifest() {
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import com.google.common.graph.MutableGraph;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.fml.loading.EarlyLoadingException.ExceptionData;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
@@ -72,7 +71,6 @@ public class ModSorter
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
private void sort()
|
||||
{
|
||||
// lambdas are identity based, so sorting them is impossible unless you hold reference to them
|
||||
@@ -121,7 +119,6 @@ public class ModSorter
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
private void addDependency(MutableGraph<ModFileInfo> topoGraph, IModInfo.ModVersion dep)
|
||||
{
|
||||
final ModFileInfo self = (ModFileInfo)dep.getOwner().getOwningFile();
|
||||
@@ -133,6 +130,7 @@ public class ModSorter
|
||||
switch (dep.getOrdering()) {
|
||||
case BEFORE -> topoGraph.putEdge(self, target);
|
||||
case AFTER -> topoGraph.putEdge(target, self);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-32
@@ -27,8 +27,7 @@ import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public abstract class AbstractModProvider implements IModProvider
|
||||
{
|
||||
public abstract class AbstractModProvider implements IModProvider {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
protected static final String MODS_TOML = "META-INF/mods.toml";
|
||||
protected static final String MANIFEST = "META-INF/MANIFEST.MF";
|
||||
@@ -36,26 +35,24 @@ public abstract class AbstractModProvider implements IModProvider
|
||||
protected IModLocator.ModFileOrException createMod(Path... path) {
|
||||
var mjm = new ModJarMetadata();
|
||||
var sj = SecureJar.from(
|
||||
Manifest::new,
|
||||
jar -> jar.moduleDataProvider().findFile(MODS_TOML).isPresent() ? mjm : JarMetadata.from(jar, path),
|
||||
(root, p) -> true,
|
||||
path
|
||||
Manifest::new,
|
||||
jar -> jar.moduleDataProvider().findFile(MODS_TOML).isPresent() ? mjm : JarMetadata.from(jar, path),
|
||||
path
|
||||
);
|
||||
|
||||
IModFile mod;
|
||||
var type = sj.moduleDataProvider().getManifest().getMainAttributes().getValue(ModFile.TYPE);
|
||||
if (type == null) {
|
||||
if (type == null)
|
||||
type = getDefaultJarModType();
|
||||
}
|
||||
|
||||
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);
|
||||
} else if (type != null) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MANIFEST, type, path);
|
||||
mod = new ModFile(sj, this, this::manifestParser, type);
|
||||
} else {
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Invalid mod file found "+ Arrays.toString(path)));
|
||||
}
|
||||
} else
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Invalid mod file found " + Arrays.toString(path)));
|
||||
|
||||
mjm.setModFile(mod);
|
||||
return new IModLocator.ModFileOrException(mod, null);
|
||||
@@ -88,36 +85,19 @@ public abstract class AbstractModProvider implements IModProvider
|
||||
}
|
||||
|
||||
private record DefaultModFileInfo(IModFile mod, String license, IConfigurable configurable) implements IModFileInfo, IConfigurable {
|
||||
@Override
|
||||
public <T> Optional<T> getConfigElement(final String... strings)
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends IConfigurable> getConfigList(final String... strings)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public <T> Optional<T> getConfigElement(final String... strings) { return Optional.empty(); }
|
||||
@Override public List<? extends IConfigurable> getConfigList(final String... strings) { return null; }
|
||||
@Override public List<IModInfo> getMods() { return Collections.emptyList(); }
|
||||
@Override public List<LanguageSpec> requiredLanguageLoaders() { return Collections.emptyList(); }
|
||||
@Override public boolean showAsResourcePack() { return false; }
|
||||
@Override public Map<String, Object> getFileProperties() { return Collections.emptyMap(); }
|
||||
@Override
|
||||
public String getLicense() { return license; }
|
||||
|
||||
@Override public String getLicense() { return license; }
|
||||
@Override public IModFile getFile() { return mod; }
|
||||
@Override public IConfigurable getConfig() { return configurable; }
|
||||
|
||||
// These Should never be called as it's only called from ModJarMetadata.version and we bypass that
|
||||
@Override public String moduleName() { return mod.getSecureJar().name(); }
|
||||
@Override public String versionString() { return null; }
|
||||
@Override public List<String> usesServices() { return null; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IModFileInfo(" + mod.getFilePath() + ")";
|
||||
}
|
||||
@Override public String toString() { return "IModFileInfo(" + mod.getFilePath() + ")"; }
|
||||
}
|
||||
}
|
||||
-12
@@ -9,13 +9,11 @@ import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.fml.loading.ImmediateWindowHandler;
|
||||
import net.minecraftforge.fml.loading.LoadingModList;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@@ -32,9 +30,6 @@ public class BackgroundScanHandler
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final ExecutorService modContentScanner;
|
||||
private final List<ModFile> pendingFiles;
|
||||
private final List<ModFile> scannedFiles;
|
||||
private final List<ModFile> allFiles;
|
||||
private final List<ModFile> modFiles;
|
||||
private ScanStatus status;
|
||||
private LoadingModList loadingModList;
|
||||
@@ -46,9 +41,6 @@ public class BackgroundScanHandler
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
scannedFiles = new ArrayList<>();
|
||||
pendingFiles = new ArrayList<>();
|
||||
allFiles = new ArrayList<>();
|
||||
status = ScanStatus.NOT_STARTED;
|
||||
}
|
||||
|
||||
@@ -63,8 +55,6 @@ public class BackgroundScanHandler
|
||||
}
|
||||
status = ScanStatus.RUNNING;
|
||||
ImmediateWindowHandler.updateProgress("Scanning mod candidates");
|
||||
allFiles.add(file);
|
||||
pendingFiles.add(file);
|
||||
final CompletableFuture<ModFileScanData> future = CompletableFuture.supplyAsync(file::compileContent, modContentScanner)
|
||||
.whenComplete(file::setScanResult)
|
||||
.whenComplete((r,t)-> this.addCompletedFile(file,r,t));
|
||||
@@ -76,8 +66,6 @@ public class BackgroundScanHandler
|
||||
status = ScanStatus.ERRORED;
|
||||
LOGGER.error(LogMarkers.SCAN,"An error occurred scanning file {}", file, throwable);
|
||||
}
|
||||
pendingFiles.remove(file);
|
||||
scannedFiles.add(file);
|
||||
}
|
||||
|
||||
public void setLoadingModList(LoadingModList loadingModList)
|
||||
|
||||
+1
-23
@@ -12,12 +12,9 @@ import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
@@ -25,8 +22,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ClasspathLocator extends AbstractJarFileModLocator
|
||||
{
|
||||
public class ClasspathLocator extends AbstractJarFileModLocator {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final List<Path> legacyClasspath = Arrays.stream(System.getProperty("legacyClassPath", "").split(File.pathSeparator)).map(Path::of).toList();
|
||||
private boolean enabled = false;
|
||||
@@ -73,22 +69,4 @@ public class ClasspathLocator extends AbstractJarFileModLocator
|
||||
var launchTarget = (String) arguments.get("launchTarget");
|
||||
enabled = launchTarget != null && launchTarget.contains("dev");
|
||||
}
|
||||
|
||||
private Path findJarPathFor(final String resourceName, final String jarName, final URL resource) {
|
||||
try {
|
||||
Path path;
|
||||
final URI uri = resource.toURI();
|
||||
if (uri.getScheme().equals("jar") && uri.getRawSchemeSpecificPart().contains("!/")) {
|
||||
int lastExcl = uri.getRawSchemeSpecificPart().lastIndexOf("!/");
|
||||
path = Paths.get(new URI(uri.getRawSchemeSpecificPart().substring(0, lastExcl)));
|
||||
} else {
|
||||
path = Paths.get(new URI("file://"+uri.getRawSchemeSpecificPart().substring(0, uri.getRawSchemeSpecificPart().length()-resourceName.length())));
|
||||
}
|
||||
//LOGGER.debug(CORE, "Found JAR {} at path {}", jarName, path.toString());
|
||||
return path;
|
||||
} catch (NullPointerException | URISyntaxException e) {
|
||||
LOGGER.error(LogMarkers.SCAN, "Failed to find JAR for class {} - {}", resourceName, jarName);
|
||||
throw new RuntimeException("Unable to locate "+resourceName+" - "+jarName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -34,7 +34,7 @@ public class ExplodedDirectoryLocator implements IModLocator {
|
||||
explodedMods.forEach(explodedMod ->
|
||||
ModJarMetadata.buildFile(this,
|
||||
jar->jar.moduleDataProvider().findFile("/META-INF/mods.toml").isPresent(),
|
||||
(a,b) -> true,
|
||||
null,
|
||||
explodedMod.paths().toArray(Path[]::new))
|
||||
.ifPresentOrElse(f->mods.put(explodedMod, f), () -> LOGGER.warn(LogMarkers.LOADING, "Failed to find exploded resource mods.toml in directory {}", explodedMod.paths().get(0).toString())));
|
||||
return mods.values().stream().map(mf->new IModLocator.ModFileOrException(mf, null)).toList();
|
||||
|
||||
+3
-4
@@ -11,12 +11,11 @@ import net.minecraftforge.forgespi.locating.ModFileLoadingException;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public class InvalidModFileException extends ModFileLoadingException
|
||||
{
|
||||
public class InvalidModFileException extends ModFileLoadingException {
|
||||
private static final long serialVersionUID = 1230464325917450374L;
|
||||
private final IModFileInfo modFileInfo;
|
||||
|
||||
public InvalidModFileException(String message, IModFileInfo modFileInfo)
|
||||
{
|
||||
public InvalidModFileException(String message, IModFileInfo modFileInfo) {
|
||||
super(String.format(Locale.ROOT, "%s (%s)", message, Optional.ofNullable(modFileInfo).map(mf->mf.getFile().getFileName()).orElse("MISSING FILE NAME")));
|
||||
this.modFileInfo = modFileInfo;
|
||||
}
|
||||
|
||||
+15
-29
@@ -10,72 +10,58 @@ import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class ModAnnotationVisitor extends AnnotationVisitor
|
||||
{
|
||||
public class ModAnnotationVisitor extends AnnotationVisitor {
|
||||
private final ModAnnotation annotation;
|
||||
private LinkedList<ModAnnotation> annotations;
|
||||
private boolean array;
|
||||
private String name;
|
||||
private boolean isSubAnnotation;
|
||||
|
||||
public ModAnnotationVisitor(LinkedList<ModAnnotation> annotations, ModAnnotation annotation)
|
||||
{
|
||||
public ModAnnotationVisitor(LinkedList<ModAnnotation> annotations, ModAnnotation annotation) {
|
||||
super(Opcodes.ASM9);
|
||||
this.annotations = annotations;
|
||||
this.annotation = annotation;
|
||||
}
|
||||
|
||||
public ModAnnotationVisitor(LinkedList<ModAnnotation> annotations, ModAnnotation annotation, String name)
|
||||
{
|
||||
public ModAnnotationVisitor(LinkedList<ModAnnotation> annotations, ModAnnotation annotation, String name) {
|
||||
this(annotations, annotation);
|
||||
this.array = true;
|
||||
this.name = name;
|
||||
annotation.addArray(name);
|
||||
}
|
||||
|
||||
public ModAnnotationVisitor(LinkedList<ModAnnotation> annotations, ModAnnotation annotation, boolean isSubAnnotation)
|
||||
{
|
||||
public ModAnnotationVisitor(LinkedList<ModAnnotation> annotations, ModAnnotation annotation, boolean isSubAnnotation) {
|
||||
this(annotations, annotation);
|
||||
this.isSubAnnotation = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(String key, Object value)
|
||||
{
|
||||
public void visit(String key, Object value) {
|
||||
annotation.addProperty(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(String name, String desc, String value)
|
||||
{
|
||||
public void visitEnum(String name, String desc, String value) {
|
||||
annotation.addEnumProperty(name, desc, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String name)
|
||||
{
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
return new ModAnnotationVisitor(annotations, annotation, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc)
|
||||
{
|
||||
ModAnnotation ma = annotations.getFirst();
|
||||
final ModAnnotation childAnnotation = ma.addChildAnnotation(name, desc);
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc) {
|
||||
var ma = annotations.getFirst();
|
||||
var childAnnotation = ma.addChildAnnotation(name, desc);
|
||||
annotations.addFirst(childAnnotation);
|
||||
return new ModAnnotationVisitor(annotations, childAnnotation,true);
|
||||
return new ModAnnotationVisitor(annotations, childAnnotation, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd()
|
||||
{
|
||||
public void visitEnd() {
|
||||
if (array)
|
||||
{
|
||||
annotation.endArray();
|
||||
}
|
||||
|
||||
if (isSubAnnotation)
|
||||
{
|
||||
ModAnnotation child = annotations.removeFirst();
|
||||
annotations.addLast(child);
|
||||
}
|
||||
annotations.addLast(annotations.removeFirst());
|
||||
}
|
||||
}
|
||||
+13
-22
@@ -15,58 +15,49 @@ import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ModClassVisitor extends ClassVisitor
|
||||
{
|
||||
public class ModClassVisitor extends ClassVisitor {
|
||||
private Type asmType;
|
||||
private Type asmSuperType;
|
||||
private Set<Type> interfaces;
|
||||
private final LinkedList<ModAnnotation> annotations = new LinkedList<>();
|
||||
public ModClassVisitor()
|
||||
{
|
||||
|
||||
public ModClassVisitor() {
|
||||
super(Opcodes.ASM9);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
||||
{
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
this.asmType = Type.getObjectType(name);
|
||||
this.asmSuperType = superName != null && superName.length() > 0 ? Type.getObjectType(superName) : null;
|
||||
this.asmSuperType = superName != null && !superName.isEmpty() ? Type.getObjectType(superName) : null;
|
||||
this.interfaces = Stream.of(interfaces).map(Type::getObjectType).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String annotationName, final boolean runtimeVisible)
|
||||
{
|
||||
public AnnotationVisitor visitAnnotation(final String annotationName, final boolean runtimeVisible) {
|
||||
ModAnnotation ann = new ModAnnotation(ElementType.TYPE, Type.getType(annotationName), this.asmType.getClassName());
|
||||
annotations.addFirst(ann);
|
||||
return new ModAnnotationVisitor(annotations, ann);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
|
||||
{
|
||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
|
||||
return new ModFieldVisitor(name, annotations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
|
||||
{
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
return new ModMethodVisitor(name, desc, annotations);
|
||||
}
|
||||
|
||||
public void buildData(final Set<ModFileScanData.ClassData> classes, final Set<ModFileScanData.AnnotationData> annotations) {
|
||||
public void buildData(final Set<ModFileScanData.ClassData> classes, final Set<ModFileScanData.AnnotationData> baked) {
|
||||
classes.add(new ModFileScanData.ClassData(this.asmType, this.asmSuperType, this.interfaces));
|
||||
final List<ModFileScanData.AnnotationData> collect = this.annotations.stream().
|
||||
filter(ma->ModFileScanData.interestingAnnotations().test(ma.getASMType())).
|
||||
map(a -> ModAnnotation.fromModAnnotation(this.asmType, a)).collect(Collectors.toList());
|
||||
annotations.addAll(collect);
|
||||
for (var a : this.annotations) {
|
||||
//if (ModFileScanData.interestingAnnotations().test(a.getASMType())) // Always true, so who cares. Left as a note to remove this in SPI later.
|
||||
baked.add(ModAnnotation.fromModAnnotation(this.asmType, a));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
||||
@@ -207,8 +206,11 @@ public class ModFile implements IModFile {
|
||||
this.securityStatus = status;
|
||||
}
|
||||
|
||||
public ArtifactVersion getJarVersion()
|
||||
{
|
||||
public SecureJar.Status getSecurityStatus() {
|
||||
return this.securityStatus;
|
||||
}
|
||||
|
||||
public ArtifactVersion getJarVersion() {
|
||||
return new DefaultArtifactVersion(this.jarVersion);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ModFileParser {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@@ -80,7 +80,8 @@ public class ModInfo implements IModInfo, IConfigurable
|
||||
this.displayName = config.<String>getConfigElement("displayName")
|
||||
.orElse(this.modId);
|
||||
this.description = config.<String>getConfigElement("description")
|
||||
.orElse("MISSING DESCRIPTION");
|
||||
.orElse("MISSING DESCRIPTION")
|
||||
.replace("\r\n", "\n").stripIndent();
|
||||
this.logoFile = Optional.ofNullable(config.<String>getConfigElement("logoFile")
|
||||
.orElseGet(() -> ownFile.flatMap(mf -> mf.<String>getConfigElement("logoFile"))
|
||||
.orElse(null)));
|
||||
@@ -205,7 +206,7 @@ public class ModInfo implements IModInfo, IConfigurable
|
||||
private final boolean mandatory;
|
||||
private final Ordering ordering;
|
||||
private final DependencySide side;
|
||||
private Optional<URL> referralUrl;
|
||||
private final Optional<URL> referralUrl;
|
||||
|
||||
public ModVersion(final IModInfo owner, final IConfigurable config) {
|
||||
this.owner = owner;
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public final class ModJarMetadata implements JarMetadata {
|
||||
// TODO: Remove helper functions to cleanup api
|
||||
@Deprecated(forRemoval = true, since="1.18")
|
||||
static IModFile buildFile(IModLocator locator, Path... files) {
|
||||
return buildFile(locator, j->true, (a,b) -> true, files).orElseThrow(()->new IllegalArgumentException("Failed to find valid JAR file"));
|
||||
return buildFile(locator, j->true, null, files).orElseThrow(()->new IllegalArgumentException("Failed to find valid JAR file"));
|
||||
}
|
||||
|
||||
// TODO: Remove helper functions to cleanup api
|
||||
|
||||
+7
-2
@@ -7,7 +7,6 @@ package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.fml.loading.FMLPaths;
|
||||
import net.minecraftforge.fml.loading.FileUtils;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.fml.loading.MavenCoordinateResolver;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -63,7 +62,7 @@ public class ModListHandler {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String extension = FileUtils.fileExtension(filePath);
|
||||
String extension = fileExtension(filePath);
|
||||
if (Objects.equals("list",extension)) {
|
||||
return readListFile(filePath).stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
|
||||
} else {
|
||||
@@ -72,6 +71,12 @@ public class ModListHandler {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static String fileExtension(final Path path) {
|
||||
String fileName = path.getFileName().toString();
|
||||
int idx = fileName.lastIndexOf('.');
|
||||
return idx > -1 ? fileName.substring(idx+1) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple list file, ending in ".list" with one mod coordinate per line
|
||||
* @param filePath path
|
||||
|
||||
+2
-3
@@ -9,7 +9,6 @@ import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||
import cpw.mods.modlauncher.api.ITransformationService;
|
||||
import net.minecraftforge.fml.loading.*;
|
||||
import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -23,7 +22,7 @@ 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 Map<IModFile.Type, List<ModFile>> modFiles;
|
||||
private final List<ModFile> candidatePlugins;
|
||||
private final List<ModFile> candidateMods;
|
||||
private LoadingModList loadingModList;
|
||||
@@ -31,7 +30,7 @@ public class ModValidator {
|
||||
private final List<EarlyLoadingException.ExceptionData> discoveryErrorData;
|
||||
|
||||
public ModValidator(final Map<IModFile.Type, List<ModFile>> modFiles, final List<IModFileInfo> brokenFiles, final List<EarlyLoadingException.ExceptionData> discoveryErrorData) {
|
||||
this.modFiles = modFiles;
|
||||
//this.modFiles = modFiles;
|
||||
this.candidateMods = lst(modFiles.get(IModFile.Type.MOD));
|
||||
this.candidateMods.addAll(lst(modFiles.get(IModFile.Type.GAMELIBRARY)));
|
||||
this.candidatePlugins = lst(modFiles.get(IModFile.Type.LANGPROVIDER));
|
||||
|
||||
-2
@@ -10,8 +10,6 @@ import com.google.common.base.CharMatcher;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class StartupNotificationManager {
|
||||
private static volatile EnumMap<Message.MessageType, List<Message>> messages = new EnumMap<>(Message.MessageType.class);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -19,6 +21,7 @@ import java.util.function.Supplier;
|
||||
* A class that attempts to parse command line arguments into key value pairs to allow addition and editing.
|
||||
* Can not use JOptSimple as that doesn't parse out the values for keys unless the spec says it has a value.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
class ArgumentList {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private List<Supplier<String[]>> entries = new ArrayList<>();
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import cpw.mods.modlauncher.api.ServiceRunner;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LibraryFinder;
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class CommonClientLaunchHandler extends CommonLaunchHandler {
|
||||
@Override public Dist getDist() { return Dist.CLIENT; }
|
||||
@Override public String getNaming() { return "srg"; }
|
||||
@Override public boolean isProduction() { return true; }
|
||||
|
||||
@Override
|
||||
protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) {
|
||||
return ()->clientService(arguments, gameLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
final var vers = FMLLoader.versionInfo();
|
||||
var mc = LibraryFinder.findPathForMaven("net.minecraft", "client", "", "srg", vers.mcAndMCPVersion());
|
||||
var mcextra = LibraryFinder.findPathForMaven("net.minecraft", "client", "", "extra", vers.mcAndMCPVersion());
|
||||
var mcstream = Stream.<Path>builder().add(mc).add(mcextra);
|
||||
var modstream = Stream.<List<Path>>builder();
|
||||
|
||||
processMCStream(vers, mcstream, modstream);
|
||||
|
||||
var fmlcore = LibraryFinder.findPathForMaven(vers.forgeGroup(), "fmlcore", "", "", vers.mcAndForgeVersion());
|
||||
var javafmllang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "javafmllanguage", "", "", vers.mcAndForgeVersion());
|
||||
var lowcodelang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "lowcodelanguage", "", "", vers.mcAndForgeVersion());
|
||||
var mclang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "mclanguage", "", "", vers.mcAndForgeVersion());
|
||||
|
||||
return new LocatedPaths(mcstream.build().toList(), (a,b) -> true, modstream.build().toList(), List.of(fmlcore, javafmllang, lowcodelang, mclang));
|
||||
}
|
||||
|
||||
protected abstract void processMCStream(VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods);
|
||||
}
|
||||
+103
-54
@@ -7,46 +7,30 @@ package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.api.ServiceRunner;
|
||||
import net.minecraftforge.fml.loading.FileUtils;
|
||||
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
protected CommonDevLaunchHandler(LaunchType type, String prefix) {
|
||||
super(type, prefix);
|
||||
}
|
||||
|
||||
@Override public String getNaming() { return "mcp"; }
|
||||
@Override public boolean isProduction() { return false; }
|
||||
|
||||
@Override
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
// Minecraft is extra jar {resources} + our exploded directories in dev
|
||||
final var mcstream = Stream.<Path>builder();
|
||||
|
||||
// The extra jar is on the classpath, so try and pull it out of the legacy classpath
|
||||
var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find client-extra").split(File.pathSeparator);
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra");
|
||||
|
||||
// The MC code/Patcher edits are in exploded directories
|
||||
final var modstream = Stream.<List<Path>>builder();
|
||||
final var mods = getModClasses();
|
||||
final var minecraft = mods.remove("minecraft");
|
||||
if (minecraft == null)
|
||||
throw new IllegalStateException("Could not find 'minecraft' mod paths.");
|
||||
minecraft.stream().distinct().forEach(mcstream::add);
|
||||
mods.values().forEach(modstream::add);
|
||||
|
||||
mcstream.add(extra);
|
||||
var mcFilter = getMcFilter(extra, minecraft, modstream);
|
||||
return new LocatedPaths(mcstream.build().toList(), mcFilter, modstream.build().toList(), getFmlStuff(legacyCP));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] preLaunch(String[] arguments, ModuleLayer layer) {
|
||||
super.preLaunch(arguments, layer);
|
||||
@@ -79,34 +63,34 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
return args.getArguments();
|
||||
}
|
||||
|
||||
protected List<Path> getFmlStuff(String[] classpath) {
|
||||
// We also want the FML things, fmlcore, javafmllanguage, mclanguage, I don't like hard coding these, but hey whatever works for now.
|
||||
return Arrays.stream(classpath)
|
||||
.filter(e -> FileUtils.matchFileName(e, "fmlcore", "javafmllanguage", "lowcodelanguage", "mclanguage"))
|
||||
.map(Paths::get)
|
||||
.toList();
|
||||
protected List<Path> getLibraries(String[] classpath) {
|
||||
// TODO: These should all be FMLModType: LIBRARY, find them that way?
|
||||
// Or at the very least include version info
|
||||
var fmlcore = findJarOnClasspath(classpath, "fmlcore");
|
||||
var javafmllang = findJarOnClasspath(classpath, "javafmllanguage");
|
||||
var lowcodelang = findJarOnClasspath(classpath, "lowcodelanguage");
|
||||
var mclang = findJarOnClasspath(classpath, "mclanguage");
|
||||
return List.of(fmlcore, javafmllang, lowcodelang, mclang);
|
||||
}
|
||||
|
||||
protected static Path findJarOnClasspath(String[] classpath, String match) {
|
||||
return Paths.get(Arrays.stream(classpath)
|
||||
.filter(e -> FileUtils.matchFileName(e, match))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("Could not find " + match + " in classpath")));
|
||||
}
|
||||
|
||||
protected BiPredicate<String, String> getMcFilter(Path extra, List<Path> minecraft, Stream.Builder<List<Path>> mods) {
|
||||
final var packages = getPackages();
|
||||
final var extraPath = extra.toString().replace('\\', '/');
|
||||
protected BiPredicate<String, String> getMcFilter(Path extra, List<Path> minecraft) {
|
||||
var packages = getPackages(); // Pulled out so it is passed to the lambda as value
|
||||
var extraPath = extra.toString().replace('\\', '/');
|
||||
|
||||
// We serve everything, except for things in the forge packages.
|
||||
BiPredicate<String, String> mcFilter = (path, base) -> {
|
||||
if (base.equals(extraPath) ||
|
||||
path.endsWith("/")) return true;
|
||||
path.endsWith("/")) return true;
|
||||
for (var pkg : packages)
|
||||
if (path.startsWith(pkg)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
return mcFilter;
|
||||
}
|
||||
|
||||
protected Path getForgeMod(List<Path> minecraft) {
|
||||
var packages = getPackages(); // Pulled out so it is passed to the lambda as value
|
||||
// We need to separate out our resources/code so that we can show up as a different data pack.
|
||||
var modJar = SecureJar.from((path, base) -> {
|
||||
if (!path.endsWith(".class")) return true;
|
||||
@@ -114,14 +98,18 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
if (path.startsWith(pkg)) return true;
|
||||
return false;
|
||||
}, minecraft.stream().distinct().toArray(Path[]::new));
|
||||
//modJar.getPackages().stream().sorted().forEach(System.out::println);
|
||||
mods.add(List.of(modJar.getRootPath()));
|
||||
|
||||
return mcFilter;
|
||||
//modJar.getPackages().stream().sorted().forEach(System.out::println);
|
||||
return modJar.getRootPath();
|
||||
}
|
||||
|
||||
protected String[] getPackages() {
|
||||
return new String[]{ "net/minecraftforge/", "META-INF/services/", "META-INF/coremods.json", "META-INF/mods.toml" };
|
||||
private static String[] getPackages() {
|
||||
return new String[] {
|
||||
"net/minecraftforge/",
|
||||
"META-INF/services/",
|
||||
"META-INF/coremods.json",
|
||||
"META-INF/mods.toml"
|
||||
};
|
||||
}
|
||||
|
||||
private static String getRandomNumbers(int length) {
|
||||
@@ -131,9 +119,70 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
|
||||
@Override
|
||||
protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) {
|
||||
var args = preLaunch(arguments, gameLayer);
|
||||
return ()->devService(args, gameLayer);
|
||||
return super.makeService(preLaunch(arguments, gameLayer), gameLayer);
|
||||
}
|
||||
|
||||
abstract void devService(final String[] arguments, final ModuleLayer gameLayer) throws Throwable;
|
||||
// TODO: Get rid of this string based classpath crap when I re-write mod loader
|
||||
protected static Map<String, List<Path>> getModClasses() {
|
||||
var modClasses = Optional.ofNullable(System.getenv("MOD_CLASSES")).orElse("");
|
||||
LOGGER.debug(LogMarkers.CORE, "Got mod coordinates {} from env", modClasses);
|
||||
|
||||
/*
|
||||
* So MOD_CLASSES at the end of the day is a Map<ModId, List<Path>> but because we want to shove that into a single string.
|
||||
* And pass it in as an environment variable.. instead od using json, or a file path, or anything sane, cpw did hacky string stuff
|
||||
* Basically what we want to do is split the string by File.pathSeperator to get each key-value pair.
|
||||
* Then we find the magic string "%%" and split on that. Using the first half as the mod id and the second as the path.
|
||||
* BUT the modID is optional, and if not specified {why wouldn't it be?} it uses "defaultmodid"
|
||||
* Anyways, it was stream hell, but now it's simpler to debug/understand.
|
||||
*/
|
||||
Map<String, List<Path>> ret = new HashMap<>();
|
||||
var entries = modClasses.split(File.pathSeparator);
|
||||
for (var entry : entries) {
|
||||
var modid = "defaultmodid";
|
||||
var path = entry;
|
||||
|
||||
int idx = entry.indexOf("%%");
|
||||
if (idx != -1) {
|
||||
modid = entry.substring(0, idx);
|
||||
path = entry.substring(idx + 2);
|
||||
}
|
||||
|
||||
var p = Paths.get(path);
|
||||
var lst = ret.computeIfAbsent(modid, k -> new ArrayList<>());
|
||||
if (!lst.contains(p))
|
||||
lst.add(p);
|
||||
}
|
||||
|
||||
LOGGER.debug(LogMarkers.CORE, "Found supplied mod coordinates:");
|
||||
ret.forEach((k, v) -> {
|
||||
if (v.size() == 1)
|
||||
LOGGER.debug(LogMarkers.CORE, "\t{}: {}", k, v.get(0));
|
||||
else {
|
||||
LOGGER.debug(LogMarkers.CORE, "\t{}:", k);
|
||||
v.forEach(e -> LOGGER.debug("\t\t{}", e));
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static Path findJarOnClasspath(String[] classpath, String match) {
|
||||
String ret = null;
|
||||
|
||||
for (var entry : classpath) {
|
||||
int idx = entry.lastIndexOf(File.separatorChar);
|
||||
if (idx == -1) continue;
|
||||
|
||||
var name = entry.substring(idx + 1);
|
||||
if (name.startsWith(match)) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == null)
|
||||
new IllegalStateException("Could not find " + match + " in classpath");
|
||||
|
||||
return Paths.get(ret);
|
||||
}
|
||||
}
|
||||
+38
-51
@@ -10,49 +10,52 @@ import cpw.mods.modlauncher.api.ILaunchHandlerService;
|
||||
import cpw.mods.modlauncher.api.ITransformingClassLoaderBuilder;
|
||||
import cpw.mods.modlauncher.api.ServiceRunner;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LogMarkers;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.ConfigurationFactory;
|
||||
import org.apache.logging.log4j.core.config.ConfigurationSource;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.slf4j.Logger;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This is required by FMLLoader because ILaunchHandlerService doesn't have the context we need.
|
||||
* I need to clean this up to make proper api. But that involves editing ModLauncher itself which i'm not gunna do right now.
|
||||
*
|
||||
* So until that happens, guess this is public api.
|
||||
*/
|
||||
public abstract class CommonLaunchHandler implements ILaunchHandlerService {
|
||||
public record LocatedPaths(List<Path> minecraftPaths, BiPredicate<String, String> minecraftFilter, List<List<Path>> otherModPaths, List<Path> otherArtifacts) {}
|
||||
public record LocatedPaths(
|
||||
List<Path> minecraftPaths,
|
||||
BiPredicate<String, String> minecraftFilter,
|
||||
List<List<Path>> otherModPaths,
|
||||
List<Path> otherArtifacts
|
||||
) {}
|
||||
|
||||
protected static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public abstract Dist getDist();
|
||||
private final LaunchType type;
|
||||
private final String prefix;
|
||||
|
||||
protected CommonLaunchHandler(LaunchType type, String prefix) {
|
||||
this.type = type;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@Override public String name() { return this.prefix + this.type.name(); }
|
||||
public Dist getDist() { return this.type.dist(); }
|
||||
public boolean isData() { return this.type.data(); }
|
||||
public boolean isProduction() { return false; }
|
||||
public abstract String getNaming();
|
||||
|
||||
public boolean isProduction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract LocatedPaths getMinecraftPaths();
|
||||
|
||||
@Override
|
||||
public void configureTransformationClassLoader(final ITransformingClassLoaderBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
protected String[] preLaunch(String[] arguments, ModuleLayer layer) {
|
||||
@@ -69,45 +72,29 @@ public abstract class CommonLaunchHandler implements ILaunchHandlerService {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
protected final Map<String, List<Path>> getModClasses() {
|
||||
final String modClasses = Optional.ofNullable(System.getenv("MOD_CLASSES")).orElse("");
|
||||
LOGGER.debug(LogMarkers.CORE, "Got mod coordinates {} from env", modClasses);
|
||||
|
||||
record ExplodedModPath(String modid, Path path) {}
|
||||
// "a/b/;c/d/;" -> "modid%%c:\fish\pepper;modid%%c:\fish2\pepper2\;modid2%%c:\fishy\bums;modid2%%c:\hmm"
|
||||
final var modClassPaths = Arrays.stream(modClasses.split(File.pathSeparator))
|
||||
.map(inp -> inp.split("%%", 2))
|
||||
.map(splitString -> new ExplodedModPath(splitString.length == 1 ? "defaultmodid" : splitString[0], Paths.get(splitString[splitString.length - 1])))
|
||||
.collect(Collectors.groupingBy(ExplodedModPath::modid, Collectors.mapping(ExplodedModPath::path, Collectors.toList())));
|
||||
|
||||
LOGGER.debug(LogMarkers.CORE, "Found supplied mod coordinates [{}]", modClassPaths);
|
||||
|
||||
//final var explodedTargets = ((Map<String, List<ExplodedDirectoryLocator.ExplodedMod>>)arguments).computeIfAbsent("explodedTargets", a -> new ArrayList<>());
|
||||
//modClassPaths.forEach((modlabel,paths) -> explodedTargets.add(new ExplodedDirectoryLocator.ExplodedMod(modlabel, paths)));
|
||||
return modClassPaths;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRunner launchService(final String[] arguments, final ModuleLayer gameLayer) {
|
||||
FMLLoader.beforeStart(gameLayer);
|
||||
return makeService(arguments, gameLayer);
|
||||
}
|
||||
|
||||
protected abstract ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer);
|
||||
|
||||
protected void clientService(final String[] arguments, final ModuleLayer layer) throws Throwable {
|
||||
runTarget("net.minecraft.client.main.Main", arguments, layer);
|
||||
protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) {
|
||||
return () -> runTarget(this.type.module(), this.type.main(), arguments, gameLayer);
|
||||
}
|
||||
|
||||
protected void serverService(final String[] arguments, final ModuleLayer layer) throws Throwable {
|
||||
runTarget("net.minecraft.server.Main", arguments, layer);
|
||||
}
|
||||
protected record LaunchType(String name, String module, String main, Dist dist, boolean data) {};
|
||||
protected static final LaunchType CLIENT = new LaunchType("client", "minecraft", "net.minecraft.client.main.Main", Dist.CLIENT, false);
|
||||
protected static final LaunchType DATA = new LaunchType("data", "minecraft", "net.minecraft.data.Main", Dist.CLIENT, true);
|
||||
protected static final LaunchType SERVER = new LaunchType("server", "minecraft", "net.minecraft.server.Main", Dist.DEDICATED_SERVER, false);
|
||||
protected static final LaunchType SERVER_GAMETEST = new LaunchType("server_gametest", "forge", "net.minecraftforge.gametest.GameTestMain", Dist.DEDICATED_SERVER, false);
|
||||
|
||||
protected void dataService(final String[] arguments, final ModuleLayer layer) throws Throwable {
|
||||
runTarget("net.minecraft.data.Main", arguments, layer);
|
||||
}
|
||||
|
||||
protected void runTarget(final String target, final String[] arguments, final ModuleLayer layer) throws Throwable {
|
||||
Class.forName(layer.findModule("minecraft").orElseThrow(),target).getMethod("main", String[].class).invoke(null, (Object)arguments);
|
||||
protected void runTarget(String module, String target, final String[] arguments, final ModuleLayer layer) throws Throwable {
|
||||
var mod = layer.findModule(module).orElseThrow();
|
||||
if (mod == null) throw new IllegalStateException("Could not find module " + module);
|
||||
var cls = Class.forName(mod, target);
|
||||
if (cls == null) throw new IllegalStateException("Could not find class " + target + " in module " + module);
|
||||
var mtd = cls.getMethod("main", String[].class);
|
||||
if (mtd == null) throw new IllegalStateException("Class " + target + " in module " + module + " does not have a main(String[]) method");
|
||||
mtd.invoke(null, (Object)arguments);
|
||||
}
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.api.ServiceRunner;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LibraryFinder;
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class CommonServerLaunchHandler extends CommonLaunchHandler {
|
||||
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
|
||||
@Override public String getNaming() { return "srg"; }
|
||||
@Override public boolean isProduction() { return true; }
|
||||
|
||||
@Override
|
||||
protected ServiceRunner makeService(String[] arguments, ModuleLayer layer) {
|
||||
return () -> serverService(arguments, layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
final var vers = FMLLoader.versionInfo();
|
||||
var mc = LibraryFinder.findPathForMaven("net.minecraft", "server", "", "srg", vers.mcAndMCPVersion());
|
||||
var mcextra = LibraryFinder.findPathForMaven("net.minecraft", "server", "", "extra", vers.mcAndMCPVersion());
|
||||
var mcextra_filtered = SecureJar.from( // We only want it for it's resources. So filter everything else out.
|
||||
(path, base) -> {
|
||||
return path.equals("META-INF/versions/") || // This is required because it bypasses our filter for the manifest, and it's a multi-release jar.
|
||||
(!path.endsWith(".class") &&
|
||||
!path.startsWith("META-INF/"));
|
||||
}, mcextra
|
||||
);
|
||||
BiPredicate<String, String> filter = (path, base) -> true;
|
||||
|
||||
var mcstream = Stream.<Path>builder().add(mc).add(mcextra_filtered.getRootPath());
|
||||
var modstream = Stream.<List<Path>>builder();
|
||||
|
||||
filter = processMCStream(vers, mcstream, filter, modstream);
|
||||
|
||||
var fmlcore = LibraryFinder.findPathForMaven(vers.forgeGroup(), "fmlcore", "", "", vers.mcAndForgeVersion());
|
||||
var javafmllang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "javafmllanguage", "", "", vers.mcAndForgeVersion());
|
||||
var lowcodelang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "lowcodelanguage", "", "", vers.mcAndForgeVersion());
|
||||
var mclang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "mclanguage", "", "", vers.mcAndForgeVersion());
|
||||
|
||||
return new LocatedPaths(mcstream.build().toList(), filter, modstream.build().toList(), List.of(fmlcore, javafmllang, lowcodelang, mclang));
|
||||
}
|
||||
|
||||
protected abstract BiPredicate<String, String> processMCStream(VersionInfo versionInfo, Stream.Builder<Path> mc, BiPredicate<String, String> filter, Stream.Builder<List<Path>> mods);
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class CommonUserdevLaunchHandler extends CommonDevLaunchHandler {
|
||||
@Override
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
final var vers = FMLLoader.versionInfo();
|
||||
|
||||
// Minecraft is extra jar {resources} + forge jar {patches}
|
||||
final var mcstream = Stream.<Path>builder();
|
||||
// Mod code is in exploded directories
|
||||
final var modstream = Stream.<List<Path>>builder();
|
||||
|
||||
// The MC extra and forge jars are on the classpath, so try and pull them out
|
||||
var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find userdev jars").split(File.pathSeparator);
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra");
|
||||
|
||||
processStreams(legacyCP, vers, mcstream, modstream);
|
||||
getModClasses().forEach((modid, paths) -> modstream.add(paths));
|
||||
|
||||
var minecraft = mcstream.build().collect(Collectors.toList());
|
||||
var mcFilter = getMcFilter(extra, minecraft, modstream);
|
||||
minecraft.add(extra); // Add extra late so the filter is made correctly
|
||||
return new LocatedPaths(minecraft, mcFilter, modstream.build().toList(), getFmlStuff(legacyCP));
|
||||
}
|
||||
|
||||
protected abstract void processStreams(String[] classpath, VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods);
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeClientDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
@Override public String name() { return "forgeclientdev"; }
|
||||
@Override public Dist getDist() { return Dist.CLIENT; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
clientService(arguments, layer);
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraftforge.fml.loading.LibraryFinder;
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
|
||||
public class ForgeClientLaunchHandler extends CommonClientLaunchHandler {
|
||||
@Override public String name() { return "forgeclient"; }
|
||||
|
||||
@Override
|
||||
protected void processMCStream(VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods) {
|
||||
var forgepatches = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "client", versionInfo.mcAndForgeVersion());
|
||||
var forgejar = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "universal", versionInfo.mcAndForgeVersion());
|
||||
mc.add(forgepatches);
|
||||
mods.add(List.of(forgejar));
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeClientUserdevLaunchHandler extends ForgeUserdevLaunchHandler {
|
||||
@Override
|
||||
public String name() { return "forgeclientuserdev"; }
|
||||
|
||||
@Override
|
||||
public Dist getDist() { return Dist.CLIENT; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
clientService(arguments, layer);
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeDataDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
@Override public String name() { return "forgedatadev"; }
|
||||
@Override public Dist getDist() { return Dist.CLIENT; }
|
||||
@Override public boolean isData() { return true; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
Class.forName(layer.findModule("minecraft").orElseThrow(), "net.minecraft.data.Main").getMethod("main", String[].class).invoke(null, (Object) arguments);
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeDataUserdevLaunchHandler extends ForgeUserdevLaunchHandler {
|
||||
@Override
|
||||
public String name() { return "forgedatauserdev"; }
|
||||
|
||||
@Override
|
||||
public Dist getDist() { return Dist.CLIENT; }
|
||||
|
||||
@Override
|
||||
public boolean isData() { return true; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
dataService(arguments, layer);
|
||||
}
|
||||
}
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
|
||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||
import com.electronwill.nightconfig.toml.TomlParser;
|
||||
import com.electronwill.nightconfig.toml.TomlWriter;
|
||||
import com.google.common.jimfs.Jimfs;
|
||||
|
||||
import cpw.mods.niofs.union.UnionFileSystemProvider;
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
private static final String MODS_TOML = "META-INF/mods.toml";
|
||||
private static final String PACK_META = "pack.mcmeta";
|
||||
private static final UnionFileSystemProvider UFSP = (UnionFileSystemProvider)FileSystemProvider.installedProviders().stream().filter(fsp->fsp.getScheme().equals("union")).findFirst().orElseThrow(()->new IllegalStateException("Couldn't find UnionFileSystemProvider"));
|
||||
|
||||
private ForgeDevLaunchHandler(LaunchType type) {
|
||||
super(type, "forge_dev_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
// Our exploded directories in development include all mods and minecraft itself.
|
||||
var mods = getModClasses();
|
||||
|
||||
// The extra jar is on the classpath, so try and pull it out of the legacy classpath
|
||||
var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find client-extra").split(File.pathSeparator);
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra");
|
||||
|
||||
|
||||
// Minecraft is extra jar {resources} + our exploded directories in dev
|
||||
var minecraft = mods.remove("minecraft");
|
||||
if (minecraft == null)
|
||||
throw new IllegalStateException("Could not find 'minecraft' mod paths.");
|
||||
var mcFilter = getMcFilter(extra, minecraft);
|
||||
|
||||
// The MC code/Patcher edits are in exploded directories
|
||||
var modstream = Stream.<List<Path>>builder();
|
||||
var forge = this.getForgeMod(minecraft);
|
||||
modstream.add(List.of(forge));
|
||||
|
||||
// Explode our test mods into a framework that treats them all as separate jars.
|
||||
var tests = mods.remove("tests");
|
||||
if (tests != null)
|
||||
explodeTestMods(tests).forEach(modstream::add);
|
||||
|
||||
mods.values().forEach(modstream::add);
|
||||
|
||||
return new LocatedPaths(
|
||||
Stream.concat(minecraft.stream(), List.of(extra).stream()).toList(),
|
||||
mcFilter,
|
||||
modstream.build().toList(),
|
||||
getLibraries(legacyCP)
|
||||
);
|
||||
}
|
||||
|
||||
private List<List<Path>> explodeTestMods(List<Path> paths) {
|
||||
var mod = new ArrayList<List<Path>>();
|
||||
var memory = Jimfs.newFileSystem();
|
||||
|
||||
// First lets find all class files, that have the @Mod annotation and map packages to modids.
|
||||
var packages = findTestModPackages(paths);
|
||||
for (var entry : packages.entrySet()) {
|
||||
var pkg = entry.getKey();
|
||||
var modids = entry.getValue();
|
||||
|
||||
var resourcePaths = new LinkedHashSet<Path>();
|
||||
// Jump down into the package for resources
|
||||
paths.stream()
|
||||
.<Path>mapMulti((p, c) -> modids.forEach(id -> c.accept(p.resolve(id))))
|
||||
.filter(Files::exists).forEach(resourcePaths::add);
|
||||
|
||||
var root = memory.getPath(modids.iterator().next()); // use the first modid as our root
|
||||
buildModsToml(resourcePaths, modids, root);
|
||||
buildPackMeta(resourcePaths, root);
|
||||
|
||||
if (Files.exists(root))
|
||||
resourcePaths.add(root);
|
||||
|
||||
// We want just the class files from the root of the input paths. So make a new union with a filter.
|
||||
var classes = UFSP.newFileSystem(
|
||||
(path, base) -> {
|
||||
if (path.endsWith("/")) {
|
||||
if (path.startsWith("/"))
|
||||
path = path.substring(1);
|
||||
return pkg.startsWith(path) || path.startsWith(pkg);
|
||||
}
|
||||
return path.endsWith(".class") && path.startsWith(pkg);
|
||||
}, paths.toArray(Path[]::new));
|
||||
// And we want the resources, and none of the classes, just in case things get kinda fucky and somehow a package overlaps a sub package {shading?}
|
||||
var resources = UFSP.newFileSystem((path, base) -> !path.endsWith(".class"), resourcePaths.toArray(Path[]::new));
|
||||
|
||||
mod.add(List.of(classes.getRoot(), resources.getRoot()));
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
// Find all the @Mods so we can generate tomls, and so we can pick packages. Right now it doesn't allow mods in parent directories,
|
||||
// I could make it merge all the way up, but I think this would be fine.
|
||||
private Map<String, Set<String>> findTestModPackages(List<Path> paths) {
|
||||
var mods = new HashMap<String, Set<String>>();
|
||||
for (var path : paths) {
|
||||
try (var files = Files.walk(path)) {
|
||||
var classes = files
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(p -> p.getFileName().toString().endsWith(".class"))
|
||||
.toList();
|
||||
|
||||
for (var cls : classes) {
|
||||
try (var is = Files.newInputStream(cls)) {
|
||||
var reader = new ClassReader(is);
|
||||
reader.accept(new ClassVisitor(Opcodes.ASM9) {
|
||||
private String clsName;
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
this.clsName = name;
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String name, boolean runtime) {
|
||||
if (!"Lnet/minecraftforge/fml/common/Mod;".equals(name))
|
||||
return super.visitAnnotation(name, runtime);
|
||||
|
||||
return new AnnotationVisitor(Opcodes.ASM9) {
|
||||
@Override
|
||||
public void visit(String key, Object value) {
|
||||
if ("value".equals(key)) {
|
||||
int idx = clsName.lastIndexOf('/');
|
||||
var pkg = clsName.substring(0, idx);
|
||||
mods.computeIfAbsent(pkg, k -> new HashSet<>()).add((String)value);
|
||||
|
||||
idx = pkg.lastIndexOf('/');
|
||||
while (idx != -1) {
|
||||
pkg = pkg.substring(0, idx);
|
||||
idx = pkg.lastIndexOf('/');
|
||||
if (mods.containsKey(pkg))
|
||||
throw new IllegalStateException("Invalid ForgeDev test mod layout, conflicting packages: " + pkg + " for " + clsName);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
sneak(e);
|
||||
}
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Builds or update the mods.toml file for all @Mods in this package
|
||||
private void buildModsToml(Set<Path> resources, Set<String> modids, Path root) {
|
||||
var toml = resources.stream()
|
||||
.map(p -> p.resolve(MODS_TOML))
|
||||
.filter(Files::exists)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Config cfg = null;
|
||||
|
||||
if (toml != null)
|
||||
cfg = new TomlParser().parse(toml, FileNotFoundAction.READ_NOTHING);
|
||||
else
|
||||
cfg = Config.inMemory();
|
||||
|
||||
boolean modified = false;
|
||||
var defaults = Map.of(
|
||||
"modLoader", "javafml",
|
||||
"loaderVersion", "[0,)",
|
||||
"license", "Doesnt fucking matter"
|
||||
);
|
||||
|
||||
for (var key : defaults.keySet()) {
|
||||
if (!cfg.contains(key)) {
|
||||
cfg.set(key, defaults.get(key));
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
var modlist = new ArrayList<Config>();
|
||||
if (cfg.contains("mods")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var existing = ((List<Config>)cfg.get("mods"));
|
||||
modlist.addAll(existing);
|
||||
}
|
||||
|
||||
for (var modid : modids) {
|
||||
if (!modlist.stream().anyMatch(c -> modid.equals(c.get("modId")))) {
|
||||
modified = true;
|
||||
var tmp = Config.inMemory();
|
||||
tmp.set("modId", modid);
|
||||
modlist.add(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
cfg.set("mods", modlist);
|
||||
|
||||
if (modified) {
|
||||
var target = root.resolve(MODS_TOML);
|
||||
try {
|
||||
Files.createDirectories(target.getParent());
|
||||
new TomlWriter().write(cfg, target, WritingMode.REPLACE);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to create in memory toml: " + target, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is optional, it just hides a warning screen when starting up. I should probably remove this once I restructure how data gen for test mods work and make it generate there.
|
||||
private void buildPackMeta(Set<Path> paths, Path root) {
|
||||
var existing = paths.stream()
|
||||
.map(p -> p.resolve(PACK_META))
|
||||
.filter(Files::exists)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (existing != null)
|
||||
return;
|
||||
var target = root.resolve(PACK_META);
|
||||
try {
|
||||
Files.createDirectories(target.getParent());
|
||||
Files.writeString(target,
|
||||
"""
|
||||
{
|
||||
"pack": {
|
||||
"description": "doesn't matter",
|
||||
"pack_format": 18
|
||||
}
|
||||
}
|
||||
""", StandardCharsets.UTF_8, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to make in memory pack.mcmeta: " + target, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <E extends Throwable, R> R sneak(Throwable e) throws E {
|
||||
throw (E)e;
|
||||
}
|
||||
|
||||
public static class Client extends ForgeDevLaunchHandler {
|
||||
public Client() {
|
||||
super(CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Data extends ForgeDevLaunchHandler {
|
||||
public Data() {
|
||||
super(DATA);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Server extends ForgeDevLaunchHandler {
|
||||
public Server() {
|
||||
super(SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ServerGameTest extends ForgeDevLaunchHandler {
|
||||
public ServerGameTest() {
|
||||
super(SERVER_GAMETEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeGametestDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
@Override public String name() { return "forgegametestserverdev"; }
|
||||
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
Class.forName(layer.findModule("forge").orElseThrow(), "net.minecraftforge.gametest.GameTestMain").getMethod("main", String[].class).invoke(null, (Object)arguments);
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeGametestUserdevLaunchHandler extends ForgeUserdevLaunchHandler {
|
||||
@Override public String name() { return "forgegametestserveruserdev"; }
|
||||
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
Class.forName(layer.findModule("forge").orElseThrow(), "net.minecraftforge.gametest.GameTestMain").getMethod("main", String[].class).invoke(null, (Object)arguments);
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LibraryFinder;
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class ForgeProdLaunchHandler extends CommonLaunchHandler {
|
||||
protected ForgeProdLaunchHandler(LaunchType type) {
|
||||
super(type, "forge_");
|
||||
}
|
||||
|
||||
@Override public String getNaming() { return "srg"; }
|
||||
@Override public boolean isProduction() { return true; }
|
||||
|
||||
protected Path mvn(VersionInfo info, String artifact) {
|
||||
return mvn(info, artifact, "");
|
||||
}
|
||||
protected Path mvn(VersionInfo info, String artifact, String classifier) {
|
||||
return mvn(info.forgeGroup(), artifact, classifier, info.mcAndForgeVersion());
|
||||
}
|
||||
protected Path mvn(String group, String artifact, String classifier, String version) {
|
||||
return LibraryFinder.findPathForMaven(group, artifact, "", classifier, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
var vers = FMLLoader.versionInfo();
|
||||
|
||||
// Minecraft
|
||||
var mc = getMCPaths(vers);
|
||||
|
||||
// mods (Forge)
|
||||
var forgejar = mvn(vers, "forge", "universal");
|
||||
|
||||
// Libraries
|
||||
var fmlcore = mvn(vers, "fmlcore");
|
||||
var javafmllang = mvn(vers, "javafmllanguage");
|
||||
var lowcodelang = mvn(vers, "lowcodelanguage");
|
||||
var mclang = mvn(vers, "mclanguage");
|
||||
|
||||
return new LocatedPaths(
|
||||
mc,
|
||||
null,
|
||||
List.of(List.of(forgejar)),
|
||||
List.of(fmlcore, javafmllang, lowcodelang, mclang)
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract List<Path> getMCPaths(VersionInfo vers);
|
||||
|
||||
public static class Client extends ForgeProdLaunchHandler {
|
||||
public Client() {
|
||||
super(CLIENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Path> getMCPaths(VersionInfo vers) {
|
||||
var mc = mvn("net.minecraft", "client", "srg", vers.mcAndMCPVersion());
|
||||
var mcextra = mvn("net.minecraft", "client", "extra", vers.mcAndMCPVersion());
|
||||
var patches = mvn(vers, "forge", "client");
|
||||
return List.of(mc, mcextra, patches);
|
||||
}
|
||||
}
|
||||
public static class Server extends ForgeProdLaunchHandler {
|
||||
public Server() {
|
||||
super(SERVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Path> getMCPaths(VersionInfo vers) {
|
||||
var mc = mvn("net.minecraft", "server", "srg", vers.mcAndMCPVersion());
|
||||
var mcextra = mvn("net.minecraft", "server", "extra", vers.mcAndMCPVersion());
|
||||
var patches = mvn(vers, "forge", "server");
|
||||
|
||||
// TODO: Get rid of this by filtering the file at install time.
|
||||
// We only want it for it's resources. So filter everything else out.
|
||||
BiPredicate<String, String> filter = (path, base) -> {
|
||||
return path.equals("META-INF/versions/") || // This is required because it bypasses our filter for the manifest, and it's a multi-release jar.
|
||||
(!path.endsWith(".class") && !path.startsWith("META-INF/"));
|
||||
};
|
||||
mcextra = SecureJar.from(filter, mcextra).getRootPath();
|
||||
|
||||
return List.of(mc, mcextra, patches);
|
||||
}
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeServerDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
@Override public String name() { return "forgeserverdev"; }
|
||||
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
serverService(arguments, layer);
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import cpw.mods.modlauncher.api.ILaunchHandlerService;
|
||||
import net.minecraftforge.fml.loading.LibraryFinder;
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ForgeServerLaunchHandler extends CommonServerLaunchHandler implements ILaunchHandlerService {
|
||||
@Override public String name() { return "forgeserver"; }
|
||||
|
||||
@Override
|
||||
protected BiPredicate<String, String> processMCStream(VersionInfo versionInfo, Stream.Builder<Path> mc, BiPredicate<String, String> filter, Stream.Builder<List<Path>> mods) {
|
||||
var forgepatches = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "server", versionInfo.mcAndForgeVersion());
|
||||
var forgejar = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "universal", versionInfo.mcAndForgeVersion());
|
||||
mc.add(forgepatches);
|
||||
mods.add(List.of(forgejar));
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
public class ForgeServerUserdevLaunchHandler extends ForgeUserdevLaunchHandler {
|
||||
@Override public String name() { return "forgeserveruserdev"; }
|
||||
@Override public Dist getDist() { return Dist.DEDICATED_SERVER; }
|
||||
|
||||
@Override
|
||||
public void devService(String[] arguments, ModuleLayer layer) throws Throwable {
|
||||
serverService(arguments, layer);
|
||||
}
|
||||
}
|
||||
+60
-6
@@ -5,16 +5,70 @@
|
||||
|
||||
package net.minecraftforge.fml.loading.targets;
|
||||
|
||||
import net.minecraftforge.fml.loading.VersionInfo;
|
||||
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class ForgeUserdevLaunchHandler extends CommonUserdevLaunchHandler {
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
|
||||
private ForgeUserdevLaunchHandler(LaunchType type) {
|
||||
super(type, "forge_userdev_");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processStreams(String[] classpath, VersionInfo versionInfo, Stream.Builder<Path> mc, Stream.Builder<List<Path>> mods) {
|
||||
var forge = findJarOnClasspath(classpath, "forge-" + versionInfo.mcAndForgeVersion());
|
||||
mc.add(forge);
|
||||
public LocatedPaths getMinecraftPaths() {
|
||||
var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find userdev jars").split(File.pathSeparator);
|
||||
var vers = FMLLoader.versionInfo();
|
||||
|
||||
// Minecraft is extra jar {resources} + forge jar {patches}
|
||||
// The MC extra and forge jars are on the classpath, so try and pull them out
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra");
|
||||
var forge = findJarOnClasspath(legacyCP, "forge-" + vers.mcAndForgeVersion());
|
||||
// We need to filter the forge jar to just MC code
|
||||
var filter = getMcFilter(extra, List.of(forge));
|
||||
|
||||
// Mods is forge classes + anything from MOD_CLASSES
|
||||
var modstream = Stream.<List<Path>>builder();
|
||||
// We want the forge as a seperate mod jar.
|
||||
var forgemod = this.getForgeMod(List.of(forge));
|
||||
modstream.add(List.of(forgemod));
|
||||
// Mod code is in exploded directories
|
||||
getModClasses().forEach((modid, paths) -> modstream.add(paths));
|
||||
|
||||
return new LocatedPaths(
|
||||
List.of(forge, extra),
|
||||
filter,
|
||||
modstream.build().toList(),
|
||||
getLibraries(legacyCP)
|
||||
);
|
||||
}
|
||||
|
||||
public static class Client extends ForgeUserdevLaunchHandler {
|
||||
public Client() {
|
||||
super(CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Data extends ForgeUserdevLaunchHandler {
|
||||
public Data() {
|
||||
super(DATA);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Server extends ForgeUserdevLaunchHandler {
|
||||
public Server() {
|
||||
super(SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ServerGameTest extends ForgeUserdevLaunchHandler {
|
||||
public ServerGameTest() {
|
||||
super(SERVER_GAMETEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -11,6 +11,7 @@ import java.util.Set;
|
||||
* An exception thrown for graphs with cycles as an argument for topological sort.
|
||||
*/
|
||||
public final class CyclePresentException extends IllegalArgumentException {
|
||||
private static final long serialVersionUID = -2609660010927054667L;
|
||||
private final Set<Set<?>> cycles;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.server;
|
||||
|
||||
import cpw.mods.modlauncher.InvalidLauncherSetupException;
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Optional;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public class ServerMain {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Class.forName("cpw.mods.modlauncher.Launcher", false, ClassLoader.getSystemClassLoader());
|
||||
Class.forName("net.minecraftforge.forgespi.Environment", false, ClassLoader.getSystemClassLoader());
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
System.err.println("FATAL ERROR, You need to run the installer. The libraries required to launch a server are missing");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
final String launchArgs = Optional.ofNullable(ServerMain.class.getProtectionDomain()).
|
||||
map(ProtectionDomain::getCodeSource).
|
||||
map(CodeSource::getLocation).
|
||||
map(ServerMain::urlToManifest).
|
||||
map(Manifest::getMainAttributes).
|
||||
map(a -> a.getValue("ServerLaunchArgs")).
|
||||
orElseThrow(ServerMain::throwMissingManifest);
|
||||
String[] defaultargs = launchArgs.split(" ");
|
||||
String[] result = new String[args.length + defaultargs.length];
|
||||
System.arraycopy(defaultargs, 0, result, 0, defaultargs.length);
|
||||
System.arraycopy(args, 0, result, defaultargs.length, args.length);
|
||||
// separate class, so the exception can resolve
|
||||
new Runner().runLauncher(result);
|
||||
}
|
||||
|
||||
private static class Runner {
|
||||
private void runLauncher(final String[] result) {
|
||||
try {
|
||||
Launcher.main(result);
|
||||
} catch (InvalidLauncherSetupException e) {
|
||||
System.err.println("The server is missing critical libraries and cannot load. Please run the installer to correct this");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Manifest urlToManifest(URL url) {
|
||||
try {
|
||||
return new JarFile(new File(url.toURI())).getManifest();
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static RuntimeException throwMissingManifest() {
|
||||
System.err.println("This is not being run from a valid JAR file, essential data is missing.");
|
||||
return new RuntimeException("Missing the manifest");
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
+15
-10
@@ -1,10 +1,15 @@
|
||||
net.minecraftforge.fml.loading.targets.ForgeClientLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeClientDevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeClientUserdevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeServerLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeServerDevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeServerUserdevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeDataDevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeDataUserdevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeGametestDevLaunchHandler
|
||||
net.minecraftforge.fml.loading.targets.ForgeGametestUserdevLaunchHandler
|
||||
# Production
|
||||
net.minecraftforge.fml.loading.targets.ForgeProdLaunchHandler$Client
|
||||
net.minecraftforge.fml.loading.targets.ForgeProdLaunchHandler$Server
|
||||
|
||||
# Mod Developers
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Client
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Data
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Server
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$ServerGameTest
|
||||
|
||||
#Working on Forge itself
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Client
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Data
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Server
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$ServerGameTest
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -85,9 +85,6 @@ done
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
@@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
@@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF,.project,*.yml
|
||||
addNewLine=true
|
||||
convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
fixLineDelimiters=false
|
||||
ignoreBlankLinesWhenTrimming=false
|
||||
inActiveContentFilterList=
|
||||
javaTabWidthForJava=true
|
||||
org.eclipse.jdt.ui.editor.tab.width=2
|
||||
projectPropsEnabled=true
|
||||
removeTrailingSpaces=true
|
||||
replaceAllSpaces=false
|
||||
replaceAllTabs=false
|
||||
saveAndAddLine=false
|
||||
saveAndConvert=true
|
||||
saveAndFixLineDelimiters=false
|
||||
saveAndTrim=true
|
||||
useModulo4Tabs=false
|
||||
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
line.separator=\n
|
||||
@@ -2,15 +2,14 @@ plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'java-library'
|
||||
id 'jacoco'
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
|
||||
compileOnly(libs.nulls)
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FMLModContainer extends ModContainer
|
||||
@@ -70,6 +72,11 @@ public class FMLModContainer extends ModContainer
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// When a mod constructor throws an exception, it's wrapped in an InvocationTargetException which hides the
|
||||
// actual exception from the mod loading error screen.
|
||||
if (e instanceof InvocationTargetException wrapped)
|
||||
e = Objects.requireNonNullElse(wrapped.getCause(), e); // unwrap the exception
|
||||
|
||||
LOGGER.error(LOADING,"Failed to create mod instance. ModID: {}, class {}", getModId(), modClass.getName(), e);
|
||||
throw new ModLoadingException(modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, modClass);
|
||||
}
|
||||
|
||||
@@ -1,50 +1,33 @@
|
||||
plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'java-library'
|
||||
id 'jacoco'
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
|
||||
java.withSourcesJar()
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
|
||||
compileOnly(libs.nulls)
|
||||
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
}
|
||||
|
||||
ext {
|
||||
MANIFESTS = [
|
||||
'': [
|
||||
'FMLModType': 'LANGPROVIDER',
|
||||
'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
'Git-Commit': GIT_INFO.abbreviatedId,
|
||||
'Git-Branch': GIT_INFO.branch,
|
||||
'Build-Number': "${System.getenv('BUILD_NUMBER')?:0}",
|
||||
] as LinkedHashMap,
|
||||
'net/minecraftforge/fml/loading/': [
|
||||
'Specification-Title': 'FMLLoader',
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': project.name.toLowerCase(),
|
||||
'FMLModType': 'LANGPROVIDER'
|
||||
] as java.util.LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'LowCodeMod',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'FML Loader',
|
||||
'Implementation-Version': '1.0',
|
||||
'Implementation-Vendor': 'Forge'
|
||||
] as LinkedHashMap
|
||||
]
|
||||
}
|
||||
|
||||
jar.doFirst {
|
||||
manifest.attributes['Automatic-Module-Name'] = project.name
|
||||
MANIFESTS.each { pkg, values ->
|
||||
if (pkg == '')
|
||||
manifest.attributes(values)
|
||||
else
|
||||
manifest.attributes(values, pkg)
|
||||
'Specification-Version': '1.0',
|
||||
'Implementation-Title': project.name,
|
||||
'Implementation-Version': FORGE_VERSION.split('\\.')[0], //project.version, TODO: Split out into a real versioned system, for now use the default that net.minecraftforge.fml.loading.LanguageLoadingProvider.loadLanguageProviders() used
|
||||
'Implementation-Vendor': 'Forge Development LLC'
|
||||
] as java.util.LinkedHashMap, 'net/minecraftforge/fml/lowcodemod/')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-41
@@ -1,52 +1,33 @@
|
||||
plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||
id 'org.cadixdev.licenser'
|
||||
id 'java-library'
|
||||
id 'jacoco'
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
|
||||
compileOnly(libs.nulls)
|
||||
implementation(project(':fmlloader'))
|
||||
implementation(project(':fmlcore'))
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
archiveClassifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
ext {
|
||||
MANIFESTS = [
|
||||
'': [
|
||||
tasks.named('jar', Jar).configure {
|
||||
manifest {
|
||||
attributes([
|
||||
'Automatic-Module-Name': project.name.toLowerCase(),
|
||||
'FMLModType': 'LANGPROVIDER',
|
||||
'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
'Git-Commit': GIT_INFO.abbreviatedId,
|
||||
'Git-Branch': GIT_INFO.branch,
|
||||
'Build-Number': "${System.getenv('BUILD_NUMBER')?:0}",
|
||||
] as LinkedHashMap,
|
||||
'net/minecraftforge/fml/mclanguageprovider/': [
|
||||
'Specification-Title': 'FMLLoader',
|
||||
] as LinkedHashMap)
|
||||
attributes([
|
||||
'Specification-Title': 'MCLanguage',
|
||||
'Specification-Vendor': 'Forge Development LLC',
|
||||
'Specification-Version': '1',
|
||||
'Implementation-Title': 'FML Loader',
|
||||
'Implementation-Title': 'MCLanguage',
|
||||
'Implementation-Version': '1.0',
|
||||
'Implementation-Vendor': 'Forge'
|
||||
] as LinkedHashMap
|
||||
]
|
||||
}
|
||||
|
||||
jar.doFirst {
|
||||
manifest.attributes['Automatic-Module-Name'] = project.name
|
||||
MANIFESTS.each { pkg, values ->
|
||||
if (pkg == '')
|
||||
manifest.attributes(values)
|
||||
else
|
||||
manifest.attributes(values, pkg)
|
||||
'Implementation-Vendor': 'Forge Development LLC',
|
||||
] as LinkedHashMap, 'net/minecraftforge/fml/mclanguageprovider/')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,16 +37,9 @@ tasks.withType(JavaCompile) {
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
|
||||
include 'net/minecraftforge/'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives jar
|
||||
archives sourcesJar
|
||||
}
|
||||
|
||||
publishing.publications.mavenJava(MavenPublication) {
|
||||
from components.java
|
||||
artifact sourcesJar
|
||||
}
|
||||
+7
-7
@@ -16,19 +16,19 @@ Step 1: Open your command-line and browse to the folder where you extracted the
|
||||
|
||||
Step 2: You're left with a choice.
|
||||
If you prefer to use Eclipse:
|
||||
1. Run the following command: `gradlew genEclipseRuns` (`./gradlew genEclipseRuns` if you are on Mac/Linux)
|
||||
1. Run the following command: `./gradlew genEclipseRuns`
|
||||
2. Open Eclipse, Import > Existing Gradle Project > Select Folder
|
||||
or run `gradlew eclipse` to generate the project.
|
||||
|
||||
If you prefer to use IntelliJ:
|
||||
1. Open IDEA, and import project.
|
||||
2. Select your build.gradle file and have it import.
|
||||
3. Run the following command: `gradlew genIntellijRuns` (`./gradlew genIntellijRuns` if you are on Mac/Linux)
|
||||
3. Run the following command: `./gradlew genIntellijRuns`
|
||||
4. Refresh the Gradle Project in IDEA if required.
|
||||
|
||||
If at any point you are missing libraries in your IDE, or you've run into problems you can
|
||||
run `gradlew --refresh-dependencies` to refresh the local cache. `gradlew clean` to reset everything
|
||||
{this does not affect your code} and then start the process again.
|
||||
(this does not affect your code) and then start the process again.
|
||||
|
||||
Mapping Names:
|
||||
=============================
|
||||
@@ -40,7 +40,7 @@ https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
|
||||
|
||||
Additional Resources:
|
||||
=========================
|
||||
Community Documentation: https://mcforge.readthedocs.io/en/latest/gettingstarted/
|
||||
LexManos' Install Video: https://www.youtube.com/watch?v=8VEdtQLuLO0
|
||||
Forge Forum: https://forums.minecraftforge.net/
|
||||
Forge Discord: https://discord.gg/UvedJ9m
|
||||
Community Documentation: https://docs.minecraftforge.net/en/latest/gettingstarted/
|
||||
LexManos' Install Video: https://youtu.be/8VEdtQLuLO0
|
||||
Forge Forums: https://forums.minecraftforge.net/
|
||||
Forge Discord: https://discord.minecraftforge.net/
|
||||
+1
-1
@@ -2,7 +2,7 @@ plugins {
|
||||
id 'eclipse'
|
||||
id 'idea'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
|
||||
id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
|
||||
}
|
||||
|
||||
version = mod_version
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
|
||||
}
|
||||
@@ -5,30 +5,30 @@
|
||||
GlStateManager._texParameter(3553, 10242, 33071);
|
||||
GlStateManager._texParameter(3553, 10243, 33071);
|
||||
+ if (!stencilEnabled)
|
||||
GlStateManager._texImage2D(3553, 0, 6402, this.f_83915_, this.f_83916_, 0, 6402, 5126, (IntBuffer)null);
|
||||
GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, (IntBuffer)null);
|
||||
+ else
|
||||
+ GlStateManager._texImage2D(3553, 0, org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8, this.f_83915_, this.f_83916_, 0, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL, org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV, null);
|
||||
+ GlStateManager._texImage2D(3553, 0, org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8, this.width, this.height, 0, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL, org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV, null);
|
||||
}
|
||||
|
||||
this.m_83936_(9728);
|
||||
this.setFilterMode(9728);
|
||||
@@ -124,7 +_,14 @@
|
||||
GlStateManager._glBindFramebuffer(36160, this.f_83920_);
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.f_83923_, 0);
|
||||
if (this.f_83919_) {
|
||||
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.colorTextureId, 0);
|
||||
if (this.useDepth) {
|
||||
+ if(!stencilEnabled)
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.f_83924_, 0);
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0);
|
||||
+ else if(net.minecraftforge.common.ForgeConfig.CLIENT.useCombinedDepthStencilAttachment.get()) {
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL_ATTACHMENT, 3553, this.f_83924_, 0);
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
|
||||
+ } else {
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_ATTACHMENT, 3553, this.f_83924_, 0);
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, 3553, this.f_83924_, 0);
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_ATTACHMENT, 3553, this.depthBufferId, 0);
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
this.m_83949_();
|
||||
this.checkStatus();
|
||||
@@ -292,4 +_,27 @@
|
||||
public int m_83980_() {
|
||||
return this.f_83924_;
|
||||
public int getDepthTextureId() {
|
||||
return this.depthBufferId;
|
||||
}
|
||||
+
|
||||
+ /*================================ FORGE START ================================================*/
|
||||
@@ -42,7 +42,7 @@
|
||||
+ public void enableStencil() {
|
||||
+ if(stencilEnabled) return;
|
||||
+ stencilEnabled = true;
|
||||
+ this.m_83941_(f_83917_, f_83918_, net.minecraft.client.Minecraft.f_91002_);
|
||||
+ this.resize(viewWidth, viewHeight, net.minecraft.client.Minecraft.ON_OSX);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
|
||||
@@ -4,25 +4,25 @@
|
||||
GLFW.glfwWindowHint(139267, 2);
|
||||
GLFW.glfwWindowHint(139272, 204801);
|
||||
GLFW.glfwWindowHint(139270, 1);
|
||||
- this.f_85349_ = GLFW.glfwCreateWindow(this.f_85359_, this.f_85360_, p_85376_, this.f_85355_ && monitor != null ? monitor.m_84954_() : 0L, 0L);
|
||||
+ this.f_85349_ = net.minecraftforge.fml.loading.ImmediateWindowHandler.setupMinecraftWindow(()->this.f_85359_, ()->this.f_85360_, ()->p_85376_, ()->this.f_85355_ && monitor != null ? monitor.m_84954_() : 0L);
|
||||
+ if (!net.minecraftforge.fml.loading.ImmediateWindowHandler.positionWindow(Optional.ofNullable(monitor), w->this.f_85359_ = this.f_85352_ = w, h->this.f_85360_ = this.f_85353_ = h, x->this.f_85357_ = this.f_85350_ = x, y->this.f_85358_ = this.f_85351_ = y)) {
|
||||
- this.window = GLFW.glfwCreateWindow(this.width, this.height, p_85376_, this.fullscreen && monitor != null ? monitor.getMonitor() : 0L, 0L);
|
||||
+ this.window = net.minecraftforge.fml.loading.ImmediateWindowHandler.setupMinecraftWindow(()->this.width, ()->this.height, ()->p_85376_, ()->this.fullscreen && monitor != null ? monitor.getMonitor() : 0L);
|
||||
+ if (!net.minecraftforge.fml.loading.ImmediateWindowHandler.positionWindow(Optional.ofNullable(monitor), w->this.width = this.windowedWidth = w, h->this.height = this.windowedHeight = h, x->this.x = this.windowedX = x, y->this.y = this.windowedY = y)) {
|
||||
if (monitor != null) {
|
||||
VideoMode videomode = monitor.m_84948_(this.f_85355_ ? this.f_85354_ : Optional.empty());
|
||||
this.f_85350_ = this.f_85357_ = monitor.m_84951_() + videomode.m_85332_() / 2 - this.f_85359_ / 2;
|
||||
VideoMode videomode = monitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
|
||||
this.windowedX = this.x = monitor.getX() + videomode.getWidth() / 2 - this.width / 2;
|
||||
@@ -93,6 +_,7 @@
|
||||
this.f_85350_ = this.f_85357_ = aint1[0];
|
||||
this.f_85351_ = this.f_85358_ = aint[0];
|
||||
this.windowedX = this.x = aint1[0];
|
||||
this.windowedY = this.y = aint[0];
|
||||
}
|
||||
+ }
|
||||
|
||||
GLFW.glfwMakeContextCurrent(this.f_85349_);
|
||||
GLFW.glfwMakeContextCurrent(this.window);
|
||||
GL.createCapabilities();
|
||||
@@ -242,6 +_,7 @@
|
||||
GLFW.glfwGetFramebufferSize(this.f_85349_, aint, aint1);
|
||||
this.f_85361_ = aint[0] > 0 ? aint[0] : 1;
|
||||
this.f_85362_ = aint1[0] > 0 ? aint1[0] : 1;
|
||||
+ if (this.f_85362_ == 0 || this.f_85361_==0) net.minecraftforge.fml.loading.ImmediateWindowHandler.updateFBSize(w->this.f_85361_=w, h->this.f_85362_=h);
|
||||
GLFW.glfwGetFramebufferSize(this.window, aint, aint1);
|
||||
this.framebufferWidth = aint[0] > 0 ? aint[0] : 1;
|
||||
this.framebufferHeight = aint1[0] > 0 ? aint1[0] : 1;
|
||||
+ if (this.framebufferHeight == 0 || this.framebufferWidth==0) net.minecraftforge.fml.loading.ImmediateWindowHandler.updateFBSize(w->this.framebufferWidth=w, h->this.framebufferHeight=h);
|
||||
}
|
||||
|
||||
private void m_85427_(long p_85428_, int p_85429_, int p_85430_) {
|
||||
private void onResize(long p_85428_, int p_85429_, int p_85430_) {
|
||||
@@ -1,17 +1,17 @@
|
||||
--- a/com/mojang/blaze3d/vertex/BufferBuilder.java
|
||||
+++ b/com/mojang/blaze3d/vertex/BufferBuilder.java
|
||||
@@ -459,4 +_,14 @@
|
||||
this.f_276566_ = p_277855_;
|
||||
this.sorting = p_277855_;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Forge start
|
||||
+ public void putBulkData(ByteBuffer buffer) {
|
||||
+ m_85722_(buffer.limit() + this.f_85658_.m_86020_());
|
||||
+ this.f_85648_.position(this.f_85652_);
|
||||
+ this.f_85648_.put(buffer);
|
||||
+ this.f_85648_.position(0);
|
||||
+ this.f_85654_ += buffer.limit() / this.f_85658_.m_86020_();
|
||||
+ this.f_85652_ += buffer.limit();
|
||||
+ ensureCapacity(buffer.limit() + this.format.getVertexSize());
|
||||
+ this.buffer.position(this.nextElementByte);
|
||||
+ this.buffer.put(buffer);
|
||||
+ this.buffer.position(0);
|
||||
+ this.vertices += buffer.limit() / this.format.getVertexSize();
|
||||
+ this.nextElementByte += buffer.limit();
|
||||
+ }
|
||||
}
|
||||
@@ -6,6 +6,6 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class PoseStack {
|
||||
+public class PoseStack implements net.minecraftforge.client.extensions.IForgePoseStack {
|
||||
private final Deque<PoseStack.Pose> f_85834_ = Util.m_137469_(Queues.newArrayDeque(), (p_85848_) -> {
|
||||
private final Deque<PoseStack.Pose> poseStack = Util.make(Queues.newArrayDeque(), (p_85848_) -> {
|
||||
Matrix4f matrix4f = new Matrix4f();
|
||||
Matrix3f matrix3f = new Matrix3f();
|
||||
@@ -2,10 +2,10 @@
|
||||
+++ b/com/mojang/blaze3d/vertex/SheetedDecalTextureGenerator.java
|
||||
@@ -46,7 +_,7 @@
|
||||
|
||||
public void m_5752_() {
|
||||
Vector3f vector3f = this.f_85869_.transform(new Vector3f(this.f_85876_, this.f_85877_, this.f_85878_));
|
||||
- Direction direction = Direction.m_122372_(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
public void endVertex() {
|
||||
Vector3f vector3f = this.normalInversePose.transform(new Vector3f(this.nx, this.ny, this.nz));
|
||||
- Direction direction = Direction.getNearest(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
+ Direction direction = net.minecraftforge.client.ForgeHooksClient.getNearestStable(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
Vector4f vector4f = this.f_85868_.transform(new Vector4f(this.f_85870_, this.f_85871_, this.f_85872_, 1.0F));
|
||||
Vector4f vector4f = this.cameraInversePose.transform(new Vector4f(this.x, this.y, this.z, 1.0F));
|
||||
vector4f.rotateY((float)Math.PI);
|
||||
vector4f.rotateX((-(float)Math.PI / 2F));
|
||||
@@ -6,20 +6,20 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public interface VertexConsumer {
|
||||
+public interface VertexConsumer extends net.minecraftforge.client.extensions.IForgeVertexConsumer {
|
||||
VertexConsumer m_5483_(double p_85945_, double p_85946_, double p_85947_);
|
||||
VertexConsumer vertex(double p_85945_, double p_85946_, double p_85947_);
|
||||
|
||||
VertexConsumer m_6122_(int p_85973_, int p_85974_, int p_85975_, int p_85976_);
|
||||
VertexConsumer color(int p_85973_, int p_85974_, int p_85975_, int p_85976_);
|
||||
@@ -64,6 +_,10 @@
|
||||
}
|
||||
|
||||
default void m_85995_(PoseStack.Pose p_85996_, BakedQuad p_85997_, float[] p_85998_, float p_85999_, float p_86000_, float p_86001_, int[] p_86002_, int p_86003_, boolean p_86004_) {
|
||||
default void putBulkData(PoseStack.Pose p_85996_, BakedQuad p_85997_, float[] p_85998_, float p_85999_, float p_86000_, float p_86001_, int[] p_86002_, int p_86003_, boolean p_86004_) {
|
||||
+ putBulkData(p_85996_, p_85997_, p_85998_, p_85999_, p_86000_, p_86001_, 1, p_86002_, p_86003_, p_86004_);
|
||||
+ }
|
||||
+
|
||||
+ default void putBulkData(PoseStack.Pose p_85996_, BakedQuad p_85997_, float[] p_85998_, float p_85999_, float p_86000_, float p_86001_, float alpha, int[] p_86002_, int p_86003_, boolean p_86004_) {
|
||||
float[] afloat = new float[]{p_85998_[0], p_85998_[1], p_85998_[2], p_85998_[3]};
|
||||
int[] aint = new int[]{p_86002_[0], p_86002_[1], p_86002_[2], p_86002_[3]};
|
||||
int[] aint1 = p_85997_.m_111303_();
|
||||
int[] aint1 = p_85997_.getVertices();
|
||||
@@ -99,11 +_,13 @@
|
||||
f5 = afloat[k] * p_86001_;
|
||||
}
|
||||
@@ -29,10 +29,10 @@
|
||||
float f9 = bytebuffer.getFloat(16);
|
||||
float f10 = bytebuffer.getFloat(20);
|
||||
Vector4f vector4f = matrix4f.transform(new Vector4f(f, f1, f2, 1.0F));
|
||||
- this.m_5954_(vector4f.x(), vector4f.y(), vector4f.z(), f3, f4, f5, 1.0F, f9, f10, p_86003_, l, vector3f.x(), vector3f.y(), vector3f.z());
|
||||
+ applyBakedNormals(vector3f, bytebuffer, p_85996_.m_252943_());
|
||||
- this.vertex(vector4f.x(), vector4f.y(), vector4f.z(), f3, f4, f5, 1.0F, f9, f10, p_86003_, l, vector3f.x(), vector3f.y(), vector3f.z());
|
||||
+ applyBakedNormals(vector3f, bytebuffer, p_85996_.normal());
|
||||
+ float vertexAlpha = p_86004_ ? alpha * (float) (bytebuffer.get(15) & 255) / 255.0F : alpha;
|
||||
+ this.m_5954_(vector4f.x(), vector4f.y(), vector4f.z(), f3, f4, f5, vertexAlpha, f9, f10, p_86003_, l, vector3f.x(), vector3f.y(), vector3f.z());
|
||||
+ this.vertex(vector4f.x(), vector4f.y(), vector4f.z(), f3, f4, f5, vertexAlpha, f9, f10, p_86003_, l, vector3f.x(), vector3f.y(), vector3f.z());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
}
|
||||
}
|
||||
+
|
||||
+ public ImmutableMap<String, VertexFormatElement> getElementMapping() { return f_166905_; }
|
||||
+ public int getOffset(int index) { return f_86013_.getInt(index); }
|
||||
+ public boolean hasPosition() { return f_86012_.stream().anyMatch(e -> e.m_86048_() == VertexFormatElement.Usage.POSITION); }
|
||||
+ public boolean hasNormal() { return f_86012_.stream().anyMatch(e -> e.m_86048_() == VertexFormatElement.Usage.NORMAL); }
|
||||
+ public boolean hasColor() { return f_86012_.stream().anyMatch(e -> e.m_86048_() == VertexFormatElement.Usage.COLOR); }
|
||||
+ public boolean hasUV(int which) { return f_86012_.stream().anyMatch(e -> e.m_86048_() == VertexFormatElement.Usage.UV && e.m_86049_() == which); }
|
||||
+ public ImmutableMap<String, VertexFormatElement> getElementMapping() { return elementMapping; }
|
||||
+ public int getOffset(int index) { return offsets.getInt(index); }
|
||||
+ public boolean hasPosition() { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.POSITION); }
|
||||
+ public boolean hasNormal() { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.NORMAL); }
|
||||
+ public boolean hasColor() { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.COLOR); }
|
||||
+ public boolean hasUV(int which) { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.UV && e.getIndex() == which); }
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
--- a/com/mojang/blaze3d/vertex/VertexFormatElement.java
|
||||
+++ b/com/mojang/blaze3d/vertex/VertexFormatElement.java
|
||||
@@ -90,6 +_,10 @@
|
||||
this.f_86031_.m_166978_(this.f_86032_, p_166964_);
|
||||
this.usage.clearBufferState(this.index, p_166964_);
|
||||
}
|
||||
|
||||
+ public int getElementCount() {
|
||||
+ return f_86033_;
|
||||
+ return count;
|
||||
+ }
|
||||
+
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
-public final class Transformation {
|
||||
+public final class Transformation implements net.minecraftforge.common.extensions.IForgeTransformation {
|
||||
private final Matrix4f f_121078_;
|
||||
public static final Codec<Transformation> f_268453_ = RecordCodecBuilder.create((p_269604_) -> {
|
||||
return p_269604_.group(ExtraCodecs.f_252432_.fieldOf("translation").forGetter((p_269599_) -> {
|
||||
private final Matrix4f matrix;
|
||||
public static final Codec<Transformation> CODEC = RecordCodecBuilder.create((p_269604_) -> {
|
||||
return p_269604_.group(ExtraCodecs.VECTOR3F.fieldOf("translation").forGetter((p_269599_) -> {
|
||||
@@ -156,6 +_,19 @@
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.f_121078_);
|
||||
return Objects.hash(this.matrix);
|
||||
}
|
||||
+
|
||||
+ private Matrix3f normalTransform = null;
|
||||
@@ -21,11 +21,11 @@
|
||||
+ }
|
||||
+ private void checkNormalTransform() {
|
||||
+ if (normalTransform == null) {
|
||||
+ normalTransform = new Matrix3f(f_121078_);
|
||||
+ normalTransform = new Matrix3f(matrix);
|
||||
+ normalTransform.invert();
|
||||
+ normalTransform.transpose();
|
||||
+ }
|
||||
+ }
|
||||
|
||||
public Transformation m_175937_(Transformation p_175938_, float p_175939_) {
|
||||
Vector3f vector3f = this.m_252829_();
|
||||
public Transformation slerp(Transformation p_175938_, float p_175939_) {
|
||||
Vector3f vector3f = this.getTranslation();
|
||||
+7
-7
@@ -1,18 +1,18 @@
|
||||
--- a/com/mojang/realmsclient/gui/screens/RealmsGenericErrorScreen.java
|
||||
+++ b/com/mojang/realmsclient/gui/screens/RealmsGenericErrorScreen.java
|
||||
@@ -61,6 +_,15 @@
|
||||
return Component.m_237119_().m_7220_(this.f_200947_.f_287789_).m_130946_(": ").m_7220_(this.f_200947_.f_287787_);
|
||||
return Component.empty().append(this.lines.title).append(": ").append(this.lines.detail);
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public boolean m_7933_(int key, int scanCode, int modifiers) {
|
||||
+ public boolean keyPressed(int key, int scanCode, int modifiers) {
|
||||
+ if (key == org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE) {
|
||||
+ f_96541_.m_91152_(this.f_88665_);
|
||||
+ minecraft.setScreen(this.nextScreen);
|
||||
+ return true;
|
||||
+ }
|
||||
+ return super.m_7933_(key, scanCode, modifiers);
|
||||
+ return super.keyPressed(key, scanCode, modifiers);
|
||||
+ }
|
||||
+
|
||||
public void m_88315_(GuiGraphics p_283497_, int p_88680_, int p_88681_, float p_88682_) {
|
||||
super.m_88315_(p_283497_, p_88680_, p_88681_, p_88682_);
|
||||
p_283497_.m_280653_(this.f_96547_, this.f_200947_.f_287789_, this.f_96543_ / 2, 80, -1);
|
||||
public void render(GuiGraphics p_283497_, int p_88680_, int p_88681_, float p_88682_) {
|
||||
super.render(p_283497_, p_88680_, p_88681_, p_88682_);
|
||||
p_283497_.drawCenteredString(this.font, this.lines.title, this.width / 2, 80, -1);
|
||||
@@ -1,32 +1,33 @@
|
||||
--- a/net/minecraft/CrashReport.java
|
||||
+++ b/net/minecraft/CrashReport.java
|
||||
@@ -57,14 +_,8 @@
|
||||
if (this.f_127506_ != null && this.f_127506_.length > 0) {
|
||||
@@ -57,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");
|
||||
- p_127520_.append("Stacktrace:\n");
|
||||
-
|
||||
- for(StackTraceElement stacktraceelement : this.f_127506_) {
|
||||
- for(StackTraceElement stacktraceelement : this.uncategorizedStackTrace) {
|
||||
- p_127520_.append("\t").append("at ").append((Object)stacktraceelement);
|
||||
- p_127520_.append("\n");
|
||||
- }
|
||||
-
|
||||
- p_127520_.append("\n");
|
||||
+ p_127520_.append(net.minecraftforge.logging.CrashReportAnalyser.appendSuspectedMods(this.exception, this.uncategorizedStackTrace));
|
||||
+ p_127520_.append("Stacktrace:");
|
||||
+ p_127520_.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.f_127506_));
|
||||
+ p_127520_.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.uncategorizedStackTrace));
|
||||
}
|
||||
|
||||
for(CrashReportCategory crashreportcategory : this.f_127503_) {
|
||||
for(CrashReportCategory crashreportcategory : this.details) {
|
||||
@@ -72,6 +_,7 @@
|
||||
p_127520_.append("\n\n");
|
||||
}
|
||||
|
||||
+ net.minecraftforge.logging.CrashReportExtender.extendSystemReport(f_178624_);
|
||||
this.f_178624_.m_143525_(p_127520_);
|
||||
+ net.minecraftforge.logging.CrashReportExtender.extendSystemReport(systemReport);
|
||||
this.systemReport.appendToCrashReportString(p_127520_);
|
||||
}
|
||||
|
||||
@@ -91,23 +_,13 @@
|
||||
throwable.setStackTrace(this.f_127501_.getStackTrace());
|
||||
@@ -91,18 +_,7 @@
|
||||
throwable.setStackTrace(this.exception.getStackTrace());
|
||||
}
|
||||
|
||||
- String s;
|
||||
@@ -44,10 +45,4 @@
|
||||
+ return net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(throwable);
|
||||
}
|
||||
|
||||
public String m_127526_() {
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
stringbuilder.append("---- Minecraft Crash Report ----\n");
|
||||
+ net.minecraftforge.logging.CrashReportExtender.addCrashReportHeader(stringbuilder, this);
|
||||
stringbuilder.append("// ");
|
||||
stringbuilder.append(m_127531_());
|
||||
stringbuilder.append("\n\n");
|
||||
public String getFriendlyReport() {
|
||||
@@ -4,35 +4,35 @@
|
||||
if (astacktraceelement.length <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
- this.f_128139_ = new StackTraceElement[astacktraceelement.length - 3 - p_128149_];
|
||||
- System.arraycopy(astacktraceelement, 3 + p_128149_, this.f_128139_, 0, this.f_128139_.length);
|
||||
- this.stackTrace = new StackTraceElement[astacktraceelement.length - 3 - p_128149_];
|
||||
- System.arraycopy(astacktraceelement, 3 + p_128149_, this.stackTrace, 0, this.stackTrace.length);
|
||||
+ int len = astacktraceelement.length - 3 - p_128149_;
|
||||
+ if (len <= 0) len = astacktraceelement.length;
|
||||
+ this.f_128139_ = new StackTraceElement[len];
|
||||
+ System.arraycopy(astacktraceelement, astacktraceelement.length - len, this.f_128139_, 0, this.f_128139_.length);
|
||||
return this.f_128139_.length;
|
||||
+ this.stackTrace = new StackTraceElement[len];
|
||||
+ System.arraycopy(astacktraceelement, astacktraceelement.length - len, this.stackTrace, 0, this.stackTrace.length);
|
||||
return this.stackTrace.length;
|
||||
}
|
||||
}
|
||||
@@ -147,17 +_,17 @@
|
||||
|
||||
if (this.f_128139_ != null && this.f_128139_.length > 0) {
|
||||
if (this.stackTrace != null && this.stackTrace.length > 0) {
|
||||
p_128169_.append("\nStacktrace:");
|
||||
-
|
||||
- for(StackTraceElement stacktraceelement : this.f_128139_) {
|
||||
- for(StackTraceElement stacktraceelement : this.stackTrace) {
|
||||
- p_128169_.append("\n\tat ");
|
||||
- p_128169_.append((Object)stacktraceelement);
|
||||
- }
|
||||
+ p_128169_.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.f_128139_));
|
||||
+ p_128169_.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.stackTrace));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public StackTraceElement[] m_128143_() {
|
||||
return this.f_128139_;
|
||||
public StackTraceElement[] getStacktrace() {
|
||||
return this.stackTrace;
|
||||
+ }
|
||||
+
|
||||
+ public void applyStackTrace(Throwable t) {
|
||||
+ this.f_128139_ = t.getStackTrace();
|
||||
+ this.stackTrace = t.getStackTrace();
|
||||
}
|
||||
|
||||
public static void m_178950_(CrashReportCategory p_178951_, LevelHeightAccessor p_178952_, BlockPos p_178953_, @Nullable BlockState p_178954_) {
|
||||
public static void populateBlockDetails(CrashReportCategory p_178951_, LevelHeightAccessor p_178952_, BlockPos p_178953_, @Nullable BlockState p_178954_) {
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
static {
|
||||
+ if (System.getProperty("io.netty.leakDetection.level") == null) // Forge: allow level to be manually specified
|
||||
ResourceLeakDetector.setLevel(f_136180_);
|
||||
ResourceLeakDetector.setLevel(NETTY_LEAK_DETECTION);
|
||||
CommandSyntaxException.ENABLE_COMMAND_STACK_TRACES = false;
|
||||
CommandSyntaxException.BUILT_IN_EXCEPTIONS = new BrigadierExceptions();
|
||||
@@ -9,15 +9,15 @@
|
||||
+ @SuppressWarnings("unused") private static java.util.function.LongSupplier INNER_CLASS_SHIFT1 = new java.util.function.LongSupplier() { public long getAsLong() { return 0; } };
|
||||
+ @SuppressWarnings("unused") private static java.util.function.LongSupplier INNER_CLASS_SHIFT2 = new java.util.function.LongSupplier() { public long getAsLong() { return 0; } };
|
||||
+
|
||||
public static ExecutorService m_183991_() {
|
||||
return f_137444_;
|
||||
public static ExecutorService backgroundExecutor() {
|
||||
return BACKGROUND_EXECUTOR;
|
||||
}
|
||||
@@ -240,7 +_,7 @@
|
||||
try {
|
||||
type = DataFixers.m_14512_().getSchema(DataFixUtils.makeKey(SharedConstants.m_183709_().m_183476_().m_193006_())).getChoiceType(p_137552_, p_137553_);
|
||||
type = DataFixers.getDataFixer().getSchema(DataFixUtils.makeKey(SharedConstants.getCurrentVersion().getDataVersion().getVersion())).getChoiceType(p_137552_, p_137553_);
|
||||
} catch (IllegalArgumentException illegalargumentexception) {
|
||||
- f_137446_.error("No data fixer registered for {}", (Object)p_137553_);
|
||||
+ f_137446_.debug("No data fixer registered for {}", (Object)p_137553_);
|
||||
if (SharedConstants.f_136183_) {
|
||||
- LOGGER.error("No data fixer registered for {}", (Object)p_137553_);
|
||||
+ LOGGER.debug("No data fixer registered for {}", (Object)p_137553_);
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
throw illegalargumentexception;
|
||||
}
|
||||
@@ -6,12 +6,25 @@
|
||||
|
||||
+ /** @deprecated Forge: use {@linkplain #fromJson(JsonObject, DeserializationContext, net.minecraftforge.common.crafting.conditions.ICondition.IContext) overload with context}. */
|
||||
+ @Deprecated
|
||||
public static Advancement m_294730_(JsonObject p_300691_, DeserializationContext p_300053_) {
|
||||
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.crafting.ConditionalAdvancement.processConditional(p_300691_, context)) == null) return null;
|
||||
Optional<ResourceLocation> optional = p_300691_.has("parent") ? Optional.of(new ResourceLocation(GsonHelper.m_13906_(p_300691_, "parent"))) : Optional.empty();
|
||||
Optional<DisplayInfo> optional1 = p_300691_.has("display") ? Optional.of(DisplayInfo.m_14981_(GsonHelper.m_13930_(p_300691_, "display"))) : Optional.empty();
|
||||
AdvancementRewards advancementrewards = p_300691_.has("rewards") ? AdvancementRewards.m_9991_(GsonHelper.m_13930_(p_300691_, "rewards")) : AdvancementRewards.f_9978_;
|
||||
+ 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 @@
|
||||
}
|
||||
|
||||
public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, String p_138391_) {
|
||||
- AdvancementHolder advancementholder = this.build(new ResourceLocation(p_138391_));
|
||||
+ return save(p_138390_, new ResourceLocation(p_138391_));
|
||||
+ }
|
||||
+
|
||||
+ public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, ResourceLocation id) {
|
||||
+ AdvancementHolder advancementholder = this.build(id);
|
||||
p_138390_.accept(advancementholder);
|
||||
return advancementholder;
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
+++ b/net/minecraft/advancements/AdvancementRewards.java
|
||||
@@ -43,7 +_,7 @@
|
||||
|
||||
public void m_9989_(ServerPlayer p_9990_) {
|
||||
p_9990_.m_6756_(this.f_9979_);
|
||||
- LootParams lootparams = (new LootParams.Builder(p_9990_.m_284548_())).m_287286_(LootContextParams.f_81455_, p_9990_).m_287286_(LootContextParams.f_81460_, p_9990_.m_20182_()).m_287235_(LootContextParamSets.f_81418_);
|
||||
+ LootParams lootparams = (new LootParams.Builder(p_9990_.m_284548_())).m_287286_(LootContextParams.f_81455_, p_9990_).m_287286_(LootContextParams.f_81460_, p_9990_.m_20182_()).m_287239_(p_9990_.m_36336_()).m_287235_(LootContextParamSets.f_81418_); // Forge: Add luck to LootContext
|
||||
public void grant(ServerPlayer p_9990_) {
|
||||
p_9990_.giveExperiencePoints(this.experience);
|
||||
- LootParams lootparams = (new LootParams.Builder(p_9990_.serverLevel())).withParameter(LootContextParams.THIS_ENTITY, p_9990_).withParameter(LootContextParams.ORIGIN, p_9990_.position()).create(LootContextParamSets.ADVANCEMENT_REWARD);
|
||||
+ LootParams lootparams = (new LootParams.Builder(p_9990_.serverLevel())).withParameter(LootContextParams.THIS_ENTITY, p_9990_).withParameter(LootContextParams.ORIGIN, p_9990_.position()).withLuck(p_9990_.getLuck()).create(LootContextParamSets.ADVANCEMENT_REWARD); // Forge: Add luck to LootContext
|
||||
boolean flag = false;
|
||||
|
||||
for(ResourceLocation resourcelocation : this.f_9980_) {
|
||||
for(ResourceLocation resourcelocation : this.loot) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- 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());
|
||||
@@ -3,9 +3,9 @@
|
||||
@@ -50,7 +_,7 @@
|
||||
return false;
|
||||
} else {
|
||||
if (!this.f_45033_.isEmpty()) {
|
||||
- Map<Enchantment, Integer> map = EnchantmentHelper.m_44882_(p_45050_.m_41785_());
|
||||
if (!this.enchantments.isEmpty()) {
|
||||
- Map<Enchantment, Integer> map = EnchantmentHelper.deserializeEnchantments(p_45050_.getEnchantmentTags());
|
||||
+ Map<Enchantment, Integer> map = p_45050_.getAllEnchantments();
|
||||
|
||||
for(EnchantmentPredicate enchantmentpredicate : this.f_45033_) {
|
||||
if (!enchantmentpredicate.m_30476_(map)) {
|
||||
for(EnchantmentPredicate enchantmentpredicate : this.enchantments) {
|
||||
if (!enchantmentpredicate.containedIn(map)) {
|
||||
@@ -1,21 +1,21 @@
|
||||
--- a/net/minecraft/client/Camera.java
|
||||
+++ b/net/minecraft/client/Camera.java
|
||||
@@ -206,6 +_,18 @@
|
||||
this.f_90549_ = false;
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
+ public void setAnglesInternal(float yaw, float pitch) {
|
||||
+ this.f_90558_ = yaw;
|
||||
+ this.f_90557_ = pitch;
|
||||
+ this.yRot = yaw;
|
||||
+ this.xRot = pitch;
|
||||
+ }
|
||||
+
|
||||
+ public net.minecraft.world.level.block.state.BlockState getBlockAtCamera() {
|
||||
+ if (!this.f_90549_)
|
||||
+ return net.minecraft.world.level.block.Blocks.f_50016_.m_49966_();
|
||||
+ if (!this.initialized)
|
||||
+ return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState();
|
||||
+ else
|
||||
+ return this.f_90550_.m_8055_(this.f_90553_).getStateAtViewpoint(this.f_90550_, this.f_90553_, this.f_90552_);
|
||||
+ return this.level.getBlockState(this.blockPosition).getStateAtViewpoint(this.level, this.blockPosition, this.position);
|
||||
+ }
|
||||
+
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class NearPlane {
|
||||
final Vec3 f_167687_;
|
||||
final Vec3 forward;
|
||||
@@ -1,20 +1,20 @@
|
||||
--- a/net/minecraft/client/ClientRecipeBook.java
|
||||
+++ b/net/minecraft/client/ClientRecipeBook.java
|
||||
@@ -56,7 +_,7 @@
|
||||
Recipe<?> recipe = recipeholder.f_291008_();
|
||||
if (!recipe.m_5598_() && !recipe.m_142505_()) {
|
||||
RecipeBookCategories recipebookcategories = m_90646_(recipeholder);
|
||||
- String s = recipe.m_6076_();
|
||||
+ String s = recipe.m_6076_().isEmpty() ? recipeholder.f_291676_().toString() : recipe.m_6076_(); // FORGE: Group value defaults to the recipe's ID if the recipe's explicit group is empty.
|
||||
Recipe<?> recipe = recipeholder.value();
|
||||
if (!recipe.isSpecial() && !recipe.isIncomplete()) {
|
||||
RecipeBookCategories recipebookcategories = getCategory(recipeholder);
|
||||
- String s = recipe.getGroup();
|
||||
+ String s = recipe.getGroup().isEmpty() ? recipeholder.id().toString() : recipe.getGroup(); // FORGE: Group value defaults to the recipe's ID if the recipe's explicit group is empty.
|
||||
if (s.isEmpty()) {
|
||||
map.computeIfAbsent(recipebookcategories, (p_90645_) -> {
|
||||
return Lists.newArrayList();
|
||||
@@ -144,6 +_,8 @@
|
||||
} else if (recipetype == RecipeType.f_44113_) {
|
||||
} else if (recipetype == RecipeType.SMITHING) {
|
||||
return RecipeBookCategories.SMITHING;
|
||||
} else {
|
||||
+ RecipeBookCategories categories = net.minecraftforge.client.RecipeBookManager.findCategories((RecipeType) recipetype, p_299041_);
|
||||
+ if (categories != null) return categories;
|
||||
f_90618_.warn("Unknown recipe category: {}/{}", LogUtils.defer(() -> {
|
||||
return BuiltInRegistries.f_256990_.m_7981_(recipe.m_6671_());
|
||||
}), LogUtils.defer(p_299041_::f_291676_));
|
||||
LOGGER.warn("Unknown recipe category: {}/{}", LogUtils.defer(() -> {
|
||||
return BuiltInRegistries.RECIPE_TYPE.getKey(recipe.getType());
|
||||
}), LogUtils.defer(p_299041_::id));
|
||||
Loaded 100 of 1626 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user