mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1f057278d | ||
|
|
6bbe2c64a9 | ||
|
|
684cd96e32 | ||
|
|
1f4e13fce0 | ||
|
|
55ad9e6d7d | ||
|
|
5c8d1618bc | ||
|
|
a6f5057840 | ||
|
|
1b0360928f | ||
|
|
921771bd11 | ||
|
|
089bb1fc84 | ||
|
|
602f1ef947 | ||
|
|
3b18e003f6 | ||
|
|
c33f2d1be6 | ||
|
|
022116141c | ||
|
|
a8b243c0cd | ||
|
|
c22355cc45 | ||
|
|
74bc36307e | ||
|
|
88d2dc6c8f | ||
|
|
de13ba8ab8 | ||
|
|
4f838a87d4 | ||
|
|
70d700e630 | ||
|
|
78fffcf45a | ||
|
|
cdba403ab6 | ||
|
|
6821d7b1cc | ||
|
|
9524ce4580 | ||
|
|
f2bbeab3b9 | ||
|
|
4a8adf5465 | ||
|
|
f5fa2f2a57 | ||
|
|
b33e168969 | ||
|
|
1f6e1ff257 | ||
|
|
7f8897141e | ||
|
|
b9a097c9e1 | ||
|
|
62f00266c5 | ||
|
|
6986cd7ab3 | ||
|
|
e7051b3484 | ||
|
|
f667d25d0b | ||
|
|
48d72fb7c6 |
No files matched your search
Vendored
+2
-2
@@ -36,8 +36,8 @@ project {
|
||||
buildType(PullRequestCompatibility)
|
||||
|
||||
params {
|
||||
text("docker_jdk_version", "17", label = "Gradle version", description = "The version of the JDK to use during execution of tasks in a JDK.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("docker_gradle_version", "7.5.1", label = "Gradle version", description = "The version of Gradle to use during execution of Gradle tasks.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("docker_jdk_version", "21", label = "Gradle version", description = "The version of the JDK to use during execution of tasks in a JDK.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("docker_gradle_version", "8.8", label = "Gradle version", description = "The version of Gradle to use during execution of Gradle tasks.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("git_main_branch", "1.20.x", label = "Git Main Branch", description = "The git main or default branch to use in VCS operations.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("git_branch_spec", """
|
||||
+:refs/heads/(main*)
|
||||
|
||||
Vendored
-125
@@ -1,125 +0,0 @@
|
||||
@Library('forge-shared-library')_
|
||||
|
||||
pipeline {
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'gradle:7-jdk16'
|
||||
//args '-v forgegc:/home/gradle/.gradle_cache/'
|
||||
}
|
||||
}
|
||||
environment {
|
||||
GRADLE_ARGS = '--no-daemon --console=plain' // No daemon for now as FG3 kinda derps. //'-Dorg.gradle.daemon.idletimeout=5000'
|
||||
DISCORD_WEBHOOK = credentials('forge-discord-jenkins-webhook')
|
||||
DISCORD_PREFIX = "Job: Forge Branch: ${BRANCH_NAME} Build: #${BUILD_NUMBER}"
|
||||
JENKINS_HEAD = 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('notify_start') {
|
||||
when {
|
||||
not {
|
||||
changeRequest()
|
||||
}
|
||||
}
|
||||
steps {
|
||||
discordSend(
|
||||
title: "${DISCORD_PREFIX} Started",
|
||||
successful: true,
|
||||
result: 'ABORTED', //White border
|
||||
thumbnail: JENKINS_HEAD,
|
||||
webhookURL: DISCORD_WEBHOOK
|
||||
)
|
||||
}
|
||||
}
|
||||
/*
|
||||
stage('pull_cache') {
|
||||
steps {
|
||||
sh 'cp -r /home/gradle/.gradle_cache/jdks/ /home/gradle/.gradle/jdks/'
|
||||
sh 'cp -r /home/gradle/.gradle_cache/wrapper/ /home/gradle/.gradle/wrapper/'
|
||||
sh 'cp -r /home/gradle/.gradle_cache/caches/ /home/gradle/.gradle/caches/'
|
||||
}
|
||||
}
|
||||
*/
|
||||
stage('setup') {
|
||||
steps {
|
||||
withGradle {
|
||||
sh './gradlew ${GRADLE_ARGS} --refresh-dependencies --continue setup'
|
||||
}
|
||||
script {
|
||||
env.MYVERSION = sh(returnStdout: true, script: './gradlew :forge:properties -q | grep "^version:" | cut -d" " -f2').trim()
|
||||
env.FMLONLY_VERSION = sh(returnStdout: true, script: './gradlew :fmlonly:properties -q | grep "^version:" | cut -d" " -f2').trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('changelog') {
|
||||
when {
|
||||
not {
|
||||
changeRequest()
|
||||
}
|
||||
}
|
||||
steps {
|
||||
writeChangelog(currentBuild, 'build/changelog.txt')
|
||||
}
|
||||
}
|
||||
stage('publish') {
|
||||
when {
|
||||
not {
|
||||
changeRequest()
|
||||
}
|
||||
}
|
||||
environment {
|
||||
CROWDIN = credentials('forge-crowdin')
|
||||
KEYSTORE = credentials('forge-jenkins-keystore-old')
|
||||
KEYSTORE_KEYPASS = credentials('forge-jenkins-keystore-old-keypass')
|
||||
KEYSTORE_STOREPASS = credentials('forge-jenkins-keystore-old-keypass')
|
||||
}
|
||||
steps {
|
||||
withCredentials([usernamePassword(credentialsId: 'maven-forge-user', usernameVariable: 'MAVEN_USER', passwordVariable: 'MAVEN_PASSWORD')]) {
|
||||
withGradle {
|
||||
sh './gradlew ${GRADLE_ARGS} publish -PkeystoreKeyPass=${KEYSTORE_KEYPASS} -PkeystoreStorePass=${KEYSTORE_STOREPASS} -Pkeystore=${KEYSTORE} -PcrowdinKey=${CROWDIN}'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote net.minecraftforge:forge ${env.MYVERSION} latest")], propagate: false, wait: false
|
||||
build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote net.minecraftforge:fmlonly ${env.FMLONLY_VERSION} latest")], propagate: false, wait: false
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('test_publish_pr') { //Publish to local repo to test full process, but don't include credentials so it can't sign/publish to maven
|
||||
when {
|
||||
changeRequest()
|
||||
}
|
||||
environment {
|
||||
CROWDIN = credentials('forge-crowdin')
|
||||
}
|
||||
steps {
|
||||
withGradle {
|
||||
sh './gradlew ${GRADLE_ARGS} publish -PcrowdinKey=${CROWDIN}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
archiveArtifacts artifacts: 'projects/forge/build/libs/**/*.*', fingerprint: true, onlyIfSuccessful: true, allowEmptyArchive: true
|
||||
|
||||
if (env.CHANGE_ID == null) { // This is unset for non-PRs
|
||||
discordSend(
|
||||
title: "${DISCORD_PREFIX} Finished ${currentBuild.currentResult}",
|
||||
description: '```\n' + getChanges(currentBuild) + '\n```',
|
||||
successful: currentBuild.resultIsBetterOrEqualTo("SUCCESS"),
|
||||
result: currentBuild.currentResult,
|
||||
thumbnail: JENKINS_HEAD,
|
||||
webhookURL: DISCORD_WEBHOOK
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-12
@@ -1,3 +1,4 @@
|
||||
import de.undercouch.gradle.tasks.download.Download
|
||||
import groovy.json.JsonBuilder
|
||||
import net.minecraftforge.forge.tasks.checks.CheckATs
|
||||
import net.minecraftforge.forge.tasks.checks.CheckExcs
|
||||
@@ -24,7 +25,7 @@ import org.objectweb.asm.Opcodes
|
||||
plugins {
|
||||
id 'org.cadixdev.licenser' version '0.6.1'
|
||||
id 'com.github.ben-manes.versions' version '0.46.0'
|
||||
id 'net.minecraftforge.gradleutils' version '2.+'
|
||||
id 'net.minecraftforge.gradleutils' version '[2.2,2.3)'
|
||||
id 'eclipse'
|
||||
id 'de.undercouch.download' version '5.4.0'
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.11,6.2)' apply false
|
||||
@@ -52,13 +53,13 @@ ext {
|
||||
SPI_VERSION = '7.0.1'
|
||||
MERGETOOL_VERSION = '1.1.5'
|
||||
ACCESSTRANSFORMERS_VERSION = '8.0.4'
|
||||
COREMODS_VERSION = '5.0.1'
|
||||
COREMODS_VERSION = '5.1.6'
|
||||
EVENTBUS_VERSION = '6.0.5'
|
||||
MODLAUNCHER_VERSION = '10.0.9'
|
||||
SECUREJARHANDLER_VERSION = '2.1.10'
|
||||
BOOTSTRAPLAUNCHER_VERSION = '1.1.2'
|
||||
ASM_VERSION = '9.5'
|
||||
INSTALLER_VERSION = '2.1.+'
|
||||
ASM_VERSION = '9.7'
|
||||
INSTALLER_VERSION = '2.2.+'
|
||||
MIXIN_VERSION = '0.8.5'
|
||||
TERMINALCONSOLEAPPENDER_VERSION = '1.2.0'
|
||||
JLINE_VERSION = '3.12.+'
|
||||
@@ -84,7 +85,7 @@ ext {
|
||||
FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1)
|
||||
|
||||
BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.1.1:fatjar'
|
||||
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.3.0'
|
||||
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.4.1'
|
||||
JAR_SPLITTER = 'net.minecraftforge:jarsplitter:1.1.4'
|
||||
FART = 'net.minecraftforge:ForgeAutoRenamingTool:0.1.22:all'
|
||||
MIN_TAG_FOR_CHANGELOG = '41.0'
|
||||
@@ -354,7 +355,7 @@ def sharedFmlonlyForge = { Project prj ->
|
||||
}
|
||||
|
||||
prj.task([type: DownloadMavenArtifact], 'downloadInstaller') {
|
||||
artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:shrunk"
|
||||
artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:fatjar"
|
||||
changing = true
|
||||
}
|
||||
|
||||
@@ -1177,9 +1178,12 @@ project(':forge') {
|
||||
]
|
||||
}
|
||||
|
||||
task crowdin(type: Crowdin) {
|
||||
key = project.hasProperty('crowdinKey') ? project.crowdinKey : null
|
||||
//TODO: Merge our english.json?
|
||||
tasks.register('downloadCrowdin', Download) {
|
||||
src 'https://files.minecraftforge.net/crowdin.zip'
|
||||
dest file('build/crowdin.zip')
|
||||
useETag 'all'
|
||||
onlyIfModified true
|
||||
quiet true
|
||||
}
|
||||
|
||||
sharedFmlonlyForge.call(project)
|
||||
@@ -1590,9 +1594,12 @@ project(':forge') {
|
||||
from extraTxts
|
||||
|
||||
// add crowdin locales
|
||||
from { crowdin.output.present && crowdin.output.get().asFile.exists() ? zipTree(crowdin.output) : null}
|
||||
dependsOn crowdin
|
||||
duplicatesStrategy = 'exclude'
|
||||
from zipTree(downloadCrowdin.dest).matching {
|
||||
include 'assets/forge/lang/*.json'
|
||||
}
|
||||
|
||||
dependsOn downloadCrowdin
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
|
||||
doFirst {
|
||||
MANIFESTS.each{ pkg, values ->
|
||||
|
||||
+1
-1
@@ -27,6 +27,6 @@ abstract class BytecodePredicateFinder extends BytecodeFinder {
|
||||
@Internal
|
||||
@Override
|
||||
protected Object getData() {
|
||||
return matches.toSorted(Comparator.naturalOrder()) ?: {throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.')}()
|
||||
return matches.stream().sorted().toList() ?: {throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.')}()
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
MinecraftForge
|
||||
=============
|
||||
[][Download]
|
||||
[][Download]
|
||||
[][Download] [][Discord] [][Patreon]
|
||||
|
||||
@@ -68,9 +68,9 @@ Please ensure you have a valid email address associated with your GitHub account
|
||||
|
||||
[Discord]: https://discord.minecraftforge.net/
|
||||
|
||||
[Documentation]: https://docs.minecraftforge.net/
|
||||
[Getting-Started]: https://docs.minecraftforge.net/en/latest/gettingstarted/
|
||||
[ForgeDev]: https://docs.minecraftforge.net/en/latest/forgedev/
|
||||
[Pull-Requests]: https://docs.minecraftforge.net/en/latest/forgedev/#making-changes-and-pull-requests
|
||||
[Documentation]: https://docs.minecraftforge.net/en/1.20.1/
|
||||
[Getting-Started]: https://docs.minecraftforge.net/en/1.20.1/gettingstarted/
|
||||
[ForgeDev]: https://docs.minecraftforge.net/en/1.20.1/forgedev/
|
||||
[Pull-Requests]: https://docs.minecraftforge.net/en/1.20.1/forgedev/#making-changes-and-pull-requests
|
||||
|
||||
[Patreon]: https://www.patreon.com/MinecraftForge
|
||||
[Patreon]: https://www.patreon.com/LexManos
|
||||
@@ -95,5 +95,24 @@ 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";
|
||||
|
||||
/**
|
||||
* Ignores any version information coming from the server - use for server only mods
|
||||
*/
|
||||
public static final Supplier<DisplayTest> IGNORE_SERVER_VERSION = () -> new DisplayTest(IGNORESERVERONLY, (remoteVersion, isFromServer) -> true);
|
||||
|
||||
/**
|
||||
* Ignores all information and provides no information
|
||||
*/
|
||||
public static final Supplier<DisplayTest> IGNORE_ALL_VERSION = () -> new DisplayTest("", (remoteVersion, isFromServer) -> true);
|
||||
|
||||
/**
|
||||
* An optional alternative to {@link #DisplayTest(Supplier, BiPredicate)} which accepts a constant version string
|
||||
* instead of a {@link Supplier}.
|
||||
* <p>Internally, the provided version string is wrapped in a Supplier for you.</p>
|
||||
*/
|
||||
public DisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
this(() -> version, remoteVersionTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -64,9 +65,9 @@ public abstract class ModContainer
|
||||
() -> new IExtensionPoint.DisplayTest(() -> this.modInfo.getVersion().toString(),
|
||||
(incoming, isNetwork) -> Objects.equals(incoming, this.modInfo.getVersion().toString()));
|
||||
case "IGNORE_SERVER_VERSION" -> // Ignores any version information coming from the server - use for server only mods
|
||||
() -> new IExtensionPoint.DisplayTest(() -> IExtensionPoint.DisplayTest.IGNORESERVERONLY, (incoming, isNetwork) -> true);
|
||||
IExtensionPoint.DisplayTest.IGNORE_SERVER_VERSION;
|
||||
case "IGNORE_ALL_VERSION" -> // Ignores all information and provides no information
|
||||
() -> new IExtensionPoint.DisplayTest(() -> "", (incoming, isNetwork) -> true);
|
||||
IExtensionPoint.DisplayTest.IGNORE_ALL_VERSION;
|
||||
case "NONE" -> null; // NO display test at all - use this if you're going to do your own display test
|
||||
default -> // any other value throws an exception
|
||||
throw new IllegalArgumentException("Invalid displayTest value supplied in mods.toml");
|
||||
@@ -145,6 +146,22 @@ public abstract class ModContainer
|
||||
extensionPoints.put(point, extension);
|
||||
}
|
||||
|
||||
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
|
||||
registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> displayTest);
|
||||
}
|
||||
|
||||
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
|
||||
registerExtensionPoint(IExtensionPoint.DisplayTest.class, displayTest);
|
||||
}
|
||||
|
||||
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
|
||||
}
|
||||
|
||||
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
|
||||
}
|
||||
|
||||
public void addConfig(final ModConfig modConfig) {
|
||||
configs.put(modConfig.getType(), modConfig);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ModLoadingContext
|
||||
@@ -50,6 +51,44 @@ public class ModLoadingContext
|
||||
getActiveContainer().registerExtensionPoint(point, extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)}.</p>
|
||||
* @param displayTest The {@link IExtensionPoint.DisplayTest} to register
|
||||
*/
|
||||
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
|
||||
getActiveContainer().registerDisplayTest(() -> displayTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest supplier with {@link #registerExtensionPoint(Class, Supplier)}.</p>
|
||||
* @param displayTest The {@link Supplier<IExtensionPoint.DisplayTest>} to register
|
||||
*/
|
||||
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
|
||||
getActiveContainer().registerDisplayTest(displayTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
|
||||
* creates the DisplayTest instance for you using the provided parameters.</p>
|
||||
* @see IExtensionPoint.DisplayTest#DisplayTest(String, BiPredicate)
|
||||
*/
|
||||
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
getActiveContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
|
||||
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
|
||||
* creates the DisplayTest instance for you using the provided parameters.</p>
|
||||
* @see IExtensionPoint.DisplayTest#DisplayTest(Supplier, BiPredicate)
|
||||
*/
|
||||
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
|
||||
getActiveContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
|
||||
}
|
||||
|
||||
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
|
||||
if (spec.isEmpty())
|
||||
{
|
||||
|
||||
+29
-15
@@ -32,7 +32,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
@@ -40,15 +40,16 @@ 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;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
@@ -78,7 +79,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("EARLYDISPLAY");
|
||||
private final AtomicBoolean animationTimerTrigger = new AtomicBoolean(true);
|
||||
|
||||
private ColourScheme colourScheme;
|
||||
private ColourScheme colourScheme = ColourScheme.RED;
|
||||
private ElementShader elementShader;
|
||||
|
||||
private RenderElement.DisplayContext context;
|
||||
@@ -86,6 +87,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
private int framecount;
|
||||
private EarlyFramebuffer framebuffer;
|
||||
private ScheduledFuture<?> windowTick;
|
||||
private ScheduledFuture<?> initializationFuture;
|
||||
|
||||
private PerformanceInfo performanceInfo;
|
||||
private ScheduledFuture<?> performanceTick;
|
||||
@@ -134,13 +136,17 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
this.colourScheme = ColourScheme.BLACK;
|
||||
} else {
|
||||
try {
|
||||
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Paths.get("options.txt")));
|
||||
var options = optionLines.stream().map(l -> l.split(":")).filter(a -> a.length == 2).collect(Collectors.toMap(a -> a[0], a -> a[1]));
|
||||
var colourScheme = Boolean.parseBoolean(options.getOrDefault("darkMojangStudiosBackground", "false"));
|
||||
this.colourScheme = colourScheme ? ColourScheme.BLACK : ColourScheme.RED;
|
||||
} catch (IOException ioe) {
|
||||
// No options
|
||||
this.colourScheme = ColourScheme.RED; // default to red colourscheme
|
||||
// check the options file for the colour scheme
|
||||
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Path.of("options.txt")));
|
||||
var keyName = "darkMojangStudiosBackground:";
|
||||
for (String line : optionLines) {
|
||||
if (line.startsWith(keyName)) {
|
||||
this.colourScheme = line.startsWith("true", keyName.length()) ? ColourScheme.BLACK : ColourScheme.RED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.colourScheme = ColourScheme.RED; // fallback to red colourScheme
|
||||
}
|
||||
}
|
||||
this.maximized = parsed.has(maximizedopt) || FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_MAXIMIZED);
|
||||
@@ -225,7 +231,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
LOGGER.error("Crash during font initialization", t);
|
||||
crashElegantly("An error occurred initializing a font for rendering. "+t.getMessage());
|
||||
}
|
||||
this.elements = new ArrayList<>(Arrays.asList(
|
||||
this.elements = new ArrayList<>(List.of(
|
||||
RenderElement.anvil(font),
|
||||
RenderElement.logMessageOverlay(font),
|
||||
RenderElement.forgeVersionOverlay(font, mcVersion+"-"+forgeVersion.split("-")[0]),
|
||||
@@ -264,7 +270,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 +292,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 +523,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()) {
|
||||
@@ -584,8 +599,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
var fm = layer.findModule("forge").orElseThrow();
|
||||
getClass().getModule().addReads(fm);
|
||||
var clz = FMLLoader.getGameLayer().findModule("forge").map(l->Class.forName(l, "net.minecraftforge.client.loading.ForgeLoadingOverlay")).orElseThrow();
|
||||
var methods = Arrays.stream(clz.getMethods()).filter(m-> Modifier.isStatic(m.getModifiers())).collect(Collectors.toMap(Method::getName, Function.identity()));
|
||||
loadingOverlay = methods.get("newInstance");
|
||||
loadingOverlay = Arrays.stream(clz.getMethods()).filter(m-> Modifier.isStatic(m.getModifiers()) && m.getName().equals("newInstance")).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public int getFramebufferTextureId() {
|
||||
|
||||
+14
-4
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.fml.earlydisplay;
|
||||
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
import net.minecraftforge.fml.loading.FMLConfig;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
@@ -13,28 +14,37 @@ import java.lang.management.MemoryUsage;
|
||||
|
||||
public class PerformanceInfo {
|
||||
|
||||
private final boolean showCPUUsage;
|
||||
private final OperatingSystemMXBean osBean;
|
||||
private final MemoryMXBean memoryBean;
|
||||
|
||||
float memory;
|
||||
private String text;
|
||||
|
||||
PerformanceInfo() {
|
||||
osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
|
||||
showCPUUsage = FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_SHOW_CPU);
|
||||
osBean = showCPUUsage ? ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class) : null;
|
||||
memoryBean = ManagementFactory.getMemoryMXBean();
|
||||
}
|
||||
|
||||
void update() {
|
||||
final MemoryUsage heapusage = memoryBean.getHeapMemoryUsage();
|
||||
memory = (float) heapusage.getUsed() / heapusage.getMax();
|
||||
|
||||
if (!showCPUUsage) {
|
||||
text = "Heap: %d/%d MB (%.1f%%) OffHeap: %d MB".formatted(heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20);
|
||||
return;
|
||||
}
|
||||
|
||||
var cpuLoad = osBean.getProcessCpuLoad();
|
||||
String cpuText;
|
||||
if (cpuLoad == -1) {
|
||||
cpuText = String.format("*CPU: %.1f%%", osBean.getCpuLoad() * 100f);
|
||||
cpuText = "*CPU: %.1f%%".formatted(osBean.getCpuLoad() * 100f);
|
||||
} else {
|
||||
cpuText = String.format("CPU: %.1f%%", cpuLoad * 100f);
|
||||
cpuText = "CPU: %.1f%%".formatted(cpuLoad * 100f);
|
||||
}
|
||||
|
||||
text = String.format("Heap: %d/%d MB (%.1f%%) OffHeap: %d MB %s", heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20, cpuText);
|
||||
text = "Heap: %d/%d MB (%.1f%%) OffHeap: %d MB %s".formatted(heapusage.getUsed() >> 20, heapusage.getMax() >> 20, memory * 100.0, memoryBean.getNonHeapMemoryUsage().getUsed() >> 20, cpuText);
|
||||
}
|
||||
|
||||
String text() {
|
||||
|
||||
+8
-2
@@ -34,11 +34,14 @@ public class RenderElement {
|
||||
};
|
||||
}
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface TextureRenderer {
|
||||
void accept(SimpleBufferBuilder bb, DisplayContext context, int[] size, int frame);
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface Initializer extends Supplier<Renderer> {}
|
||||
|
||||
@FunctionalInterface
|
||||
interface TextGenerator {
|
||||
void accept(SimpleBufferBuilder bb, SimpleFont fh, DisplayContext ctx);
|
||||
}
|
||||
@@ -201,14 +204,17 @@ public class RenderElement {
|
||||
bar.then(label).accept(buffer, context, frameNumber);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ColourFunction {
|
||||
int colour(int frame);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ProgressDisplay {
|
||||
float[] progress(int frame);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface BarPosition {
|
||||
int[] location(DisplayContext context);
|
||||
}
|
||||
@@ -280,7 +286,7 @@ public class RenderElement {
|
||||
if (num < min) {
|
||||
return min;
|
||||
} else {
|
||||
return num > max ? max : num;
|
||||
return Math.min(num, max);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +294,7 @@ public class RenderElement {
|
||||
if (num < min) {
|
||||
return min;
|
||||
} else {
|
||||
return num > max ? max : num;
|
||||
return Math.min(num, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ jar.doFirst {
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << '-Xlint:unchecked'
|
||||
options.compilerArgs << '-Xlint:-unchecked'
|
||||
}
|
||||
|
||||
license {
|
||||
|
||||
@@ -36,7 +36,8 @@ public class FMLConfig
|
||||
EARLY_WINDOW_FBSCALE("earlyWindowFBScale", 1, "Early window framebuffer scale"),
|
||||
EARLY_WINDOW_MAXIMIZED("earlyWindowMaximized", Boolean.FALSE, "Early window starts maximized"),
|
||||
EARLY_WINDOW_SKIP_GL_VERSIONS("earlyWindowSkipGLVersions", List.of(), "Skip specific GL versions, may help with buggy graphics card drivers"),
|
||||
EARLY_WINDOW_SQUIR("earlyWindowSquir", Boolean.FALSE, "Squir?")
|
||||
EARLY_WINDOW_SQUIR("earlyWindowSquir", Boolean.FALSE, "Squir?"),
|
||||
EARLY_WINDOW_SHOW_CPU("earlyWindowShowCPU", Boolean.FALSE, "Whether to show CPU usage stats in early window"),
|
||||
;
|
||||
|
||||
private final String entry;
|
||||
|
||||
@@ -18,12 +18,15 @@ import java.util.function.BiPredicate;
|
||||
public class VersionSupportMatrix {
|
||||
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
|
||||
static {
|
||||
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
|
||||
if (MavenVersionAdapter.createFromVersionSpec("[1.19.2]").containsVersion(version)) {
|
||||
// 1.19.2 is Compatible with 1.19.1
|
||||
add("languageloader.javafml", "42");
|
||||
add("mod.minecraft", "1.19.1");
|
||||
add("mod.forge", "42.0.9");
|
||||
// final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
|
||||
// if (MavenVersionAdapter.createFromVersionSpec("[1.19.2]").containsVersion(version)) {
|
||||
// // 1.19.2 is Compatible with 1.19.1
|
||||
// add("languageloader.javafml", "42");
|
||||
// add("mod.minecraft", "1.19.1");
|
||||
// add("mod.forge", "42.0.9");
|
||||
// }
|
||||
if (FMLLoader.versionInfo().mcVersion().equals("1.20.1")) {
|
||||
add("mod.forge", "47.1.79");
|
||||
}
|
||||
}
|
||||
private static void add(String key, String value) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
+26
-4
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||
import cpw.mods.modlauncher.api.ITransformationService;
|
||||
import net.minecraftforge.fml.loading.*;
|
||||
@@ -26,14 +27,17 @@ public class ModValidator {
|
||||
private final Map<IModFile.Type, List<ModFile>> modFiles;
|
||||
private final List<ModFile> candidatePlugins;
|
||||
private final List<ModFile> candidateMods;
|
||||
private final List<ModFile> gameLibraries;
|
||||
private LoadingModList loadingModList;
|
||||
private List<IModFile> brokenFiles;
|
||||
private final List<IModFile> brokenFiles;
|
||||
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.candidateMods = lst(modFiles.get(IModFile.Type.MOD));
|
||||
this.candidateMods.addAll(lst(modFiles.get(IModFile.Type.GAMELIBRARY)));
|
||||
this.gameLibraries = lst(modFiles.get(IModFile.Type.GAMELIBRARY));
|
||||
this.candidateMods.addAll(this.gameLibraries);
|
||||
this.candidatePlugins = lst(modFiles.get(IModFile.Type.LANGPROVIDER));
|
||||
this.candidatePlugins.addAll(lst(modFiles.get(IModFile.Type.LIBRARY)));
|
||||
this.discoveryErrorData = discoveryErrorData;
|
||||
@@ -55,8 +59,7 @@ public class ModValidator {
|
||||
@NotNull
|
||||
private List<ModFile> validateFiles(final List<ModFile> mods) {
|
||||
final List<ModFile> brokenFiles = new ArrayList<>();
|
||||
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
for (Iterator<ModFile> iterator = mods.iterator(); iterator.hasNext();) {
|
||||
ModFile modFile = iterator.next();
|
||||
if (!modFile.getProvider().isValid(modFile) || !modFile.identifyMods()) {
|
||||
LOGGER.warn(LogMarkers.SCAN, "File {} has been ignored - it is invalid", modFile.getFilePath());
|
||||
@@ -72,7 +75,26 @@ public class ModValidator {
|
||||
}
|
||||
|
||||
public ITransformationService.Resource getModResources() {
|
||||
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, this.candidateMods.stream().map(IModFile::getSecureJar).toList());
|
||||
var mods = new ArrayList<SecureJar>();
|
||||
// Add only the valid mods that we will be attempting to load.
|
||||
// If any detectable error happens during the sorting process {missing deps, duplicates,
|
||||
// This helps prevent coremods/mixins from screwing up us displaying the error screens that the sorting/validation is trying to display.
|
||||
// This won't fix them all as they are still loaded and will still apply but it might help
|
||||
for (var info : this.loadingModList.getModFiles())
|
||||
mods.add(info.getFile().getSecureJar());
|
||||
|
||||
// Add any game libraries, this *may* be duplicates, depending on the state of the sorting. But until I get around to re-writing
|
||||
// that clusterfuck of a system, have this simple de-duplication. Order of resource is important, but i'm unsure if duplication is
|
||||
// so might as well waste a few cycles on checking. Still faster then converting from a set to a list.
|
||||
// Ideally we would explicitly list out which mods to load {forge and MC being the only ones} but some coremods could require extra things.
|
||||
// So try game libraries as well
|
||||
for (var lib : this.gameLibraries) {
|
||||
var jar = lib.getSecureJar();
|
||||
if (!mods.contains(jar))
|
||||
mods.add(jar);
|
||||
}
|
||||
|
||||
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, mods);
|
||||
}
|
||||
|
||||
private List<EarlyLoadingException.ExceptionData> validateLanguages() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public final class ProgressMeter {
|
||||
private final String name;
|
||||
private final int steps;
|
||||
private AtomicInteger current;
|
||||
private final AtomicInteger current;
|
||||
private Message label;
|
||||
|
||||
public ProgressMeter(String name, int steps, int current, Message label) {
|
||||
|
||||
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.8-bin.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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+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/1.20.1/gettingstarted/
|
||||
LexManos' Install Video: https://youtu.be/8VEdtQLuLO0
|
||||
Forge Forums: https://forums.minecraftforge.net/
|
||||
Forge Discord: https://discord.minecraftforge.net/
|
||||
+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'
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/CrashReport.java
|
||||
+++ b/net/minecraft/CrashReport.java
|
||||
@@ -57,14 +_,8 @@
|
||||
@@ -57,14 +_,9 @@
|
||||
if (this.f_127506_ != null && this.f_127506_.length > 0) {
|
||||
p_127520_.append("-- Head --\n");
|
||||
p_127520_.append("Thread: ").append(Thread.currentThread().getName()).append("\n");
|
||||
@@ -12,6 +12,7 @@
|
||||
- }
|
||||
-
|
||||
- p_127520_.append("\n");
|
||||
+ p_127520_.append(net.minecraftforge.logging.CrashReportAnalyser.appendSuspectedMods(this.f_127501_, this.f_127506_));
|
||||
+ p_127520_.append("Stacktrace:");
|
||||
+ p_127520_.append(net.minecraftforge.logging.CrashReportExtender.generateEnhancedStackTrace(this.f_127506_));
|
||||
}
|
||||
|
||||
@@ -90,12 +90,12 @@
|
||||
}
|
||||
|
||||
public String m_90865_() {
|
||||
@@ -184,4 +_,84 @@
|
||||
@@ -183,5 +_,88 @@
|
||||
|
||||
public void m_7249_(boolean p_90846_) {
|
||||
this.f_90817_ = p_90846_;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ /****************** Forge Start *****************************/
|
||||
+ private net.minecraftforge.client.settings.KeyModifier keyModifierDefault = net.minecraftforge.client.settings.KeyModifier.NONE;
|
||||
+ private net.minecraftforge.client.settings.KeyModifier keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
|
||||
+ private net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext = net.minecraftforge.client.settings.KeyConflictContext.UNIVERSAL;
|
||||
@@ -165,13 +165,17 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier keyModifier, InputConstants.Key keyCode) {
|
||||
+ this.f_90816_ = keyCode;
|
||||
+ if (keyModifier.matches(keyCode))
|
||||
+ keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
|
||||
+ public void setKeyModifierAndCode(@org.jetbrains.annotations.Nullable net.minecraftforge.client.settings.KeyModifier keyModifier, InputConstants.Key keyCode) {
|
||||
+ f_90810_.remove(this);
|
||||
+
|
||||
+ if (keyModifier == null)
|
||||
+ keyModifier = net.minecraftforge.client.settings.KeyModifier.getModifier(this.f_90816_);
|
||||
+ if (keyModifier == null || keyCode == InputConstants.f_84822_ || net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(keyCode))
|
||||
+ keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
|
||||
+
|
||||
+ this.f_90816_ = keyCode;
|
||||
+ this.keyModifier = keyModifier;
|
||||
+
|
||||
+ f_90810_.put(keyCode, this);
|
||||
+ }
|
||||
+ /****************** Forge End *****************************/
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,5 @@
|
||||
--- a/net/minecraft/client/KeyboardHandler.java
|
||||
+++ b/net/minecraft/client/KeyboardHandler.java
|
||||
@@ -329,7 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
- if (p_90897_ == 1 && (!(this.f_90867_.f_91080_ instanceof KeyBindsScreen) || ((KeyBindsScreen)screen).f_193976_ <= Util.m_137550_() - 20L)) {
|
||||
+
|
||||
+ if ((!(this.f_90867_.f_91080_ instanceof KeyBindsScreen) || ((KeyBindsScreen)screen).f_193976_ <= Util.m_137550_() - 20L)) {
|
||||
+ if (p_90897_ == 1) {
|
||||
if (this.f_90867_.f_91066_.f_92105_.m_90832_(p_90895_, p_90896_)) {
|
||||
this.f_90867_.m_91268_().m_85438_();
|
||||
this.f_90867_.f_91066_.m_231829_().m_231514_(this.f_90867_.m_91268_().m_85440_());
|
||||
@@ -347,6 +_,8 @@
|
||||
});
|
||||
return;
|
||||
}
|
||||
+ } else if (p_90897_ == 0 /*GLFW_RELEASE*/ && this.f_90867_.f_91080_ instanceof KeyBindsScreen)
|
||||
+ ((KeyBindsScreen)this.f_90867_.f_91080_).f_193975_ = null; //Forge: Unset pure modifiers.
|
||||
}
|
||||
|
||||
if (this.f_90867_.m_240477_().m_93316_()) {
|
||||
@@ -369,11 +_,15 @@
|
||||
Screen.m_96579_(() -> {
|
||||
if (p_90897_ != 1 && p_90897_ != 2) {
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
}
|
||||
|
||||
public int m_5759_() {
|
||||
@@ -129,10 +_,11 @@
|
||||
@@ -128,11 +_,13 @@
|
||||
this.f_193911_ = p_193917_;
|
||||
this.f_193912_ = Button.m_253074_(p_193917_, (p_269618_) -> {
|
||||
KeyBindsList.this.f_193858_.f_193975_ = p_193916_;
|
||||
+ p_193916_.setKeyModifierAndCode(null, com.mojang.blaze3d.platform.InputConstants.f_84822_);
|
||||
KeyBindsList.this.m_269130_();
|
||||
- }).m_252987_(0, 0, 75, 20).m_252778_((p_253311_) -> {
|
||||
+ }).m_252987_(0, 0, 75 + 20 /* Forge: Add space */, 20).m_252778_((p_253311_) -> {
|
||||
|
||||
+23
-3
@@ -13,14 +13,34 @@
|
||||
public boolean m_7933_(int p_193987_, int p_193988_, int p_193989_) {
|
||||
if (this.f_193975_ != null) {
|
||||
if (p_193987_ == 256) {
|
||||
+ this.f_193975_.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.getActiveModifier(), InputConstants.f_84822_);
|
||||
+ this.f_193975_.setKeyModifierAndCode(null, InputConstants.f_84822_);
|
||||
this.f_96282_.m_92159_(this.f_193975_, InputConstants.f_84822_);
|
||||
} else {
|
||||
+ this.f_193975_.setKeyModifierAndCode(net.minecraftforge.client.settings.KeyModifier.getActiveModifier(), InputConstants.m_84827_(p_193987_, p_193988_));
|
||||
+ this.f_193975_.setKeyModifierAndCode(null, InputConstants.m_84827_(p_193987_, p_193988_));
|
||||
this.f_96282_.m_92159_(this.f_193975_, InputConstants.m_84827_(p_193987_, p_193988_));
|
||||
}
|
||||
|
||||
+ if(!net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(this.f_193975_.getKey()))
|
||||
+ if (p_193987_ == 256 || !net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(this.f_193975_.getKey()))
|
||||
this.f_193975_ = null;
|
||||
this.f_193976_ = Util.m_137550_();
|
||||
this.f_193977_.m_269130_();
|
||||
@@ -67,6 +_,19 @@
|
||||
} else {
|
||||
return super.m_7933_(p_193987_, p_193988_, p_193989_);
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean m_7920_(int keyCode, int scanCode, int modifiers) {
|
||||
+ // Forge: We wait for a second key above if the first press is a modifier
|
||||
+ // but if they release the modifier then set it explicitly.
|
||||
+ var key = InputConstants.m_84827_(keyCode, scanCode);
|
||||
+ if (this.f_193975_ != null && this.f_193975_.getKey() == key) {
|
||||
+ this.f_193975_ = null;
|
||||
+ this.f_193976_ = Util.m_137550_();
|
||||
+ this.f_193977_.m_269130_();
|
||||
+ }
|
||||
+ return super.m_7920_(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
public void m_88315_(GuiGraphics p_282556_, int p_193992_, int p_193993_, float p_193994_) {
|
||||
@@ -9,11 +9,11 @@
|
||||
}
|
||||
|
||||
static <E> void m_255048_(RegistryOps.RegistryInfoLookup p_256369_, ResourceManager p_256349_, ResourceKey<? extends Registry<E>> p_255792_, WritableRegistry<E> p_256211_, Decoder<E> p_256232_, Map<ResourceKey<?>, Exception> p_255884_) {
|
||||
@@ -139,6 +_,7 @@
|
||||
@@ -138,6 +_,7 @@
|
||||
|
||||
try (Reader reader = resource.m_215508_()) {
|
||||
JsonElement jsonelement = JsonParser.parseReader(reader);
|
||||
+ if (!net.minecraftforge.common.crafting.conditions.ICondition.shouldRegisterEntry(jsonelement)) continue;
|
||||
DataResult<E> dataresult = p_256232_.parse(registryops, jsonelement);
|
||||
+ if (!net.minecraftforge.common.crafting.conditions.ICondition.shouldRegisterEntry(jsonelement)) continue;
|
||||
E e = dataresult.getOrThrow(false, (p_248715_) -> {
|
||||
});
|
||||
p_256211_.m_255290_(resourcekey, e, resource.m_247137_() ? Lifecycle.stable() : dataresult.lifecycle());
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
private Either<Collection<TagLoader.EntryWithSource>, Collection<T>> m_215978_(TagEntry.Lookup<T> p_215979_, List<TagLoader.EntryWithSource> p_215980_) {
|
||||
- ImmutableSet.Builder<T> builder = ImmutableSet.builder();
|
||||
+ var builder = new java.util.HashSet<T>();
|
||||
+ var builder = new java.util.LinkedHashSet<T>(); // Order is important, as ImmutableSet is ordered and some people rely on that. https://github.com/MinecraftForge/MinecraftForge/issues/9774
|
||||
List<TagLoader.EntryWithSource> list = new ArrayList<>();
|
||||
|
||||
for(TagLoader.EntryWithSource tagloader$entrywithsource : p_215980_) {
|
||||
@@ -34,7 +34,7 @@
|
||||
dependencysorter.m_284430_((p_284682_, p_284683_) -> {
|
||||
this.m_215978_(lookup, p_284683_.f_283922_).ifLeft((p_215977_) -> {
|
||||
- f_13445_.error("Couldn't load tag {} as it is missing following references: {}", p_284682_, p_215977_.stream().map(Objects::toString).collect(Collectors.joining(", ")));
|
||||
+ f_13445_.error("Couldn't load tag {} as it is missing following references: {}", p_215977_, p_215977_.stream().map(Objects::toString).collect(Collectors.joining(", \n\t")));
|
||||
+ f_13445_.error("Couldn't load tag {} as it is missing following references: {}", p_284682_, p_215977_.stream().map(Objects::toString).collect(Collectors.joining(", \n\t")));
|
||||
}).ifRight((p_216001_) -> {
|
||||
map.put(p_284682_, p_216001_);
|
||||
});
|
||||
|
||||
@@ -182,21 +182,16 @@
|
||||
if (!p_21016_.m_269533_(DamageTypeTags.f_268524_)) {
|
||||
Entity entity = p_21016_.m_7640_();
|
||||
if (entity instanceof LivingEntity) {
|
||||
@@ -1065,12 +_,13 @@
|
||||
@@ -1065,7 +_,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- flag = true;
|
||||
+ flag = p_21017_ <= 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (p_21016_.m_269533_(DamageTypeTags.f_268419_) && this.m_6095_().m_204039_(EntityTypeTags.f_144295_)) {
|
||||
p_21017_ *= 5.0F;
|
||||
}
|
||||
+ }
|
||||
|
||||
this.f_267362_.m_267771_(1.5F);
|
||||
boolean flag1 = true;
|
||||
@@ -1108,11 +_,10 @@
|
||||
Player player1 = (Player)entity1;
|
||||
this.f_20889_ = 100;
|
||||
@@ -736,7 +731,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
|
||||
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && this.m_6084_()) {
|
||||
+ if (facing == null) return handlers[2].cast();
|
||||
+ else if (facing.m_122434_().m_122478_()) return handlers[0].cast();
|
||||
+ else if (facing.m_122434_().m_122479_()) return handlers[1].cast();
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.core.Direction facing) {
|
||||
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && itemHandler != null)
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && itemHandler != null && this.m_6084_())
|
||||
+ return itemHandler.cast();
|
||||
+ return super.getCapability(capability, facing);
|
||||
+ }
|
||||
|
||||
@@ -19,15 +19,21 @@
|
||||
if (p_36049_.m_41782_()) {
|
||||
itemstack.m_41751_(p_36049_.m_41783_().m_6426_());
|
||||
}
|
||||
@@ -229,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
+ f_35975_.forEach(e -> e.onArmorTick(f_35978_.m_9236_(), f_35978_));
|
||||
@@ -222,11 +_,13 @@
|
||||
}
|
||||
|
||||
public boolean m_36054_(ItemStack p_36055_) {
|
||||
public void m_36068_() {
|
||||
+ int idx = 0;
|
||||
for(NonNullList<ItemStack> nonnulllist : this.f_35979_) {
|
||||
for(int i = 0; i < nonnulllist.size(); ++i) {
|
||||
if (!nonnulllist.get(i).m_41619_()) {
|
||||
- nonnulllist.get(i).m_41666_(this.f_35978_.m_9236_(), this.f_35978_, i, this.f_35977_ == i);
|
||||
+ nonnulllist.get(i).onInventoryTick(this.f_35978_.m_9236_(), this.f_35978_, idx, this.f_35977_);
|
||||
}
|
||||
+ idx++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +_,8 @@
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.m_127521_(throwable, "Adding item to inventory");
|
||||
|
||||
@@ -452,7 +452,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
|
||||
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && this.m_6084_()) {
|
||||
+ if (facing == null) return playerJoinedHandler.cast();
|
||||
+ else if (facing.m_122434_().m_122478_()) return playerMainHandler.cast();
|
||||
+ else if (facing.m_122434_().m_122479_()) return playerEquipmentHandler.cast();
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.core.Direction facing) {
|
||||
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && this.m_6084_())
|
||||
+ return itemHandler.cast();
|
||||
+ return super.getCapability(capability, facing);
|
||||
+ }
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.core.Direction facing) {
|
||||
+ if (this.m_6084_() && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && this.m_6084_())
|
||||
+ return itemHandler.cast();
|
||||
+ return super.getCapability(capability, facing);
|
||||
+ }
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
public LevelSettings m_247275_(WorldDataConfiguration p_250867_) {
|
||||
- return new LevelSettings(this.f_46902_, this.f_46903_, this.f_46904_, this.f_46905_, this.f_46906_, this.f_46907_, p_250867_);
|
||||
+ return new LevelSettings(this.f_46902_, this.f_46903_, this.f_46904_, this.f_46905_, this.f_46906_, this.f_46907_, f_243681_, this.lifecycle);
|
||||
+ return new LevelSettings(this.f_46902_, this.f_46903_, this.f_46904_, this.f_46905_, this.f_46906_, this.f_46907_, p_250867_, this.lifecycle);
|
||||
}
|
||||
|
||||
public LevelSettings m_46935_() {
|
||||
|
||||
@@ -16,11 +16,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,14 +_,14 @@
|
||||
p_221161_.m_186460_(p_221162_, this, m_221148_(p_221161_.f_46441_));
|
||||
if (p_221161_.m_46469_().m_46207_(GameRules.f_46131_)) {
|
||||
if (!p_221160_.m_60710_(p_221161_, p_221162_)) {
|
||||
- p_221161_.m_7471_(p_221162_, false);
|
||||
@@ -133,7 +_,7 @@
|
||||
}
|
||||
|
||||
BlockState blockstate = p_221161_.m_8055_(p_221162_.m_7495_());
|
||||
@@ -29,10 +25,6 @@
|
||||
int i = p_221160_.m_61143_(f_53408_);
|
||||
if (!flag && p_221161_.m_46471_() && this.m_53428_(p_221161_, p_221162_) && p_221163_.m_188501_() < 0.2F + (float)i * 0.03F) {
|
||||
p_221161_.m_7471_(p_221162_, false);
|
||||
+ p_221161_.m_7471_(p_221162_, false);
|
||||
} else {
|
||||
int j = Math.min(15, i + p_221163_.m_188503_(3) / 2);
|
||||
if (i != j) {
|
||||
@@ -154,7 +_,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
+7
-8
@@ -153,7 +153,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,5 +_,34 @@
|
||||
@@ -494,5 +_,33 @@
|
||||
p_58342_.m_36491_(itemstack);
|
||||
}
|
||||
|
||||
@@ -164,13 +164,12 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
|
||||
+ if (!this.f_58859_ && facing != null && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
|
||||
+ if (facing == Direction.UP)
|
||||
+ return handlers[0].cast();
|
||||
+ else if (facing == Direction.DOWN)
|
||||
+ return handlers[1].cast();
|
||||
+ else
|
||||
+ return handlers[2].cast();
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && facing != null && !this.f_58859_) {
|
||||
+ return switch (facing) {
|
||||
+ case UP -> handlers[0].cast();
|
||||
+ case DOWN -> handlers[1].cast();
|
||||
+ default -> handlers[2].cast();
|
||||
+ };
|
||||
+ }
|
||||
+ return super.getCapability(capability, facing);
|
||||
+ }
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
+ }
|
||||
+
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, @org.jetbrains.annotations.Nullable net.minecraft.core.Direction side) {
|
||||
+ if (!this.f_58859_ && cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
|
||||
+ if (cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && !this.f_58859_)
|
||||
+ return itemHandler.cast();
|
||||
+ return super.getCapability(cap, side);
|
||||
+ }
|
||||
|
||||
+7
-8
@@ -51,7 +51,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,5 +_,34 @@
|
||||
@@ -255,5 +_,33 @@
|
||||
|
||||
protected AbstractContainerMenu m_6555_(int p_58990_, Inventory p_58991_) {
|
||||
return new BrewingStandMenu(p_58990_, p_58991_, this, this.f_58971_);
|
||||
@@ -62,13 +62,12 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing) {
|
||||
+ if (!this.f_58859_ && facing != null && capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
|
||||
+ if (facing == Direction.UP)
|
||||
+ return handlers[0].cast();
|
||||
+ else if (facing == Direction.DOWN)
|
||||
+ return handlers[1].cast();
|
||||
+ else
|
||||
+ return handlers[2].cast();
|
||||
+ if (capability == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && facing != null && !this.f_58859_) {
|
||||
+ return switch (facing) {
|
||||
+ case UP -> handlers[0].cast();
|
||||
+ case DOWN -> handlers[1].cast();
|
||||
+ default -> handlers[2].cast();
|
||||
+ };
|
||||
+ }
|
||||
+ return super.getCapability(capability, facing);
|
||||
+ }
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, Direction side) {
|
||||
+ if (!this.f_58859_ && cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER) {
|
||||
+ if (cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && !this.f_58859_) {
|
||||
+ if (this.chestHandler == null)
|
||||
+ this.chestHandler = net.minecraftforge.common.util.LazyOptional.of(this::createHandler);
|
||||
+ return this.chestHandler.cast();
|
||||
@@ -27,10 +27,10 @@
|
||||
+
|
||||
+ private net.minecraftforge.items.IItemHandlerModifiable createHandler() {
|
||||
+ BlockState state = this.m_58900_();
|
||||
+ if (!(state.m_60734_() instanceof ChestBlock)) {
|
||||
+ if (!(state.m_60734_() instanceof ChestBlock chestBlock)) {
|
||||
+ return new net.minecraftforge.items.wrapper.InvWrapper(this);
|
||||
+ }
|
||||
+ Container inv = ChestBlock.m_51511_((ChestBlock) state.m_60734_(), state, m_58904_(), m_58899_(), true);
|
||||
+ Container inv = ChestBlock.m_51511_(chestBlock, state, m_58904_(), m_58899_(), true);
|
||||
+ return new net.minecraftforge.items.wrapper.InvWrapper(inv == null ? this : inv);
|
||||
+ }
|
||||
+
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, @org.jetbrains.annotations.Nullable net.minecraft.core.Direction side) {
|
||||
+ if (!this.f_58859_ && cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER)
|
||||
+ if (cap == net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER && !this.f_58859_)
|
||||
+ return itemHandler.cast();
|
||||
+ return super.getCapability(cap, side);
|
||||
+ }
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ buildscript {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
|
||||
}
|
||||
|
||||
rootProject.name = 'ForgeRoot'
|
||||
|
||||
@@ -13,10 +13,30 @@ import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ConfigScreenHandler
|
||||
{
|
||||
public record ConfigScreenFactory(BiFunction<Minecraft, Screen, Screen> screenFunction) implements IExtensionPoint<ConfigScreenFactory> {}
|
||||
/**
|
||||
* @param screenFunction A function that takes the {@link Minecraft} client instance and the mods screen as
|
||||
* arguments and returns your config screen to show when the player clicks the config button
|
||||
* for your mod on the mods screen.
|
||||
* <p>You should call {@link Minecraft#setScreen(Screen)} with the provided client instance
|
||||
* and mods screen for the action of your close button.</p>
|
||||
*/
|
||||
public record ConfigScreenFactory(BiFunction<Minecraft, Screen, Screen> screenFunction) implements IExtensionPoint<ConfigScreenFactory> {
|
||||
/**
|
||||
* @param screenFunction A function that takes the mods screen as an argument and returns your config screen to
|
||||
* show when the player clicks the config button for your mod on the mods screen.
|
||||
* <p>You should call {@link Minecraft#setScreen(Screen)} with the provided mods screen
|
||||
* for the action of your close button, using {@link Screen#minecraft} to get the client
|
||||
* instance.</p>
|
||||
*/
|
||||
public ConfigScreenFactory(Function<Screen, Screen> screenFunction) {
|
||||
this((mcClient, modsScreen) -> screenFunction.apply(modsScreen));
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<BiFunction<Minecraft, Screen, Screen>> getScreenFactoryFor(IModInfo selectedMod)
|
||||
{
|
||||
return ModList.get().getModContainerById(selectedMod.getModId()).
|
||||
|
||||
@@ -512,7 +512,7 @@ public class ForgeHooksClient
|
||||
public static void fillNormal(int[] faceData, Direction facing, boolean calculateNormals)
|
||||
{
|
||||
Vector3f v2;
|
||||
if (calculateNormals || ForgeConfig.CLIENT.calculateAllNormals.get()) {
|
||||
if (calculateNormals || ForgeConfig.CLIENT.calculateAllNormals()) {
|
||||
Vector3f v1 = getVertexPos(faceData, 3);
|
||||
Vector3f t1 = getVertexPos(faceData, 1);
|
||||
v2 = getVertexPos(faceData, 2);
|
||||
|
||||
@@ -14,11 +14,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* Extension interface for {@link KeyMapping}.
|
||||
*/
|
||||
public interface IForgeKeyMapping
|
||||
{
|
||||
private KeyMapping self()
|
||||
{
|
||||
return (KeyMapping) this;
|
||||
public interface IForgeKeyMapping {
|
||||
private KeyMapping self() {
|
||||
return (KeyMapping)this;
|
||||
}
|
||||
|
||||
@NotNull InputConstants.Key getKey();
|
||||
@@ -26,13 +24,11 @@ public interface IForgeKeyMapping
|
||||
/**
|
||||
* {@return true if the key conflict context and modifier are active and the keyCode matches this binding, false otherwise}
|
||||
*/
|
||||
default boolean isActiveAndMatches(InputConstants.Key keyCode)
|
||||
{
|
||||
default boolean isActiveAndMatches(InputConstants.Key keyCode) {
|
||||
return keyCode != InputConstants.UNKNOWN && keyCode.equals(getKey()) && getKeyConflictContext().isActive() && getKeyModifier().isActive(getKeyConflictContext());
|
||||
}
|
||||
|
||||
default void setToDefault()
|
||||
{
|
||||
default void setToDefault() {
|
||||
setKeyModifierAndCode(getDefaultKeyModifier(), self().getDefaultKey());
|
||||
}
|
||||
|
||||
@@ -46,22 +42,17 @@ public interface IForgeKeyMapping
|
||||
|
||||
void setKeyModifierAndCode(KeyModifier keyModifier, InputConstants.Key keyCode);
|
||||
|
||||
default boolean isConflictContextAndModifierActive()
|
||||
{
|
||||
default boolean isConflictContextAndModifierActive() {
|
||||
return getKeyConflictContext().isActive() && getKeyModifier().isActive(getKeyConflictContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when one of the bindings' key codes conflicts with the other's modifier.
|
||||
*/
|
||||
default boolean hasKeyModifierConflict(KeyMapping other)
|
||||
{
|
||||
if (getKeyConflictContext().conflicts(other.getKeyConflictContext()) || other.getKeyConflictContext().conflicts(getKeyConflictContext()))
|
||||
{
|
||||
default boolean hasKeyModifierConflict(KeyMapping other) {
|
||||
if (getKeyConflictContext().conflicts(other.getKeyConflictContext()) || other.getKeyConflictContext().conflicts(getKeyConflictContext())) {
|
||||
if (getKeyModifier().matches(other.getKey()) || other.getKeyModifier().matches(getKey()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||
for (FormattedCharSequence string : strings)
|
||||
{
|
||||
if (center)
|
||||
guiGraphics.drawString(font, string, left + (width) - font.width(string) / 2F, (float) y, 0xFFFFFF, false);
|
||||
guiGraphics.drawString(font, string, left + (width / 2F) - font.width(string) / 2F, (float) y, 0xFFFFFF, false);
|
||||
else
|
||||
guiGraphics.drawString(font, string, left + 5, y, 0xFFFFFF, false);
|
||||
y += font.lineHeight;
|
||||
|
||||
@@ -85,8 +85,10 @@ public class ModListScreen extends Screen
|
||||
}
|
||||
|
||||
private static final int PADDING = 6;
|
||||
private static final int BUTTON_MARGIN = 1;
|
||||
private static final int NUM_BUTTONS = SortType.values().length;
|
||||
|
||||
private Screen parentScreen;
|
||||
private final Screen parentScreen;
|
||||
|
||||
private ModListWidget modList;
|
||||
private InfoPanel modInfo;
|
||||
@@ -96,8 +98,6 @@ public class ModListScreen extends Screen
|
||||
private final List<IModInfo> unsortedMods;
|
||||
private Button configButton, openModsFolderButton, doneButton;
|
||||
|
||||
private int buttonMargin = 1;
|
||||
private int numButtons = SortType.values().length;
|
||||
private String lastFilterText = "";
|
||||
|
||||
private EditBox search;
|
||||
@@ -109,8 +109,8 @@ public class ModListScreen extends Screen
|
||||
{
|
||||
super(Component.translatable("fml.menu.mods.title"));
|
||||
this.parentScreen = parentScreen;
|
||||
this.mods = Collections.unmodifiableList(ModList.get().getMods());
|
||||
this.unsortedMods = Collections.unmodifiableList(this.mods);
|
||||
this.mods = ModList.get().getMods();
|
||||
this.unsortedMods = List.copyOf(this.mods);
|
||||
}
|
||||
|
||||
class InfoPanel extends ScrollPanel {
|
||||
@@ -207,7 +207,7 @@ public class ModListScreen extends Screen
|
||||
if (!isMouseOver(mouseX, mouseY))
|
||||
return null;
|
||||
|
||||
double offset = (mouseY - top) + border + scrollDistance + 1;
|
||||
double offset = (mouseY - top - PADDING - border) + scrollDistance;
|
||||
if (logoPath != null) {
|
||||
offset -= 50;
|
||||
}
|
||||
@@ -215,10 +215,10 @@ public class ModListScreen extends Screen
|
||||
return null;
|
||||
|
||||
int lineIdx = (int) (offset / font.lineHeight);
|
||||
if (lineIdx >= lines.size() || lineIdx < 1)
|
||||
if (lineIdx >= lines.size() || lineIdx < 0)
|
||||
return null;
|
||||
|
||||
FormattedCharSequence line = lines.get(lineIdx-1);
|
||||
FormattedCharSequence line = lines.get(lineIdx);
|
||||
if (line != null)
|
||||
{
|
||||
return font.getSplitter().componentStyleAtWidth(line, mouseX - left - border);
|
||||
@@ -255,7 +255,7 @@ public class ModListScreen extends Screen
|
||||
listWidth = Math.max(listWidth,getFontRenderer().width(MavenVersionStringHelper.artifactVersionToString(mod.getVersion())) + 5);
|
||||
}
|
||||
listWidth = Math.max(Math.min(listWidth, width/3), 100);
|
||||
listWidth += listWidth % numButtons != 0 ? (numButtons - listWidth % numButtons) : 0;
|
||||
listWidth += listWidth % NUM_BUTTONS != 0 ? (NUM_BUTTONS - listWidth % NUM_BUTTONS) : 0;
|
||||
|
||||
int modInfoWidth = this.width - this.listWidth - (PADDING * 3);
|
||||
int doneButtonWidth = Math.min(modInfoWidth, 200);
|
||||
@@ -284,13 +284,13 @@ public class ModListScreen extends Screen
|
||||
search.setCanLoseFocus(true);
|
||||
configButton.active = false;
|
||||
|
||||
final int width = listWidth / numButtons;
|
||||
final int width = listWidth / NUM_BUTTONS;
|
||||
int x = PADDING;
|
||||
addRenderableWidget(SortType.NORMAL.button = Button.builder(SortType.NORMAL.getButtonText(), b -> resortMods(SortType.NORMAL)).bounds(x, PADDING, width - buttonMargin, 20).build());
|
||||
x += width + buttonMargin;
|
||||
addRenderableWidget(SortType.A_TO_Z.button = Button.builder(SortType.A_TO_Z.getButtonText(), b -> resortMods(SortType.A_TO_Z)).bounds(x, PADDING, width - buttonMargin, 20).build());
|
||||
x += width + buttonMargin;
|
||||
addRenderableWidget(SortType.Z_TO_A.button = Button.builder(SortType.Z_TO_A.getButtonText(), b -> resortMods(SortType.Z_TO_A)).bounds(x, PADDING, width - buttonMargin, 20).build());
|
||||
addRenderableWidget(SortType.NORMAL.button = Button.builder(SortType.NORMAL.getButtonText(), b -> resortMods(SortType.NORMAL)).bounds(x, PADDING, width - BUTTON_MARGIN, 20).build());
|
||||
x += width + BUTTON_MARGIN;
|
||||
addRenderableWidget(SortType.A_TO_Z.button = Button.builder(SortType.A_TO_Z.getButtonText(), b -> resortMods(SortType.A_TO_Z)).bounds(x, PADDING, width - BUTTON_MARGIN, 20).build());
|
||||
x += width + BUTTON_MARGIN;
|
||||
addRenderableWidget(SortType.Z_TO_A.button = Button.builder(SortType.Z_TO_A.getButtonText(), b -> resortMods(SortType.Z_TO_A)).bounds(x, PADDING, width - BUTTON_MARGIN, 20).build());
|
||||
resortMods(SortType.NORMAL);
|
||||
updateCache();
|
||||
}
|
||||
@@ -341,8 +341,12 @@ public class ModListScreen extends Screen
|
||||
|
||||
private void reloadMods()
|
||||
{
|
||||
this.mods = this.unsortedMods.stream().
|
||||
filter(mi->StringUtils.toLowerCase(stripControlCodes(mi.getDisplayName())).contains(StringUtils.toLowerCase(search.getValue()))).collect(Collectors.toList());
|
||||
this.mods = this.unsortedMods
|
||||
.stream()
|
||||
.filter(mi ->
|
||||
StringUtils.toLowerCase(stripControlCodes(mi.getDisplayName()))
|
||||
.contains(StringUtils.toLowerCase(search.getValue()))
|
||||
).collect(Collectors.toList());
|
||||
lastFilterText = search.getValue();
|
||||
}
|
||||
|
||||
@@ -464,7 +468,7 @@ public class ModListScreen extends Screen
|
||||
}
|
||||
*/
|
||||
|
||||
if ((vercheck.status() == VersionChecker.Status.OUTDATED || vercheck.status() == VersionChecker.Status.BETA_OUTDATED) && vercheck.changes().size() > 0)
|
||||
if ((vercheck.status() == VersionChecker.Status.OUTDATED || vercheck.status() == VersionChecker.Status.BETA_OUTDATED) && !vercheck.changes().isEmpty())
|
||||
{
|
||||
lines.add(null);
|
||||
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.changelogheader"));
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.client.loading;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -119,12 +118,8 @@ public class ClientModLoader
|
||||
public static boolean completeModLoading()
|
||||
{
|
||||
var warnings = ModLoader.get().getWarnings();
|
||||
boolean showWarnings = true;
|
||||
try {
|
||||
showWarnings = ForgeConfig.CLIENT.showLoadWarnings.get();
|
||||
} catch (NullPointerException | IllegalStateException e) {
|
||||
// We're in an early error state, config is not available. Assume true.
|
||||
}
|
||||
boolean showWarnings = ForgeConfig.CLIENT.showLoadWarnings();
|
||||
|
||||
if (!showWarnings) {
|
||||
//User disabled warning screen, as least log them
|
||||
if (!warnings.isEmpty()) {
|
||||
|
||||
@@ -368,6 +368,10 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements DataPr
|
||||
return singleTexture(name, BLOCK_FOLDER + "/carpet", "wool", wool);
|
||||
}
|
||||
|
||||
public T leaves(String name, ResourceLocation texture) {
|
||||
return singleTexture(name, BLOCK_FOLDER + "/leaves", "all", texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a model builder that's not directly saved to disk. Meant for use in custom model loaders.}
|
||||
*/
|
||||
|
||||
@@ -10,53 +10,40 @@ import net.minecraft.client.KeyMapping;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class KeyMappingLookup
|
||||
{
|
||||
private static final EnumMap<KeyModifier, Map<InputConstants.Key, Collection<KeyMapping>>> map = new EnumMap<>(KeyModifier.class);
|
||||
static
|
||||
{
|
||||
public class KeyMappingLookup {
|
||||
private static final EnumMap<KeyModifier, Map<InputConstants.Key, List<KeyMapping>>> map = new EnumMap<>(KeyModifier.class);
|
||||
static {
|
||||
for (KeyModifier modifier : KeyModifier.values())
|
||||
{
|
||||
map.put(modifier, new HashMap<>());
|
||||
}
|
||||
}
|
||||
|
||||
/** Replaced by {@link #getAll(InputConstants.Key) getAll} */
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
@Nullable
|
||||
public KeyMapping get(InputConstants.Key keyCode)
|
||||
{
|
||||
KeyModifier activeModifier = KeyModifier.getActiveModifier();
|
||||
if (!activeModifier.matches(keyCode))
|
||||
{
|
||||
KeyMapping binding = get(keyCode, activeModifier);
|
||||
public KeyMapping get(InputConstants.Key keyCode) {
|
||||
var activeModifier = KeyModifier.getActiveModifier();
|
||||
if (!activeModifier.matches(keyCode)) {
|
||||
var binding = get(keyCode, activeModifier);
|
||||
if (binding != null)
|
||||
{
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
return get(keyCode, KeyModifier.NONE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
private KeyMapping get(InputConstants.Key keyCode, KeyModifier keyModifier)
|
||||
{
|
||||
Collection<KeyMapping> bindings = map.get(keyModifier).get(keyCode);
|
||||
if (bindings != null)
|
||||
{
|
||||
for (KeyMapping binding : bindings)
|
||||
{
|
||||
private KeyMapping get(InputConstants.Key keyCode, KeyModifier keyModifier) {
|
||||
var bindings = map.get(keyModifier).get(keyCode);
|
||||
if (bindings != null) {
|
||||
for (var binding : bindings) {
|
||||
if (binding.isActiveAndMatches(keyCode))
|
||||
{
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -69,54 +56,52 @@ public class KeyMappingLookup
|
||||
* @param keyCode the key being pressed
|
||||
* @return the list of key mappings
|
||||
*/
|
||||
public List<KeyMapping> getAll(InputConstants.Key keyCode)
|
||||
{
|
||||
List<KeyMapping> matchingBindings = new ArrayList<KeyMapping>();
|
||||
for (Map<InputConstants.Key, Collection<KeyMapping>> bindingsMap : map.values())
|
||||
{
|
||||
Collection<KeyMapping> bindings = bindingsMap.get(keyCode);
|
||||
if (bindings != null)
|
||||
{
|
||||
matchingBindings.addAll(bindings);
|
||||
public List<KeyMapping> getAll(InputConstants.Key keyCode) {
|
||||
var ret = new ArrayList<KeyMapping>();
|
||||
for (var modifier : KeyModifier.getValues(false)) {
|
||||
if (!modifier.isActive(null) || modifier.matches(keyCode))
|
||||
continue;
|
||||
|
||||
for (var binding : get(modifier, keyCode)) {
|
||||
if (binding.isActiveAndMatches(keyCode))
|
||||
ret.add(binding);
|
||||
}
|
||||
}
|
||||
return matchingBindings;
|
||||
|
||||
if (!ret.isEmpty())
|
||||
return ret;
|
||||
|
||||
for (var binding : get(KeyModifier.NONE, keyCode)) {
|
||||
if (binding.isActiveAndMatches(keyCode))
|
||||
ret.add(binding);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void put(InputConstants.Key keyCode, KeyMapping keyBinding)
|
||||
{
|
||||
KeyModifier keyModifier = keyBinding.getKeyModifier();
|
||||
Map<InputConstants.Key, Collection<KeyMapping>> bindingsMap = map.get(keyModifier);
|
||||
Collection<KeyMapping> bindingsForKey = bindingsMap.get(keyCode);
|
||||
if (bindingsForKey == null)
|
||||
{
|
||||
bindingsForKey = new ArrayList<KeyMapping>();
|
||||
bindingsMap.put(keyCode, bindingsForKey);
|
||||
}
|
||||
private List<KeyMapping> get(KeyModifier modifier, InputConstants.Key keyCode) {
|
||||
var bindings = map.get(modifier).get(keyCode);
|
||||
return bindings == null ? Collections.emptyList() : bindings;
|
||||
}
|
||||
|
||||
public void put(InputConstants.Key keyCode, KeyMapping keyBinding) {
|
||||
var bindingsMap = map.get(keyBinding.getKeyModifier());
|
||||
var bindingsForKey = bindingsMap.computeIfAbsent(keyCode, k -> new ArrayList<KeyMapping>());
|
||||
bindingsForKey.add(keyBinding);
|
||||
}
|
||||
|
||||
public void remove(KeyMapping keyBinding)
|
||||
{
|
||||
KeyModifier keyModifier = keyBinding.getKeyModifier();
|
||||
InputConstants.Key keyCode = keyBinding.getKey();
|
||||
Map<InputConstants.Key, Collection<KeyMapping>> bindingsMap = map.get(keyModifier);
|
||||
Collection<KeyMapping> bindingsForKey = bindingsMap.get(keyCode);
|
||||
if (bindingsForKey != null)
|
||||
{
|
||||
public void remove(KeyMapping keyBinding) {
|
||||
var keyCode = keyBinding.getKey();
|
||||
var bindingsMap = map.get(keyBinding.getKeyModifier());
|
||||
var bindingsForKey = bindingsMap.get(keyCode);
|
||||
if (bindingsForKey != null) {
|
||||
bindingsForKey.remove(keyBinding);
|
||||
if (bindingsForKey.isEmpty())
|
||||
{
|
||||
bindingsMap.remove(keyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
for (Map<InputConstants.Key, Collection<KeyMapping>> bindings : map.values())
|
||||
{
|
||||
bindings.clear();
|
||||
}
|
||||
public void clear() {
|
||||
map.values().forEach(Map::clear);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.client.settings;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -18,134 +19,120 @@ import org.lwjgl.glfw.GLFW;
|
||||
public enum KeyModifier {
|
||||
CONTROL {
|
||||
@Override
|
||||
public boolean matches(InputConstants.Key key)
|
||||
{
|
||||
public boolean matches(InputConstants.Key key) {
|
||||
int keyCode = key.getValue();
|
||||
if (Minecraft.ON_OSX)
|
||||
{
|
||||
return keyCode == GLFW.GLFW_KEY_LEFT_SUPER || keyCode == GLFW.GLFW_KEY_RIGHT_SUPER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return keyCode == GLFW.GLFW_KEY_LEFT_CONTROL || keyCode == GLFW.GLFW_KEY_RIGHT_CONTROL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext)
|
||||
{
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext) {
|
||||
return Screen.hasControlDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getCombinedName(InputConstants.Key key, Supplier<Component> defaultLogic)
|
||||
{
|
||||
public Component getCombinedName(InputConstants.Key key, Supplier<Component> defaultLogic) {
|
||||
String localizationFormatKey = Minecraft.ON_OSX ? "forge.controlsgui.control.mac" : "forge.controlsgui.control";
|
||||
return Component.translatable(localizationFormatKey, defaultLogic.get());
|
||||
}
|
||||
},
|
||||
SHIFT {
|
||||
@Override
|
||||
public boolean matches(InputConstants.Key key)
|
||||
{
|
||||
public boolean matches(InputConstants.Key key) {
|
||||
return key.getValue() == GLFW.GLFW_KEY_LEFT_SHIFT || key.getValue() == GLFW.GLFW_KEY_RIGHT_SHIFT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext)
|
||||
{
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext) {
|
||||
return Screen.hasShiftDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getCombinedName(InputConstants.Key key, Supplier<Component> defaultLogic)
|
||||
{
|
||||
public Component getCombinedName(InputConstants.Key key, Supplier<Component> defaultLogic) {
|
||||
return Component.translatable("forge.controlsgui.shift", defaultLogic.get());
|
||||
}
|
||||
},
|
||||
ALT {
|
||||
@Override
|
||||
public boolean matches(InputConstants.Key key)
|
||||
{
|
||||
public boolean matches(InputConstants.Key key) {
|
||||
return key.getValue() == GLFW.GLFW_KEY_LEFT_ALT || key.getValue() == GLFW.GLFW_KEY_RIGHT_ALT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext)
|
||||
{
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext) {
|
||||
return Screen.hasAltDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getCombinedName(InputConstants.Key keyCode, Supplier<Component> defaultLogic)
|
||||
{
|
||||
public Component getCombinedName(InputConstants.Key keyCode, Supplier<Component> defaultLogic) {
|
||||
return Component.translatable("forge.controlsgui.alt", defaultLogic.get());
|
||||
}
|
||||
},
|
||||
NONE {
|
||||
@Override
|
||||
public boolean matches(InputConstants.Key key)
|
||||
{
|
||||
public boolean matches(InputConstants.Key key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext)
|
||||
{
|
||||
if (conflictContext != null && !conflictContext.conflicts(KeyConflictContext.IN_GAME))
|
||||
{
|
||||
for (KeyModifier keyModifier : MODIFIER_VALUES)
|
||||
{
|
||||
public boolean isActive(@Nullable IKeyConflictContext conflictContext) {
|
||||
if (conflictContext != null && !conflictContext.conflicts(KeyConflictContext.IN_GAME)) {
|
||||
for (KeyModifier keyModifier : VALUES) {
|
||||
if (keyModifier.isActive(conflictContext))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getCombinedName(InputConstants.Key key, Supplier<Component> defaultLogic)
|
||||
{
|
||||
public Component getCombinedName(InputConstants.Key key, Supplier<Component> defaultLogic) {
|
||||
return defaultLogic.get();
|
||||
}
|
||||
};
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.20.2")
|
||||
public static final KeyModifier[] MODIFIER_VALUES = {SHIFT, CONTROL, ALT};
|
||||
|
||||
public static KeyModifier getActiveModifier()
|
||||
{
|
||||
for (KeyModifier keyModifier : MODIFIER_VALUES)
|
||||
{
|
||||
@Deprecated(forRemoval = true, since = "1.20.2")
|
||||
public static KeyModifier getActiveModifier() {
|
||||
for (var keyModifier : VALUES) {
|
||||
if (keyModifier.isActive(null))
|
||||
{
|
||||
return keyModifier;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
|
||||
public static boolean isKeyCodeModifier(InputConstants.Key key)
|
||||
{
|
||||
for (KeyModifier keyModifier : MODIFIER_VALUES)
|
||||
{
|
||||
private static final KeyModifier[] VALUES = {SHIFT, CONTROL, ALT};
|
||||
private static final List<KeyModifier> VALUES_LIST = List.of(SHIFT, CONTROL, ALT);
|
||||
private static final List<KeyModifier> ALL = List.of(SHIFT, CONTROL, ALT, NONE);
|
||||
public static final List<KeyModifier> getValues(boolean includeNone) {
|
||||
return includeNone ? ALL : VALUES_LIST;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KeyModifier getModifier(InputConstants.Key key) {
|
||||
for (var modifier : VALUES) {
|
||||
if (modifier.matches(key))
|
||||
return modifier;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isKeyCodeModifier(InputConstants.Key key) {
|
||||
for (KeyModifier keyModifier : VALUES) {
|
||||
if (keyModifier.matches(key))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static KeyModifier valueFromString(String stringValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
public static KeyModifier valueFromString(String stringValue) {
|
||||
try {
|
||||
return valueOf(stringValue);
|
||||
}
|
||||
catch (NullPointerException | IllegalArgumentException ignored)
|
||||
{
|
||||
} catch (NullPointerException | IllegalArgumentException ignored) {
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,16 @@ public class ForgeConfig {
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
// Allow these to be called before the config is loaded because its used before loading the error screens.
|
||||
// Prevents a ton of spam when an error screen is displayed.
|
||||
public final boolean calculateAllNormals() {
|
||||
return clientSpec.isLoaded() ? calculateAllNormals.get() : calculateAllNormals.getDefault();
|
||||
}
|
||||
|
||||
public final boolean showLoadWarnings() {
|
||||
return clientSpec.isLoaded() ? showLoadWarnings.get() : showLoadWarnings.getDefault();
|
||||
}
|
||||
}
|
||||
|
||||
static final ForgeConfigSpec clientSpec;
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraftforge.fml.Logging;
|
||||
@@ -49,15 +50,16 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfig> implements IConfigSpec<ForgeConfigSpec>//TODO: Remove extends and pipe everything through getSpec/getValues?
|
||||
{
|
||||
private Map<List<String>, String> levelComments;
|
||||
private Map<List<String>, String> levelTranslationKeys;
|
||||
private final Map<List<String>, String> levelComments;
|
||||
private final Map<List<String>, String> levelTranslationKeys;
|
||||
|
||||
private UnmodifiableConfig values;
|
||||
private final UnmodifiableConfig values;
|
||||
private Config childConfig;
|
||||
|
||||
private boolean isCorrecting = false;
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Pattern WINDOWS_NEWLINE = Pattern.compile("\r\n");
|
||||
|
||||
private ForgeConfigSpec(UnmodifiableConfig storage, UnmodifiableConfig values, Map<List<String>, String> levelComments, Map<List<String>, String> levelTranslationKeys) {
|
||||
super(storage);
|
||||
@@ -119,11 +121,9 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
|
||||
private void resetCaches(final Iterable<Object> configValues) {
|
||||
configValues.forEach(value -> {
|
||||
if (value instanceof ConfigValue) {
|
||||
final ConfigValue<?> configValue = (ConfigValue<?>) value;
|
||||
if (value instanceof ConfigValue<?> configValue) {
|
||||
configValue.clearCache();
|
||||
} else if (value instanceof Config) {
|
||||
final Config innerConfig = (Config) value;
|
||||
} else if (value instanceof Config innerConfig) {
|
||||
this.resetCaches(innerConfig.valueMap().values());
|
||||
}
|
||||
});
|
||||
@@ -264,10 +264,10 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
{
|
||||
if (obj1 instanceof String string1 && obj2 instanceof String string2)
|
||||
{
|
||||
if (string1.length() > 0 && string2.length() > 0)
|
||||
if (!string1.isEmpty() && !string2.isEmpty())
|
||||
{
|
||||
return string1.replaceAll("\r\n", "\n")
|
||||
.equals(string2.replaceAll("\r\n", "\n"));
|
||||
return WINDOWS_NEWLINE.matcher(string1).replaceAll("\n")
|
||||
.equals(WINDOWS_NEWLINE.matcher(string2).replaceAll("\n"));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -279,10 +279,10 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
{
|
||||
private final Config storage = Config.of(LinkedHashMap::new, InMemoryFormat.withUniversalSupport()); // Use LinkedHashMap for consistent ordering
|
||||
private BuilderContext context = new BuilderContext();
|
||||
private Map<List<String>, String> levelComments = new HashMap<>();
|
||||
private Map<List<String>, String> levelTranslationKeys = new HashMap<>();
|
||||
private List<String> currentPath = new ArrayList<>();
|
||||
private List<ConfigValue<?>> values = new ArrayList<>();
|
||||
private final Map<List<String>, String> levelComments = new HashMap<>();
|
||||
private final Map<List<String>, String> levelTranslationKeys = new HashMap<>();
|
||||
private final List<String> currentPath = new ArrayList<>();
|
||||
private final List<ConfigValue<?>> values = new ArrayList<>();
|
||||
|
||||
//Object
|
||||
public <T> ConfigValue<T> define(String path, T defaultValue) {
|
||||
@@ -346,7 +346,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
return defineInList(path, () -> defaultValue, acceptableValues);
|
||||
}
|
||||
public <T> ConfigValue<T> defineInList(List<String> path, Supplier<T> defaultSupplier, Collection<? extends T> acceptableValues) {
|
||||
return define(path, defaultSupplier, acceptableValues::contains);
|
||||
return define(path, defaultSupplier, o -> o != null && acceptableValues.contains(o));
|
||||
}
|
||||
public <T> ConfigValue<List<? extends T>> defineList(String path, List<? extends T> defaultValue, Predicate<Object> elementValidator) {
|
||||
return defineList(split(path), defaultValue, elementValidator);
|
||||
@@ -366,7 +366,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction. It is null, not a list, or an empty list. Modders, consider defineListAllowEmpty?", path.get(path.size() - 1));
|
||||
return getDefault();
|
||||
}
|
||||
List<?> list = Lists.newArrayList((List<?>) value);
|
||||
List<?> list = new ArrayList<>((List<?>) value);
|
||||
list.removeIf(elementValidator.negate());
|
||||
if (list.isEmpty()) {
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
|
||||
@@ -394,7 +394,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction, as it is null or not a list.", path.get(path.size() - 1));
|
||||
return getDefault();
|
||||
}
|
||||
List<?> list = Lists.newArrayList((List<?>) value);
|
||||
List<?> list = new ArrayList<>((List<?>) value);
|
||||
list.removeIf(elementValidator.negate());
|
||||
if (list.isEmpty()) {
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
|
||||
@@ -695,7 +695,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class Range<V extends Comparable<? super V>> implements Predicate<Object>
|
||||
public static class Range<V extends Comparable<? super V>> implements Predicate<Object>
|
||||
{
|
||||
private final Class<? extends V> clazz;
|
||||
private final V min;
|
||||
@@ -825,7 +825,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
|
||||
public List<String> getPath()
|
||||
{
|
||||
return Lists.newArrayList(path);
|
||||
return new ArrayList<>(path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.ClientCommandHandler;
|
||||
import net.minecraftforge.client.ConfigScreenHandler;
|
||||
import net.minecraftforge.eventbus.api.BusBuilder;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.network.DualStackUtils;
|
||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||
@@ -17,6 +21,9 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MinecraftForge
|
||||
{
|
||||
/**
|
||||
@@ -46,6 +53,36 @@ public class MinecraftForge
|
||||
DualStackUtils.initialise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a config screen for the active mod container.
|
||||
* @param screenFunction A function that takes the mods screen as an argument and returns your config screen to
|
||||
* show when the player clicks the config button for your mod on the mods screen.
|
||||
* <p>You should call {@link Minecraft#setScreen(Screen)} with the provided mods screen for the
|
||||
* action of your close button, using {@link Screen#minecraft} to get the client instance.</p>
|
||||
* @see ModLoadingContext#registerExtensionPoint(Class, Supplier)
|
||||
* @see ModLoadingContext#registerConfig(ModConfig.Type, IConfigSpec)
|
||||
*/
|
||||
public static void registerConfigScreen(Function<Screen, Screen> screenFunction) {
|
||||
registerConfigScreen((mcClient, modsScreen) -> screenFunction.apply(modsScreen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a config screen for the active mod container.
|
||||
* @param screenFunction A function that takes the {@link Minecraft} client instance and the mods screen as
|
||||
* arguments and returns your config screen to show when the player clicks the config button
|
||||
* for your mod on the mods screen.
|
||||
* <p>You should call {@link Minecraft#setScreen(Screen)} with the provided client instance
|
||||
* and mods screen for the action of your close button.</p>
|
||||
* @see ModLoadingContext#registerExtensionPoint(Class, Supplier)
|
||||
* @see ModLoadingContext#registerConfig(ModConfig.Type, IConfigSpec)
|
||||
*/
|
||||
public static void registerConfigScreen(BiFunction<Minecraft, Screen, Screen> screenFunction) {
|
||||
ModLoadingContext.get().registerExtensionPoint(
|
||||
ConfigScreenHandler.ConfigScreenFactory.class,
|
||||
() -> new ConfigScreenHandler.ConfigScreenFactory(screenFunction)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
public static void preloadCrashClasses(ASMDataTable table, String modID, Set<String> classes)
|
||||
{
|
||||
|
||||
@@ -7,12 +7,11 @@ package net.minecraftforge.common.capabilities;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -36,9 +35,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
@MethodsReturnNonnullByDefault
|
||||
public final class CapabilityDispatcher implements INBTSerializable<CompoundTag>, ICapabilityProvider
|
||||
{
|
||||
private ICapabilityProvider[] caps;
|
||||
private INBTSerializable<Tag>[] writers;
|
||||
private String[] names;
|
||||
private final ICapabilityProvider[] caps;
|
||||
private final INBTSerializable<Tag>[] writers;
|
||||
private final String[] names;
|
||||
private final List<Runnable> listeners;
|
||||
|
||||
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, List<Runnable> listeners)
|
||||
@@ -49,9 +48,9 @@ public final class CapabilityDispatcher implements INBTSerializable<CompoundTag>
|
||||
@SuppressWarnings("unchecked")
|
||||
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, List<Runnable> listeners, @Nullable ICapabilityProvider parent)
|
||||
{
|
||||
List<ICapabilityProvider> lstCaps = Lists.newArrayList();
|
||||
List<INBTSerializable<Tag>> lstWriters = Lists.newArrayList();
|
||||
List<String> lstNames = Lists.newArrayList();
|
||||
List<ICapabilityProvider> lstCaps = new ArrayList<>();
|
||||
List<INBTSerializable<Tag>> lstWriters = new ArrayList<>();
|
||||
List<String> lstNames = new ArrayList<>();
|
||||
this.listeners = listeners;
|
||||
|
||||
if (parent != null) // Parents go first!
|
||||
|
||||
@@ -340,16 +340,17 @@ public interface IForgeItem
|
||||
*/
|
||||
default void onInventoryTick(ItemStack stack, Level level, Player player, int slotIndex, int selectedIndex)
|
||||
{
|
||||
// For compatibility reasons we have to use non-local index values, I think this is a vanilla bug but lets maintain compatibility
|
||||
int vanillaIndex = slotIndex;
|
||||
if (slotIndex >= 36) {
|
||||
vanillaIndex -= 36;
|
||||
if (vanillaIndex >= 4)
|
||||
vanillaIndex -= 4;
|
||||
else
|
||||
onArmorTick(stack, level, player);
|
||||
}
|
||||
stack.inventoryTick(level, player, vanillaIndex, selectedIndex == vanillaIndex);
|
||||
// For compatibility reasons we have to use non-local index values, I think this is a vanilla bug but lets maintain compatibility
|
||||
var inv = player.getInventory();
|
||||
int vanillaIndex = slotIndex;
|
||||
if (slotIndex >= inv.items.size()) {
|
||||
vanillaIndex -= inv.items.size();
|
||||
if (vanillaIndex >= inv.armor.size())
|
||||
vanillaIndex -= inv.armor.size();
|
||||
else
|
||||
onArmorTick(stack, level, player);
|
||||
}
|
||||
stack.inventoryTick(level, player, vanillaIndex, selectedIndex == vanillaIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,19 @@ public interface IForgeTagAppender<T>
|
||||
return builder;
|
||||
}
|
||||
|
||||
default TagsProvider.TagAppender<T> addOptionalTag(TagKey<T> value) {
|
||||
return self().addOptionalTag(value.location());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default TagsProvider.TagAppender<T> addOptionalTags(TagKey<T>... values) {
|
||||
TagsProvider.TagAppender<T> builder = self();
|
||||
for (TagKey<T> value : values) {
|
||||
builder.addOptionalTag(value.location());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
default TagsProvider.TagAppender<T> replace() {
|
||||
return replace(true);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class LazyOptional<T> {
|
||||
// non-null and contains non-null value -> resolved
|
||||
// non-null and contains null -> resolved, but supplier returned null (contract violation)
|
||||
private Mutable<T> resolved;
|
||||
private Set<NonNullConsumer<LazyOptional<T>>> listeners = new HashSet<>();
|
||||
private final Set<NonNullConsumer<LazyOptional<T>>> listeners = new HashSet<>();
|
||||
private boolean isValid = true;
|
||||
|
||||
private static final @NotNull LazyOptional<Void> EMPTY = new LazyOptional<>(null);
|
||||
|
||||
@@ -621,7 +621,7 @@ public class ForgeEventFactory
|
||||
private static CapabilityDispatcher gatherCapabilities(AttachCapabilitiesEvent<?> event, @Nullable ICapabilityProvider parent)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
return event.getCapabilities().size() > 0 || parent != null ? new CapabilityDispatcher(event.getCapabilities(), event.getListeners(), parent) : null;
|
||||
return !event.getCapabilities().isEmpty() || parent != null ? new CapabilityDispatcher(event.getCapabilities(), event.getListeners(), parent) : null;
|
||||
}
|
||||
|
||||
public static boolean fireSleepingLocationCheck(LivingEntity player, BlockPos sleepingLocation)
|
||||
|
||||
@@ -10,19 +10,20 @@ import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Fires when a player joins the server or when the reload command is ran,
|
||||
* before tags and crafting recipes are sent to the client. Send datapack data
|
||||
* to clients when this event fires.
|
||||
*/
|
||||
public class OnDatapackSyncEvent extends Event
|
||||
{
|
||||
public class OnDatapackSyncEvent extends Event {
|
||||
private final PlayerList playerList;
|
||||
|
||||
@Nullable
|
||||
private final ServerPlayer player;
|
||||
|
||||
public OnDatapackSyncEvent(PlayerList playerList, @Nullable ServerPlayer player)
|
||||
{
|
||||
public OnDatapackSyncEvent(PlayerList playerList, @Nullable ServerPlayer player) {
|
||||
this.playerList = playerList;
|
||||
this.player = player;
|
||||
}
|
||||
@@ -30,8 +31,7 @@ public class OnDatapackSyncEvent extends Event
|
||||
/**
|
||||
* @return The server's player list to get a view of all players.
|
||||
*/
|
||||
public PlayerList getPlayerList()
|
||||
{
|
||||
public PlayerList getPlayerList() {
|
||||
return this.playerList;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,15 @@ public class OnDatapackSyncEvent extends Event
|
||||
* such as when the reload command runs.
|
||||
*/
|
||||
@Nullable
|
||||
public ServerPlayer getPlayer()
|
||||
{
|
||||
public ServerPlayer getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A list of players that should receive data during this event, which is the specified player (if not null)
|
||||
* or all players otherwise.
|
||||
*/
|
||||
public List<ServerPlayer> getPlayers() {
|
||||
return this.player == null ? this.playerList.getPlayers() : List.of(this.player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.logging;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
import org.spongepowered.asm.mixin.transformer.ClassInfo;
|
||||
import org.spongepowered.asm.mixin.transformer.meta.MixinMerged;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public final class CrashReportAnalyser {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Map<String, IModInfo> PACKAGE_MOD_CACHE = new HashMap<>();
|
||||
private static final Map<IModInfo, String[]> SUSPECTED_MODS = new HashMap<>();
|
||||
|
||||
private CrashReportAnalyser() {}
|
||||
|
||||
/**
|
||||
* Tries to cache, analyze and append the suspected mods for this crash to the crash report.
|
||||
* */
|
||||
public static String appendSuspectedMods(Throwable throwable, StackTraceElement[] uncategorizedStackTrace) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
try {
|
||||
cacheModList();
|
||||
analyseCrashReport(throwable, uncategorizedStackTrace);
|
||||
buildSuspectedModsSection(stringBuilder);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOGGER.error("Failed to append suspected mod(s) to crash report!", t);
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to analyze the given exception and uncategorized stacktrace of the crash report.
|
||||
* It checks the stacktrace for any occurrence of the package names cached in the {@link #PACKAGE_MOD_CACHE},
|
||||
* including mixin classes.
|
||||
* **/
|
||||
private static void analyseCrashReport(Throwable throwable, StackTraceElement[] uncategorizedStackTrace) {
|
||||
scanThrowable(throwable);
|
||||
scanStacktrace(uncategorizedStackTrace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the suspected mod(s) for this crash to a String to be added to the crash report,
|
||||
* including the mods name, its id, version and an issues link if available,
|
||||
* as well as the position where the exception occurred (either the stacktrace element
|
||||
* or the mixin class and its target(s))
|
||||
* **/
|
||||
private static void buildSuspectedModsSection(StringBuilder stringBuilder) {
|
||||
stringBuilder.append("Suspected Mod");
|
||||
stringBuilder.append(SUSPECTED_MODS.size() == 1 ? ": " : "s: ");
|
||||
if (SUSPECTED_MODS.isEmpty()) {
|
||||
stringBuilder.append("NONE\n");
|
||||
}
|
||||
else {
|
||||
SUSPECTED_MODS.forEach((iModInfo, position) -> {
|
||||
stringBuilder
|
||||
.append("\n\t")
|
||||
.append(iModInfo.getDisplayName())
|
||||
.append(" (").append(iModInfo.getModId()).append("),")
|
||||
.append(" Version: ").append(iModInfo.getVersion());
|
||||
|
||||
iModInfo.getOwningFile().getConfig().<String>getConfigElement("issueTrackerURL").ifPresent(issuesLink -> {
|
||||
stringBuilder
|
||||
.append("\n\t\t")
|
||||
.append("Issue tracker URL: ")
|
||||
.append(issuesLink);
|
||||
});
|
||||
|
||||
stringBuilder.append("\n\t\t");
|
||||
|
||||
for (String s : position) {
|
||||
stringBuilder.append(s);
|
||||
}
|
||||
stringBuilder.append("\n");
|
||||
});
|
||||
SUSPECTED_MODS.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the stacktrace of the given throwable and all its children for any occurrence of the package names cached in the {@link #PACKAGE_MOD_CACHE},
|
||||
* including mixin classes.
|
||||
* **/
|
||||
private static void scanThrowable(Throwable throwable) {
|
||||
scanStacktrace(throwable.getStackTrace());
|
||||
|
||||
if (throwable.getCause() != null && throwable.getCause() != throwable) {
|
||||
scanThrowable(throwable.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given stacktrace for any occurrence of the package names cached in the {@link #PACKAGE_MOD_CACHE},
|
||||
* including mixin classes.
|
||||
* **/
|
||||
private static void scanStacktrace(StackTraceElement[] stackTrace) {
|
||||
for (StackTraceElement stackTraceElement : stackTrace) {
|
||||
identifyByClass(stackTraceElement);
|
||||
identifyByMixins(stackTraceElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterates over all loaded mods, resolving and caching their package names with the corresponding {@link IModInfo}.
|
||||
* **/
|
||||
private static void cacheModList() {
|
||||
ModList modList = ModList.get();
|
||||
ModuleLayer gameLayer = FMLLoader.getGameLayer();
|
||||
|
||||
if (modList != null) {
|
||||
modList.getMods().forEach(iModInfo -> {
|
||||
//Don't cache minecraft or forge as they will always be included in the stacktrace
|
||||
if (!iModInfo.getModId().equals("forge") && !iModInfo.getModId().equals("minecraft")) {
|
||||
Set<String> packages = new HashSet<>();
|
||||
|
||||
gameLayer.findModule(iModInfo.getModId()).ifPresent(module -> packages.addAll(module.getPackages()));
|
||||
|
||||
packages.forEach(s -> PACKAGE_MOD_CACHE.put(s, iModInfo));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void identifyByClass(StackTraceElement stackTraceElement) {
|
||||
blameIfPresent(stackTraceElement);
|
||||
}
|
||||
|
||||
private static void identifyByMixins(StackTraceElement stackTraceElement) {
|
||||
IMixinInfo mixinInfo = getMixinInfo(stackTraceElement);
|
||||
|
||||
if (mixinInfo != null) {
|
||||
String elementAsString = stackTraceElement.toString();
|
||||
String mixinClassName = mixinInfo.getClassName();
|
||||
List<String> targetClasses = mixinInfo.getTargetClasses();
|
||||
blameIfPresent(mixinClassName, "Mixin class: ", mixinClassName, "\n\t\tTarget", (targetClasses.size() == 1 ? ": " + targetClasses.get(0) : "s: " + targetClasses).replaceAll("/", "."), "\n\t\tat ", elementAsString);
|
||||
}
|
||||
}
|
||||
|
||||
private static void blameIfPresent(StackTraceElement stackTraceElement) {
|
||||
blameIfPresent(stackTraceElement.getClassName(), "at ", stackTraceElement.toString());
|
||||
}
|
||||
|
||||
private static void blameIfPresent(String className, String... position) {
|
||||
String commonPackage = findMatchingPackage(className);
|
||||
|
||||
if (commonPackage != null) {
|
||||
SUSPECTED_MODS.putIfAbsent(PACKAGE_MOD_CACHE.get(commonPackage), position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the beginning of the given class name is contained in the {@link #PACKAGE_MOD_CACHE}
|
||||
* @return the package name of the class or null if it is not present in the cache
|
||||
* */
|
||||
@Nullable
|
||||
private static String findMatchingPackage(String className) {
|
||||
for (String s : PACKAGE_MOD_CACHE.keySet()) {
|
||||
if (className.startsWith(s)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static MixinMerged findMixinMerged(StackTraceElement element) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(element.getClassName());
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals(element.getMethodName())) {
|
||||
MixinMerged mixinMerged = method.getAnnotation(MixinMerged.class);
|
||||
if (mixinMerged != null) {
|
||||
return mixinMerged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException | NoClassDefFoundError ignored) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries to identify any applied mixin for the class and method provided by the stacktrace element.
|
||||
* @param element the stacktrace element to check
|
||||
* @return the {@link IMixinInfo} for the class and method or null if there is no mixin applied at this position
|
||||
* **/
|
||||
@Nullable
|
||||
private static IMixinInfo getMixinInfo(StackTraceElement element) {
|
||||
MixinMerged mixinMerged = findMixinMerged(element);
|
||||
if (mixinMerged != null) {
|
||||
ClassInfo classInfo = ClassInfo.forName(mixinMerged.mixin().replace('.', '/'));
|
||||
if (classInfo != null) {
|
||||
try {
|
||||
Field mixinField = ClassInfo.class.getDeclaredField("mixin");
|
||||
mixinField.setAccessible(true);
|
||||
return (IMixinInfo) mixinField.get(classInfo);
|
||||
}
|
||||
catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ public class ForgeRegistries
|
||||
* Calling {@link Supplier#get()} before {@link NewRegistryEvent} is fired will result in a null registry returned.
|
||||
* Use {@link Keys#HOLDER_SET_TYPES} to create a {@link DeferredRegister}.
|
||||
*/
|
||||
public static final Supplier<IForgeRegistry<HolderSetType>> HOLDER_SET_TYPES = DEFERRED_HOLDER_SET_TYPES.makeRegistry(GameData::getHolderSetTypeRegistryBuilder);
|
||||
public static final Supplier<IForgeRegistry<HolderSetType>> HOLDER_SET_TYPES = DEFERRED_HOLDER_SET_TYPES.makeRegistry(GameData::makeUnsavedAndUnsynced);
|
||||
|
||||
static final DeferredRegister<ItemDisplayContext> DEFERRED_DISPLAY_CONTEXTS = DeferredRegister.create(Keys.DISPLAY_CONTEXTS, "forge");
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -7,7 +7,6 @@ package net.minecraftforge.registries;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
@@ -23,6 +22,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.IdMapper;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
@@ -30,6 +32,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.syncher.EntityDataSerializer;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.SpawnPlacements;
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
@@ -38,7 +41,10 @@ import net.minecraft.world.entity.ai.village.poi.PoiType;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.alchemy.Potion;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||
@@ -57,7 +63,6 @@ import net.minecraftforge.fml.StartupMessageManager;
|
||||
import net.minecraftforge.fml.util.EnhancedRuntimeException;
|
||||
import net.minecraftforge.fml.util.thread.EffectiveSide;
|
||||
import net.minecraftforge.registries.ForgeRegistries.Keys;
|
||||
import net.minecraftforge.registries.holdersets.HolderSetType;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -68,12 +73,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* INTERNAL ONLY
|
||||
* MODDERS SHOULD HAVE NO REASON TO USE THIS CLASS
|
||||
* <p>Use the public {@link IForgeRegistry} and {@link ForgeRegistries} APIs to get the data</p>
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public class GameData
|
||||
{
|
||||
public class GameData {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static Marker REGISTRIES = ForgeRegistry.REGISTRIES;
|
||||
private static final Marker REGISTRIES = ForgeRegistry.REGISTRIES;
|
||||
private static final int MAX_VARINT = Integer.MAX_VALUE - 1; //We were told it is their intention to have everything in a reg be unlimited, so assume that until we find cases where it isnt.
|
||||
|
||||
private static final ResourceLocation BLOCK_TO_ITEM = new ResourceLocation("minecraft:blocktoitemmap");
|
||||
@@ -82,16 +87,15 @@ public class GameData
|
||||
|
||||
private static boolean hasInit = false;
|
||||
private static final boolean DISABLE_VANILLA_REGISTRIES = Boolean.parseBoolean(System.getProperty("forge.disableVanillaGameData", "false")); // Use for unit tests/debugging
|
||||
private static final BiConsumer<ResourceLocation, ForgeRegistry<?>> LOCK_VANILLA = (name, reg) -> reg.slaves.values().stream().filter(o -> o instanceof ILockableRegistry).forEach(o -> ((ILockableRegistry)o).lock());
|
||||
private static final BiConsumer<ResourceLocation, ForgeRegistry<?>> LOCK_VANILLA = (name, reg) -> reg.slaves.values().stream().filter(o -> o instanceof ILockableRegistry).forEach(o -> ((ILockableRegistry) o).lock());
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
public static void init()
|
||||
{
|
||||
if (DISABLE_VANILLA_REGISTRIES)
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void init() {
|
||||
if (DISABLE_VANILLA_REGISTRIES) {
|
||||
LOGGER.warn(REGISTRIES, "DISABLING VANILLA REGISTRY CREATION AS PER SYSTEM VARIABLE SETTING! forge.disableVanillaGameData");
|
||||
return;
|
||||
}
|
||||
@@ -138,59 +142,50 @@ public class GameData
|
||||
makeRegistry(Keys.BIOMES).disableSync().create();
|
||||
}
|
||||
|
||||
static RegistryBuilder<EntityDataSerializer<?>> getDataSerializersRegistryBuilder()
|
||||
{
|
||||
static RegistryBuilder<EntityDataSerializer<?>> getDataSerializersRegistryBuilder() {
|
||||
return makeRegistry(Keys.ENTITY_DATA_SERIALIZERS, 256 /*vanilla space*/, MAX_VARINT).disableSaving().disableOverrides();
|
||||
}
|
||||
|
||||
static RegistryBuilder<Codec<? extends IGlobalLootModifier>> getGLMSerializersRegistryBuilder()
|
||||
{
|
||||
static RegistryBuilder<Codec<? extends IGlobalLootModifier>> getGLMSerializersRegistryBuilder() {
|
||||
return makeRegistry(Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS).disableSaving().disableSync();
|
||||
}
|
||||
|
||||
static RegistryBuilder<Codec<? extends BiomeModifier>> getBiomeModifierSerializersRegistryBuilder()
|
||||
{
|
||||
static RegistryBuilder<Codec<? extends BiomeModifier>> getBiomeModifierSerializersRegistryBuilder() {
|
||||
return new RegistryBuilder<Codec<? extends BiomeModifier>>().disableSaving().disableSync();
|
||||
}
|
||||
|
||||
static RegistryBuilder<Codec<? extends StructureModifier>> getStructureModifierSerializersRegistryBuilder()
|
||||
{
|
||||
static RegistryBuilder<Codec<? extends StructureModifier>> getStructureModifierSerializersRegistryBuilder() {
|
||||
return new RegistryBuilder<Codec<? extends StructureModifier>>().disableSaving().disableSync();
|
||||
}
|
||||
|
||||
static RegistryBuilder<FluidType> getFluidTypeRegistryBuilder()
|
||||
{
|
||||
static RegistryBuilder<FluidType> getFluidTypeRegistryBuilder() {
|
||||
return makeRegistry(Keys.FLUID_TYPES).disableSaving();
|
||||
}
|
||||
|
||||
static RegistryBuilder<HolderSetType> getHolderSetTypeRegistryBuilder()
|
||||
{
|
||||
return new RegistryBuilder<HolderSetType>().disableSaving().disableSync();
|
||||
static <T> RegistryBuilder<T> makeUnsavedAndUnsynced() {
|
||||
return RegistryBuilder.<T>of().disableSaving().disableSync();
|
||||
}
|
||||
|
||||
static RegistryBuilder<ItemDisplayContext> getItemDisplayContextRegistryBuilder()
|
||||
{
|
||||
static RegistryBuilder<ItemDisplayContext> getItemDisplayContextRegistryBuilder() {
|
||||
return new RegistryBuilder<ItemDisplayContext>()
|
||||
.setMaxID(128 * 2) /* 0 -> 127 gets positive ID, 128 -> 256 gets negative ID */.disableOverrides().disableSaving()
|
||||
.setDefaultKey(new ResourceLocation("minecraft:none"))
|
||||
.onAdd(ItemDisplayContext.ADD_CALLBACK);
|
||||
.setMaxID(128 * 2) /* 0 -> 127 gets positive ID, 128 -> 256 gets negative ID */.disableOverrides().disableSaving()
|
||||
.setDefaultKey(new ResourceLocation("minecraft:none"))
|
||||
.onAdd(ItemDisplayContext.ADD_CALLBACK);
|
||||
}
|
||||
|
||||
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key)
|
||||
{
|
||||
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key) {
|
||||
return new RegistryBuilder<T>().setName(key.location()).setMaxID(MAX_VARINT).hasWrapper();
|
||||
}
|
||||
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key, int min, int max)
|
||||
{
|
||||
|
||||
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key, int min, int max) {
|
||||
return new RegistryBuilder<T>().setName(key.location()).setIDRange(min, max).hasWrapper();
|
||||
}
|
||||
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key, String _default)
|
||||
{
|
||||
|
||||
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key, String _default) {
|
||||
return new RegistryBuilder<T>().setName(key.location()).setMaxID(MAX_VARINT).hasWrapper().setDefaultKey(new ResourceLocation(_default));
|
||||
}
|
||||
|
||||
public static <T> MappedRegistry<T> getWrapper(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle)
|
||||
{
|
||||
public static <T> MappedRegistry<T> getWrapper(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
|
||||
IForgeRegistry<T> reg = RegistryManager.ACTIVE.getRegistry(key);
|
||||
Validate.notNull(reg, "Attempted to get vanilla wrapper for unknown registry: " + key.toString());
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -199,8 +194,7 @@ public class GameData
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static <T> MappedRegistry<T> getWrapper(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle, String defKey)
|
||||
{
|
||||
public static <T> MappedRegistry<T> getWrapper(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle, String defKey) {
|
||||
IForgeRegistry<T> reg = RegistryManager.ACTIVE.getRegistry(key);
|
||||
Validate.notNull(reg, "Attempted to get vanilla wrapper for unknown registry: " + key.toString());
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -210,26 +204,21 @@ public class GameData
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<Block,Item> getBlockItemMap()
|
||||
{
|
||||
public static Map<Block, Item> getBlockItemMap() {
|
||||
return RegistryManager.ACTIVE.getRegistry(Keys.ITEMS).getSlaveMap(BLOCK_TO_ITEM, Map.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static IdMapper<BlockState> getBlockStateIDMap()
|
||||
{
|
||||
public static IdMapper<BlockState> getBlockStateIDMap() {
|
||||
return RegistryManager.ACTIVE.getRegistry(Keys.BLOCKS).getSlaveMap(BLOCKSTATE_TO_ID, IdMapper.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<BlockState, PoiType> getBlockStatePointOfInterestTypeMap()
|
||||
{
|
||||
public static Map<BlockState, PoiType> getBlockStatePointOfInterestTypeMap() {
|
||||
return RegistryManager.ACTIVE.getRegistry(Keys.POI_TYPES).getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static void vanillaSnapshot()
|
||||
{
|
||||
public static void vanillaSnapshot() {
|
||||
LOGGER.debug(REGISTRIES, "Creating vanilla freeze snapshot");
|
||||
for (Map.Entry<ResourceLocation, ForgeRegistry<?>> r : RegistryManager.ACTIVE.registries.entrySet())
|
||||
{
|
||||
@@ -245,13 +234,12 @@ public class GameData
|
||||
LOGGER.debug(REGISTRIES, "Vanilla freeze snapshot created");
|
||||
}
|
||||
|
||||
public static void unfreezeData()
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void unfreezeData() {
|
||||
LOGGER.debug(REGISTRIES, "Unfreezing vanilla registries");
|
||||
BuiltInRegistries.REGISTRY.stream().filter(r -> r instanceof MappedRegistry).forEach(r -> ((MappedRegistry<?>)r).unfreeze());
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static void freezeData()
|
||||
{
|
||||
LOGGER.debug(REGISTRIES, "Freezing registries");
|
||||
@@ -281,7 +269,7 @@ public class GameData
|
||||
public static void revertToFrozen() {
|
||||
revertTo(RegistryManager.FROZEN, true);
|
||||
}
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
|
||||
public static void revertTo(final RegistryManager target, boolean fireEvents)
|
||||
{
|
||||
if (target.registries.isEmpty())
|
||||
@@ -307,7 +295,6 @@ public class GameData
|
||||
LOGGER.debug(REGISTRIES, "{} state restored.", target.getName());
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static void revert(RegistryManager state, ResourceLocation registry, boolean lock)
|
||||
{
|
||||
LOGGER.debug(REGISTRIES, "Reverting {} to {}", registry, state.getName());
|
||||
@@ -376,11 +363,12 @@ public class GameData
|
||||
this.nextId = 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void remove(I key)
|
||||
{
|
||||
Integer prev = this.tToId.remove(key);
|
||||
if (prev != null)
|
||||
{
|
||||
boolean hadId = this.tToId.containsKey(key);
|
||||
int prev = this.tToId.removeInt(key);
|
||||
if (hadId) {
|
||||
this.idToT.set(prev, null);
|
||||
}
|
||||
}
|
||||
@@ -430,21 +418,17 @@ public class GameData
|
||||
@Override
|
||||
public void onCreate(IForgeRegistryInternal<Block> owner, RegistryManager stage)
|
||||
{
|
||||
final ClearableObjectIntIdentityMap<BlockState> idMap = new ClearableObjectIntIdentityMap<BlockState>()
|
||||
final ClearableObjectIntIdentityMap<BlockState> idMap = new ClearableObjectIntIdentityMap<>()
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public int getId(BlockState key)
|
||||
{
|
||||
Integer integer = (Integer)this.tToId.get(key);
|
||||
// There are some cases where this map is queried to serialize a state that is valid,
|
||||
//but somehow not in this list, so attempt to get real metadata. Doing this hear saves us 7 patches
|
||||
//if (integer == null && key != null)
|
||||
// integer = this.identityMap.get(key.getBlock().getStateFromMeta(key.getBlock().getMetaFromState(key)));
|
||||
return integer == null ? -1 : integer.intValue();
|
||||
return this.tToId.containsKey(key) ? this.tToId.getInt(key) : -1;
|
||||
}
|
||||
};
|
||||
owner.setSlaveMap(BLOCKSTATE_TO_ID, idMap);
|
||||
owner.setSlaveMap(BLOCK_TO_ITEM, Maps.newHashMap());
|
||||
owner.setSlaveMap(BLOCK_TO_ITEM, new HashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -522,6 +506,7 @@ public class GameData
|
||||
@Override
|
||||
public void onAdd(IForgeRegistryInternal<PoiType> owner, RegistryManager stage, int id, ResourceKey<PoiType> key, PoiType obj, @Nullable PoiType oldObj)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<BlockState, PoiType> map = owner.getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class);
|
||||
if (oldObj != null)
|
||||
{
|
||||
@@ -590,7 +575,6 @@ public class GameData
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static Multimap<ResourceLocation, ResourceLocation> injectSnapshot(Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot, boolean injectFrozenData, boolean isLocalWorld)
|
||||
{
|
||||
LOGGER.info(REGISTRIES, "Injecting existing registry data into this {} instance", EffectiveSide.get());
|
||||
@@ -605,11 +589,11 @@ public class GameData
|
||||
|
||||
if (isLocalWorld)
|
||||
{
|
||||
List<ResourceLocation> missingRegs = snapshot.keySet().stream().filter(name -> !RegistryManager.ACTIVE.registries.containsKey(name)).collect(Collectors.toList());
|
||||
if (missingRegs.size() > 0)
|
||||
ResourceLocation[] missingRegs = snapshot.keySet().stream().filter(name -> !RegistryManager.ACTIVE.registries.containsKey(name)).toArray(ResourceLocation[]::new);
|
||||
if (missingRegs.length > 0)
|
||||
{
|
||||
String header = "Forge Mod Loader detected missing/unknown registrie(s).\n\n" +
|
||||
"There are " + missingRegs.size() + " missing registries in this save.\n" +
|
||||
"There are " + missingRegs.length + " missing registries in this save.\n" +
|
||||
"If you continue the missing registries will get removed.\n" +
|
||||
"This may cause issues, it is advised that you create a world backup before continuing.\n\n";
|
||||
|
||||
@@ -625,13 +609,13 @@ public class GameData
|
||||
|
||||
RegistryManager STAGING = new RegistryManager();
|
||||
|
||||
final Map<ResourceLocation, Map<ResourceLocation, IdMappingEvent.IdRemapping>> remaps = Maps.newHashMap();
|
||||
final LinkedHashMap<ResourceLocation, Map<ResourceLocation, Integer>> missing = Maps.newLinkedHashMap();
|
||||
final Map<ResourceLocation, Map<ResourceLocation, IdMappingEvent.IdRemapping>> remaps = new HashMap<>();
|
||||
final LinkedHashMap<ResourceLocation, Object2IntMap<ResourceLocation>> missing = new LinkedHashMap<>();
|
||||
// Load the snapshot into the "STAGING" registry
|
||||
snapshot.forEach((key, value) ->
|
||||
{
|
||||
remaps.put(key, Maps.newLinkedHashMap());
|
||||
missing.put(key, Maps.newLinkedHashMap());
|
||||
remaps.put(key, new LinkedHashMap<>());
|
||||
missing.put(key, new Object2IntLinkedOpenHashMap<>());
|
||||
loadPersistentDataToStagingRegistry(RegistryManager.ACTIVE, STAGING, remaps.get(key), missing.get(key), key, value);
|
||||
});
|
||||
|
||||
@@ -642,11 +626,12 @@ public class GameData
|
||||
Multimap<ResourceLocation, ResourceLocation> defaulted = ArrayListMultimap.create();
|
||||
Multimap<ResourceLocation, ResourceLocation> failed = ArrayListMultimap.create();
|
||||
|
||||
missing.entrySet().stream().filter(e -> e.getValue().size() > 0).forEach(m ->
|
||||
missing.entrySet().stream().filter(e -> !e.getValue().isEmpty()).forEach(m ->
|
||||
{
|
||||
ResourceLocation name = m.getKey();
|
||||
ForgeRegistry<?> reg = STAGING.getRegistry(name);
|
||||
MissingMappingsEvent event = reg.getMissingEvent(name, m.getValue());
|
||||
Object2IntMap<ResourceLocation> missingIds = m.getValue();
|
||||
MissingMappingsEvent event = reg.getMissingEvent(name, missingIds);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
|
||||
List<MissingMappingsEvent.Mapping<?>> lst = event.getAllMappings(reg.getRegistryKey()).stream()
|
||||
@@ -664,7 +649,7 @@ public class GameData
|
||||
.filter(e -> e.action == MissingMappingsEvent.Action.FAIL)
|
||||
.forEach(fail -> failed.put(name, fail.key));
|
||||
|
||||
processMissing(name, STAGING, event, m.getValue(), remaps.get(name), defaulted.get(name), failed.get(name), !isLocalWorld);
|
||||
processMissing(name, STAGING, event, missingIds, remaps.get(name), defaulted.get(name), failed.get(name), !isLocalWorld);
|
||||
});
|
||||
|
||||
if (!defaulted.isEmpty() && !isLocalWorld)
|
||||
@@ -681,7 +666,7 @@ public class GameData
|
||||
defaulted.asMap().forEach((name, entries) ->
|
||||
{
|
||||
buf.append("Missing ").append(name).append(":\n");
|
||||
entries.stream().sorted((o1, o2) -> o1.compareNamespaced(o2)).forEach(rl -> buf.append(" ").append(rl).append("\n"));
|
||||
entries.stream().sorted(ResourceLocation::compareNamespaced).forEach(rl -> buf.append(" ").append(rl).append("\n"));
|
||||
buf.append("\n");
|
||||
});
|
||||
|
||||
@@ -739,7 +724,7 @@ public class GameData
|
||||
}
|
||||
|
||||
//Has to be split because of generics, Yay!
|
||||
private static <T> void loadPersistentDataToStagingRegistry(RegistryManager pool, RegistryManager to, Map<ResourceLocation, IdMappingEvent.IdRemapping> remaps, Map<ResourceLocation, Integer> missing, ResourceLocation name, ForgeRegistry.Snapshot snap)
|
||||
private static <T> void loadPersistentDataToStagingRegistry(RegistryManager pool, RegistryManager to, Map<ResourceLocation, IdMappingEvent.IdRemapping> remaps, Object2IntMap<ResourceLocation> missing, ResourceLocation name, ForgeRegistry.Snapshot snap)
|
||||
{
|
||||
ForgeRegistry<T> active = pool.getRegistry(name);
|
||||
if (active == null)
|
||||
@@ -751,8 +736,7 @@ public class GameData
|
||||
}
|
||||
|
||||
//Another bouncer for generic reasons
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> void processMissing(ResourceLocation name, RegistryManager STAGING, MissingMappingsEvent e, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, IdMappingEvent.IdRemapping> remaps, Collection<ResourceLocation> defaulted, Collection<ResourceLocation> failed, boolean injectNetworkDummies)
|
||||
private static <T> void processMissing(ResourceLocation name, RegistryManager STAGING, MissingMappingsEvent e, Object2IntMap<ResourceLocation> missing, Map<ResourceLocation, IdMappingEvent.IdRemapping> remaps, Collection<ResourceLocation> defaulted, Collection<ResourceLocation> failed, boolean injectNetworkDummies)
|
||||
{
|
||||
List<MissingMappingsEvent.Mapping<T>> mappings = e.getAllMappings(ResourceKey.createRegistryKey(name));
|
||||
ForgeRegistry<T> active = RegistryManager.ACTIVE.getRegistry(name);
|
||||
@@ -764,9 +748,9 @@ public class GameData
|
||||
{
|
||||
ForgeRegistry<T> frozen = RegistryManager.FROZEN.getRegistry(name);
|
||||
ForgeRegistry<T> newRegistry = STAGING.getRegistry(name, RegistryManager.FROZEN);
|
||||
Map<ResourceLocation, Integer> _new = Maps.newLinkedHashMap();
|
||||
Object2IntMap<ResourceLocation> _new = new Object2IntLinkedOpenHashMap<>();
|
||||
frozen.getKeys().stream().filter(key -> !newRegistry.containsKey(key)).forEach(key -> _new.put(key, frozen.getID(key)));
|
||||
newRegistry.loadIds(_new, frozen.getOverrideOwners(), Maps.newLinkedHashMap(), remaps, frozen, name);
|
||||
newRegistry.loadIds(_new, frozen.getOverrideOwners(), new Object2IntLinkedOpenHashMap<>(), remaps, frozen, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -785,11 +769,11 @@ public class GameData
|
||||
String oldPrefix = index == -1 ? "" : name.substring(0, index).toLowerCase(Locale.ROOT);
|
||||
name = index == -1 ? name : name.substring(index + 1);
|
||||
String prefix = ModLoadingContext.get().getActiveNamespace();
|
||||
if (warnOverrides && !oldPrefix.equals(prefix) && oldPrefix.length() > 0)
|
||||
if (warnOverrides && !oldPrefix.equals(prefix) && !oldPrefix.isEmpty())
|
||||
{
|
||||
LogManager.getLogger().debug("Mod `{}` attempting to register `{}` to the namespace `{}`. This could be intended, but likely means an EventBusSubscriber without a modid.", prefix, name, oldPrefix);
|
||||
prefix = oldPrefix;
|
||||
}
|
||||
return new ResourceLocation(prefix, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,19 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class RegistryBuilder<T>
|
||||
{
|
||||
public class RegistryBuilder<T> {
|
||||
public static <T> RegistryBuilder<T> of() {
|
||||
return new RegistryBuilder<T>();
|
||||
}
|
||||
|
||||
public static <T> RegistryBuilder<T> of(String name) {
|
||||
return of(new ResourceLocation(name));
|
||||
}
|
||||
|
||||
public static <T> RegistryBuilder<T> of(ResourceLocation name) {
|
||||
return new RegistryBuilder<T>().setName(name);
|
||||
}
|
||||
|
||||
private static final int MAX_ID = Integer.MAX_VALUE - 1;
|
||||
|
||||
private ResourceLocation registryName;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
modLoader="javafml"
|
||||
loaderVersion="[24,]"
|
||||
issueTrackerURL="http://www.minecraftforge.net/"
|
||||
issueTrackerURL="https://minecraftforge.net/"
|
||||
logoFile="forge_logo.png"
|
||||
license="LGPL v2.1"
|
||||
|
||||
[[mods]]
|
||||
modId="forge"
|
||||
# We use the global forge version
|
||||
version="${global.forgeVersion}"
|
||||
updateJSONURL="https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"
|
||||
displayURL="https://minecraftforge.net/"
|
||||
displayName="Forge"
|
||||
credits="Anyone who has contributed on Github and supports our development"
|
||||
authors="LexManos,cpw"
|
||||
description='''
|
||||
Forge, a broad compatibility API.
|
||||
'''
|
||||
'''
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug;
|
||||
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Test that the mod loading error screen shows the cause of the crash when a mod constructor throws an exception.
|
||||
* <p>Enable or disable this test in the mods.toml</p>
|
||||
*/
|
||||
@Mod("constructor_throw_test")
|
||||
public class ConstructorThrowTest {
|
||||
public ConstructorThrowTest() {
|
||||
throw new RuntimeException("Test");
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,9 @@ modId="mdk_datagen"
|
||||
[[mods]]
|
||||
modId="calculate_normals_test"
|
||||
|
||||
#[[mods]]
|
||||
# modId="constructor_throw_test"
|
||||
|
||||
# LEGACY TEST CASES
|
||||
###### The mods below are from the old test framework and need to be yeeted later again.
|
||||
|
||||
|
||||
Reference in new issue
Block a user