mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01bfc33b28 | ||
|
|
17e1002e86 | ||
|
|
da1b8f4efa | ||
|
|
42bbe44a34 | ||
|
|
f095474adf | ||
|
|
1b5ca64f20 | ||
|
|
b518c804fb | ||
|
|
e50a0ffc6c | ||
|
|
7ea0a41fe2 | ||
|
|
f3d16621c0 | ||
|
|
aa55a6a831 | ||
|
|
3449217c65 | ||
|
|
41609a03d2 | ||
|
|
9b8e5c7109 | ||
|
|
f05ad3afd0 | ||
|
|
6a615f1a4b | ||
|
|
4376cd6b85 | ||
|
|
d17a111dc0 | ||
|
|
1b99b2cea4 | ||
|
|
4ef6695a30 | ||
|
|
0e6341a23e | ||
|
|
17ce723edf | ||
|
|
fc80e30289 | ||
|
|
ecd1491f96 | ||
|
|
8f7fbc76e1 | ||
|
|
ec405958c9 | ||
|
|
e2ff990601 | ||
|
|
8443262e39 | ||
|
|
8e09d47cd6 | ||
|
|
0404d2d776 | ||
|
|
aea804cb6e | ||
|
|
0bffcb83c5 | ||
|
|
9a022d1451 | ||
|
|
58aa3b276c |
No files matched your search
@@ -0,0 +1,28 @@
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '1.21.11' ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: MinecraftForge/SharedActions/.github/workflows/gradle.yml@main
|
||||
with:
|
||||
java: 21
|
||||
gradle_setup: './gradlew setup'
|
||||
gradle_tasks: 'build publish'
|
||||
artifact_name: 'forge'
|
||||
secrets:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
PROMOTE_ARTIFACT_WEBHOOK: ${{ secrets.PROMOTE_ARTIFACT_WEBHOOK }}
|
||||
PROMOTE_ARTIFACT_USERNAME: ${{ secrets.PROMOTE_ARTIFACT_USERNAME }}
|
||||
PROMOTE_ARTIFACT_PASSWORD: ${{ secrets.PROMOTE_ARTIFACT_PASSWORD }}
|
||||
MAVEN_USER: ${{ secrets.MAVEN_USER }}
|
||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
SIGN_KEY_ALIAS: ${{ secrets.SIGN_KEY_ALIAS }}
|
||||
SIGN_KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
|
||||
SIGN_KEYSTORE_PASSWORD: ${{ secrets.SIGN_KEYSTORE_PASSWORD }}
|
||||
SIGN_KEYSTORE_DATA: ${{ secrets.SIGN_KEYSTORE_DATA }}
|
||||
Vendored
-104
@@ -1,104 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<name>MinecraftForge_Forge Config DSL Script</name>
|
||||
<groupId>MinecraftForge_Forge</groupId>
|
||||
<artifactId>MinecraftForge_Forge_dsl</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.jetbrains.teamcity</groupId>
|
||||
<artifactId>configs-dsl-kotlin-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jetbrains-all</id>
|
||||
<url>https://download.jetbrains.com/teamcity-repository</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>teamcity-server</id>
|
||||
<url>https://teamcity.minecraftforge.net/app/dsl-plugins-repository</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>JetBrains</id>
|
||||
<url>https://download.jetbrains.com/teamcity-repository</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>${basedir}</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<version>${kotlin.version}</version>
|
||||
|
||||
<configuration/>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>process-test-sources</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.teamcity</groupId>
|
||||
<artifactId>teamcity-configs-maven-plugin</artifactId>
|
||||
<version>${teamcity.dsl.version}</version>
|
||||
<configuration>
|
||||
<format>kotlin</format>
|
||||
<dstDir>target/generated-configs</dstDir>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.teamcity</groupId>
|
||||
<artifactId>configs-dsl-kotlin</artifactId>
|
||||
<version>${teamcity.dsl.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.teamcity</groupId>
|
||||
<artifactId>configs-dsl-kotlin-plugins</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-script-runtime</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
Vendored
-193
@@ -1,193 +0,0 @@
|
||||
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
||||
import jetbrains.buildServer.configs.kotlin.v2019_2.projectFeatures.githubIssues
|
||||
import jetbrains.buildServer.configs.kotlin.*
|
||||
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
|
||||
|
||||
/*
|
||||
The settings script is an entry point for defining a TeamCity
|
||||
project hierarchy. The script should contain a single call to the
|
||||
project() function with a Project instance or an init function as
|
||||
an argument.
|
||||
|
||||
VcsRoots, BuildTypes, Templates, and subprojects can be
|
||||
registered inside the project using the vcsRoot(), buildType(),
|
||||
template(), and subProject() methods respectively.
|
||||
|
||||
To debug settings scripts in command-line, run the
|
||||
|
||||
mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate
|
||||
|
||||
command and attach your debugger to the port 8000.
|
||||
|
||||
To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View
|
||||
-> Tool Windows -> Maven Projects), find the generate task node
|
||||
(Plugins -> teamcity-configs -> teamcity-configs:generate), the
|
||||
'Debug' option is available in the context menu for the task.
|
||||
*/
|
||||
|
||||
version = "2021.2"
|
||||
|
||||
project {
|
||||
|
||||
buildType(Build)
|
||||
buildType(BuildSecondaryBranches)
|
||||
buildType(PullRequests)
|
||||
buildType(PullRequestChecks)
|
||||
buildType(PullRequestCompatibility)
|
||||
|
||||
params {
|
||||
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.7", 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.21.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*)
|
||||
+:refs/heads/(master*)
|
||||
+:refs/heads/(develop|release|staging|main|master)
|
||||
+:refs/heads/(1.*)
|
||||
""".trimIndent(), label = "The branch specification of the repository", description = "By default all main branches are build by the configuration. Modify this value to adapt the branches build.", display = ParameterDisplay.HIDDEN, allowEmpty = true)
|
||||
text("github_repository_name", "MinecraftForge", label = "The github repository name. Used to connect to it in VCS Roots.", description = "This is the repository slug on github. So for example `MinecraftForge` or `MinecraftForge`. It is interpolated into the global VCS Roots.", display = ParameterDisplay.HIDDEN, allowEmpty = false)
|
||||
text("env.PUBLISHED_JAVA_ARTIFACT_ID", "forge", label = "Published artifact id", description = "The maven coordinate artifact id that has been published by this build. Can not be empty.", allowEmpty = false)
|
||||
text("env.PUBLISHED_JAVA_GROUP", "net.minecraftforge", label = "Published group", description = "The maven coordinate group that has been published by this build. Can not be empty.", allowEmpty = false)
|
||||
//These are references and not actually keys
|
||||
password("env.CROWDIN_KEY", "credentialsJSON:a3102dbe-805d-4177-9f54-3d2c2eb08fd5", display = ParameterDisplay.HIDDEN)
|
||||
password("env.KEYSTORE_URL", "credentialsJSON:a7ae1c82-8058-4061-8d12-7f6bc2618d2e", display = ParameterDisplay.HIDDEN)
|
||||
password("env.KEYSTORE_PASSWORD", "credentialsJSON:d7b964e3-a1fd-47a8-b892-6f601fe47479", display = ParameterDisplay.HIDDEN)
|
||||
text("additional_publishing_gradle_parameters", "-PcrowdinKey=%env.CROWDIN_KEY% -PkeystoreKeyPass=%env.KEYSTORE_PASSWORD% -PkeystoreStorePass=%env.KEYSTORE_PASSWORD% -Pkeystore=%env.KEYSTORE_URL%", label = "Additional gradle parameters for publish", description = "Contains the additional gradle parameters used during publishing.", display = ParameterDisplay.HIDDEN, allowEmpty = true)
|
||||
|
||||
checkbox("should_execute_build", "false", label = "Should build", description = "Indicates if the build task should be executed.", display = ParameterDisplay.HIDDEN,
|
||||
checked = "true", unchecked = "false")
|
||||
checkbox("should_execute_test", "false", label = "Should build", description = "Indicates if the build task should be executed.", display = ParameterDisplay.HIDDEN,
|
||||
checked = "true", unchecked = "false")
|
||||
}
|
||||
|
||||
features {
|
||||
githubIssues {
|
||||
id = "MinecraftForge_MinecraftForge__IssueTracker"
|
||||
displayName = "MinecraftForge/MinecraftForge"
|
||||
repositoryURL = "https://github.com/MinecraftForge/MinecraftForge"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Build : BuildType({
|
||||
templates(AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_BuildMainBranches"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"), AbsoluteId("MinecraftForge_BuildUsingGradle"), AbsoluteId("MinecraftForge_PublishProjectUsingGradle"), AbsoluteId("MinecraftForge_TriggersStaticFilesWebpageGenerator"))
|
||||
id("MinecraftForge_MinecraftForge__Build")
|
||||
name = "Build"
|
||||
description = "Builds and Publishes the main branches of the project."
|
||||
})
|
||||
|
||||
object BuildSecondaryBranches : BuildType({
|
||||
templates(AbsoluteId("MinecraftForge_ExcludesBuildingDefaultBranch"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_BuildMainBranches"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"), AbsoluteId("MinecraftForge_BuildUsingGradle"))
|
||||
id("MinecraftForge_MinecraftForge__BuildSecondaryBranches")
|
||||
name = "Build - Secondary Branches"
|
||||
description = "Builds and Publishes the secondary branches of the project."
|
||||
params {
|
||||
text("git_branch_spec", """
|
||||
+:refs/heads/(*)
|
||||
-:refs/heads/noci*
|
||||
""".trimIndent(), label = "The branch specification of the repository", description = "By default all main branches are build by the configuration. Modify this value to adapt the branches build.", display = ParameterDisplay.HIDDEN, allowEmpty = true)
|
||||
}
|
||||
vcs {
|
||||
branchFilter = """
|
||||
+:*
|
||||
-:1.*
|
||||
-:<default>
|
||||
""".trimIndent()
|
||||
}
|
||||
})
|
||||
|
||||
object PullRequests : BuildType({
|
||||
templates(AbsoluteId("MinecraftForge_BuildPullRequests"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"), AbsoluteId("MinecraftForge_BuildUsingGradle"))
|
||||
id("MinecraftForge_MinecraftForge__PullRequests")
|
||||
name = "Pull Requests"
|
||||
description = "Builds pull requests for the project"
|
||||
|
||||
params {
|
||||
checkbox("should_execute_build", "true", label = "Should build", description = "Indicates if the build task should be executed.", display = ParameterDisplay.HIDDEN,
|
||||
checked = "true", unchecked = "false")
|
||||
text(
|
||||
"gradle_build_task",
|
||||
"assemble",
|
||||
label = "Gradle build task to execute during build",
|
||||
description = "Determines the build task that is executed to build the project.",
|
||||
display = ParameterDisplay.HIDDEN,
|
||||
allowEmpty = false
|
||||
)
|
||||
}
|
||||
|
||||
vcs {
|
||||
branchFilter = """
|
||||
+:*
|
||||
-:1.*
|
||||
-:<default>
|
||||
""".trimIndent()
|
||||
}
|
||||
})
|
||||
|
||||
object PullRequestChecks : BuildType({
|
||||
templates(AbsoluteId("MinecraftForge_BuildPullRequests"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"))
|
||||
id("MinecraftForge_MinecraftForge__PullRequestChecks")
|
||||
name = "Pull Requests (Checks)"
|
||||
description = "Checks pull requests for the project"
|
||||
|
||||
steps {
|
||||
gradle {
|
||||
name = "Check"
|
||||
id = "RUNNER_10_Check"
|
||||
|
||||
tasks = "checkAll"
|
||||
gradleParams = "--continue %gradle_custom_args%"
|
||||
enableStacktrace = true
|
||||
dockerImage = "%docker_gradle_image%"
|
||||
dockerRunParameters = """
|
||||
-v "/opt/cache/agent/gradle:/home/gradle/.gradle"
|
||||
-v "/opt/cache/shared/gradle:/home/gradle/rocache:ro"
|
||||
--network=host
|
||||
-u 1000:1000
|
||||
%docker_additional_args%
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
vcs {
|
||||
branchFilter = """
|
||||
+:*
|
||||
-:1.*
|
||||
-:<default>
|
||||
""".trimIndent()
|
||||
}
|
||||
})
|
||||
|
||||
object PullRequestCompatibility : BuildType({
|
||||
templates(AbsoluteId("MinecraftForge_BuildPullRequests"), AbsoluteId("MinecraftForge_SetupGradleUtilsCiEnvironmen"), AbsoluteId("MinecraftForge_BuildWithDiscordNotifications"), AbsoluteId("MinecraftForge_SetupProjectUsingGradle"))
|
||||
id("MinecraftForge_MinecraftForge__PullRequestCompatibility")
|
||||
name = "Pull Requests (Compatibility)"
|
||||
description = "Validates binary compatibility for pull requests made to the project"
|
||||
|
||||
steps {
|
||||
gradle {
|
||||
name = "Validate"
|
||||
id = "RUNNER_10_Compatibility"
|
||||
|
||||
tasks = "checkJarCompatibility"
|
||||
gradleParams = "--continue %gradle_custom_args%"
|
||||
enableStacktrace = true
|
||||
dockerImage = "%docker_gradle_image%"
|
||||
dockerRunParameters = """
|
||||
-v "/opt/cache/agent/gradle:/home/gradle/.gradle"
|
||||
-v "/opt/cache/shared/gradle:/home/gradle/rocache:ro"
|
||||
--network=host
|
||||
-u 1000:1000
|
||||
%docker_additional_args%
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
vcs {
|
||||
branchFilter = """
|
||||
+:*
|
||||
-:1.*
|
||||
-:<default>
|
||||
""".trimIndent()
|
||||
}
|
||||
})
|
||||
+2
-2
@@ -7,8 +7,8 @@ plugins {
|
||||
id 'net.minecraftforge.gradleutils' version '[2.6.4,2.7)'
|
||||
id 'eclipse'
|
||||
id 'de.undercouch.download' version '5.4.0'
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.22,6.2)' apply false
|
||||
id 'net.minecraftforge.gradle.mcp' version '[6.0.22,6.2)' apply false
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.46,6.2)' apply false
|
||||
id 'net.minecraftforge.gradle.mcp' version '[6.0.46,6.2)' apply false
|
||||
id 'net.minecraftforge.gradlejarsigner' version '1.0.4'
|
||||
id 'org.barfuin.gradle.taskinfo' version '2.1.0'
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ dependencies {
|
||||
implementation 'org.ow2.asm:asm:9.8'
|
||||
implementation 'org.ow2.asm:asm-tree:9.8'
|
||||
implementation 'net.minecraftforge:srgutils:0.5.10'
|
||||
implementation 'net.minecraftforge:JarJarMetadata:0.3.27'
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
implementation 'org.eclipse.jgit:org.eclipse.jgit:6.7.0.202309050840-r'
|
||||
|
||||
@@ -21,6 +21,8 @@ abstract class BundleList extends DefaultTask {
|
||||
configure {
|
||||
dependsOn(project.tasks.universalJar)
|
||||
inputs.file(project.tasks.universalJar.archiveFile)
|
||||
dependsOn(project.tasks.applyServerBinPatches)
|
||||
inputs.file(project.tasks.applyServerBinPatches.output)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.forge.tasks;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedJarIdentifier;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedJarMetadata;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedVersion;
|
||||
import net.minecraftforge.jarjar.metadata.Metadata;
|
||||
import net.minecraftforge.jarjar.metadata.MetadataIOHandler;
|
||||
import net.minecraftforge.jarjar.metadata.json.ArtifactVersionSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.ContainedJarIdentifierSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.ContainedJarMetadataSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.ContainedVersionSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.MetadataSerializer;
|
||||
import net.minecraftforge.jarjar.metadata.json.VersionRangeSerializer;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
||||
import org.apache.maven.artifact.versioning.VersionRange;
|
||||
import org.codehaus.groovy.runtime.InvokerHelper;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency;
|
||||
import org.gradle.api.artifacts.FileCollectionDependency;
|
||||
import org.gradle.api.artifacts.MinimalExternalModuleDependency;
|
||||
import org.gradle.api.artifacts.ModuleDependency;
|
||||
import org.gradle.api.artifacts.ModuleIdentifier;
|
||||
import org.gradle.api.artifacts.ModuleVersionIdentifier;
|
||||
import org.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.gradle.api.file.ProjectLayout;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
// TODO SUPER SUPER SUPER UGLY, CLEAN UP IN FORGEDEV 7
|
||||
@Deprecated(forRemoval = true) // Will be moved to JarJar plugin in ForgeDev 7
|
||||
public abstract class JarJarMetadataOptions extends DefaultTask {
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.registerTypeAdapter(VersionRange.class, new VersionRangeSerializer())
|
||||
.registerTypeAdapter(ArtifactVersion.class, new ArtifactVersionSerializer())
|
||||
.registerTypeAdapter(DefaultArtifactVersion.class, new ArtifactVersionSerializer())
|
||||
.registerTypeAdapter(ContainedJarIdentifier.class, new ContainedJarIdentifierSerializer())
|
||||
.registerTypeAdapter(ContainedJarMetadata.class, new ContainedJarMetadataSerializer())
|
||||
.registerTypeAdapter(ContainedVersion.class, new ContainedVersionSerializer())
|
||||
.registerTypeAdapter(Metadata.class, new MetadataSerializer())
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
protected abstract @Input SetProperty<ResolvedDependencyInfoImpl> getResolvedDependencies();
|
||||
|
||||
protected abstract @OutputFile RegularFileProperty getMetadataFile();
|
||||
|
||||
protected abstract @Inject ProjectLayout getLayout();
|
||||
|
||||
// NOTE: I'm not adding a non-provider version. please just use the version catalog entries for now.
|
||||
public void add(Provider<MinimalExternalModuleDependency> dependency, Action<? super ResolvedDependencyInfo> action) {
|
||||
this.getResolvedDependencies().add(dependency.map(d -> {
|
||||
var ret = ResolvedDependencyInfoImpl.from(this.getProject().getConfigurations(), d);
|
||||
action.execute(ret);
|
||||
return ret;
|
||||
}));
|
||||
}
|
||||
|
||||
@Inject
|
||||
public JarJarMetadataOptions() {
|
||||
this.getMetadataFile().convention(this.getLayout().getBuildDirectory().file(this.getName() + "/options.json"));
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
record ForgeLocaterOptions(String resource, String layer, String id, List<ContainedJarMetadata> deps, ContainedJarMetadata meta, boolean nested) { }
|
||||
|
||||
var resolved = this.getResolvedDependencies().get();
|
||||
var jars = new ArrayList<ForgeLocaterOptions>(resolved.size());
|
||||
for (var dependency : resolved) {
|
||||
var deps = new ArrayList<ContainedJarMetadata>();
|
||||
try (var zip = new ZipFile(dependency.artifact)) {
|
||||
var entry = zip.getEntry("META-INF/jarjar/metadata.json");
|
||||
if (entry != null) {
|
||||
try (var stream = zip.getInputStream(entry)) {
|
||||
var meta = MetadataIOHandler.fromStream(stream).orElse(null);
|
||||
if (meta == null)
|
||||
throw new IllegalStateException("Corrupt metadata.json in " + dependency.artifact.getAbsolutePath());
|
||||
for (var dep : meta.jars())
|
||||
deps.add(new ContainedJarMetadata(dep.identifier(), dep.version(), "", dep.isObfuscated()));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
jars.add(new ForgeLocaterOptions(
|
||||
dependency.resource,
|
||||
dependency.layer,
|
||||
dependency.identifier,
|
||||
deps,
|
||||
new ContainedJarMetadata(
|
||||
new ContainedJarIdentifier(validateGroup(dependency), dependency.module.getName()),
|
||||
new ContainedVersion(null, parseVersion(dependency)),
|
||||
Objects.requireNonNull(dependency.path, "Dependency path is unspecified: " + dependency.asString),
|
||||
false
|
||||
),
|
||||
dependency.nested
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
record Meta(List<ForgeLocaterOptions> options){}
|
||||
|
||||
Files.writeString(
|
||||
this.getMetadataFile().getAsFile().get().toPath(),
|
||||
GSON.toJson(new Meta(jars), Meta.class)
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String validateGroup(ResolvedDependencyInfoImpl dependency) {
|
||||
try {
|
||||
return Objects.requireNonNull(dependency.module.getGroup());
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException("Module dependency has no group: " + dependency.asString, e);
|
||||
}
|
||||
}
|
||||
|
||||
private ArtifactVersion parseVersion(ResolvedDependencyInfoImpl resolved) {
|
||||
try {
|
||||
return VersionRange.createFromVersionSpec(Objects.requireNonNull(resolved.version)).getRecommendedVersion();
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new IllegalArgumentException("Version is invalid for: " + resolved.asString, e);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException("Version is unspecified for: " + resolved.asString, e);
|
||||
}
|
||||
}
|
||||
|
||||
private VersionRange parseVersionRange(ResolvedDependencyInfoImpl dependency) {
|
||||
if (dependency.hasManuallySpecifiedRange) {
|
||||
try {
|
||||
return VersionRange.createFromVersionSpec(dependency.versionRange);
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new IllegalArgumentException("Version is invalid for: " + dependency.asString, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return VersionRange.createFromVersionSpec("[%s,)".formatted(Objects.requireNonNull(dependency.versionRange)));
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new IllegalArgumentException("Version range is invalid for: " + dependency.asString, e);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException("Version is unspecified for: " + dependency.asString, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResolvedDependencyInfo {
|
||||
void containedJarMetadata(Action<? super ContainedJarMetadataInfo> action);
|
||||
|
||||
void setResource(String resource);
|
||||
|
||||
void setLayer(String layer);
|
||||
|
||||
void setId(String identifier);
|
||||
|
||||
void setNested(boolean nested);
|
||||
|
||||
interface ContainedJarMetadataInfo {
|
||||
void setGroup(String group);
|
||||
|
||||
void setName(String name);
|
||||
|
||||
void setPath(String version);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ResolvedDependencyInfoImpl implements ResolvedDependencyInfo, ResolvedDependencyInfo.ContainedJarMetadataInfo, Serializable {
|
||||
private static final @Serial long serialVersionUID = -7577318115877822993L;
|
||||
|
||||
final MinimalModuleVersionIdentifier module;
|
||||
final String version;
|
||||
String versionRange;
|
||||
boolean hasManuallySpecifiedRange;
|
||||
boolean nested;
|
||||
final File artifact;
|
||||
String path;
|
||||
String resource;
|
||||
String layer;
|
||||
String identifier;
|
||||
final String asString;
|
||||
|
||||
public ResolvedDependencyInfoImpl(MinimalModuleVersionIdentifier module, String version, File artifact, String asString) {
|
||||
this.module = module;
|
||||
this.version = version;
|
||||
this.artifact = artifact;
|
||||
this.asString = asString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containedJarMetadata(Action<? super ContainedJarMetadataInfo> action) {
|
||||
action.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroup(String group) {
|
||||
this.module.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.module.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayer(String layer) {
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNested(boolean nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
static Set<File> getFiles(Set<ResolvedDependencyInfoImpl> resolvedDependencies) {
|
||||
var ret = new HashSet<File>(resolvedDependencies.size());
|
||||
for (var dependency : resolvedDependencies) {
|
||||
ret.add(dependency.artifact);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ResolvedDependencyInfoImpl from(ConfigurationContainer configurations, Dependency dependency) {
|
||||
var group = dependency.getGroup();
|
||||
var name = dependency.getName();
|
||||
var version = dependency.getVersion();
|
||||
|
||||
if (dependency instanceof FileCollectionDependency filesDependency) {
|
||||
File artifact;
|
||||
try {
|
||||
artifact = filesDependency.getFiles().getSingleFile();
|
||||
} catch (IllegalStateException e) {
|
||||
// TODO fileCollectionDependencyIsNotSingleFile
|
||||
throw e;
|
||||
}
|
||||
|
||||
return new ResolvedDependencyInfoImpl(
|
||||
new MinimalModuleVersionIdentifier(group, name, version),
|
||||
version,
|
||||
artifact,
|
||||
filesDependency.toString()
|
||||
);
|
||||
} else if (dependency instanceof ModuleDependency moduleDependency) {
|
||||
moduleDependency = moduleDependency.copy();
|
||||
if (moduleDependency instanceof ExternalModuleDependency externalModuleDependency) {
|
||||
externalModuleDependency.version(v -> v.strictly(version.toString()));
|
||||
}
|
||||
|
||||
var detachedConfiguration = configurations.detachedConfiguration(moduleDependency);
|
||||
detachedConfiguration.setTransitive(false);
|
||||
|
||||
ResolvedDependencyInfoImpl ret = null;
|
||||
for (var artifact : detachedConfiguration.getResolvedConfiguration().getFirstLevelModuleDependencies().iterator().next().getModuleArtifacts()) {
|
||||
var fileName = getFileName(artifact);
|
||||
if (!fileName.endsWith(".jar"))
|
||||
continue;
|
||||
|
||||
if (ret != null)
|
||||
throw new IllegalArgumentException("Module dependency has too many Jar artifacts: " + moduleDependency);
|
||||
|
||||
ret = new ResolvedDependencyInfoImpl(
|
||||
new MinimalModuleVersionIdentifier(group, name, artifact.getModuleVersion().getId().getVersion()),
|
||||
version,
|
||||
artifact.getFile(),
|
||||
moduleDependency.toString()
|
||||
);
|
||||
}
|
||||
if (ret == null)
|
||||
throw new IllegalArgumentException("Module dependency has no Jar artifacts: " + moduleDependency);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported dependency type: " + dependency.getClass().getName() + " -- " + dependency);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFileName(ResolvedArtifact artifact) {
|
||||
try {
|
||||
return InvokerHelper.getProperty(artifact.getId(), "fileName").toString();
|
||||
} catch (Throwable e) {
|
||||
// NOTE: Why not just use this to begin with?
|
||||
// ComponentArtifactIdentifier can have a getFileName() method, which doesn't necessarily resolve the file itself.
|
||||
// This allows us to get the name of the file to be used without asking Gradle to download the file.
|
||||
// So, if a file is not a JAR file, we can check the name without actually downloading it.
|
||||
return artifact.getFile().getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||
var that = (ResolvedDependencyInfoImpl) obj;
|
||||
return Objects.equals(this.module, that.module) &&
|
||||
Objects.equals(this.version, that.version) &&
|
||||
Objects.equals(this.versionRange, that.versionRange) &&
|
||||
Objects.equals(this.artifact, that.artifact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(module, version, versionRange, artifact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ResolvedDependencyInfo[" +
|
||||
"module=" + module + ", " +
|
||||
"fixedVersion=" + version + ", " +
|
||||
"versionRange=" + versionRange + ", " +
|
||||
"artifact=" + artifact + ']';
|
||||
}
|
||||
|
||||
static final class MinimalModuleVersionIdentifier implements ModuleIdentifier, ModuleVersionIdentifier {
|
||||
private static final @Serial long serialVersionUID = -955346236759069739L;
|
||||
|
||||
private String group;
|
||||
private String name;
|
||||
private final String version;
|
||||
|
||||
@Inject
|
||||
public MinimalModuleVersionIdentifier(String group, String name, String version) {
|
||||
this.group = group;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleIdentifier getModule() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj || obj instanceof MinimalModuleVersionIdentifier o
|
||||
&& Objects.equals(this.group, o.group)
|
||||
&& Objects.equals(this.name, o.name)
|
||||
&& Objects.equals(this.version, o.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(group, name, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MinimalModuleVersionIdentifier[" +
|
||||
"group=" + group + ", " +
|
||||
"name=" + name + ", " +
|
||||
"version=" + version + ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,6 +113,7 @@ dependencies {
|
||||
// And this is only needed because custom file systems are REQUIRED to be on the boot classloader.
|
||||
// This has ASM/BootStrap/Unsafe all because I haven't gotten around to moving UnionFileSystem out to its own project.
|
||||
bootstrap(libs.jarjar.fs) // JarInJar file system
|
||||
bootstrap(libs.roimfs) // JarInJar File System - FileSystems need to be on boot loader.
|
||||
bootstrap(libs.bundles.jimfs) // In memory file system used for ForgeDev launches
|
||||
bootstrap(libs.securemodules) // Has Union file system in it
|
||||
bootstrap(libs.unsafe) // Needed by securemodules
|
||||
@@ -134,7 +135,9 @@ dependencies {
|
||||
installer(libs.maven.artifact)
|
||||
installer(libs.bundles.terminalconsoleappender)
|
||||
installer(libs.mixin)
|
||||
installer(libs.mixinextras.forge)
|
||||
installer(libs.bundles.jarjar)
|
||||
installer(libs.roimfs)
|
||||
|
||||
installer(project(':fmlcore'))
|
||||
installer(project(':fmlloader'))
|
||||
@@ -299,6 +302,11 @@ tasks.userdevConfig.configure {
|
||||
libraries.add(dep)
|
||||
}
|
||||
|
||||
// TODO [ForgeDev][UserDev] Split API/Runtime elements in userdev config
|
||||
// so we don't gotta keep making exceptions for MixinExtras
|
||||
addCompileDependency(libs.mixinextras.common)
|
||||
addAnnotationProcessorDependency(libs.mixinextras.common)
|
||||
|
||||
inject = '' // We don't have a userdev sourceset anymore. Empty as a gradle workaround...
|
||||
runs {
|
||||
client {
|
||||
|
||||
@@ -38,6 +38,10 @@ tasks.register('generateResources') {
|
||||
dependsOn('writeManifest')
|
||||
}
|
||||
|
||||
tasks.named('processResources') {
|
||||
dependsOn(generateResources)
|
||||
}
|
||||
|
||||
// Make sure out manifests get written before compiling the code, IDEA calls this task if you tell it to use the gradle build.
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
dependsOn 'generateResources'
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
|
||||
MinecraftForge
|
||||
=============
|
||||
[][Download]
|
||||
[][Download]
|
||||
[][Download] [][Discord] [][Patreon]
|
||||
|
||||
Forge is a free, open-source modding API all of your favourite mods use!
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.fml.config.IConfigEvent;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
@@ -157,6 +158,14 @@ public abstract class ModContainer {
|
||||
*/
|
||||
public abstract Object getMod();
|
||||
|
||||
/**
|
||||
* @return the mod bus group for this specific mod, or null if there is none.
|
||||
* Leave null if you use {@link BusGroup#DEFAULT} for your mod lifecycle events.
|
||||
*/
|
||||
public BusGroup getModBusGroup() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept an arbitrary event for processing by the mod. Probably posted to an event bus in the lower level container.
|
||||
* @param e Event to accept
|
||||
|
||||
@@ -41,14 +41,14 @@ public class ModList {
|
||||
private List<ModContainer> sortedContainers;
|
||||
|
||||
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList) {
|
||||
this.modFiles = modFiles.stream().map(ModFile::getModFileInfo).toList();
|
||||
var modFileInfos = this.modFiles = modFiles.stream().map(ModFile::getModFileInfo).toList();
|
||||
this.sortedList = sortedList.stream().map(IModInfo.class::cast).toList();
|
||||
var byId = new HashMap<String, IModFileInfo>();
|
||||
for (var file : this.modFiles) {
|
||||
for (var file : modFileInfos) {
|
||||
for (var mod : file.getMods())
|
||||
byId.put(mod.getModId(), mod.getOwningFile());
|
||||
}
|
||||
this.fileById = Collections.unmodifiableMap(byId);
|
||||
this.fileById = Map.copyOf(byId);
|
||||
CrashReportCallables.registerCrashCallable("Mod List", this::crashReport);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ModList {
|
||||
}
|
||||
|
||||
private String crashReport() {
|
||||
return "\n"+applyForEachModFile(this::fileToLine).collect(Collectors.joining("\n\t\t", "\t\t", ""));
|
||||
return "\n" + applyForEachModFile(this::fileToLine).collect(Collectors.joining("\n\t\t", "\t\t", ""));
|
||||
}
|
||||
|
||||
public static ModList of(List<ModFile> modFiles, List<ModInfo> sortedList) {
|
||||
@@ -126,10 +126,9 @@ public class ModList {
|
||||
map(IModFileInfo::getFile).
|
||||
distinct().
|
||||
map(IModFile::getScanResult).
|
||||
collect(Collectors.toList());
|
||||
toList();
|
||||
}
|
||||
return modFileScanData;
|
||||
|
||||
}
|
||||
|
||||
public void forEachModFile(Consumer<IModFile> fileConsumer) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
@@ -84,20 +85,20 @@ public class ModLoader {
|
||||
private ModList modList;
|
||||
|
||||
private ModLoader() {
|
||||
this.loadingModList = FMLLoader.getLoadingModList();
|
||||
this.loadingExceptions = this.loadingModList.getErrors().stream()
|
||||
var loadingModList = this.loadingModList = FMLLoader.getLoadingModList();
|
||||
var loadingExceptions = this.loadingExceptions = loadingModList.getErrors().stream()
|
||||
.flatMap(ModLoadingException::fromEarlyException)
|
||||
.collect(Collectors.toList());
|
||||
this.loadingWarnings = this.loadingModList.getBrokenFiles().stream()
|
||||
this.loadingWarnings = loadingModList.getBrokenFiles().stream()
|
||||
.map(file -> new ModLoadingWarning(null, ModLoadingStage.VALIDATE, InvalidModIdentifier.identifyJarProblem(file.getFilePath()).orElse("fml.modloading.brokenfile"), file.getFileName()))
|
||||
.collect(Collectors.toList());
|
||||
if (this.loadingExceptions.isEmpty()) {
|
||||
if (loadingExceptions.isEmpty()) {
|
||||
this.erroredModInfos = Collections.emptySet();
|
||||
} else {
|
||||
this.erroredModInfos = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
this.erroredModInfos.addAll(this.loadingExceptions.stream().map(ModLoadingException::getModInfo).toList());
|
||||
this.erroredModInfos.addAll(loadingExceptions.stream().map(ModLoadingException::getModInfo).toList());
|
||||
}
|
||||
this.loadingModList.getModFiles().stream()
|
||||
loadingModList.getModFiles().stream()
|
||||
.filter(ModFileInfo::missingLicense)
|
||||
.filter(modFileInfo -> modFileInfo.getMods().stream().noneMatch(this.erroredModInfos::contains)) //Ignore files where any other mod already encountered an error
|
||||
.map(modFileInfo -> new ModLoadingException(null, ModLoadingStage.VALIDATE, "fml.modloading.missinglicense", null, modFileInfo.getFile()))
|
||||
@@ -112,16 +113,16 @@ public class ModLoader {
|
||||
|
||||
private static String computeLanguageList() {
|
||||
return "\n" + FMLLoader.getLanguageLoadingProvider()
|
||||
.applyForEach(lp -> lp.name() + "@" + lp.getClass().getPackage().getImplementationVersion())
|
||||
.applyForEach(lp -> lp.name() + '@' + lp.getClass().getPackage().getImplementationVersion())
|
||||
.collect(Collectors.joining("\n\t\t", "\t\t", ""));
|
||||
}
|
||||
|
||||
private static String computeModLauncherServiceList() {
|
||||
final List<Map<String, String>> mods = FMLLoader.modLauncherModList();
|
||||
return "\n"+mods.stream().map(mod->mod.getOrDefault("file","nofile")+
|
||||
" "+mod.getOrDefault("name", "missing")+
|
||||
" "+mod.getOrDefault("type","NOTYPE")+
|
||||
" "+mod.getOrDefault("description", "")).
|
||||
return "\n" + mods.stream().map(mod -> mod.getOrDefault("file","nofile") +
|
||||
' ' + mod.getOrDefault("name", "missing") +
|
||||
' ' + mod.getOrDefault("type","NOTYPE") +
|
||||
' ' + mod.getOrDefault("description", "")).
|
||||
collect(Collectors.joining("\n\t\t","\t\t",""));
|
||||
}
|
||||
|
||||
@@ -232,7 +233,19 @@ public class ModLoader {
|
||||
for (IModLoadingState mls : stateList) {
|
||||
dispatchAndHandleError(mls, syncExecutor, parallelExecutor, periodicTask, progress);
|
||||
}
|
||||
statusConsumer.accept(String.format("Mod loading complete - %d mods loaded", this.modList.size()));
|
||||
|
||||
var modBusGroups = Set.of(
|
||||
modList.getLoadedMods().stream()
|
||||
.map(ModContainer::getModBusGroup)
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(BusGroup[]::new)
|
||||
);
|
||||
for (var modBusGroup : modBusGroups) {
|
||||
parallelExecutor.execute(modBusGroup::trim);
|
||||
}
|
||||
parallelExecutor.execute(BusGroup.DEFAULT::trim);
|
||||
|
||||
statusConsumer.accept("Mod loading complete - %d mods loaded".formatted(this.modList.size()));
|
||||
progress.complete();
|
||||
}
|
||||
|
||||
@@ -254,7 +267,7 @@ public class ModLoader {
|
||||
}
|
||||
|
||||
private void handleInlineTransition(final Consumer<ModList> transition, final IModLoadingState state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker) {
|
||||
var pb = StartupMessageManager.addProgressBar("State transition " +state.name()+" running", 0);
|
||||
var pb = StartupMessageManager.addProgressBar("State transition " + state.name() + " running", 0);
|
||||
syncExecutor.drive(ticker);
|
||||
transition.accept(this.modList);
|
||||
syncExecutor.drive(ticker);
|
||||
@@ -353,11 +366,17 @@ public class ModLoader {
|
||||
return loadingStateValid;
|
||||
}
|
||||
|
||||
/** @deprecated Use {@link #hasCompletedState(IModLoadingState)} instead */
|
||||
@Deprecated(forRemoval = true)
|
||||
public boolean hasCompletedState(final String stateName) {
|
||||
IModLoadingState state = stateManager.findState(stateName);
|
||||
return completedStates.contains(state);
|
||||
}
|
||||
|
||||
public boolean hasCompletedState(IModLoadingState state) {
|
||||
return completedStates.contains(state);
|
||||
}
|
||||
|
||||
public static <T extends IModBusEvent> void runEventGenerator(Function<ModContainer, T> generator) {
|
||||
if (!loadingStateValid) {
|
||||
LOGGER.error("Cowardly refusing to send event generator to a broken mod state");
|
||||
|
||||
@@ -19,7 +19,13 @@ public class ModLoadingContext {
|
||||
private Object languageExtension;
|
||||
|
||||
/**
|
||||
* @deprecated Use the context provided by your language loader in your mod's constructor
|
||||
* @deprecated Use the context provided by your language loader in your mod's constructor. Example for Java mods: {@snippet :
|
||||
* @Mod("examplemod")
|
||||
* public final class ExampleMod {
|
||||
* public ExampleMod(FMLJavaModLoadingContext context) {
|
||||
* // Use context from the param instead of FMLJavaModLoadingContext.get() or ModLoadingContext.get()
|
||||
* }
|
||||
* }}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since="1.21.1")
|
||||
public static ModLoadingContext get() {
|
||||
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.fml;
|
||||
|
||||
import net.minecraftforge.fml.loading.progress.ProgressMeter;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -59,7 +60,7 @@ public record ModLoadingState(
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
public static ModLoadingState empty(final String name, final String previous, final ModLoadingPhase phase) {
|
||||
return of(name, phase).after(previous).empty();
|
||||
return new ModLoadingState(name, previous, ml -> "", ml -> 0, phase, Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,6 +121,22 @@ public record ModLoadingState(
|
||||
return new Builder(name, phase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof ModLoadingState that
|
||||
&& this.phase == that.phase
|
||||
&& this.name.equals(that.name)
|
||||
&& Objects.equals(this.previous, that.previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = phase.hashCode();
|
||||
result = 31 * result + name.hashCode();
|
||||
result = 31 * result + Objects.hashCode(previous);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final String name;
|
||||
private final ModLoadingPhase phase;
|
||||
|
||||
@@ -41,11 +41,13 @@ public class ModStateManager {
|
||||
}
|
||||
|
||||
public IModLoadingState findState(final String stateName) {
|
||||
return stateMap.values()
|
||||
var result = stateMap.values()
|
||||
.stream()
|
||||
.flatMap(List::stream)
|
||||
.filter(mls -> mls.name().equals(stateName))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Unknown IModLoadingState: " + stateName));
|
||||
.orElse(null);
|
||||
if (result != null) return result;
|
||||
else throw new IllegalArgumentException("Unknown IModLoadingState: " + stateName);
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,22 @@ package net.minecraftforge.fml.event;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.InheritableEvent;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
/**
|
||||
* Marker interface for events dispatched on the ModLifecycle event bus instead of the primary event bus
|
||||
* Marker interface for mod lifecycle events dispatched on the
|
||||
* {@linkplain net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext#getModBusGroup() mod BusGroup} instead
|
||||
* of the {@linkplain BusGroup#DEFAULT default BusGroup}.
|
||||
*
|
||||
* @apiNote Each mod gets its own unique mod BusGroup instance, obtained from the mod loading context. Most events
|
||||
* should go on the default BusGroup.
|
||||
*/
|
||||
public interface IModBusEvent extends InheritableEvent {
|
||||
/**
|
||||
* @param modEventBusGroup Obtained from {@link net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext#getModBusGroup()} or your language provider's equivalent.
|
||||
* @param eventClass The event type you want to get the associated bus for.
|
||||
*/
|
||||
static <T extends IModBusEvent> EventBus<T> getBus(BusGroup modEventBusGroup, Class<T> eventClass) {
|
||||
static <T extends IModBusEvent> @NonNull EventBus<@NonNull T> getBus(@NonNull BusGroup modEventBusGroup, @NonNull Class<T> eventClass) {
|
||||
// Do not copy! Temporary solution until the FML rewrite is complete. May throw in future
|
||||
// without prior notice.
|
||||
//
|
||||
|
||||
@@ -7,8 +7,11 @@ package net.minecraftforge.fml.util.thread;
|
||||
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
|
||||
public class EffectiveSide
|
||||
{
|
||||
/**
|
||||
* Attempts to determine the effect side of the current thread, based on know threads in networking.
|
||||
* This is not guaranteed to be correct, and modders should use other methods to determine the logical side when possible.
|
||||
*/
|
||||
public class EffectiveSide {
|
||||
public static LogicalSide get() {
|
||||
final ThreadGroup group = Thread.currentThread().getThreadGroup();
|
||||
return group instanceof SidedThreadGroup ? ((SidedThreadGroup) group).getSide() : LogicalSide.CLIENT;
|
||||
|
||||
@@ -7,11 +7,13 @@ package net.minecraftforge.fml.util.thread;
|
||||
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
|
||||
public final class SidedThreadGroups
|
||||
{
|
||||
public final class SidedThreadGroups {
|
||||
public static final SidedThreadGroup CLIENT = new SidedThreadGroup(LogicalSide.CLIENT);
|
||||
public static final SidedThreadGroup SERVER = new SidedThreadGroup(LogicalSide.SERVER);
|
||||
|
||||
private SidedThreadGroups() {
|
||||
public static SidedThreadGroup get(boolean client) {
|
||||
return client ? CLIENT : SERVER;
|
||||
}
|
||||
|
||||
private SidedThreadGroups() { }
|
||||
}
|
||||
@@ -36,6 +36,7 @@ dependencies {
|
||||
implementation(libs.accesstransformers)
|
||||
implementation(libs.terminalconsoleappender)
|
||||
implementation(libs.jimfs)
|
||||
implementation(libs.roimfs)
|
||||
|
||||
// Needed because we have a custom log4j plugin, and they removed package scanning and require a data file to be generated
|
||||
implementation(libs.log4j.core)
|
||||
@@ -103,11 +104,31 @@ tasks.register('writeForgeVersionJson') {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('jarJarOptionsJson', net.minecraftforge.forge.tasks.JarJarMetadataOptions) {
|
||||
metadataFile = project.file('src/main/resources/jarjar_options.json')
|
||||
// This is resolved too early by cpw.mods.modlauncher.TransformationServicesHandler.discoverServices(DiscoveryData) But eventually...
|
||||
//add(libs.mixin, 'org/spongepowered/asm/mixin/Mixin.class')
|
||||
add(libs.mixinextras.forge) {
|
||||
containedJarMetadata {
|
||||
path = ''
|
||||
}
|
||||
resource = 'com/llamalad7/mixinextras/platform/forge/MixinExtrasConfigPlugin.class'
|
||||
layer = 'GAMELIBRARY'
|
||||
id = 'mixinextras'
|
||||
nested = true
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('generateResources').configure {
|
||||
dependsOn('eclipseJdt')
|
||||
dependsOn('eclipseJdtApt')
|
||||
dependsOn('eclipseFactorypath')
|
||||
dependsOn('writeForgeVersionJson')
|
||||
dependsOn('jarJarOptionsJson')
|
||||
}
|
||||
|
||||
tasks.named('sourcesJar') {
|
||||
dependsOn('jarJarOptionsJson')
|
||||
}
|
||||
|
||||
eclipse {
|
||||
|
||||
+7
-9
@@ -34,11 +34,10 @@ import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
|
||||
* }</code>
|
||||
* </pre>
|
||||
*/
|
||||
public class CapabilityTokenSubclass implements ILaunchPluginService {
|
||||
|
||||
public final class CapabilityTokenSubclass implements ILaunchPluginService {
|
||||
private static final String FUNC_NAME = "getType";
|
||||
private static final String FUNC_DESC = "()Ljava/lang/String;";
|
||||
private static final String CAP_INJECT = "net/minecraftforge/common/capabilities/CapabilityToken"; //Don't directly reference this to prevent class loading.
|
||||
private static final String CAP_INJECT = "net/minecraftforge/common/capabilities/CapabilityToken"; // Don't directly reference this to prevent class loading.
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
@@ -56,8 +55,11 @@ public class CapabilityTokenSubclass implements ILaunchPluginService {
|
||||
String internalName = classType.getInternalName();
|
||||
if (internalName.startsWith("net/minecraft/") || internalName.startsWith("com/mojang/"))
|
||||
return NAY;
|
||||
|
||||
if (internalName.startsWith("net/minecraftforge/common/capabilities/"))
|
||||
return YAY;
|
||||
|
||||
return YAY;
|
||||
return internalName.contains("$") ? YAY : NAY; // Anonymous subclasses only
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +72,7 @@ public class CapabilityTokenSubclass implements ILaunchPluginService {
|
||||
}
|
||||
return ComputeFlags.SIMPLE_REWRITE;
|
||||
} else if (CAP_INJECT.equals(classNode.superName)) {
|
||||
Holder cls = new Holder();
|
||||
var cls = new Object() { String value = null; };
|
||||
|
||||
SignatureReader reader = new SignatureReader(classNode.signature); // Having a node version of this would probably be useful.
|
||||
reader.accept(new SignatureVisitor(Opcodes.ASM9) {
|
||||
@@ -106,8 +108,4 @@ public class CapabilityTokenSubclass implements ILaunchPluginService {
|
||||
return ComputeFlags.NO_REWRITE;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Holder {
|
||||
String value;
|
||||
}
|
||||
}
|
||||
@@ -146,9 +146,8 @@ public class FMLLoader {
|
||||
}
|
||||
|
||||
public static List<ITransformationService.Resource> beginModScan(final Map<String,?> arguments) {
|
||||
LOGGER.debug(SCAN,"Scanning for Mod Locators");
|
||||
var modDiscoverer = new ModDiscoverer(arguments);
|
||||
modValidator = modDiscoverer.discoverMods();
|
||||
LOGGER.debug(SCAN, "Scanning for Mod Locators");
|
||||
modValidator = ModDiscoverer.discoverMods(arguments);
|
||||
var pluginResources = modValidator.getPluginResources();
|
||||
return List.of(pluginResources);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,7 @@ public class LoadingModList {
|
||||
.map(ModFile::getModFileInfo)
|
||||
.map(ModFileInfo.class::cast)
|
||||
.toList();
|
||||
this.sortedList = sortedList.stream()
|
||||
.map(ModInfo.class::cast)
|
||||
.toList();
|
||||
this.sortedList = sortedList.stream().toList();
|
||||
this.fileById = this.modFiles.stream()
|
||||
.map(ModFileInfo::getMods)
|
||||
.flatMap(Collection::stream)
|
||||
|
||||
+13
@@ -7,8 +7,10 @@ package net.minecraftforge.fml.loading;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import cpw.mods.modlauncher.api.NamedPath;
|
||||
import cpw.mods.modlauncher.api.TypesafeMap;
|
||||
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -40,6 +42,17 @@ public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService
|
||||
|
||||
@Override
|
||||
public void earlyInitialization(final String launchTarget, final String[] arguments) {
|
||||
boolean isMixinEnabledInDev = false;
|
||||
for (String arg : arguments) {
|
||||
if (arg.startsWith("-mixin") || arg.startsWith("--mixin")) {
|
||||
isMixinEnabledInDev = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Launcher.INSTANCE.blackboard().putIfAbsent(
|
||||
TypesafeMap.Key.getOrCreate(Launcher.INSTANCE.blackboard(), "isMixinEnabledInDev", Boolean.class),
|
||||
isMixinEnabledInDev
|
||||
);
|
||||
ImmediateWindowHandler.load(launchTarget, arguments);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ModSorter {
|
||||
List<ModFile> modFiles;
|
||||
|
||||
try {
|
||||
modFiles = new UniqueModListBuilder(mods).buildUniqueList().modFiles();
|
||||
modFiles = UniqueModListBuilder.buildUniqueList(mods).modFiles();
|
||||
} catch (EarlyLoadingException e) {
|
||||
// We cannot build any list with duped mods. We have to abort immediately and report it
|
||||
// Note this will never actually throw an error because the duplicate checks are done in ModDiscovererer before we get to this phase
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
public class RuntimeDistCleaner implements ILaunchPluginService {
|
||||
public final class RuntimeDistCleaner implements ILaunchPluginService {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Marker DISTXFORM = MarkerFactory.getMarker("DISTXFORM");
|
||||
private static String DIST;
|
||||
@@ -52,6 +52,10 @@ public class RuntimeDistCleaner implements ILaunchPluginService {
|
||||
if (internalName.startsWith("net/minecraftforge/"))
|
||||
return NAY;
|
||||
|
||||
// No Vanilla classes use @OnlyIn(Dist.SERVER), so we can skip them entirely when we're running on a client
|
||||
if (FMLEnvironment.dist.isClient() && (internalName.startsWith("net/minecraft/") || internalName.startsWith("com/mojang/")))
|
||||
return NAY;
|
||||
|
||||
return YAY;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@ import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
@@ -26,19 +24,12 @@ import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(since = "1.21.3", forRemoval = true) // TODO: [FML][Loading] Convert to package private in 1.22
|
||||
public class UniqueModListBuilder {
|
||||
private final static Logger LOGGER = LogUtils.getLogger();
|
||||
public final class UniqueModListBuilder {
|
||||
private UniqueModListBuilder() {}
|
||||
|
||||
private final List<ModFile> modFiles;
|
||||
|
||||
public UniqueModListBuilder(final List<ModFile> modFiles) {
|
||||
this.modFiles = modFiles;
|
||||
}
|
||||
|
||||
public UniqueModListData buildUniqueList() {
|
||||
List<ModFile> uniqueModList;
|
||||
List<ModFile> uniqueLibListWithVersion;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static UniqueModListData buildUniqueList(List<ModFile> modFiles) {
|
||||
// Collect mod files by module name. This will be used for deduping purposes
|
||||
final Map<String, List<ModFile>> modFilesByFirstId = modFiles.stream()
|
||||
.filter(mf -> mf.getModFileInfo() != null)
|
||||
@@ -49,12 +40,12 @@ public class UniqueModListBuilder {
|
||||
.collect(groupingBy(UniqueModListBuilder::getModId));
|
||||
|
||||
// Select the newest by artifact version sorting of non-unique files thus identified
|
||||
uniqueModList = modFilesByFirstId.entrySet().stream()
|
||||
final List<ModFile> uniqueModList = modFilesByFirstId.entrySet().stream()
|
||||
.map(UniqueModListBuilder::selectNewestModInfo)
|
||||
.toList();
|
||||
|
||||
// Select the newest by artifact version sorting of non-unique files thus identified
|
||||
uniqueLibListWithVersion = libFilesWithVersionByModuleName.entrySet().stream()
|
||||
final List<ModFile> uniqueLibListWithVersion = libFilesWithVersionByModuleName.entrySet().stream()
|
||||
.map(UniqueModListBuilder::selectNewestModInfo)
|
||||
.toList();
|
||||
|
||||
@@ -66,12 +57,10 @@ public class UniqueModListBuilder {
|
||||
.collect(groupingBy(IModInfo::getModId));
|
||||
|
||||
// Transform to the full lib id list
|
||||
final Map<String, List<ModFile>> versionedLibIds = uniqueLibListWithVersion.stream()
|
||||
final List<List<ModFile>> versionedLibs = uniqueLibListWithVersion.stream()
|
||||
.map(UniqueModListBuilder::getModId)
|
||||
.collect(Collectors.toMap(
|
||||
Function.identity(),
|
||||
libFilesWithVersionByModuleName::get
|
||||
));
|
||||
.map(libFilesWithVersionByModuleName::get)
|
||||
.toList();
|
||||
|
||||
// Its theoretically possible that some mod has somehow moved an id to a secondary place, thus causing a dupe.
|
||||
// We can't handle this
|
||||
@@ -84,24 +73,24 @@ public class UniqueModListBuilder {
|
||||
)).toList();
|
||||
|
||||
if (!dupedModErrors.isEmpty()) {
|
||||
LOGGER.error(LOADING, "Found duplicate mods:\n{}", dupedModErrors.stream().collect(joining("\n")));
|
||||
LOGGER.error(LOADING, "Found duplicate mods:\n{}", String.join("\n", dupedModErrors));
|
||||
throw new EarlyLoadingException("Duplicate mods found", null, dupedModErrors.stream()
|
||||
.map(s -> new EarlyLoadingException.ExceptionData(s))
|
||||
.map(EarlyLoadingException.ExceptionData::new)
|
||||
.toList());
|
||||
}
|
||||
|
||||
|
||||
final List<String> dupedLibErrors = versionedLibIds.values().stream()
|
||||
.filter(modFiles -> modFiles.size() > 1)
|
||||
final List<String> dupedLibErrors = versionedLibs.stream()
|
||||
.filter(libModFiles -> libModFiles.size() > 1)
|
||||
.map(mods -> String.format("\tLibrary: '%s' from files: %s",
|
||||
getModId(mods.getFirst()),
|
||||
mods.stream().map(ModFile::getFileName).collect(joining(", "))
|
||||
)).toList();
|
||||
|
||||
if (!dupedLibErrors.isEmpty()) {
|
||||
LOGGER.error(LOADING, "Found duplicate plugins or libraries:\n{}", dupedLibErrors.stream().collect(joining("\n")));
|
||||
LOGGER.error(LOADING, "Found duplicate plugins or libraries:\n{}", String.join("\n", dupedLibErrors));
|
||||
throw new EarlyLoadingException("Duplicate plugins or libraries found", null, dupedLibErrors.stream()
|
||||
.map(s -> new EarlyLoadingException.ExceptionData(s))
|
||||
.map(EarlyLoadingException.ExceptionData::new)
|
||||
.toList());
|
||||
}
|
||||
|
||||
@@ -122,7 +111,7 @@ public class UniqueModListBuilder {
|
||||
modInfoList.sort(Comparator.comparing(UniqueModListBuilder::getVersion).reversed());
|
||||
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.getFirst().getFileName(), fullList.getKey(), getVersion(modInfoList.getFirst()));
|
||||
}
|
||||
return modInfoList.get(0);
|
||||
return modInfoList.getFirst();
|
||||
}
|
||||
|
||||
private static ArtifactVersion getVersion(final ModFile mf) {
|
||||
@@ -130,7 +119,7 @@ public class UniqueModListBuilder {
|
||||
return mf.getJarVersion();
|
||||
}
|
||||
|
||||
return mf.getModInfos().get(0).getVersion();
|
||||
return mf.getModInfos().getFirst().getVersion();
|
||||
}
|
||||
|
||||
private static String getModId(ModFile modFile) {
|
||||
@@ -138,7 +127,7 @@ public class UniqueModListBuilder {
|
||||
return modFile.getSecureJar().name();
|
||||
}
|
||||
|
||||
return modFile.getModFileInfo().getMods().get(0).getModId();
|
||||
return modFile.getModFileInfo().getMods().getFirst().getModId();
|
||||
}
|
||||
|
||||
public record UniqueModListData(List<ModFile> modFiles, Map<String, List<ModFile>> modFilesByFirstId) {}
|
||||
|
||||
+15
-5
@@ -54,12 +54,16 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
|
||||
@Nullable
|
||||
protected IModLocator.ModFileOrException createMod(Path path, boolean ignoreUnknown, String defaultType) {
|
||||
var debug = path.toString();
|
||||
if (debug.equals("/"))
|
||||
debug = path.toUri().toString();
|
||||
|
||||
var mjm = new ModJarMetadata();
|
||||
SecureJar sj = null;
|
||||
try {
|
||||
sj = SecureJar.from(jar -> loadMetaFromJar(jar, mjm), path);
|
||||
} catch (Throwable t) {
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Failed to create secure jar for \"" + path + "\" - " + t.getMessage()));
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Failed to create secure jar for \"" + debug + "\" - " + t.getMessage()));
|
||||
}
|
||||
|
||||
IModFile mod;
|
||||
@@ -68,7 +72,7 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
type = defaultType;
|
||||
|
||||
if (sj.moduleDataProvider().findFile(MODS_TOML).isPresent()) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MODS_TOML, type, path);
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MODS_TOML, type, debug);
|
||||
mod = new ModFile(sj, this, ModFileParser::modsTomlParser);
|
||||
// ModJarMetadata is only used when loading mods.toml mods as ModJarMetadata
|
||||
mjm.setModFile(mod);
|
||||
@@ -77,17 +81,17 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("File \"%s\" is not a Forge mod and cannot be loaded. Look for a Forge version of this mod or consider alternative mods.".formatted(mod.getFileName())));
|
||||
}
|
||||
} else if (type != null) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", JarFile.MANIFEST_NAME, type, path);
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", JarFile.MANIFEST_NAME, type, debug);
|
||||
mod = new ModFile(sj, this, this::manifestParser, type);
|
||||
} else if (ignoreUnknown) {
|
||||
return null;
|
||||
} else
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Invalid mod file found " + path));
|
||||
return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Invalid mod file found " + debug));
|
||||
|
||||
return new IModLocator.ModFileOrException(mod, null);
|
||||
}
|
||||
|
||||
private static JarMetadata loadMetaFromJar(SecureJar jar, ModJarMetadata mjm) {
|
||||
protected static JarMetadata loadMetaFromJar(SecureJar jar, ModJarMetadata mjm) {
|
||||
var info = jar.moduleDataProvider().open(MODULE_INFO).orElse(null);
|
||||
if (info != null) {
|
||||
try {
|
||||
@@ -145,6 +149,12 @@ public abstract class AbstractModProvider implements IModProvider {
|
||||
public <T> Optional<T> getConfigElement(String... key) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends IConfigurable> getConfigList(String key) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends IConfigurable> getConfigList(String... key) {
|
||||
return Collections.emptyList();
|
||||
|
||||
+3
-2
@@ -74,7 +74,8 @@ public final class ClasspathLocator extends AbstractModProvider implements IModL
|
||||
var ret = new ArrayList<ModFileOrException>();
|
||||
for (var path : claimed) {
|
||||
// Filter out anything found by the ServiceLoader
|
||||
if (!ModDirTransformerDiscoverer.isServiceProvider(path))
|
||||
if (!ModDirTransformerDiscoverer.isServiceProvider(path)
|
||||
&& !JarInJarDependencyLocator.isOption(path))
|
||||
ret.add(createMod(path));
|
||||
}
|
||||
return ret;
|
||||
@@ -107,7 +108,7 @@ public final class ClasspathLocator extends AbstractModProvider implements IModL
|
||||
return Path.of(URI.create(str));
|
||||
}
|
||||
|
||||
private static Path getPathFromResource(ClassLoader cl, String resource) {
|
||||
static Path getPathFromResource(ClassLoader cl, String resource) {
|
||||
var url = cl.getResource(resource);
|
||||
if (url == null)
|
||||
return null;
|
||||
|
||||
+621
-102
@@ -5,22 +5,39 @@
|
||||
|
||||
package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||
import com.electronwill.nightconfig.core.file.FileConfig;
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
import cpw.mods.modlauncher.api.TypesafeMap;
|
||||
import net.minecraftforge.fml.loading.EarlyLoadingException;
|
||||
import net.minecraftforge.fml.loading.EarlyLoadingException.ExceptionData;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.locating.IDependencyLocator;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.forgespi.locating.ModFileLoadingException;
|
||||
import net.minecraftforge.forgespi.locating.IModFile.Type;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedJarIdentifier;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedJarMetadata;
|
||||
import net.minecraftforge.jarjar.metadata.ContainedVersion;
|
||||
import net.minecraftforge.jarjar.metadata.MetadataIOHandler;
|
||||
import net.minecraftforge.jarjar.selection.JarSelector;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
|
||||
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
||||
import org.apache.maven.artifact.versioning.VersionRange;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
@@ -28,14 +45,20 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.TreeMap;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class JarInJarDependencyLocator extends AbstractModProvider implements IDependencyLocator {
|
||||
private static final String ROIMFS = "roimfs";
|
||||
private static final String COLOR_CODE = "\u00a7";
|
||||
private static final String RESET = COLOR_CODE + "r";
|
||||
private static final String YELLOW = COLOR_CODE + "e";
|
||||
@@ -43,32 +66,238 @@ public class JarInJarDependencyLocator extends AbstractModProvider implements ID
|
||||
private static final String GREEN = COLOR_CODE + "2";
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Marker MARKER = MarkerFactory.getMarker("JAR-JAR"); // LogMarkers.SCAN;
|
||||
|
||||
private static final Map<Path, Option> OPTIONS = new HashMap<>();
|
||||
private static volatile boolean optionsLoaded = false;
|
||||
|
||||
private static final Attributes.Name MIXIN_CONFIGS_ATTR = new Attributes.Name("MixinConfigs");
|
||||
private static final Attributes.Name MIXIN_CONNECTOR_ATTR = new Attributes.Name("MixinConnector");
|
||||
private static final ContainedJarMetadata MIXIN_EXTRAS_DEPENDENCY = makeMixinExtraDependency();
|
||||
|
||||
private static ContainedJarMetadata makeMixinExtraDependency() {
|
||||
VersionRange range = null;
|
||||
try {
|
||||
range = VersionRange.createFromVersionSpec("[0,)");
|
||||
} catch (InvalidVersionSpecificationException e) {
|
||||
throw new RuntimeException("Failed to create version range for mixinextras-forge dependency", e);
|
||||
}
|
||||
|
||||
return new ContainedJarMetadata(
|
||||
new ContainedJarIdentifier("io.github.llamalad7", "mixinextras-forge"),
|
||||
new ContainedVersion(range, null),
|
||||
null, false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "JarInJar";
|
||||
}
|
||||
|
||||
private int fsID = 0;
|
||||
private synchronized int nextId() {
|
||||
return fsID++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IModFile> scanMods(Iterable<IModFile> loadedMods) {
|
||||
final List<IModFile> sources = new ArrayList<>();
|
||||
loadedMods.forEach(sources::add);
|
||||
var mods = new ArrayList<IModFile>();
|
||||
loadedMods.forEach(mods::add);
|
||||
|
||||
var dependenciesToLoad = JarSelector.detectAndSelect(
|
||||
sources,
|
||||
this::loadResourceFromModFile,
|
||||
this::loadModFileFrom,
|
||||
this::identifyMod,
|
||||
this::exception
|
||||
);
|
||||
var selector = new Selector(mods);
|
||||
|
||||
if (dependenciesToLoad.isEmpty()) {
|
||||
// Add a synthetic Mixin-Extras dependency if we detect anyone using Mixin
|
||||
if (anyMixinsLoaded(mods)) {
|
||||
if (!selector.isRequired(MIXIN_EXTRAS_DEPENDENCY.identifier()))
|
||||
selector.addRequirement(MIXIN_EXTRAS_DEPENDENCY);
|
||||
} else if (selector.entries.size() == mods.size()) {
|
||||
LOGGER.info("No dependencies to load found. Skipping!");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
LOGGER.info("Found {} dependencies adding them to mods collection", dependenciesToLoad.size());
|
||||
return dependenciesToLoad;
|
||||
loadOptions();
|
||||
|
||||
// Ideally, the json would be in order so we only have to loop once. But its written this way just in case.
|
||||
var seen = new HashSet<Option>();
|
||||
var added = false;
|
||||
do {
|
||||
added = false;
|
||||
for (var entry : OPTIONS.values()) {
|
||||
if (seen.contains(entry) || !selector.isRequired(entry.meta.identifier()))
|
||||
continue;
|
||||
|
||||
seen.add(entry);
|
||||
|
||||
entry.addTo(selector);
|
||||
|
||||
if (entry.deps != null && !entry.deps.isEmpty()) {
|
||||
added = true;
|
||||
for (var dep : entry.deps)
|
||||
selector.addRequirement(dep);
|
||||
}
|
||||
}
|
||||
} while (added);
|
||||
|
||||
var selected = selector.select();
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
var ids = new TreeMap<String, List<Entry>>();
|
||||
for (var entry : selector.entries.values()) {
|
||||
if (entry != FAILED && entry.coord != null)
|
||||
ids.computeIfAbsent(entry.coord, id -> new ArrayList<>()).add(entry);
|
||||
}
|
||||
|
||||
for (var entry : ids.entrySet()) {
|
||||
LOGGER.info(MARKER, "JarJar Candidated for {}", entry.getKey());
|
||||
Collections.sort(entry.getValue());
|
||||
for (var option : entry.getValue())
|
||||
LOGGER.info(MARKER, "\t{}{}", selected.contains(option) ? '*' : ' ', option);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected.isEmpty()) {
|
||||
LOGGER.info("No dependencies to load found. Skipping!");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/* Since Java 11, the JRE decompresses all zip files to memory when getting a ByteChannel for them.
|
||||
* JarJar only targets Minecraft 1.18+ which is Java17+ Which means we can exploit the fact that
|
||||
* these are Disjointed file systems, and close all unselected libraries.
|
||||
*
|
||||
* https://github.com/openjdk/jdk11u/blob/25a9b9e5594e88c9e1e66f95c7ca45d5a9da8854/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java#L703
|
||||
*
|
||||
* Combined with the fact that the JarJarFileSystem has always simply called into FileSystems.newFileSystem for its wrapped targets.
|
||||
* https://github.com/MinecraftForge/JarJar/blame/b39b2051439c81519d826d38898778bf3081356f/src/main/java/net/minecraftforge/jarjar/nio/pathfs/PathFileSystem.java#L38
|
||||
*
|
||||
* This effectively means that JarJar has ALWAYS been a wrapper around in-memory copies of every jar it scans.
|
||||
*
|
||||
* It also never closes these FileSystems, which potentially means they are leaked if the GC can't inherently GC them.
|
||||
*
|
||||
* Ideally we would extract these contained jars to a temp folder, so that we can use the nice optimizations Java has for ZipFile/JarFile.
|
||||
* But in order to do that we would need to write the file to a place that could potentially have conflicts.
|
||||
* To resolve those conflicts we should take a hint out of maven/gradle/minecraft's book and key the filepath based on a hash of the file being extracted.
|
||||
* However, because that hash is no available in existing metadata we would need to re-calculate it.
|
||||
*
|
||||
* To do it in an efficient way we I needed to be able to share the single opened FileSystem with both the SecureJar implementation, and with our recursive search.
|
||||
* So I use my new ReadOnlyInMemoryFileSystem which is specifically designed to use the same backing array for the JarInJar search as it does with the resulting dependency
|
||||
* selected SecureJars.
|
||||
*
|
||||
* This means that if we wanted to we could rather efficiently calculate a hash for extracting the file. However, it also means that we don't have to extract to file to
|
||||
* support ZipFileSystem caching properly. So as long as we are okay with not using the JRE's optimized ZipFile implementation, or we want to support legacy JarInJar metadata,
|
||||
* using this efficient in memory file system is the best option performance wise. Extracting the files during launch without an efficient caching/unique identifier system
|
||||
* would incur a lot of Disc IO which can be super slow depending on your setup.
|
||||
*
|
||||
* So, it is a stated goal of our future re-write to extract files into a cache directory to gain the benefits of JRE optimizations, using a FileSystem much simpler then
|
||||
* the existing JarInJarFileSystem is good enough.
|
||||
*/
|
||||
|
||||
// Lets close all unselected FileSystems
|
||||
var wasSelected = new HashSet<>(selected);
|
||||
for (var entry : selector.entries.values())
|
||||
entry.cleanup(wasSelected.contains(entry));
|
||||
|
||||
LOGGER.info(MARKER, "Found {} dependencies adding them to mods collection", selected.size());
|
||||
var ret = new ArrayList<IModFile>(selected.size());
|
||||
|
||||
// Now lets build the actual mod files
|
||||
for (var entry : selected) {
|
||||
try {
|
||||
var root = entry.getFinalPath();
|
||||
var mod = createMod(root, false, entry.type.name());
|
||||
|
||||
if (mod.ex() != null)
|
||||
throw fail("Failed to load JarInJar file " + entry, mod.ex());
|
||||
|
||||
ret.add(mod.file());
|
||||
} catch (EarlyLoadingException e) {
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
throw fail("Failed to load JarInJar file " + entry, e);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Boolean anyMixinsLoaded = null;
|
||||
private static boolean anyMixinsLoaded(List<IModFile> mods) {
|
||||
var ret = anyMixinsLoaded;
|
||||
if (ret != null) return ret;
|
||||
|
||||
if (!FMLEnvironment.production
|
||||
&& Launcher.INSTANCE.blackboard().get(TypesafeMap.Key.getOrCreate(Launcher.INSTANCE.blackboard(), "isMixinEnabledInDev", Boolean.class)).orElse(false)) {
|
||||
anyMixinsLoaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var mod : mods) {
|
||||
var attributes = mod.getSecureJar().moduleDataProvider().getManifest().getMainAttributes();
|
||||
if (attributes.getValue(MIXIN_CONFIGS_ATTR) != null || attributes.getValue(MIXIN_CONNECTOR_ATTR) != null) {
|
||||
anyMixinsLoaded = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
anyMixinsLoaded = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
private record Options(List<OptionMetadata> options) {}
|
||||
private record OptionMetadata(String resource, Type layer, String id, List<ContainedJarMetadata> deps, ContainedJarMetadata meta, boolean nested) {}
|
||||
|
||||
private static void loadOptions() {
|
||||
if (optionsLoaded)
|
||||
return;
|
||||
|
||||
synchronized (OPTIONS) {
|
||||
if (optionsLoaded)
|
||||
return;
|
||||
|
||||
optionsLoaded = true;
|
||||
|
||||
var self = JarInJarDependencyLocator.class;
|
||||
|
||||
try (var stream = self.getModule().getResourceAsStream("/jarjar_options.json")) {
|
||||
if (stream == null) {
|
||||
LOGGER.error(MARKER, "Failed to find jarjar_options.json");
|
||||
return;
|
||||
}
|
||||
|
||||
var meta = MetadataIOHandler.getGson().fromJson(new InputStreamReader(stream), Options.class);
|
||||
//var meta = MetadataIOHandler.fromStream(stream).orElse(null);
|
||||
if (meta == null) {
|
||||
LOGGER.error(MARKER, "Corrupted jarjar_options.json");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var jar : meta.options()) {
|
||||
Path path = ClasspathLocator.getPathFromResource(self.getClassLoader(), jar.resource());
|
||||
if (path == null) {
|
||||
LOGGER.error(MARKER, "Failed to find JarJar option for {}", jar.resource());
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGGER.debug(MARKER, "Found JarJar Option: {}", path.toAbsolutePath());
|
||||
if (jar.nested())
|
||||
OPTIONS.put(path, new NestedOption(jar.id(), path, jar.layer(), jar.meta(), jar.deps()));
|
||||
else
|
||||
OPTIONS.put(path, new Option(jar.id(), path, jar.layer(), jar.meta(), jar.deps()));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error(MARKER, "Failed to read JarJar Options file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isOption(Path path) {
|
||||
loadOptions();
|
||||
return OPTIONS.containsKey(path);
|
||||
}
|
||||
|
||||
private static EarlyLoadingException fail(String message, @Nullable Throwable cause) {
|
||||
LOGGER.error(MARKER, message);
|
||||
return new EarlyLoadingException(message, cause, Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,89 +305,7 @@ public class JarInJarDependencyLocator extends AbstractModProvider implements ID
|
||||
return IModFile.Type.GAMELIBRARY.name();
|
||||
}
|
||||
|
||||
protected Optional<IModFile> loadModFileFrom(IModFile file, Path path) {
|
||||
try {
|
||||
final Path pathInModFile = file.findResource(path.toString());
|
||||
final URI filePathUri = new URI("jij:" + (pathInModFile.toAbsolutePath().toUri().getRawSchemeSpecificPart())).normalize();
|
||||
final Map<String, ?> outerFsArgs = ImmutableMap.of("packagePath", pathInModFile);
|
||||
final FileSystem zipFS = FileSystems.newFileSystem(filePathUri, outerFsArgs);
|
||||
final Path pathInFS = zipFS.getPath("/");
|
||||
final IModFile.Type parentType = file.getType();
|
||||
final String modType;
|
||||
if (parentType == IModFile.Type.LIBRARY || parentType == IModFile.Type.LANGPROVIDER) {
|
||||
modType = IModFile.Type.LIBRARY.name();
|
||||
} else {
|
||||
modType = IModFile.Type.GAMELIBRARY.name();
|
||||
}
|
||||
return Optional.of(createMod(pathInFS, false, modType).file());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to load mod file {} from {}", path, file.getFileName());
|
||||
final RuntimeException exception = new ModFileLoadingException("Failed to load mod file " + file.getFileName());
|
||||
exception.initCause(e);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
protected EarlyLoadingException exception(Collection<JarSelector.ResolutionFailureInformation<IModFile>> failedDependencies) {
|
||||
final List<EarlyLoadingException.ExceptionData> errors = failedDependencies.stream()
|
||||
.filter(entry -> !entry.sources().isEmpty()) //Should never be the case, but just to be sure
|
||||
.map(JarInJarDependencyLocator::buildExceptionData)
|
||||
.toList();
|
||||
|
||||
return new EarlyLoadingException(failedDependencies.size() + " Dependency restrictions were not met.", null, errors);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static EarlyLoadingException.ExceptionData buildExceptionData(JarSelector.ResolutionFailureInformation<IModFile> entry) {
|
||||
return new EarlyLoadingException.ExceptionData(
|
||||
getErrorTranslationKey(entry),
|
||||
entry.identifier().group() + ":" + entry.identifier().artifact(),
|
||||
entry.sources()
|
||||
.stream()
|
||||
.flatMap(JarInJarDependencyLocator::getModWithVersionRangeStream)
|
||||
.map(JarInJarDependencyLocator::formatError)
|
||||
.collect(Collectors.joining(", "))
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getErrorTranslationKey(JarSelector.ResolutionFailureInformation<IModFile> entry) {
|
||||
return entry.failureReason() == JarSelector.FailureReason.VERSION_RESOLUTION_FAILED ?
|
||||
"fml.dependencyloading.conflictingdependencies" :
|
||||
"fml.dependencyloading.mismatchedcontaineddependencies";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Stream<ModWithVersionRange> getModWithVersionRangeStream(JarSelector.SourceWithRequestedVersionRange<IModFile> file) {
|
||||
return file.sources()
|
||||
.stream()
|
||||
.map(IModFile::getModFileInfo)
|
||||
.flatMap(modFileInfo -> modFileInfo.getMods().stream())
|
||||
.map(modInfo -> new ModWithVersionRange(modInfo, file.requestedVersionRange(), file.includedVersion()));
|
||||
}
|
||||
|
||||
protected Optional<InputStream> loadResourceFromModFile(IModFile modFile, Path path) {
|
||||
try {
|
||||
var pathInModFile = modFile.findResource(path.toString());
|
||||
if (!Files.exists(pathInModFile)) {
|
||||
LOGGER.debug("Failed to load resource {} from {}, it does not contain dependency information.", path, modFile.getFileName());
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(Files.newInputStream(pathInModFile));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to load resource {} from mod {}, cause {}", path, modFile.getFileName(), e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String formatError(ModWithVersionRange modWithVersionRange){
|
||||
return YELLOW + modWithVersionRange.modInfo().getModId() + RESET + " - " +
|
||||
RED + modWithVersionRange.versionRange().toString() + RESET + " - " +
|
||||
GREEN + modWithVersionRange.artifactVersion().toString() + RESET;
|
||||
}
|
||||
|
||||
protected String identifyMod(IModFile modFile) {
|
||||
protected static String identifyMod(IModFile modFile) {
|
||||
if (modFile.getModFileInfo() != null && !modFile.getModInfos().isEmpty())
|
||||
return modFile.getModInfos().stream().map(IModInfo::getModId).collect(Collectors.joining());
|
||||
|
||||
@@ -169,5 +316,377 @@ public class JarInJarDependencyLocator extends AbstractModProvider implements ID
|
||||
return modFile.getFileName();
|
||||
}
|
||||
|
||||
private record ModWithVersionRange(IModInfo modInfo, VersionRange versionRange, ArtifactVersion artifactVersion) {}
|
||||
private static final Entry FAILED = new Entry("FAILED ENTRY", Path.of(""), Type.LIBRARY, null);
|
||||
private static sealed class Entry implements Comparable<Entry> {
|
||||
final String id;
|
||||
final Path path;
|
||||
final Type type;
|
||||
final @Nullable String coord;
|
||||
|
||||
private Entry(String id, Path path, Type type, @Nullable String coord) {
|
||||
this.id = id;
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
this.coord = coord;
|
||||
}
|
||||
|
||||
Path getFinalPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
void cleanup(boolean selected) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (path.getFileName() == null)
|
||||
return path.toUri().toString();
|
||||
return path.getFileName().toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Path getResource(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Entry o) {
|
||||
return o.toString().compareTo(toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ModEntry extends Entry {
|
||||
private final IModFile mod;
|
||||
|
||||
ModEntry(IModFile mod) {
|
||||
super(identifyMod(mod), mod.getFilePath(), mod.getType(), null);
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
Path getResource(String path) {
|
||||
return mod.findResource(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static sealed class Option extends Entry {
|
||||
final ContainedJarMetadata meta;
|
||||
final List<ContainedJarMetadata> deps;
|
||||
|
||||
private Option(String id, Path path, Type type, ContainedJarMetadata meta, List<ContainedJarMetadata> deps) {
|
||||
super(id, path, type, meta.identifier().group() + ':' + meta.identifier().artifact());
|
||||
this.meta = meta;
|
||||
this.deps = deps;
|
||||
}
|
||||
|
||||
public void addTo(Selector selector) {
|
||||
selector.option(this, meta);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NestedOption extends Option {
|
||||
private FileSystem zip;
|
||||
private Path root;
|
||||
|
||||
private NestedOption(String id, Path path, Type type, ContainedJarMetadata meta, List<ContainedJarMetadata> deps) {
|
||||
super(id, path, type, meta, deps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTo(Selector selector) {
|
||||
super.addTo(selector);
|
||||
selector.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
void cleanup(boolean selected) {
|
||||
if (this.zip != null) {
|
||||
try {
|
||||
zip.close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(MARKER, "Failed to close unselected FileSystem {}", this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Path getResource(String path) {
|
||||
if (zip == null) {
|
||||
try {
|
||||
this.zip = FileSystems.newFileSystem(this.path);
|
||||
this.root = zip.getRootDirectories().iterator().next();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(MARKER, "Failed to open FileSystem for option root {}", this, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var target = root.resolve(path);
|
||||
if (Files.exists(target))
|
||||
return target;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class Nested extends Entry {
|
||||
private final Entry parent;
|
||||
private final String nestedPath;
|
||||
private final Path zipPath;
|
||||
|
||||
Nested(String id, Path path, Type type, String coords, Entry parent, String nestedPath, Path zipPath) {
|
||||
super(id, path, type, coords);
|
||||
this.parent = parent;
|
||||
this.nestedPath = nestedPath;
|
||||
this.zipPath = zipPath;
|
||||
}
|
||||
|
||||
/*
|
||||
* Due to a bug in Mixin, anything that is not on the DefaultFileSystem MUST be a directory.
|
||||
* Or else it can't resolve resources correctly. So for anything we put on the roimfs we need
|
||||
* to return the nested zip file system.
|
||||
*
|
||||
* This will be an annoying to backport, but we can cross that bridge when we come to it.
|
||||
*
|
||||
* See: https://github.com/SpongePowered/Mixin/blob/4053421aa10aaac6127d969028a29c94fe3054f6/src/main/java/org/spongepowered/asm/launch/platform/MainAttributes.java#L102
|
||||
*/
|
||||
@Override
|
||||
public Path getFinalPath() {
|
||||
return zipPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
void cleanup(boolean selected) {
|
||||
if (selected)
|
||||
return;
|
||||
|
||||
LOGGER.info(MARKER, "Closeing unselected FileSystem {}", this);
|
||||
try {
|
||||
zipPath.getFileSystem().close();
|
||||
path.getFileSystem().close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(MARKER, "Failed to close unselected FileSystem {}", this, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
Path getResource(String path) {
|
||||
return zipPath.resolve(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return parent + "!/" + nestedPath;
|
||||
}
|
||||
}
|
||||
|
||||
private record Key(Entry parent, String path) {}
|
||||
|
||||
private final class Selector extends JarSelector<Entry> {
|
||||
private final HashMap<Key, Entry> entries = new HashMap<>();
|
||||
private final HashMap<Entry, HashMap<String, String>> children = new HashMap<>();
|
||||
|
||||
private Selector(Iterable<IModFile> mods) {
|
||||
for (var mod : mods)
|
||||
this.force(new ModEntry(mod));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void force(Entry entry) {
|
||||
super.force(entry);
|
||||
entries.put(new Key(entry, ""), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void option(Entry entry, ContainedJarMetadata meta) {
|
||||
super.option(entry, meta);
|
||||
entries.put(new Key(entry, ""), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Entry entry) {
|
||||
super.add(entry);
|
||||
entries.put(new Key(entry, ""), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected InputStream getResource(Entry source, String path) {
|
||||
try {
|
||||
Path target = source.getResource(path);
|
||||
if (target == null || !Files.exists(target)) {
|
||||
LOGGER.debug(MARKER, "Failed to load resource {} from {}, it does not contain dependency information.", path, source);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Read the metadata file and store identifiers so we can group them later.
|
||||
if (JarSelector.CONTAINED_JARS_METADATA_PATH.equals(path)) {
|
||||
try (var is = Files.newInputStream(target)) {
|
||||
var meta = MetadataIOHandler.fromStream(is).orElse(null);
|
||||
if (meta == null)
|
||||
return Files.newInputStream(target);
|
||||
var children = new HashMap<String, String>();
|
||||
for (var child : meta.jars())
|
||||
children.put(child.path().replace('\\', '/'), child.identifier().group() + ':' + child.identifier().artifact());
|
||||
this.children.put(source, children);
|
||||
}
|
||||
}
|
||||
|
||||
return Files.newInputStream(target);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(MARKER, "Failed to load resource {} from {}, cause {}", path, source, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Entry getNested(Entry source, String path) {
|
||||
var cleaned = path.replace('\\', '/');
|
||||
var key = new Key(source, cleaned);
|
||||
var entry = entries.get(key);
|
||||
if (entry == null) {
|
||||
entry = createNested(source, path, cleaned);
|
||||
if (entry == null)
|
||||
entry = FAILED;
|
||||
entries.put(key, entry);
|
||||
}
|
||||
return entry == FAILED ? null : entry;
|
||||
}
|
||||
|
||||
private Entry createNested(Entry source, String path, String cleaned) {
|
||||
var targetPath = source.getResource(path);
|
||||
|
||||
if (targetPath == null || !Files.isRegularFile(targetPath))
|
||||
return null;
|
||||
|
||||
Path roimfsPath = null;
|
||||
Path zipPath = null;
|
||||
try {
|
||||
// Lets copy the uncompressed file to memory, and then create a ReadOnlyInMemorryFileSystem for it, this allows us to reference it by URI.
|
||||
// Which is needed because a lot of things require navigation via URI.
|
||||
// And ZipFileSystem only caches the FileSystem instance when accessed via URI.
|
||||
byte[] data = Files.readAllBytes(targetPath);
|
||||
String filename = targetPath.getFileName().toString();
|
||||
URI uri = new URI(ROIMFS, "jar-jar-" + nextId() + "/" + filename, null);
|
||||
var roimfs = FileSystems.newFileSystem(uri, Collections.singletonMap("data", data));
|
||||
roimfsPath = roimfs.getPath(filename);
|
||||
var zip = FileSystems.newFileSystem(new URI("jar:" + roimfsPath.toUri()), Collections.emptyMap());
|
||||
zipPath = zip.getRootDirectories().iterator().next(); // Get first root, which on ZipFileSystem is the only root
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
LOGGER.error(MARKER, "Failed to create FileSystem for nested jar {}", source, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
var mf = new Manifest();
|
||||
var mfPath = zipPath.resolve(JarFile.MANIFEST_NAME);
|
||||
if (Files.exists(mfPath)) {
|
||||
try (var is = Files.newInputStream(mfPath)) {
|
||||
mf = new Manifest(is);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(MARKER, "Failed to read manifest from {}", source, e);
|
||||
}
|
||||
}
|
||||
|
||||
IModFile.Type type = null;
|
||||
String id = null;
|
||||
var tomlPath = zipPath.resolve(MODS_TOML);
|
||||
if (Files.exists(tomlPath)) {
|
||||
var cfg = FileConfig.builder(tomlPath).build();
|
||||
cfg.load();
|
||||
cfg.close();
|
||||
if (cfg.getOrElse("mods", null) instanceof Collection collection) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var mods = (Collection<UnmodifiableConfig>)collection;
|
||||
if (!mods.isEmpty()) {
|
||||
var first = mods.iterator().next();
|
||||
var modId = first.getOrElse("modId", null);
|
||||
if (modId instanceof String str)
|
||||
id = str;
|
||||
}
|
||||
}
|
||||
var value = mf.getMainAttributes().getValue(ModFile.TYPE);
|
||||
if (value != null)
|
||||
type = IModFile.Type.valueOf(value);
|
||||
else
|
||||
type = IModFile.Type.MOD;
|
||||
} else {
|
||||
var value = mf.getMainAttributes().getValue(ModFile.TYPE);
|
||||
if (value != null)
|
||||
type = IModFile.Type.valueOf(value);
|
||||
else {
|
||||
// No mods.toml, no entry value, so decide based on the container's type
|
||||
if (source.type == IModFile.Type.LIBRARY || source.type == IModFile.Type.LANGPROVIDER)
|
||||
type = IModFile.Type.LIBRARY;
|
||||
else
|
||||
type = IModFile.Type.GAMELIBRARY;
|
||||
}
|
||||
}
|
||||
|
||||
if (id == null) {
|
||||
var modulePath = zipPath.resolve(MODULE_INFO);
|
||||
if (Files.exists(modulePath)) {
|
||||
try (var is = Files.newInputStream(modulePath)) {
|
||||
var module = ModuleDescriptor.read(is);
|
||||
id = module.name();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(MARKER, "Failed to read module-info.class from {}", source, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (id == null)
|
||||
id = mf.getMainAttributes().getValue("Automatic-Module-Name");
|
||||
|
||||
if (id == null)
|
||||
id = Path.of(path).getFileName().toString();
|
||||
|
||||
String coords = null;
|
||||
var child = this.children.get(source);
|
||||
if (child != null)
|
||||
coords = child.get(cleaned);
|
||||
|
||||
return new Nested(id, roimfsPath, type, coords, source, cleaned, zipPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getIdentifier(Entry entry) {
|
||||
return entry.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Throwable getFailureException(Collection<ResolutionFailureInformation<Entry>> failures) {
|
||||
var errors = new ArrayList<ExceptionData>();
|
||||
for (var failure : failures) {
|
||||
var message = failure.failureReason() == JarSelector.FailureReason.VERSION_RESOLUTION_FAILED ? "fml.dependencyloading.conflictingdependencies" : "fml.dependencyloading.mismatchedcontaineddependencies";
|
||||
var joiner = new StringJoiner(", ");
|
||||
for (var source : failure.sources()) {
|
||||
String paths = null;
|
||||
if (source.sources().size() == 0) {
|
||||
paths = "[No Sources]";
|
||||
} else if (source.sources().size() == 1) {
|
||||
var entry = source.sources().iterator().next();
|
||||
paths = entry.toString();
|
||||
} else {
|
||||
var j = new StringJoiner(", ", "[", "]");
|
||||
for (var entry : source.sources())
|
||||
j.add(entry.toString());
|
||||
paths = j.toString();
|
||||
}
|
||||
|
||||
var error = YELLOW + paths + RESET + " - " +
|
||||
RED + source.requestedVersionRange() + RESET + " - " +
|
||||
GREEN + source.includedVersion() + RESET;
|
||||
joiner.add(error);
|
||||
}
|
||||
|
||||
errors.add(new ExceptionData(message, failure.identifier().group() + ":" + failure.identifier().artifact(), joiner.toString()));
|
||||
}
|
||||
|
||||
return new EarlyLoadingException(failures.size() + " Dependency restrictions were not met.", null, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-37
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
import cpw.mods.modlauncher.api.IModuleLayerManager;
|
||||
@@ -35,41 +34,36 @@ import java.util.ServiceLoader;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ModDiscoverer {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final ServiceLoader<IModLocator> modLocators;
|
||||
private final ServiceLoader<IDependencyLocator> dependencyLocators;
|
||||
private final List<IModLocator> modLocatorList;
|
||||
private final List<IDependencyLocator> dependencyLocatorList;
|
||||
public final class ModDiscoverer {
|
||||
private ModDiscoverer() {}
|
||||
|
||||
public ModDiscoverer(Map<String, ?> arguments) {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static ModValidator discoverMods(Map<String, ?> arguments) {
|
||||
Launcher.INSTANCE.environment().computePropertyIfAbsent(Environment.Keys.MODDIRECTORYFACTORY.get(), v->ModsFolderLocator::new);
|
||||
Launcher.INSTANCE.environment().computePropertyIfAbsent(Environment.Keys.PROGRESSMESSAGE.get(), v-> StartupNotificationManager.locatorConsumer().orElseGet(()-> s->{}));
|
||||
final var moduleLayerManager = Launcher.INSTANCE.environment().findModuleLayerManager().orElseThrow();
|
||||
modLocators = ServiceLoader.load(moduleLayerManager.getLayer(IModuleLayerManager.Layer.SERVICE).orElseThrow(), IModLocator.class);
|
||||
dependencyLocators = ServiceLoader.load(moduleLayerManager.getLayer(IModuleLayerManager.Layer.SERVICE).orElseThrow(), IDependencyLocator.class);
|
||||
modLocatorList = ServiceLoaderUtils.streamServiceLoader(()-> modLocators, sce->LOGGER.error("Failed to load mod locator list", sce)).collect(Collectors.toList());
|
||||
ServiceLoader<IModLocator> modLocators = ServiceLoader.load(moduleLayerManager.getLayer(IModuleLayerManager.Layer.SERVICE).orElseThrow(), IModLocator.class);
|
||||
ServiceLoader<IDependencyLocator> dependencyLocators = ServiceLoader.load(moduleLayerManager.getLayer(IModuleLayerManager.Layer.SERVICE).orElseThrow(), IDependencyLocator.class);
|
||||
List<IModLocator> modLocatorList = ServiceLoaderUtils.streamWithErrorHandling(modLocators, sce -> LOGGER.error("Failed to load mod locator list", sce)).toList();
|
||||
for (IModLocator iModLocator : modLocatorList) {
|
||||
iModLocator.initArguments(arguments);
|
||||
}
|
||||
dependencyLocatorList = ServiceLoaderUtils.streamServiceLoader(()-> dependencyLocators, sce->LOGGER.error("Failed to load dependency locator list", sce)).collect(Collectors.toList());
|
||||
List<IDependencyLocator> dependencyLocatorList = ServiceLoaderUtils.streamWithErrorHandling(dependencyLocators, sce -> LOGGER.error("Failed to load dependency locator list", sce)).toList();
|
||||
for (IDependencyLocator l : dependencyLocatorList) {
|
||||
l.initArguments(arguments);
|
||||
}
|
||||
if (LOGGER.isDebugEnabled(LogMarkers.CORE))
|
||||
{
|
||||
if (LOGGER.isDebugEnabled(LogMarkers.CORE)) {
|
||||
LOGGER.debug(LogMarkers.CORE, "Found Mod Locators : {}", modLocatorList.stream()
|
||||
.map(modLocator -> "(%s:%s)".formatted(modLocator.name(),
|
||||
modLocator.getClass().getPackage().getImplementationVersion())).collect(Collectors.joining(",")));
|
||||
.map(modLocator -> "(%s:%s)".formatted(modLocator.name(),
|
||||
modLocator.getClass().getPackage().getImplementationVersion())).collect(Collectors.joining(",")));
|
||||
|
||||
LOGGER.debug(LogMarkers.CORE, "Found Dependency Locators : {}", dependencyLocatorList.stream()
|
||||
.map(dependencyLocator -> "(%s:%s)".formatted(dependencyLocator.name(),
|
||||
dependencyLocator.getClass().getPackage().getImplementationVersion())).collect(Collectors.joining(",")));
|
||||
.map(dependencyLocator -> "(%s:%s)".formatted(dependencyLocator.name(),
|
||||
dependencyLocator.getClass().getPackage().getImplementationVersion())).collect(Collectors.joining(",")));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public ModValidator discoverMods() {
|
||||
LOGGER.debug(LogMarkers.SCAN,"Scanning for mods and other resources to load. We know {} ways to find mods", modLocatorList.size());
|
||||
List<ModFile> loadedFiles = new ArrayList<>();
|
||||
List<EarlyLoadingException.ExceptionData> discoveryErrorData = new ArrayList<>();
|
||||
@@ -117,7 +111,7 @@ public class ModDiscoverer {
|
||||
}
|
||||
|
||||
LOGGER.debug(LogMarkers.SCAN, "Locator {} found {} valid mod files", locator, locatedFiles.size());
|
||||
handleLocatedFiles(loadedFiles, locatedFiles);
|
||||
handleLocatedFiles(loadedFiles, locatedFiles, locator);
|
||||
} catch (InvalidModFileException imfe) {
|
||||
// We don't generally expect this exception, since it should come from the candidates stream above and be handled in the Locator, but just in case.
|
||||
LOGGER.error(LogMarkers.SCAN, "Locator {} found an invalid mod file {}", locator, imfe.getBrokenFile(), imfe);
|
||||
@@ -131,8 +125,7 @@ public class ModDiscoverer {
|
||||
//First processing run of the mod list. Any duplicates will cause resolution failure and dependency loading will be skipped.
|
||||
Map<IModFile.Type, List<ModFile>> modFilesMap = new EnumMap<>(IModFile.Type.class);
|
||||
try {
|
||||
final UniqueModListBuilder modsUniqueListBuilder = new UniqueModListBuilder(loadedFiles);
|
||||
final UniqueModListBuilder.UniqueModListData uniqueModsData = modsUniqueListBuilder.buildUniqueList();
|
||||
final UniqueModListBuilder.UniqueModListData uniqueModsData = UniqueModListBuilder.buildUniqueList(loadedFiles);
|
||||
|
||||
//Grab the temporary results.
|
||||
//This allows loading to continue to a base state, in case dependency loading fails.
|
||||
@@ -152,14 +145,10 @@ public class ModDiscoverer {
|
||||
for (IDependencyLocator locator : dependencyLocatorList) {
|
||||
try {
|
||||
LOGGER.debug(LogMarkers.SCAN,"Trying locator {}", locator);
|
||||
final List<IModFile> locatedMods = ImmutableList.copyOf(loadedFiles);
|
||||
final List<IModFile> locatedMods = List.copyOf(loadedFiles);
|
||||
|
||||
var locatedFiles = locator.scanMods(locatedMods);
|
||||
if (locatedFiles.stream().anyMatch(file -> !(file instanceof ModFile))) {
|
||||
LOGGER.error(LogMarkers.SCAN, "A dependency locator returned a file which is not a ModFile instance!. They will be skipped!");
|
||||
}
|
||||
|
||||
handleLocatedFiles(loadedFiles, locatedFiles);
|
||||
handleLocatedFiles(loadedFiles, locatedFiles, locator);
|
||||
}
|
||||
catch (EarlyLoadingException exception) {
|
||||
LOGGER.error(LogMarkers.SCAN, "Failed to load dependencies with locator {}", locator, exception);
|
||||
@@ -169,8 +158,7 @@ public class ModDiscoverer {
|
||||
|
||||
//Second processing run of the mod list. Any duplicates will cause resolution failure and only the mods list will be loaded.
|
||||
try {
|
||||
final UniqueModListBuilder modsAndDependenciesUniqueListBuilder = new UniqueModListBuilder(loadedFiles);
|
||||
final UniqueModListBuilder.UniqueModListData uniqueModsAndDependenciesData = modsAndDependenciesUniqueListBuilder.buildUniqueList();
|
||||
final UniqueModListBuilder.UniqueModListData uniqueModsAndDependenciesData = UniqueModListBuilder.buildUniqueList(loadedFiles);
|
||||
|
||||
//We now only need the mod files map, not the list.
|
||||
modFilesMap = uniqueModsAndDependenciesData.modFiles().stream()
|
||||
@@ -193,11 +181,14 @@ public class ModDiscoverer {
|
||||
return validator;
|
||||
}
|
||||
|
||||
private static void handleLocatedFiles(final List<ModFile> loadedFiles, final List<IModFile> locatedFiles) {
|
||||
var locatedModFiles = locatedFiles.stream().filter(ModFile.class::isInstance).map(ModFile.class::cast).toList();
|
||||
for (IModFile mf : locatedModFiles) {
|
||||
LOGGER.info(LogMarkers.SCAN, "Found mod file {} of type {} with provider {}", mf.getFileName(), mf.getType(), mf.getProvider());
|
||||
private static void handleLocatedFiles(final List<ModFile> loadedFiles, final List<IModFile> locatedFiles, final Object locator) {
|
||||
for (IModFile mf : locatedFiles) {
|
||||
if (mf instanceof ModFile modFile) {
|
||||
LOGGER.info(LogMarkers.SCAN, "Found mod file {} of type {} with provider {}", mf.getFileName(), mf.getType(), mf.getProvider());
|
||||
loadedFiles.add(modFile);
|
||||
} else {
|
||||
LOGGER.error(LogMarkers.SCAN, "Skipping mod file {} found by {}, as it was not a ModFile instance!", mf.getFileName(), locator);
|
||||
}
|
||||
}
|
||||
loadedFiles.addAll(locatedModFiles);
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,13 @@ import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -98,7 +98,7 @@ public class ModFile implements IModFile {
|
||||
|
||||
public boolean identifyMods() {
|
||||
if (this.modFileInfo == null) return this.getType() != Type.MOD;
|
||||
LOGGER.debug(LogMarkers.LOADING,"Loading mod file {} with languages {}", this.getFilePath(), this.modFileInfo.requiredLanguageLoaders());
|
||||
LOGGER.debug(LogMarkers.LOADING,"Loading mod file {} with languages {}", this.getFileName(), this.modFileInfo.requiredLanguageLoaders());
|
||||
this.coreMods = ModFileParser.getCoreMods(this);
|
||||
if (!this.coreMods.isEmpty())
|
||||
LOGGER.warn("Mod file {} contains javascript coremods! JS CoreMods are deprecated and will be removed in a future release. Consider using Mixin or ModLauncher transformers.", this.getFileName());
|
||||
@@ -179,12 +179,28 @@ public class ModFile implements IModFile {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mod File: " + Objects.toString(this.jar.getPrimaryPath());
|
||||
var path = getFilePath();
|
||||
return "Mod File: " + path == null ? "null" : path.toUri().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return getFilePath().getFileName().toString();
|
||||
// This is only used for debugging, so lets try and make it a useful debug
|
||||
var path = getFilePath();
|
||||
var filename = path.getFileName();
|
||||
|
||||
// ZipFileSystem toString will return the outer file path
|
||||
var ret = filename == null ? path.getFileSystem().toString() : filename.toString();
|
||||
|
||||
// If it's a directory on the default file system, return the full path
|
||||
if (Files.isDirectory(path) && path.getFileSystem() == FileSystems.getDefault())
|
||||
ret = path.toAbsolutePath().toString();
|
||||
|
||||
// If we are in a FileSystem 'root' like UnionFS, return the full uri
|
||||
if (ret.isEmpty() || ret.equals("/"))
|
||||
ret = path.toUri().toString();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ public class ModFileInfo implements IModFileInfo, IConfigurable {
|
||||
|
||||
@Override
|
||||
public String versionString() {
|
||||
return getMods().get(0).getVersion().toString();
|
||||
return getMods().getFirst().getVersion().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-4
@@ -34,7 +34,6 @@ public class ModValidator {
|
||||
private LoadingModList loadingModList;
|
||||
private final List<IModFile> brokenFiles = new ArrayList<>();
|
||||
private final List<EarlyLoadingException.ExceptionData> discoveryErrorData;
|
||||
private final List<ModFileLoadingException> modFileLoadingExceptions;
|
||||
|
||||
public ModValidator(Map<IModFile.Type, List<ModFile>> modFiles, List<IModFileInfo> brokenFiles, List<EarlyLoadingException.ExceptionData> discoveryErrorData, List<ModFileLoadingException> modFileLoadingExceptions) {
|
||||
this.candidateMods = lst(modFiles.get(IModFile.Type.MOD));
|
||||
@@ -44,7 +43,6 @@ public class ModValidator {
|
||||
this.candidatePlugins.addAll(lst(modFiles.get(IModFile.Type.LIBRARY)));
|
||||
this.discoveryErrorData = discoveryErrorData;
|
||||
this.brokenFiles.addAll(brokenFiles.stream().map(IModFileInfo::getFile).toList());
|
||||
this.modFileLoadingExceptions = modFileLoadingExceptions;
|
||||
}
|
||||
|
||||
public ModValidator(Map<IModFile.Type, List<ModFile>> modFiles, List<IModFileInfo> brokenFiles, List<EarlyLoadingException.ExceptionData> discoveryErrorData) {
|
||||
@@ -52,7 +50,9 @@ public class ModValidator {
|
||||
}
|
||||
|
||||
private static List<ModFile> lst(List<ModFile> files) {
|
||||
return files == null ? new ArrayList<>() : new ArrayList<>(files);
|
||||
if (files == null) return new ArrayList<>();
|
||||
if (files instanceof ArrayList) return files;
|
||||
return new ArrayList<>(files);
|
||||
}
|
||||
|
||||
public void stage1Validation() {
|
||||
@@ -60,7 +60,7 @@ public class ModValidator {
|
||||
if (LOGGER.isDebugEnabled(LogMarkers.SCAN)) {
|
||||
LOGGER.debug(LogMarkers.SCAN, "Found {} mod files with {} mods", candidateMods.size(), candidateMods.stream().mapToInt(mf -> mf.getModInfos().size()).sum());
|
||||
}
|
||||
ImmediateWindowHandler.updateProgress("Found "+candidateMods.size()+" mod candidates");
|
||||
ImmediateWindowHandler.updateProgress("Found " + candidateMods.size() + " mod candidates");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"options": [
|
||||
{
|
||||
"resource": "com/llamalad7/mixinextras/platform/forge/MixinExtrasConfigPlugin.class",
|
||||
"layer": "GAMELIBRARY",
|
||||
"id": "mixinextras",
|
||||
"deps": [
|
||||
{
|
||||
"identifier": {
|
||||
"group": "com.github.LlamaLad7",
|
||||
"artifact": "MixinExtras"
|
||||
},
|
||||
"version": {
|
||||
"range": "[0.5.0,)",
|
||||
"artifactVersion": "0.5.0"
|
||||
},
|
||||
"path": "",
|
||||
"isObfuscated": false
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"identifier": {
|
||||
"group": "io.github.llamalad7",
|
||||
"artifact": "mixinextras-forge"
|
||||
},
|
||||
"version": {
|
||||
"artifactVersion": "0.5.0"
|
||||
},
|
||||
"path": "",
|
||||
"isObfuscated": false
|
||||
},
|
||||
"nested": true
|
||||
}
|
||||
]
|
||||
}
|
||||
-1
@@ -10,7 +10,6 @@ import cpw.mods.modlauncher.api.ITransformationService;
|
||||
import cpw.mods.modlauncher.api.ITransformer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
[
|
||||
{
|
||||
"class": "net/minecraft/gametest/framework/GameTestHelper",
|
||||
"methods": [
|
||||
"spawn(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/entity/EntitySpawnReason;)Lnet/minecraft/world/entity/Entity;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/server/commands/RaidCommand",
|
||||
"methods": [
|
||||
@@ -23,31 +29,25 @@
|
||||
"trySpawn(Lnet/minecraft/server/level/ServerLevel;)V"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/animal/equine/SkeletonTrapGoal",
|
||||
"methods": [
|
||||
"createHorse(Lnet/minecraft/world/DifficultyInstance;)Lnet/minecraft/world/entity/animal/equine/AbstractHorse;",
|
||||
"createSkeleton(Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/animal/equine/AbstractHorse;)Lnet/minecraft/world/entity/monster/skeleton/Skeleton;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/animal/equine/ZombieHorse",
|
||||
"methods": [
|
||||
"finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/animal/frog/Tadpole",
|
||||
"methods": [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/animal/horse/SkeletonTrapGoal",
|
||||
"methods": [
|
||||
"createHorse(Lnet/minecraft/world/DifficultyInstance;)Lnet/minecraft/world/entity/animal/horse/AbstractHorse;",
|
||||
"createSkeleton(Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/animal/horse/AbstractHorse;)Lnet/minecraft/world/entity/monster/Skeleton;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/Evoker$EvokerSummonSpellGoal",
|
||||
"methods": [
|
||||
"performSpellCasting()V"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/Spider",
|
||||
"methods": [
|
||||
"finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/Strider",
|
||||
"methods": [
|
||||
@@ -55,14 +55,38 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/Zombie",
|
||||
"class": "net/minecraft/world/entity/monster/illager/Evoker$EvokerSummonSpellGoal",
|
||||
"methods": [
|
||||
"performSpellCasting()V"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/spider/Spider",
|
||||
"methods": [
|
||||
"finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/zombie/Drowned",
|
||||
"methods": [
|
||||
"finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/zombie/Husk",
|
||||
"methods": [
|
||||
"finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/zombie/Zombie",
|
||||
"methods": [
|
||||
"hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z",
|
||||
"finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/monster/ZombieVillager",
|
||||
"class": "net/minecraft/world/entity/monster/zombie/ZombieVillager",
|
||||
"methods": [
|
||||
|
||||
]
|
||||
@@ -74,9 +98,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"class": "net/minecraft/world/entity/npc/Villager",
|
||||
"class": "net/minecraft/world/entity/npc/villager/Villager",
|
||||
"methods": [
|
||||
"getBreedOffspring(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/AgeableMob;)Lnet/minecraft/world/entity/npc/Villager;"
|
||||
"getBreedOffspring(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/AgeableMob;)Lnet/minecraft/world/entity/npc/villager/Villager;"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+3
-3
@@ -5,11 +5,11 @@ org.gradle.daemon=false
|
||||
org.gradle.parallel=true
|
||||
|
||||
JAVA_VERSION=21
|
||||
MC_VERSION=1.21.9
|
||||
MC_VERSION=1.21.11
|
||||
MC_NEXT_VERSION=1.22
|
||||
MCP_VERSION=20250930.103108
|
||||
MCP_VERSION=20251209.095502
|
||||
MAPPING_CHANNEL=official
|
||||
MAPPING_VERSION=1.21.9
|
||||
MAPPING_VERSION=1.21.11
|
||||
|
||||
# Set to true before the first build of a new MC version, so we don't do compatibility checks
|
||||
CHECK_COMPATIBILITY=false
|
||||
|
||||
+21
-9
@@ -48,11 +48,13 @@ import java.util.stream.Collectors;
|
||||
* annotations and passes the class instances to the {@link Bus}
|
||||
* defined by the annotation. Defaults to {@code MinecraftForge#EVENT_BUS}
|
||||
*/
|
||||
public class AutomaticEventSubscriber {
|
||||
public final class AutomaticEventSubscriber {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Type AUTO_SUBSCRIBER = Type.getType(EventBusSubscriber.class);
|
||||
private static final Type MOD_TYPE = Type.getType(Mod.class);
|
||||
private static final Type ONLY_IN_TYPE = Type.getType(OnlyIn.class);
|
||||
private static final List<EnumData> DEFAULT_SIDES = List.of(new EnumData(null, "CLIENT"), new EnumData(null, "DEDICATED_SERVER"));
|
||||
private static final EnumData DEFAULT_BUS = new EnumData(null, "BOTH");
|
||||
|
||||
public static void inject(ModContainer mod, ModFileScanData scanData, ClassLoader loader) {
|
||||
if (scanData == null) return;
|
||||
@@ -71,9 +73,6 @@ public class AutomaticEventSubscriber {
|
||||
.filter(data -> MOD_TYPE.equals(data.annotationType()))
|
||||
.collect(Collectors.toMap(a -> a.clazz().getClassName(), a -> (String)a.annotationData().get("value")));
|
||||
|
||||
var defaultSides = List.of(new EnumData(null, "CLIENT"), new EnumData(null, "DEDICATED_SERVER"));
|
||||
var defaultBus = new EnumData(null, "FORGE");
|
||||
|
||||
for (var data : targets) {
|
||||
if (!FMLEnvironment.production && onlyIns.contains(data.clazz().getClassName())) {
|
||||
throw new RuntimeException("Found @OnlyIn on @EventBusSubscriber class " + data.clazz().getClassName() + " - this is not allowed as it causes crashes. Remove the OnlyIn and set value=Dist.CLIENT in the EventBusSubscriber annotation instead");
|
||||
@@ -82,13 +81,13 @@ public class AutomaticEventSubscriber {
|
||||
var modId = modids.getOrDefault(data.clazz().getClassName(), mod.getModId());
|
||||
modId = value(data, "modid", modId);
|
||||
|
||||
var sidesValue = value(data, "value", defaultSides);
|
||||
var sidesValue = value(data, "value", DEFAULT_SIDES);
|
||||
var sides = sidesValue.stream()
|
||||
.map(EnumData::value)
|
||||
.map(Dist::valueOf)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
var busName = value(data, "bus", defaultBus).value();
|
||||
var busName = value(data, "bus", DEFAULT_BUS).value();
|
||||
var busTarget = Bus.valueOf(busName);
|
||||
if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.dist)) {
|
||||
try {
|
||||
@@ -173,7 +172,7 @@ public class AutomaticEventSubscriber {
|
||||
Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
|
||||
var subscribeEventAnnotation = method.getAnnotation(SubscribeEvent.class);
|
||||
|
||||
registerListener(busGroup, paramCount, returnType, eventType, subscribeEventAnnotation, method);
|
||||
registerListener(busGroup, paramCount, returnType, eventType, subscribeEventAnnotation, method, false);
|
||||
listenersCount++;
|
||||
|
||||
if (firstValidListenerEventType == null)
|
||||
@@ -259,7 +258,7 @@ public class AutomaticEventSubscriber {
|
||||
throw fail(method, "Return type boolean is only valid for cancellable events");
|
||||
}
|
||||
|
||||
registerListener(busGroup, paramCount, returnType, eventType, subscribeEventAnnotation, method);
|
||||
registerListener(busGroup, paramCount, returnType, eventType, subscribeEventAnnotation, method, true);
|
||||
listenersCount++;
|
||||
|
||||
if (firstValidListenerEventType == null)
|
||||
@@ -276,11 +275,24 @@ public class AutomaticEventSubscriber {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static EventListener registerListener(@Nullable BusGroup busGroup,
|
||||
int paramCount, Class<?> returnType, Class<? extends Event> eventType,
|
||||
SubscribeEvent subscribeEventAnnotation, Method method) {
|
||||
SubscribeEvent subscribeEventAnnotation, Method method, boolean strict) {
|
||||
if (busGroup == null) {
|
||||
busGroup = IModBusEvent.class.isAssignableFrom(eventType)
|
||||
? FMLJavaModLoadingContext.get().getModBusGroup()
|
||||
: BusGroup.DEFAULT;
|
||||
} else if (strict) {
|
||||
String solution = "To fix this, remove the bus param from your @EventBusSubscriber annotation or move this event listener to another class.";
|
||||
var isDefaultBusGroup = busGroup == BusGroup.DEFAULT;
|
||||
var isModBusEvent = IModBusEvent.class.isAssignableFrom(eventType);
|
||||
if (isDefaultBusGroup && isModBusEvent) { // requested forge bus and has IModBusEvent
|
||||
throw fail(method, "Event type " + eventType.getName()
|
||||
+ " is on the mod BusGroup but you are asking to register it on the default BusGroup (BusGroup.DEFAULT/EventBusSubscriber.Bus.FORGE). "
|
||||
+ solution);
|
||||
} else if (!isDefaultBusGroup && !isModBusEvent) { // requested mod bus and does not have IModBusEvent
|
||||
throw fail(method, "Event type " + eventType.getName()
|
||||
+ " is on the default BusGroup but you are asking to register it on the mod BusGroup (context.getModBusGroup()/EventBusSubscriber.Bus.MOD). "
|
||||
+ solution);
|
||||
}
|
||||
}
|
||||
|
||||
// determine the listener type from its parameters and return type
|
||||
|
||||
+6
-4
@@ -43,12 +43,13 @@ public class FMLModContainer extends ModContainer {
|
||||
LOGGER.debug(LOADING,"Creating FMLModContainer instance for {}", className);
|
||||
this.scanResults = modFileScanResults;
|
||||
activityMap.put(ModLoadingStage.CONSTRUCT, this::constructMod);
|
||||
this.eventBusGroup = BusGroup.create("modBusFor" + info.getModId());
|
||||
this.eventBusGroup = BusGroup.create("modBusFor" + info.getModId(), IModBusEvent.class);
|
||||
this.contextExtension = () -> context;
|
||||
try {
|
||||
var moduleName = info.getOwningFile().moduleName();
|
||||
var module = gameLayer.findModule(moduleName)
|
||||
.orElseThrow(() -> new IllegalStateException("Failed to find " + moduleName + " in " + gameLayer));
|
||||
var module = gameLayer.findModule(moduleName).orElse(null);
|
||||
if (module == null)
|
||||
throw new IllegalStateException("Failed to find " + moduleName + " in " + gameLayer);
|
||||
|
||||
openModules(gameLayer, module, info.getOwningFile().getFile().getSecureJar());
|
||||
|
||||
@@ -166,6 +167,7 @@ public class FMLModContainer extends ModContainer {
|
||||
return modInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusGroup getModBusGroup() {
|
||||
return this.eventBusGroup;
|
||||
}
|
||||
@@ -193,6 +195,6 @@ public class FMLModContainer extends ModContainer {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FMLModContainer[" + this.getModInfo().getModId() + ", " + this.getClass().getName() + "]";
|
||||
return "FMLModContainer[" + this.getModInfo().getModId() + ", " + this.getClass().getName() + ']';
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,7 +2,7 @@ plugins {
|
||||
id 'eclipse'
|
||||
id 'idea'
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.gradle' version '[6.0.36,6.2)'
|
||||
id 'net.minecraftforge.gradle' version '[6.0.46,6.2)'
|
||||
}
|
||||
|
||||
version = mod_version
|
||||
@@ -145,7 +145,7 @@ dependencies {
|
||||
// Forge 1.21.6+ uses EventBus 7, which shifts most of its runtime validation to compile-time via an annotation processor
|
||||
// to improve performance in production environments. This line is required to enable said compile-time validation
|
||||
// in your development environment, helping you catch issues early.
|
||||
annotationProcessor 'net.minecraftforge:eventbus-validator:7.0-beta.10'
|
||||
annotationProcessor 'net.minecraftforge:eventbus-validator:7.0-beta.12'
|
||||
|
||||
// Example mod dependency with JEI
|
||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlCommandEncoder.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlCommandEncoder.java
|
||||
@@ -131,6 +_,9 @@
|
||||
@@ -133,6 +_,9 @@
|
||||
GlStateManager._colorMask(true, true, true, true);
|
||||
GlStateManager._clear(16384);
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, 0, 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlDebug.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlDebug.java
|
||||
@@ -23,6 +_,14 @@
|
||||
@@ -24,6 +_,14 @@
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class GlDebug {
|
||||
@@ -24,10 +24,10 @@
|
||||
}
|
||||
|
||||
public List<String> getLastOpenGlDebugMessages() {
|
||||
@@ -121,6 +_,7 @@
|
||||
@@ -120,6 +_,7 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GlDebug enableDebugCallback(int p_394351_, boolean p_393026_, Set<String> p_393339_) {
|
||||
public static @Nullable GlDebug enableDebugCallback(int p_394351_, boolean p_393026_, Set<String> p_393339_) {
|
||||
+ p_393026_ |= PRINT_STACKTRACE_ON_ERROR;
|
||||
if (p_394351_ <= 0) {
|
||||
return null;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlDevice.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlDevice.java
|
||||
@@ -90,8 +_,15 @@
|
||||
public GpuTexture createTexture(
|
||||
@Nullable Supplier<String> p_397830_, int p_394481_, TextureFormat p_394839_, int p_391831_, int p_395609_, int p_407582_, int p_408928_
|
||||
@@ -124,8 +_,15 @@
|
||||
int p_407582_,
|
||||
int p_408928_
|
||||
) {
|
||||
+ return createTexture(p_397830_, p_394481_, p_394839_, p_391831_, p_395609_, p_407582_, p_408928_, false);
|
||||
+ }
|
||||
@@ -17,23 +17,23 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,6 +_,15 @@
|
||||
@@ -133,6 +_,15 @@
|
||||
public GpuTexture createTexture(
|
||||
@Nullable String p_394142_, int p_395535_, TextureFormat p_394951_, int p_393944_, int p_392329_, int p_408015_, int p_406483_
|
||||
@Nullable String p_394142_, @GpuTexture.Usage int p_395535_, TextureFormat p_394951_, int p_393944_, int p_392329_, int p_408015_, int p_406483_
|
||||
) {
|
||||
+ return createTexture(p_394142_, p_395535_, p_394951_, p_393944_, p_392329_, p_408015_, p_406483_, false);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public GpuTexture createTexture(
|
||||
+ @Nullable String p_394142_, int p_395535_, TextureFormat p_394951_, int p_393944_, int p_392329_, int p_408015_, int p_406483_, boolean stencil
|
||||
+ @Nullable String p_394142_, @GpuTexture.Usage int p_395535_, TextureFormat p_394951_, int p_393944_, int p_392329_, int p_408015_, int p_406483_, boolean stencil
|
||||
+ ) {
|
||||
+ // Forge: stencil rendering is only for depth
|
||||
+ stencil &= p_394951_.hasDepthAspect();
|
||||
if (p_406483_ < 1) {
|
||||
throw new IllegalArgumentException("mipLevels must be at least 1");
|
||||
} else if (p_408015_ < 1) {
|
||||
@@ -149,11 +_,14 @@
|
||||
@@ -183,11 +_,14 @@
|
||||
GlStateManager._texImage2D(
|
||||
k,
|
||||
l,
|
||||
@@ -48,7 +48,7 @@
|
||||
GlConst.toGlType(p_394951_),
|
||||
null
|
||||
);
|
||||
@@ -164,11 +_,14 @@
|
||||
@@ -198,11 +_,14 @@
|
||||
GlStateManager._texImage2D(
|
||||
j,
|
||||
i1,
|
||||
@@ -63,7 +63,7 @@
|
||||
GlConst.toGlType(p_394951_),
|
||||
null
|
||||
);
|
||||
@@ -181,7 +_,7 @@
|
||||
@@ -215,7 +_,7 @@
|
||||
} else if (j1 != 0) {
|
||||
throw new IllegalStateException("OpenGL error " + j1);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlStateManager.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlStateManager.java
|
||||
@@ -85,6 +_,11 @@
|
||||
@@ -86,6 +_,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlTexture.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlTexture.java
|
||||
@@ -19,8 +_,13 @@
|
||||
private int views;
|
||||
|
||||
protected GlTexture(int p_394590_, String p_393950_, TextureFormat p_392837_, int p_391379_, int p_391947_, int p_396659_, int p_408255_, int p_408889_) {
|
||||
@@ -21,8 +_,13 @@
|
||||
protected GlTexture(
|
||||
@GpuTexture.Usage int p_394590_, String p_393950_, TextureFormat p_392837_, int p_391379_, int p_391947_, int p_396659_, int p_408255_, int p_408889_
|
||||
) {
|
||||
+ this(p_394590_, p_393950_, p_392837_, p_391379_, p_391947_, p_396659_, p_408255_, p_408889_, false);
|
||||
+ }
|
||||
+
|
||||
@@ -14,20 +14,16 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,6 +_,16 @@
|
||||
public void setTextureFilter(FilterMode p_394977_, FilterMode p_397175_, boolean p_393558_) {
|
||||
super.setTextureFilter(p_394977_, p_397175_, p_393558_);
|
||||
this.modesDirty = true;
|
||||
@@ -89,5 +_,12 @@
|
||||
if (this.closed && this.views == 0) {
|
||||
this.destroyImmediately();
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* FORGE START */
|
||||
+
|
||||
+ private final boolean stencilEnabled;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isStencilEnabled() {
|
||||
+ return this.stencilEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
--- a/com/mojang/blaze3d/pipeline/RenderTarget.java
|
||||
+++ b/com/mojang/blaze3d/pipeline/RenderTarget.java
|
||||
@@ -86,7 +_,7 @@
|
||||
@@ -80,7 +_,7 @@
|
||||
this.width = p_83951_;
|
||||
this.height = p_83952_;
|
||||
if (this.useDepth) {
|
||||
- this.depthTexture = gpudevice.createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, p_83951_, p_83952_, 1, 1);
|
||||
+ this.depthTexture = gpudevice.createTexture(() -> this.label + " / Depth", 15, TextureFormat.DEPTH32, p_83951_, p_83952_, 1, 1, this.stencilEnabled);
|
||||
this.depthTextureView = gpudevice.createTextureView(this.depthTexture);
|
||||
this.depthTexture.setTextureFilter(FilterMode.NEAREST, false);
|
||||
this.depthTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE);
|
||||
@@ -155,5 +_,26 @@
|
||||
@Nullable
|
||||
public GpuTextureView getDepthTextureView() {
|
||||
}
|
||||
|
||||
@@ -126,5 +_,26 @@
|
||||
|
||||
public @Nullable GpuTextureView getDepthTextureView() {
|
||||
return this.depthTextureView;
|
||||
+ }
|
||||
+
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/com/mojang/blaze3d/systems/GpuDevice.java
|
||||
+++ b/com/mojang/blaze3d/systems/GpuDevice.java
|
||||
@@ -26,7 +_,17 @@
|
||||
@Nullable Supplier<String> p_394357_, int p_395623_, TextureFormat p_395807_, int p_395802_, int p_396157_, int p_408810_, int p_407070_
|
||||
@@ -36,9 +_,19 @@
|
||||
int p_407070_
|
||||
);
|
||||
|
||||
+ /** Forge: same as {@link #createTexture(Supplier, int, TextureFormat, int, int, int)} but with stencil support */
|
||||
@@ -9,7 +9,9 @@
|
||||
+ return this.createTexture(p_394357_, p_395623_, p_395807_, p_395802_, p_396157_, p_408810_, p_407070_);
|
||||
+ }
|
||||
+
|
||||
GpuTexture createTexture(@Nullable String p_391798_, int p_391800_, TextureFormat p_393333_, int p_395600_, int p_394065_, int p_408732_, int p_407125_);
|
||||
GpuTexture createTexture(
|
||||
@Nullable String p_391798_, @GpuTexture.Usage int p_391800_, TextureFormat p_393333_, int p_395600_, int p_394065_, int p_408732_, int p_407125_
|
||||
);
|
||||
+
|
||||
+ /** Forge: same as {@link #createTexture(String, int, TextureFormat, int, int, int)} but with stencil support */
|
||||
+ default GpuTexture createTexture(@Nullable String p_391798_, int p_391800_, TextureFormat p_393333_, int p_395600_, int p_394065_, int p_408732_, int p_407125_, boolean stencil) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/textures/GpuTexture.java
|
||||
+++ b/com/mojang/blaze3d/textures/GpuTexture.java
|
||||
@@ -6,7 +_,7 @@
|
||||
@@ -10,7 +_,7 @@
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@DontObfuscate
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/com/mojang/blaze3d/vertex/VertexConsumer.java
|
||||
+++ b/com/mojang/blaze3d/vertex/VertexConsumer.java
|
||||
@@ -15,7 +_,7 @@
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
@@ -14,7 +_,7 @@
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public interface VertexConsumer {
|
||||
@@ -9,15 +9,3 @@
|
||||
VertexConsumer addVertex(float p_344294_, float p_342213_, float p_344859_);
|
||||
|
||||
VertexConsumer setColor(int p_342749_, int p_344324_, int p_343336_, int p_342831_);
|
||||
@@ -131,9 +_,11 @@
|
||||
|
||||
int j1 = ARGB.color(k, (int)f3, (int)f4, (int)f5);
|
||||
int k1 = LightTexture.lightCoordsWithEmission(p_331444_[i1], l);
|
||||
+ k1 = applyBakedLighting(k1, bytebuffer);
|
||||
float f10 = bytebuffer.getFloat(16);
|
||||
float f9 = bytebuffer.getFloat(20);
|
||||
Vector3f vector3f1 = matrix4f.transformPosition(f, f1, f2, new Vector3f());
|
||||
+ applyBakedNormals(vector3f, bytebuffer, p_85988_.normal());
|
||||
this.addVertex(vector3f1.x(), vector3f1.y(), vector3f1.z(), j1, f10, f9, p_85993_, k1, vector3f.x(), vector3f.y(), vector3f.z());
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,15 @@
|
||||
public static final int UNKNOWN_ELEMENT = -1;
|
||||
private final List<VertexFormatElement> elements;
|
||||
private final List<String> names;
|
||||
@@ -31,6 +_,7 @@
|
||||
private GpuBuffer immediateDrawVertexBuffer;
|
||||
@Nullable
|
||||
private GpuBuffer immediateDrawIndexBuffer;
|
||||
@@ -29,6 +_,7 @@
|
||||
private final int[] offsetsByElement = new int[32];
|
||||
private @Nullable GpuBuffer immediateDrawVertexBuffer;
|
||||
private @Nullable GpuBuffer immediateDrawIndexBuffer;
|
||||
+ private final com.google.common.collect.ImmutableMap<String, VertexFormatElement> elementMapping;
|
||||
|
||||
VertexFormat(List<VertexFormatElement> p_343616_, List<String> p_345241_, IntList p_345522_, int p_344162_) {
|
||||
this.elements = p_343616_;
|
||||
@@ -43,6 +_,11 @@
|
||||
@@ -41,6 +_,11 @@
|
||||
int j = vertexformatelement != null ? p_343616_.indexOf(vertexformatelement) : -1;
|
||||
this.offsetsByElement[i] = j != -1 ? p_345522_.getInt(j) : -1;
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
public static VertexFormat.Builder builder() {
|
||||
@@ -141,6 +_,9 @@
|
||||
@@ -139,6 +_,9 @@
|
||||
this.immediateDrawIndexBuffer = uploadToBuffer(this.immediateDrawIndexBuffer, p_391835_, 72, () -> "Immediate index buffer for " + this);
|
||||
return this.immediateDrawIndexBuffer;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
--- a/com/mojang/math/Transformation.java
|
||||
+++ b/com/mojang/math/Transformation.java
|
||||
@@ -14,7 +_,7 @@
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
@@ -16,7 +_,7 @@
|
||||
import org.joml.Vector3fc;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
-public final class Transformation {
|
||||
+public final class Transformation implements net.minecraftforge.common.extensions.IForgeTransformation {
|
||||
private final Matrix4fc matrix;
|
||||
public static final Codec<Transformation> CODEC = RecordCodecBuilder.create(
|
||||
p_269604_ -> p_269604_.group(
|
||||
@@ -174,5 +_,19 @@
|
||||
vector3f1.lerp(p_175938_.getScale(), p_175939_);
|
||||
quaternionf1.slerp(p_175938_.getRightRotation(), p_175939_);
|
||||
return new Transformation(vector3f, quaternionf, vector3f1, quaternionf1);
|
||||
@@ -168,5 +_,19 @@
|
||||
this.getScale().lerp(p_175938_.getScale(), p_175939_, new Vector3f()),
|
||||
this.getRightRotation().slerp(p_175938_.getRightRotation(), p_175939_, new Quaternionf())
|
||||
);
|
||||
+ }
|
||||
+
|
||||
+ private Matrix3f normalTransform = null;
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/realmsclient/gui/screens/RealmsGenericErrorScreen.java
|
||||
+++ b/com/mojang/realmsclient/gui/screens/RealmsGenericErrorScreen.java
|
||||
@@ -71,6 +_,15 @@
|
||||
@@ -62,6 +_,15 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,4 +15,4 @@
|
||||
+ @Override
|
||||
public void render(GuiGraphics p_283497_, int p_88680_, int p_88681_, float p_88682_) {
|
||||
super.render(p_283497_, p_88680_, p_88681_, p_88682_);
|
||||
p_283497_.drawCenteredString(this.font, this.lines.title, this.width / 2, 80, -1);
|
||||
p_283497_.drawCenteredString(this.font, this.title, this.width / 2, 80, -1);
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
--- a/com/mojang/realmsclient/gui/screens/RealmsResetWorldScreen.java
|
||||
+++ b/com/mojang/realmsclient/gui/screens/RealmsResetWorldScreen.java
|
||||
@@ -263,7 +_,7 @@
|
||||
int k = this.getY();
|
||||
p_282595_.blit(RenderPipelines.GUI_TEXTURED, this.image, j + 2, k + 2, 0.0F, 0.0F, 56, 56, 56, 56, 56, 56, i);
|
||||
p_282595_.blitSprite(RenderPipelines.GUI_TEXTURED, SLOT_FRAME_SPRITE, j, k, 60, 60, i);
|
||||
- int l = flag ? -6250336 : -1;
|
||||
+ int l = getFGColor();
|
||||
p_282595_.drawCenteredString(RealmsResetWorldScreen.this.font, this.getMessage(), j + 28, k - 14, l);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/SharedConstants.java
|
||||
+++ b/net/minecraft/SharedConstants.java
|
||||
@@ -224,6 +_,7 @@
|
||||
@@ -216,6 +_,7 @@
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/advancements/Advancement.java
|
||||
+++ b/net/minecraft/advancements/Advancement.java
|
||||
@@ -233,7 +_,11 @@
|
||||
@@ -231,7 +_,11 @@
|
||||
}
|
||||
|
||||
public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, String p_138391_) {
|
||||
- AdvancementHolder advancementholder = this.build(ResourceLocation.parse(p_138391_));
|
||||
+ return save(p_138390_, ResourceLocation.parse(p_138391_));
|
||||
- AdvancementHolder advancementholder = this.build(Identifier.parse(p_138391_));
|
||||
+ return save(p_138390_, Identifier.parse(p_138391_));
|
||||
+ }
|
||||
+
|
||||
+ public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, ResourceLocation id) {
|
||||
+ public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, Identifier id) {
|
||||
+ AdvancementHolder advancementholder = this.build(id);
|
||||
p_138390_.accept(advancementholder);
|
||||
return advancementholder;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/advancements/AdvancementRewards.java
|
||||
+++ b/net/minecraft/advancements/AdvancementRewards.java
|
||||
@@ -43,6 +_,7 @@
|
||||
@@ -44,6 +_,7 @@
|
||||
LootParams lootparams = new LootParams.Builder(serverlevel)
|
||||
.withParameter(LootContextParams.THIS_ENTITY, p_9990_)
|
||||
.withParameter(LootContextParams.ORIGIN, p_9990_.position())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Camera.java
|
||||
+++ b/net/minecraft/client/Camera.java
|
||||
@@ -132,9 +_,13 @@
|
||||
@@ -136,9 +_,13 @@
|
||||
}
|
||||
|
||||
protected void setRotation(float p_90573_, float p_90574_) {
|
||||
@@ -15,10 +15,10 @@
|
||||
FORWARDS.rotate(this.rotation, this.forwards);
|
||||
UP.rotate(this.rotation, this.up);
|
||||
LEFT.rotate(this.rotation, this.left);
|
||||
@@ -250,6 +_,13 @@
|
||||
@@ -168,6 +_,13 @@
|
||||
|
||||
public float getPartialTickTime() {
|
||||
return this.partialTickTime;
|
||||
public float yRot() {
|
||||
return this.yRot;
|
||||
+ }
|
||||
+
|
||||
+ public net.minecraft.world.level.block.state.BlockState getBlockAtCamera() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/client/KeyMapping.java
|
||||
+++ b/net/minecraft/client/KeyMapping.java
|
||||
@@ -19,9 +_,9 @@
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class KeyMapping implements Comparable<KeyMapping> {
|
||||
@@ -12,7 +12,7 @@
|
||||
private final String name;
|
||||
private final InputConstants.Key defaultKey;
|
||||
private final KeyMapping.Category category;
|
||||
@@ -38,7 +_,7 @@
|
||||
@@ -39,7 +_,7 @@
|
||||
}
|
||||
|
||||
private static void forAllKeyMappings(InputConstants.Key p_424096_, Consumer<KeyMapping> p_427756_) {
|
||||
@@ -21,7 +21,7 @@
|
||||
if (list != null && !list.isEmpty()) {
|
||||
for (KeyMapping keymapping : list) {
|
||||
p_427756_.accept(keymapping);
|
||||
@@ -100,7 +_,7 @@
|
||||
@@ -106,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean isDown() {
|
||||
@@ -30,12 +30,13 @@
|
||||
}
|
||||
|
||||
public KeyMapping.Category getCategory() {
|
||||
@@ -140,7 +_,16 @@
|
||||
public int compareTo(KeyMapping p_90841_) {
|
||||
return this.category == p_90841_.category
|
||||
? I18n.get(this.name).compareTo(I18n.get(p_90841_.name))
|
||||
- : Integer.compare(KeyMapping.Category.SORT_ORDER.indexOf(this.category), KeyMapping.Category.SORT_ORDER.indexOf(p_90841_.category));
|
||||
+ : compareSort(this.category, p_90841_.category);
|
||||
@@ -149,8 +_,17 @@
|
||||
? I18n.get(this.name).compareTo(I18n.get(p_90841_.name))
|
||||
: Integer.compare(this.order, p_90841_.order);
|
||||
} else {
|
||||
- return Integer.compare(KeyMapping.Category.SORT_ORDER.indexOf(this.category), KeyMapping.Category.SORT_ORDER.indexOf(p_90841_.category));
|
||||
+ return compareSort(this.category, p_90841_.category);
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ private static int compareSort(Category c1, Category c2) {
|
||||
@@ -48,7 +49,7 @@
|
||||
}
|
||||
|
||||
public static Supplier<Component> createNameSupplier(String p_90843_) {
|
||||
@@ -149,6 +_,20 @@
|
||||
@@ -159,6 +_,20 @@
|
||||
}
|
||||
|
||||
public boolean same(KeyMapping p_90851_) {
|
||||
@@ -69,7 +70,7 @@
|
||||
return this.key.equals(p_90851_.key);
|
||||
}
|
||||
|
||||
@@ -167,11 +_,13 @@
|
||||
@@ -177,11 +_,13 @@
|
||||
}
|
||||
|
||||
public Component getTranslatedKeyMessage() {
|
||||
@@ -84,7 +85,7 @@
|
||||
}
|
||||
|
||||
public String saveString() {
|
||||
@@ -183,12 +_,94 @@
|
||||
@@ -193,11 +_,94 @@
|
||||
}
|
||||
|
||||
private void registerMapping(InputConstants.Key p_423386_) {
|
||||
@@ -92,8 +93,7 @@
|
||||
+ MAP.put(p_423386_, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KeyMapping get(String p_378660_) {
|
||||
public static @Nullable KeyMapping get(String p_378660_) {
|
||||
return ALL.get(p_378660_);
|
||||
+ }
|
||||
+
|
||||
@@ -104,28 +104,28 @@
|
||||
+ /**
|
||||
+ * Convenience constructor for creating KeyBindings with keyConflictContext set.
|
||||
+ */
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, final InputConstants.Type inputType, final int keyCode, Category category) {
|
||||
+ this(description, keyConflictContext, inputType.getOrCreate(keyCode), category);
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, final InputConstants.Type inputType, final int keyCode, Category category, int order) {
|
||||
+ this(description, keyConflictContext, inputType.getOrCreate(keyCode), category, order);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Convenience constructor for creating KeyBindings with keyConflictContext set.
|
||||
+ */
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, InputConstants.Key keyCode, Category category) {
|
||||
+ this(description, keyConflictContext, net.minecraftforge.client.settings.KeyModifier.NONE, keyCode, category);
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, InputConstants.Key keyCode, Category category, int order) {
|
||||
+ this(description, keyConflictContext, net.minecraftforge.client.settings.KeyModifier.NONE, keyCode, category, order);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Convenience constructor for creating KeyBindings with keyConflictContext and keyModifier set.
|
||||
+ */
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, net.minecraftforge.client.settings.KeyModifier keyModifier, final InputConstants.Type inputType, final int keyCode, Category category) {
|
||||
+ this(description, keyConflictContext, keyModifier, inputType.getOrCreate(keyCode), category);
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, net.minecraftforge.client.settings.KeyModifier keyModifier, final InputConstants.Type inputType, final int keyCode, Category category, int order) {
|
||||
+ this(description, keyConflictContext, keyModifier, inputType.getOrCreate(keyCode), category, order);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Convenience constructor for creating KeyBindings with keyConflictContext and keyModifier set.
|
||||
+ */
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, net.minecraftforge.client.settings.KeyModifier keyModifier, InputConstants.Key keyCode, Category category) {
|
||||
+ public KeyMapping(String description, net.minecraftforge.client.settings.IKeyConflictContext keyConflictContext, net.minecraftforge.client.settings.KeyModifier keyModifier, InputConstants.Key keyCode, Category category, int order) {
|
||||
+ this.name = description;
|
||||
+ this.key = keyCode;
|
||||
+ this.defaultKey = keyCode;
|
||||
@@ -133,6 +133,7 @@
|
||||
+ this.keyConflictContext = keyConflictContext;
|
||||
+ this.keyModifier = keyModifier;
|
||||
+ this.keyModifierDefault = keyModifier;
|
||||
+ this.order = order;
|
||||
+ if (this.keyModifier.matches(keyCode))
|
||||
+ this.keyModifier = net.minecraftforge.client.settings.KeyModifier.NONE;
|
||||
+ ALL.put(description, this);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
--- a/net/minecraft/client/KeyboardHandler.java
|
||||
+++ b/net/minecraft/client/KeyboardHandler.java
|
||||
@@ -499,12 +_,12 @@
|
||||
@@ -497,7 +_,7 @@
|
||||
if (screen != null) {
|
||||
try {
|
||||
if (p_90895_ != 1 && p_90895_ != 2) {
|
||||
- if (p_90895_ == 0 && screen.keyReleased(p_423534_)) {
|
||||
+ if (p_90895_ == 0 && net.minecraftforge.client.ForgeHooksClient.onScreenKeyReleased(screen, p_423534_)) {
|
||||
return;
|
||||
if (options.keyDebugModifier.matches(p_423534_)) {
|
||||
this.usedDebugKeyAsModifier = false;
|
||||
}
|
||||
@@ -506,7 +_,7 @@
|
||||
}
|
||||
} else {
|
||||
screen.afterKeyboardAction();
|
||||
@@ -15,7 +18,7 @@
|
||||
if (this.minecraft.screen == null) {
|
||||
InputConstants.Key inputconstants$key = InputConstants.getKey(p_423534_);
|
||||
KeyMapping.set(inputconstants$key, false);
|
||||
@@ -568,6 +_,7 @@
|
||||
@@ -582,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +26,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,7 +_,7 @@
|
||||
@@ -590,7 +_,7 @@
|
||||
Screen screen = this.minecraft.screen;
|
||||
if (screen != null && this.minecraft.getOverlay() == null) {
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Minecraft.java
|
||||
+++ b/net/minecraft/client/Minecraft.java
|
||||
@@ -260,7 +_,7 @@
|
||||
@@ -265,7 +_,7 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -9,7 +9,7 @@
|
||||
static Minecraft instance;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int MAX_TICKS_PER_UPDATE = 10;
|
||||
@@ -439,7 +_,6 @@
|
||||
@@ -431,7 +_,6 @@
|
||||
}
|
||||
}, Util.nonCriticalIoPool());
|
||||
LOGGER.info("Setting user: {}", this.user.getName());
|
||||
@@ -17,7 +17,7 @@
|
||||
this.demo = p_91084_.game.demo;
|
||||
this.allowsMultiplayer = !p_91084_.game.disableMultiplayer;
|
||||
this.allowsChat = !p_91084_.game.disableChat;
|
||||
@@ -491,10 +_,9 @@
|
||||
@@ -483,10 +_,9 @@
|
||||
LOGGER.error("Couldn't set icon", (Throwable)ioexception);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
RenderSystem.initRenderer(
|
||||
this.window.handle(),
|
||||
this.options.glDebugVerbosity,
|
||||
@@ -505,6 +_,7 @@
|
||||
@@ -498,6 +_,7 @@
|
||||
LOGGER.info("Using optional rendering extensions: {}", String.join(", ", RenderSystem.getDevice().getEnabledExtensions()));
|
||||
this.mainRenderTarget = new MainTarget(this.window.getWidth(), this.window.getHeight());
|
||||
this.resourceManager = new ReloadableResourceManager(PackType.CLIENT_RESOURCES);
|
||||
@@ -37,7 +37,7 @@
|
||||
this.resourcePackRepository.reload();
|
||||
this.options.loadSelectedResourcePacks(this.resourcePackRepository);
|
||||
this.languageManager = new LanguageManager(this.options.languageCode, p_340763_ -> {
|
||||
@@ -593,6 +_,7 @@
|
||||
@@ -585,6 +_,7 @@
|
||||
this.particleResources = new ParticleResources();
|
||||
this.resourceManager.registerReloadListener(this.particleResources);
|
||||
this.particleEngine = new ParticleEngine(this.level, this.particleResources);
|
||||
@@ -45,7 +45,7 @@
|
||||
this.particleResources.onReload(this.particleEngine::clearParticles);
|
||||
this.waypointStyles = new WaypointStyleManager();
|
||||
this.resourceManager.registerReloadListener(this.waypointStyles);
|
||||
@@ -604,6 +_,9 @@
|
||||
@@ -596,6 +_,9 @@
|
||||
this.resourceManager.registerReloadListener(this.gpuWarnlistManager);
|
||||
this.resourceManager.registerReloadListener(this.regionalCompliancies);
|
||||
this.gui = new Gui(this);
|
||||
@@ -55,7 +55,7 @@
|
||||
RealmsClient realmsclient = RealmsClient.getOrCreate(this);
|
||||
this.realmsDataFetcher = new RealmsDataFetcher(realmsclient);
|
||||
RenderSystem.setErrorCallback(this::onFullscreenError);
|
||||
@@ -636,6 +_,7 @@
|
||||
@@ -628,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,14 +63,14 @@
|
||||
this.window.updateVsync(this.options.enableVsync().get());
|
||||
this.window.updateRawMouseInput(this.options.rawMouseInput().get());
|
||||
this.window.setAllowCursorChanges(this.options.allowCursorChanges().get());
|
||||
@@ -659,16 +_,17 @@
|
||||
@@ -651,16 +_,17 @@
|
||||
GameLoadTimesEvent.INSTANCE.beginStep(TelemetryProperty.LOAD_TIME_LOADING_OVERLAY_MS);
|
||||
Minecraft.GameLoadCookie minecraft$gameloadcookie = new Minecraft.GameLoadCookie(realmsclient, p_91084_.quickPlay);
|
||||
this.setOverlay(
|
||||
- new LoadingOverlay(
|
||||
- this, reloadinstance, p_296164_ -> Util.ifElse(p_296164_, p_296162_ -> this.rollbackResourcePacks(p_296162_, minecraft$gameloadcookie), () -> {
|
||||
- this, reloadinstance, p_447796_ -> Util.ifElse(p_447796_, p_296162_ -> this.rollbackResourcePacks(p_296162_, minecraft$gameloadcookie), () -> {
|
||||
+ net.minecraftforge.fml.loading.ImmediateWindowHandler.<LoadingOverlay>loadingOverlay(
|
||||
+ () -> this, () -> reloadinstance, p_296164_ -> Util.ifElse(p_296164_, p_296162_ -> this.rollbackResourcePacks(p_296162_, minecraft$gameloadcookie), () -> {
|
||||
+ () -> this, () -> reloadinstance, p_296164_ -> Util.ifElse(p_296164_, p_447796_ -> this.rollbackResourcePacks(p_447796_, minecraft$gameloadcookie), () -> {
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
this.selfTest();
|
||||
}
|
||||
@@ -84,7 +84,7 @@
|
||||
);
|
||||
this.quickPlayLog = QuickPlayLog.of(p_91084_.quickPlay.logPath());
|
||||
this.framerateLimitTracker = new FramerateLimitTracker(this.options, this);
|
||||
@@ -787,6 +_,7 @@
|
||||
@@ -779,6 +_,7 @@
|
||||
StringBuilder stringbuilder = new StringBuilder("Minecraft");
|
||||
if (checkModStatus().shouldReportAsModified()) {
|
||||
stringbuilder.append("*");
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
|
||||
stringbuilder.append(" ");
|
||||
@@ -810,6 +_,8 @@
|
||||
@@ -802,6 +_,8 @@
|
||||
}
|
||||
|
||||
private UserApiService createUserApiService(YggdrasilAuthenticationService p_193586_, GameConfig p_193587_) {
|
||||
@@ -101,16 +101,16 @@
|
||||
return p_193587_.game.offlineDeveloperMode ? UserApiService.OFFLINE : p_193586_.createUserApiService(p_193587_.user.user.getAccessToken());
|
||||
}
|
||||
|
||||
@@ -822,7 +_,7 @@
|
||||
@@ -814,7 +_,7 @@
|
||||
}
|
||||
|
||||
private void rollbackResourcePacks(Throwable p_91240_, @Nullable Minecraft.GameLoadCookie p_299515_) {
|
||||
private void rollbackResourcePacks(Throwable p_91240_, Minecraft.@Nullable GameLoadCookie p_299515_) {
|
||||
- if (this.resourcePackRepository.getSelectedIds().size() > 1) {
|
||||
+ if (this.resourcePackRepository.getSelectedPacks().stream().anyMatch(e -> !e.isRequired())) { //Forge: This caused infinite loop if any resource packs are forced. Such as mod resources. So check if we can disable any.
|
||||
this.clearResourcePacksOnError(p_91240_, null, p_299515_);
|
||||
} else {
|
||||
Util.throwAsRuntime(p_91240_);
|
||||
@@ -1108,12 +_,6 @@
|
||||
@@ -1100,12 +_,6 @@
|
||||
LOGGER.error("setScreen called from non-game thread");
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
if (p_91153_ == null) {
|
||||
if (this.clientLevelTeardownInProgress) {
|
||||
throw new IllegalStateException("Trying to return to in-game GUI during disconnection");
|
||||
@@ -1132,6 +_,23 @@
|
||||
@@ -1124,6 +_,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,28 +147,28 @@
|
||||
this.screen = p_91153_;
|
||||
if (this.screen != null) {
|
||||
this.screen.added();
|
||||
@@ -1214,6 +_,7 @@
|
||||
FreeTypeUtil.destroy();
|
||||
@@ -1207,6 +_,7 @@
|
||||
Util.shutdownExecutors();
|
||||
RenderSystem.getSamplerCache().close();
|
||||
RenderSystem.getDevice().close();
|
||||
+ net.minecraftforge.fml.config.ConfigTracker.INSTANCE.forceUnload();
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Shutdown failure!", throwable);
|
||||
throw throwable;
|
||||
@@ -1278,7 +_,9 @@
|
||||
RenderSystem.getDevice().createCommandEncoder().clearColorAndDepthTextures(rendertarget.getColorTexture(), 0, rendertarget.getDepthTexture(), 1.0);
|
||||
profilerfiller.push("gameRenderer");
|
||||
if (!this.noRender) {
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickStart(this.deltaTracker);
|
||||
this.gameRenderer.render(this.deltaTracker, p_91384_);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickEnd(this.deltaTracker);
|
||||
}
|
||||
@@ -1289,7 +_,9 @@
|
||||
RenderSystem.getDevice().createCommandEncoder().clearColorAndDepthTextures(rendertarget.getColorTexture(), 0, rendertarget.getDepthTexture(), 1.0);
|
||||
profilerfiller.push("gameRenderer");
|
||||
if (!this.noRender) {
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickStart(this.deltaTracker);
|
||||
this.gameRenderer.render(this.deltaTracker, p_91384_);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickEnd(this.deltaTracker);
|
||||
}
|
||||
|
||||
profilerfiller.popPush("blit");
|
||||
@@ -1388,10 +_,12 @@
|
||||
profilerfiller.popPush("blit");
|
||||
@@ -1401,10 +_,12 @@
|
||||
this.window.setGuiScale(i);
|
||||
if (this.screen != null) {
|
||||
this.screen.resize(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
this.screen.resize(this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
+ net.minecraftforge.client.ForgeHooksClient.resizeGuiLayers(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
this.gameRenderer.resize(this.window.getWidth(), this.window.getHeight());
|
||||
this.mouseHandler.setIgnoreFirstMove();
|
||||
}
|
||||
@@ -1529,6 +_,7 @@
|
||||
@@ -1542,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -186,58 +186,59 @@
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@@ -1556,10 +_,18 @@
|
||||
if (p_91387_ && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- if (!this.level.getBlockState(blockpos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(blockpos)) {
|
||||
@@ -1571,10 +_,18 @@
|
||||
if (p_91387_ && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- if (!this.level.getBlockState(blockpos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(blockpos)) {
|
||||
+ var inputEvent = new net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered(0, this.options.keyAttack, InteractionHand.MAIN_HAND);
|
||||
+ if (net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent)) {
|
||||
+ if (inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(blockpos, blockhitresult);
|
||||
+ this.player.swing(InteractionHand.MAIN_HAND);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
Direction direction = blockhitresult.getDirection();
|
||||
- if (this.gameMode.continueDestroyBlock(blockpos, direction)) {
|
||||
- this.level.addBreakingBlockEffect(blockpos, direction);
|
||||
+ if (this.gameMode.continueDestroyBlock(blockpos, direction) && inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(blockpos, blockhitresult);
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
}
|
||||
@@ -1611,6 +_,8 @@
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
return true;
|
||||
} else {
|
||||
+ var inputEvent = new net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered(0, this.options.keyAttack, InteractionHand.MAIN_HAND);
|
||||
+ if (net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent)) {
|
||||
+ if (inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(blockpos, blockhitresult);
|
||||
+ this.player.swing(InteractionHand.MAIN_HAND);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
Direction direction = blockhitresult.getDirection();
|
||||
- if (this.gameMode.continueDestroyBlock(blockpos, direction)) {
|
||||
- this.level.addBreakingBlockEffect(blockpos, direction);
|
||||
+ if (this.gameMode.continueDestroyBlock(blockpos, direction) && inputEvent.shouldSwingHand()) {
|
||||
+ this.level.addBreakingBlockEffect(blockpos, blockhitresult);
|
||||
+ if (!net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent))
|
||||
switch (this.hitResult.getType()) {
|
||||
case ENTITY:
|
||||
AttackRange attackrange = itemstack.get(DataComponents.ATTACK_RANGE);
|
||||
@@ -1621,7 +_,7 @@
|
||||
case BLOCK:
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- if (!this.level.getBlockState(blockpos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(blockpos)) {
|
||||
this.gameMode.startDestroyBlock(blockpos, blockhitresult.getDirection());
|
||||
if (this.level.getBlockState(blockpos).isAir()) {
|
||||
flag = true;
|
||||
@@ -1634,9 +_,10 @@
|
||||
}
|
||||
|
||||
this.player.resetAttackStrengthTicker();
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onLeftClickEmpty(this.player);
|
||||
}
|
||||
|
||||
- if (!this.player.isSpectator()) {
|
||||
+ if (!this.player.isSpectator() && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
}
|
||||
@@ -1587,6 +_,8 @@
|
||||
return false;
|
||||
} else {
|
||||
boolean flag = false;
|
||||
+ var inputEvent = new net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered(0, this.options.keyAttack, InteractionHand.MAIN_HAND);
|
||||
+ if (!net.minecraftforge.client.event.InputEvent.InteractionKeyMappingTriggered.BUS.post(inputEvent))
|
||||
switch (this.hitResult.getType()) {
|
||||
case ENTITY:
|
||||
this.gameMode.attack(this.player, ((EntityHitResult)this.hitResult).getEntity());
|
||||
@@ -1594,7 +_,7 @@
|
||||
case BLOCK:
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- if (!this.level.getBlockState(blockpos).isAir()) {
|
||||
+ if (!this.level.isEmptyBlock(blockpos)) {
|
||||
this.gameMode.startDestroyBlock(blockpos, blockhitresult.getDirection());
|
||||
if (this.level.getBlockState(blockpos).isAir()) {
|
||||
flag = true;
|
||||
@@ -1607,8 +_,10 @@
|
||||
}
|
||||
|
||||
this.player.resetAttackStrengthTicker();
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onLeftClickEmpty(this.player);
|
||||
}
|
||||
|
||||
+ if (inputEvent.shouldSwingHand())
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
return flag;
|
||||
}
|
||||
@@ -1624,6 +_,12 @@
|
||||
@@ -1655,6 +_,12 @@
|
||||
}
|
||||
|
||||
for (InteractionHand interactionhand : InteractionHand.values()) {
|
||||
@@ -250,16 +251,16 @@
|
||||
ItemStack itemstack = this.player.getItemInHand(interactionhand);
|
||||
if (!itemstack.isItemEnabled(this.level.enabledFeatures())) {
|
||||
return;
|
||||
@@ -1644,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (interactionresult instanceof InteractionResult.Success interactionresult$success2) {
|
||||
- if (interactionresult$success2.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (interactionresult$success2.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(interactionhand);
|
||||
@@ -1676,7 +_,7 @@
|
||||
}
|
||||
|
||||
@@ -1656,7 +_,7 @@
|
||||
if (interactionresult instanceof InteractionResult.Success interactionresult$success2) {
|
||||
- if (interactionresult$success2.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (interactionresult$success2.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(interactionhand);
|
||||
}
|
||||
|
||||
@@ -1689,7 +_,7 @@
|
||||
int i = itemstack.getCount();
|
||||
InteractionResult interactionresult1 = this.gameMode.useItemOn(this.player, interactionhand, blockhitresult);
|
||||
if (interactionresult1 instanceof InteractionResult.Success interactionresult$success) {
|
||||
@@ -268,7 +269,7 @@
|
||||
this.player.swing(interactionhand);
|
||||
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.player.hasInfiniteMaterials())) {
|
||||
this.gameRenderer.itemInHandRenderer.itemUsed(interactionhand);
|
||||
@@ -1672,6 +_,9 @@
|
||||
@@ -1705,6 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +279,7 @@
|
||||
if (!itemstack.isEmpty()
|
||||
&& this.gameMode.useItem(this.player, interactionhand) instanceof InteractionResult.Success interactionresult$success1) {
|
||||
if (interactionresult$success1.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
@@ -1701,6 +_,8 @@
|
||||
@@ -1734,6 +_,8 @@
|
||||
}
|
||||
|
||||
ProfilerFiller profilerfiller = Profiler.get();
|
||||
@@ -287,7 +288,7 @@
|
||||
profilerfiller.push("gui");
|
||||
this.chatListener.tick();
|
||||
this.gui.tick(this.pause);
|
||||
@@ -1786,6 +_,7 @@
|
||||
@@ -1815,6 +_,7 @@
|
||||
|
||||
this.tutorial.tick();
|
||||
|
||||
@@ -295,7 +296,7 @@
|
||||
try {
|
||||
this.level.tick(() -> true);
|
||||
} catch (Throwable throwable1) {
|
||||
@@ -1799,6 +_,7 @@
|
||||
@@ -1828,6 +_,7 @@
|
||||
|
||||
throw new ReportedException(crashreport1);
|
||||
}
|
||||
@@ -303,7 +304,7 @@
|
||||
}
|
||||
|
||||
profilerfiller.popPush("animateTick");
|
||||
@@ -1823,6 +_,7 @@
|
||||
@@ -1852,6 +_,7 @@
|
||||
profilerfiller.popPush("keyboard");
|
||||
this.keyboardHandler.tick();
|
||||
profilerfiller.pop();
|
||||
@@ -311,7 +312,7 @@
|
||||
}
|
||||
|
||||
private boolean isLevelRunningNormally() {
|
||||
@@ -2041,6 +_,7 @@
|
||||
@@ -2070,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void setLevel(ClientLevel p_91157_) {
|
||||
@@ -319,7 +320,7 @@
|
||||
this.level = p_91157_;
|
||||
this.updateLevelInEngines(p_91157_);
|
||||
}
|
||||
@@ -2094,6 +_,7 @@
|
||||
@@ -2131,6 +_,7 @@
|
||||
IntegratedServer integratedserver = this.singleplayerServer;
|
||||
this.singleplayerServer = null;
|
||||
this.gameRenderer.resetData();
|
||||
@@ -327,7 +328,7 @@
|
||||
this.gameMode = null;
|
||||
this.narrator.clear();
|
||||
this.clientLevelTeardownInProgress = true;
|
||||
@@ -2101,6 +_,7 @@
|
||||
@@ -2138,6 +_,7 @@
|
||||
try {
|
||||
if (this.level != null) {
|
||||
this.gui.onDisconnected();
|
||||
@@ -335,15 +336,15 @@
|
||||
}
|
||||
|
||||
if (integratedserver != null) {
|
||||
@@ -2113,6 +_,7 @@
|
||||
@@ -2150,6 +_,7 @@
|
||||
}
|
||||
|
||||
profilerfiller.pop();
|
||||
+ net.minecraftforge.client.ForgeHooksClient.handleClientLevelClosing(this.level);
|
||||
}
|
||||
|
||||
this.setScreenAndShow(p_335030_);
|
||||
@@ -2254,6 +_,7 @@
|
||||
this.setScreenAndShow(p_457642_);
|
||||
@@ -2292,6 +_,7 @@
|
||||
|
||||
private void pickBlock() {
|
||||
if (this.hitResult != null && this.hitResult.getType() != HitResult.Type.MISS) {
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
this.activeButton = null;
|
||||
}
|
||||
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPre(mousebuttoninfo.button(), p_423948_, mousebuttoninfo.modifiers())) return;
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPre(mousebuttoninfo, p_423948_)) return;
|
||||
if (this.minecraft.getOverlay() == null) {
|
||||
if (this.minecraft.screen == null) {
|
||||
if (!this.mouseGrabbed && flag) {
|
||||
@@ -103,7 +_,7 @@
|
||||
try {
|
||||
long i = Util.getMillis();
|
||||
boolean flag1 = i - this.lastClickTime < 250L && this.lastClickButton == mousebuttonevent.button();
|
||||
@@ -106,7 +_,7 @@
|
||||
&& i - this.lastClick.time() < 250L
|
||||
&& this.lastClick.screen() == screen
|
||||
&& this.lastClickButton == mousebuttonevent.button();
|
||||
- if (screen.mouseClicked(mousebuttonevent, flag1)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseClicked(screen, d0, d1, mousebuttonevent, flag1)) {
|
||||
this.lastClickTime = i;
|
||||
this.lastClick = new MouseHandler.LastClick(i, screen);
|
||||
this.lastClickButton = mousebuttoninfo.button();
|
||||
return;
|
||||
@@ -118,7 +_,7 @@
|
||||
@@ -121,7 +_,7 @@
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
@@ -26,15 +26,15 @@
|
||||
return;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
@@ -148,6 +_,7 @@
|
||||
@@ -151,6 +_,7 @@
|
||||
KeyMapping.click(inputconstants$key);
|
||||
}
|
||||
}
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(mousebuttoninfo.button(), p_423948_, mousebuttoninfo.modifiers());
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(mousebuttoninfo, p_423948_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +_,9 @@
|
||||
@@ -207,7 +_,9 @@
|
||||
if (this.minecraft.screen != null) {
|
||||
double d3 = this.getScaledXPos(this.minecraft.getWindow());
|
||||
double d4 = this.getScaledYPos(this.minecraft.getWindow());
|
||||
@@ -45,7 +45,7 @@
|
||||
this.minecraft.screen.afterMouseAction();
|
||||
} else if (this.minecraft.player != null) {
|
||||
Vector2i vector2i = this.scrollWheelHandler.onMouseScroll(d1, d2);
|
||||
@@ -213,6 +_,7 @@
|
||||
@@ -216,6 +_,7 @@
|
||||
}
|
||||
|
||||
int i = vector2i.y == 0 ? -vector2i.x : vector2i.y;
|
||||
@@ -53,7 +53,7 @@
|
||||
if (this.minecraft.player.isSpectator()) {
|
||||
if (this.minecraft.gui.getSpectatorGui().isMenuActive()) {
|
||||
this.minecraft.gui.getSpectatorGui().onMouseScrolled(-i);
|
||||
@@ -321,7 +_,7 @@
|
||||
@@ -324,7 +_,7 @@
|
||||
double d5 = getScaledYPos(window, this.accumulatedDY);
|
||||
|
||||
try {
|
||||
@@ -62,7 +62,7 @@
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport1 = CrashReport.forThrowable(throwable, "mouseDragged event handler");
|
||||
screen.fillCrashDetails(crashreport1);
|
||||
@@ -408,6 +_,14 @@
|
||||
@@ -411,6 +_,14 @@
|
||||
|
||||
public double ypos() {
|
||||
return this.ypos;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Options.java
|
||||
+++ b/net/minecraft/client/Options.java
|
||||
@@ -709,7 +_,8 @@
|
||||
@@ -816,7 +_,8 @@
|
||||
},
|
||||
new OptionInstance.LazyEnum<>(
|
||||
() -> Stream.concat(Stream.of(""), Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().stream()).toList(),
|
||||
@@ -10,15 +10,15 @@
|
||||
? Optional.empty()
|
||||
: Optional.of(p_232011_),
|
||||
Codec.STRING
|
||||
@@ -743,6 +_,7 @@
|
||||
@@ -848,6 +_,7 @@
|
||||
);
|
||||
public boolean syncWrites;
|
||||
public boolean startedCleanly = true;
|
||||
+ private final Map<String, String> unknownKeys = new java.util.HashMap<>();
|
||||
|
||||
public OptionInstance<Boolean> darkMojangStudiosBackground() {
|
||||
return this.darkMojangStudiosBackground;
|
||||
@@ -1150,6 +_,7 @@
|
||||
private static void operateOnLevelRenderer(Consumer<LevelRenderer> p_457625_) {
|
||||
LevelRenderer levelrenderer = Minecraft.getInstance().levelRenderer;
|
||||
@@ -1313,6 +_,7 @@
|
||||
}
|
||||
|
||||
public Options(Minecraft p_92138_, File p_92139_) {
|
||||
@@ -26,9 +26,9 @@
|
||||
this.minecraft = p_92138_;
|
||||
this.optionsFile = new File(p_92139_, "options.txt");
|
||||
boolean flag = Runtime.getRuntime().maxMemory() >= 1000000000L;
|
||||
@@ -1290,15 +_,28 @@
|
||||
@@ -1463,15 +_,28 @@
|
||||
this.startedCleanly = p_168428_.process("startedCleanly", this.startedCleanly);
|
||||
p_168428_.process("showNowPlayingToast", this.showNowPlayingToast);
|
||||
p_168428_.process("musicToast", this.musicToast);
|
||||
p_168428_.process("musicFrequency", this.musicFrequency);
|
||||
+ processOptionsKeysOnly(p_168428_);
|
||||
+ processOptionsEnd(p_168428_);
|
||||
@@ -56,7 +56,7 @@
|
||||
for (SoundSource soundsource : SoundSource.values()) {
|
||||
p_168428_.process("soundCategory_" + soundsource.getName(), this.soundSourceVolumes.get(soundsource));
|
||||
}
|
||||
@@ -1313,6 +_,10 @@
|
||||
@@ -1486,6 +_,10 @@
|
||||
}
|
||||
|
||||
public void load() {
|
||||
@@ -67,17 +67,17 @@
|
||||
try {
|
||||
if (!this.optionsFile.exists()) {
|
||||
return;
|
||||
@@ -1337,7 +_,8 @@
|
||||
this.graphicsMode.set(isTrue(optional.get()) ? GraphicsStatus.FANCY : GraphicsStatus.FAST);
|
||||
@@ -1505,7 +_,8 @@
|
||||
}
|
||||
|
||||
final CompoundTag compoundtag1 = this.dataFix(compoundtag);
|
||||
- this.processOptions(
|
||||
+ java.util.function.Consumer<FieldAccess> processor = limited ? this::processOptionsKeysOnly : this::processOptions;
|
||||
+ processor.accept(
|
||||
new Options.FieldAccess() {
|
||||
@Nullable
|
||||
private String getValue(String p_394210_) {
|
||||
@@ -1418,6 +_,17 @@
|
||||
private @Nullable String getValue(String p_394210_) {
|
||||
Tag tag = compoundtag1.get(p_394210_);
|
||||
@@ -1585,6 +_,17 @@
|
||||
);
|
||||
compoundtag1.getString("fullscreenResolution").ifPresent(p_389133_ -> this.fullscreenVideoModeString = p_389133_);
|
||||
KeyMapping.resetMapping();
|
||||
@@ -95,7 +95,7 @@
|
||||
} catch (Exception exception) {
|
||||
LOGGER.error("Failed to load options", (Throwable)exception);
|
||||
}
|
||||
@@ -1445,9 +_,11 @@
|
||||
@@ -1612,9 +_,11 @@
|
||||
public void save() {
|
||||
try (final PrintWriter printwriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.optionsFile), StandardCharsets.UTF_8))) {
|
||||
printwriter.println("version:" + SharedConstants.getCurrentVersion().dataVersion().version());
|
||||
@@ -107,7 +107,7 @@
|
||||
printwriter.print(p_168491_);
|
||||
printwriter.print(':');
|
||||
}
|
||||
@@ -1503,6 +_,12 @@
|
||||
@@ -1670,6 +_,12 @@
|
||||
if (s != null) {
|
||||
printwriter.println("fullscreenResolution:" + s);
|
||||
}
|
||||
@@ -120,7 +120,7 @@
|
||||
} catch (Exception exception) {
|
||||
LOGGER.error("Failed to save options", (Throwable)exception);
|
||||
}
|
||||
@@ -1541,6 +_,7 @@
|
||||
@@ -1707,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void broadcastOptions() {
|
||||
@@ -128,7 +128,7 @@
|
||||
if (this.minecraft.player != null) {
|
||||
this.minecraft.player.connection.broadcastClientInformation(this.buildPlayerInformation());
|
||||
}
|
||||
@@ -1654,6 +_,23 @@
|
||||
@@ -1820,6 +_,23 @@
|
||||
|
||||
public static Component genericValueLabel(Component p_231901_, int p_231902_) {
|
||||
return genericValueLabel(p_231901_, Component.literal(Integer.toString(p_231902_)));
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
file2 = new File(file1, p_92297_);
|
||||
}
|
||||
|
||||
+ var event = new net.minecraftforge.client.event.ScreenshotEvent(p_389141_, file2);
|
||||
+ var event = new net.minecraftforge.client.event.ScreenshotEvent(p_447863_, file2);
|
||||
+ if (net.minecraftforge.client.event.ScreenshotEvent.BUS.post(event)) {
|
||||
+ p_92301_.accept(event.getCancelMessage());
|
||||
+ return;
|
||||
@@ -15,12 +15,12 @@
|
||||
.execute(
|
||||
() -> {
|
||||
@@ -50,10 +_,13 @@
|
||||
NativeImage $$4x = p_389141_;
|
||||
NativeImage $$4x = p_447863_;
|
||||
|
||||
try {
|
||||
- p_389141_.writeToFile(file2);
|
||||
- p_447863_.writeToFile(file2);
|
||||
- Component component = Component.literal(file2.getName())
|
||||
+ p_389141_.writeToFile(target);
|
||||
+ p_447863_.writeToFile(target);
|
||||
+ Component component = Component.literal(target.getName())
|
||||
.withStyle(ChatFormatting.UNDERLINE)
|
||||
.withStyle(p_389149_ -> p_389149_.withClickEvent(new ClickEvent.OpenFile(file2.getAbsoluteFile())));
|
||||
@@ -29,4 +29,4 @@
|
||||
+ else
|
||||
p_92301_.accept(Component.translatable("screenshot.success", component));
|
||||
} catch (Throwable throwable1) {
|
||||
if (p_389141_ != null) {
|
||||
if (p_447863_ != null) {
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/data/Main.java
|
||||
+++ b/net/minecraft/client/data/Main.java
|
||||
@@ -31,13 +_,18 @@
|
||||
@@ -30,13 +_,18 @@
|
||||
OptionSpec<Void> optionspec1 = optionparser.accepts("client", "Include client generators");
|
||||
OptionSpec<Void> optionspec2 = optionparser.accepts("all", "Include all generators");
|
||||
OptionSpec<String> optionspec3 = optionparser.accepts("output", "Output folder").withRequiredArg().defaultsTo("generated");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
+++ b/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
@@ -882,6 +_,9 @@
|
||||
@@ -912,6 +_,9 @@
|
||||
this.declareCustomModelItem(Items.COD);
|
||||
this.declareCustomModelItem(Items.FEATHER);
|
||||
this.declareCustomModelItem(Items.LEAD);
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
}
|
||||
|
||||
+ protected Stream<Block> getKnownBlocks() {
|
||||
+ return BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().location().getNamespace()));
|
||||
+ return BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().identifier().getNamespace()));
|
||||
+ }
|
||||
+
|
||||
+ protected Stream<Item> getKnownItems() {
|
||||
+ return BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().location().getNamespace()));
|
||||
+ return BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().identifier().getNamespace()));
|
||||
+ }
|
||||
+
|
||||
+ protected BlockModelGenerators getBlockModelGenerators(BlockStateGeneratorCollector blocks, ItemInfoCollector items, SimpleModelCollector models) {
|
||||
@@ -46,7 +46,7 @@
|
||||
+ private final Supplier<Stream<Block>> known;
|
||||
+
|
||||
+ public BlockStateGeneratorCollector() {
|
||||
+ this(() -> BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().location().getNamespace())));
|
||||
+ this(() -> BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().identifier().getNamespace())));
|
||||
+ }
|
||||
+
|
||||
+ public BlockStateGeneratorCollector(Supplier<Stream<Block>> known) {
|
||||
@@ -61,8 +61,8 @@
|
||||
public void validate() {
|
||||
- Stream<Holder.Reference<Block>> stream = BuiltInRegistries.BLOCK.listElements().filter(p_376480_ -> true);
|
||||
+ Stream<Holder.Reference<Block>> stream = known.get().map(Block::builtInRegistryHolder);
|
||||
List<ResourceLocation> list = stream.filter(p_378423_ -> !this.generators.containsKey(p_378423_.value()))
|
||||
.map(p_378200_ -> p_378200_.key().location())
|
||||
List<Identifier> list = stream.filter(p_378423_ -> !this.generators.containsKey(p_378423_.value()))
|
||||
.map(p_447940_ -> p_447940_.key().identifier())
|
||||
.toList();
|
||||
@@ -97,6 +_,15 @@
|
||||
public static class ItemInfoCollector implements ItemModelOutput {
|
||||
@@ -71,7 +71,7 @@
|
||||
+ private final Supplier<Stream<Item>> known;
|
||||
+
|
||||
+ public ItemInfoCollector() {
|
||||
+ this(() -> BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().location().getNamespace())));
|
||||
+ this(() -> BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().identifier().getNamespace())));
|
||||
+ }
|
||||
+
|
||||
+ public ItemInfoCollector(Supplier<Stream<Item>> known) {
|
||||
@@ -79,16 +79,16 @@
|
||||
+ }
|
||||
|
||||
@Override
|
||||
public void accept(Item p_376450_, ItemModel.Unbaked p_378513_) {
|
||||
public void accept(Item p_376450_, ItemModel.Unbaked p_378513_, ClientItem.Properties p_455809_) {
|
||||
@@ -115,7 +_,7 @@
|
||||
this.copies.put(p_376965_, p_377438_);
|
||||
}
|
||||
|
||||
- public void finalizeAndValidate() {
|
||||
+ public void generateDefaultBlockModels() {
|
||||
BuiltInRegistries.ITEM.forEach(p_378629_ -> {
|
||||
if (!this.copies.containsKey(p_378629_)) {
|
||||
if (p_378629_ instanceof BlockItem blockitem && !this.itemInfos.containsKey(blockitem)) {
|
||||
BuiltInRegistries.ITEM.forEach(p_447944_ -> {
|
||||
if (!this.copies.containsKey(p_447944_)) {
|
||||
if (p_447944_ instanceof BlockItem blockitem && !this.itemInfos.containsKey(blockitem)) {
|
||||
@@ -124,6 +_,8 @@
|
||||
}
|
||||
}
|
||||
@@ -102,10 +102,10 @@
|
||||
this.register(p_376289_, clientitem);
|
||||
}
|
||||
});
|
||||
- List<ResourceLocation> list = BuiltInRegistries.ITEM
|
||||
- List<Identifier> list = BuiltInRegistries.ITEM
|
||||
- .listElements()
|
||||
+ List<ResourceLocation> list = known.get()
|
||||
+ List<Identifier> list = known.get()
|
||||
+ .map(item -> item.builtInRegistryHolder())
|
||||
.filter(p_377225_ -> !this.itemInfos.containsKey(p_377225_.value()))
|
||||
.map(p_378591_ -> p_378591_.key().location())
|
||||
.map(p_447943_ -> p_447943_.key().identifier())
|
||||
.toList();
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/client/gui/Font.java
|
||||
+++ b/net/minecraft/client/gui/Font.java
|
||||
@@ -31,7 +_,7 @@
|
||||
import org.joml.Matrix4f;
|
||||
@@ -32,7 +_,7 @@
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class Font {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
private final SubtitleOverlay subtitleOverlay;
|
||||
private final SpectatorGui spectatorGui;
|
||||
private final PlayerTabOverlay tabList;
|
||||
@@ -196,6 +_,7 @@
|
||||
@@ -193,6 +_,7 @@
|
||||
() -> new JumpableVehicleBarRenderer(p_330021_)
|
||||
);
|
||||
this.resetTitleTimes();
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
|
||||
public void resetTitleTimes() {
|
||||
@@ -206,6 +_,10 @@
|
||||
@@ -203,6 +_,10 @@
|
||||
|
||||
public void render(GuiGraphics p_282884_, DeltaTracker p_342095_) {
|
||||
if (!(this.minecraft.screen instanceof LevelLoadingScreen)) {
|
||||
@@ -28,16 +28,16 @@
|
||||
if (!this.minecraft.options.hideGui) {
|
||||
this.renderCameraOverlays(p_282884_, p_342095_);
|
||||
this.renderCrosshair(p_282884_, p_342095_);
|
||||
@@ -389,7 +_,7 @@
|
||||
@@ -386,7 +_,7 @@
|
||||
int i = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window));
|
||||
int j = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window));
|
||||
p_329202_.nextStratum();
|
||||
- this.chat.render(p_329202_, this.tickCount, i, j, false);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeChatEvent(p_329202_, this.chat, window, i, j, this.tickCount);
|
||||
- this.chat.render(p_329202_, this.getFont(), this.tickCount, i, j, false, false);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeChatEvent(p_329202_, this.chat, window, i, j, this.tickCount, this.getFont());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,6 +_,8 @@
|
||||
@@ -476,6 +_,8 @@
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
|
||||
Holder<MobEffect> holder = mobeffectinstance.getEffect();
|
||||
@@ -46,7 +46,7 @@
|
||||
if (mobeffectinstance.showIcon()) {
|
||||
int k = p_282812_.guiWidth();
|
||||
int l = 1;
|
||||
@@ -507,6 +_,7 @@
|
||||
@@ -506,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
p_282812_.blitSprite(RenderPipelines.GUI_TEXTURED, getMobEffectSprite(holder), k + 3, l + 3, 18, 18, ARGB.white(f));
|
||||
}
|
||||
}
|
||||
@@ -603,6 +_,10 @@
|
||||
@@ -602,6 +_,10 @@
|
||||
}
|
||||
|
||||
public void renderSelectedItemName(GuiGraphics p_283501_) {
|
||||
@@ -65,7 +65,7 @@
|
||||
Profiler.get().push("selectedItemName");
|
||||
if (this.toolHighlightTimer > 0 && !this.lastToolHighlight.isEmpty()) {
|
||||
MutableComponent mutablecomponent = Component.empty().append(this.lastToolHighlight.getHoverName()).withStyle(this.lastToolHighlight.getRarity().color());
|
||||
@@ -610,9 +_,13 @@
|
||||
@@ -609,9 +_,13 @@
|
||||
mutablecomponent.withStyle(ChatFormatting.ITALIC);
|
||||
}
|
||||
|
||||
@@ -81,16 +81,16 @@
|
||||
if (!this.minecraft.gameMode.canHurtPlayer()) {
|
||||
k += 14;
|
||||
}
|
||||
@@ -623,7 +_,7 @@
|
||||
@@ -622,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (l > 0) {
|
||||
- p_283501_.drawStringWithBackdrop(this.getFont(), mutablecomponent, j, k, i, ARGB.color(l, -1));
|
||||
+ p_283501_.drawStringWithBackdrop(font, highlightTip, j, k, i, ARGB.color(l, -1));
|
||||
- p_283501_.drawStringWithBackdrop(this.getFont(), mutablecomponent, j, k, i, ARGB.white(l));
|
||||
+ p_283501_.drawStringWithBackdrop(font, highlightTip, j, k, i, ARGB.white(l));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1151,7 +_,7 @@
|
||||
@@ -1148,7 +_,7 @@
|
||||
ItemStack itemstack = this.minecraft.player.getInventory().getSelectedItem();
|
||||
if (itemstack.isEmpty()) {
|
||||
this.toolHighlightTimer = 0;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
--- a/net/minecraft/client/gui/GuiGraphics.java
|
||||
+++ b/net/minecraft/client/gui/GuiGraphics.java
|
||||
@@ -83,7 +_,7 @@
|
||||
import org.joml.Vector3f;
|
||||
@@ -86,7 +_,7 @@
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class GuiGraphics {
|
||||
+public class GuiGraphics implements net.minecraftforge.client.extensions.IForgeGuiGraphics {
|
||||
private static final int EXTRA_SPACE_AFTER_FIRST_TOOLTIP_LINE = 2;
|
||||
private final Minecraft minecraft;
|
||||
final Minecraft minecraft;
|
||||
private final Matrix3x2fStack pose;
|
||||
@@ -950,6 +_,7 @@
|
||||
@@ -972,6 +_,7 @@
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item");
|
||||
CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered");
|
||||
crashreportcategory.setDetail("Item Type", () -> String.valueOf(p_283653_.getItem()));
|
||||
@@ -17,7 +17,7 @@
|
||||
crashreportcategory.setDetail("Item Components", () -> String.valueOf(p_283653_.getComponents()));
|
||||
crashreportcategory.setDetail("Item Foil", () -> String.valueOf(p_283653_.hasFoil()));
|
||||
throw new ReportedException(crashreport);
|
||||
@@ -968,6 +_,7 @@
|
||||
@@ -990,6 +_,7 @@
|
||||
this.renderItemCooldown(p_283349_, p_282641_, p_282146_);
|
||||
this.renderItemCount(p_282005_, p_283349_, p_282641_, p_282146_, p_282803_);
|
||||
this.pose.popMatrix();
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -979,21 +_,30 @@
|
||||
@@ -1001,21 +_,30 @@
|
||||
this.setTooltipForNextFrame(this.minecraft.font, p_407686_, DefaultTooltipPositioner.INSTANCE, p_410475_, p_407139_, false);
|
||||
}
|
||||
|
||||
@@ -50,15 +50,15 @@
|
||||
+ }
|
||||
+
|
||||
public void setTooltipForNextFrame(
|
||||
Font p_407847_, List<Component> p_408847_, Optional<TooltipComponent> p_410489_, int p_409369_, int p_407472_, @Nullable ResourceLocation p_410303_
|
||||
Font p_408450_, List<Component> p_405939_, Optional<TooltipComponent> p_456997_, int p_409519_, int p_410392_, @Nullable Identifier p_460731_
|
||||
) {
|
||||
- List<ClientTooltipComponent> list = p_408847_.stream().map(Component::getVisualOrderText).map(ClientTooltipComponent::create).collect(Util.toMutableList());
|
||||
- p_410489_.ifPresent(p_325321_ -> list.add(list.isEmpty() ? 0 : 1, ClientTooltipComponent.create(p_325321_)));
|
||||
+ List<ClientTooltipComponent> list = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, p_408847_, p_410489_, p_409369_, guiWidth(), guiHeight(), p_407847_);
|
||||
this.setTooltipForNextFrameInternal(p_407847_, list, p_409369_, p_407472_, DefaultTooltipPositioner.INSTANCE, p_410303_, false);
|
||||
- List<ClientTooltipComponent> list = p_405939_.stream().map(Component::getVisualOrderText).map(ClientTooltipComponent::create).collect(Util.toMutableList());
|
||||
- p_456997_.ifPresent(p_325321_ -> list.add(list.isEmpty() ? 0 : 1, ClientTooltipComponent.create(p_325321_)));
|
||||
+ List<ClientTooltipComponent> list = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, p_405939_, p_456997_, p_409519_, guiWidth(), guiHeight(), p_408450_);
|
||||
this.setTooltipForNextFrameInternal(p_408450_, list, p_409519_, p_410392_, DefaultTooltipPositioner.INSTANCE, p_460731_, false);
|
||||
}
|
||||
|
||||
@@ -1006,7 +_,22 @@
|
||||
@@ -1028,7 +_,22 @@
|
||||
}
|
||||
|
||||
public void setComponentTooltipForNextFrame(Font p_406239_, List<Component> p_410275_, int p_410594_, int p_409343_) {
|
||||
@@ -81,12 +81,33 @@
|
||||
+ this.tooltipStack = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public void setComponentTooltipForNextFrame(Font p_408650_, List<Component> p_407512_, int p_406019_, int p_408123_, @Nullable ResourceLocation p_409993_) {
|
||||
@@ -1069,11 +_,13 @@
|
||||
ClientTooltipPositioner p_409451_,
|
||||
@Nullable ResourceLocation p_409298_
|
||||
public void setComponentTooltipForNextFrame(Font p_408650_, List<Component> p_407512_, int p_406019_, int p_408123_, @Nullable Identifier p_456486_) {
|
||||
@@ -1073,24 +_,31 @@
|
||||
int p_407794_,
|
||||
int p_408784_,
|
||||
ClientTooltipPositioner p_408798_,
|
||||
- @Nullable Identifier p_451079_,
|
||||
+ @Nullable Identifier p_456486_,
|
||||
boolean p_410618_
|
||||
) {
|
||||
+ var preEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipPre(this.tooltipStack, this, p_283678_, p_281696_, guiWidth(), guiHeight(), p_282716_, p_283128_, p_409451_);
|
||||
if (!p_409928_.isEmpty()) {
|
||||
if (this.deferredTooltip == null || p_410618_) {
|
||||
- this.deferredTooltip = () -> this.renderTooltip(p_406605_, p_409928_, p_407794_, p_408784_, p_408798_, p_451079_);
|
||||
+ final var stackContext = this.tooltipStack;
|
||||
+ this.deferredTooltip = () -> this.renderTooltip(p_406605_, p_409928_, p_407794_, p_408784_, p_408798_, p_456486_, stackContext);
|
||||
}
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ public void renderTooltip(Font p_283128_, List<ClientTooltipComponent> p_282716_, int p_283678_, int p_281696_, ClientTooltipPositioner p_409451_, @Nullable Identifier p_456486_) {
|
||||
+ renderTooltip(p_283128_, p_282716_, p_283678_, p_281696_, p_409451_, p_456486_, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
public void renderTooltip(
|
||||
- Font p_283128_, List<ClientTooltipComponent> p_282716_, int p_283678_, int p_281696_, ClientTooltipPositioner p_409451_, @Nullable Identifier p_459396_
|
||||
+ Font p_283128_, List<ClientTooltipComponent> p_282716_, int p_283678_, int p_281696_, ClientTooltipPositioner p_409451_, @Nullable Identifier p_459396_, ItemStack itemstack
|
||||
) {
|
||||
+ var preEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipPre(itemstack, this, p_283678_, p_281696_, guiWidth(), guiHeight(), p_282716_, p_283128_, p_409451_, p_459396_);
|
||||
+ if (preEvent == null) return;
|
||||
int i = 0;
|
||||
int j = p_282716_.size() == 1 ? -2 : 0;
|
||||
@@ -97,7 +118,7 @@
|
||||
if (k > i) {
|
||||
i = k;
|
||||
}
|
||||
@@ -1083,16 +_,17 @@
|
||||
@@ -1100,16 +_,16 @@
|
||||
|
||||
int l1 = i;
|
||||
int i2 = j;
|
||||
@@ -106,9 +127,8 @@
|
||||
int l = vector2ic.x();
|
||||
int i1 = vector2ic.y();
|
||||
this.pose.pushMatrix();
|
||||
- TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, p_409298_);
|
||||
+ var background_event = net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTooltipBackground(this.tooltipStack, this, l, i1, preEvent.getFont(), p_282716_, p_409298_);
|
||||
+ TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, background_event.getBackground());
|
||||
- TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, p_459396_);
|
||||
+ TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, preEvent.getBackground());
|
||||
int j1 = i1;
|
||||
|
||||
for (int k1 = 0; k1 < p_282716_.size(); k1++) {
|
||||
@@ -118,7 +138,7 @@
|
||||
j1 += clienttooltipcomponent1.getHeight(p_283128_) + (k1 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -1100,7 +_,7 @@
|
||||
@@ -1117,7 +_,7 @@
|
||||
|
||||
for (int j2 = 0; j2 < p_282716_.size(); j2++) {
|
||||
ClientTooltipComponent clienttooltipcomponent2 = p_282716_.get(j2);
|
||||
@@ -127,7 +147,7 @@
|
||||
j1 += clienttooltipcomponent2.getHeight(p_283128_) + (j2 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -1315,6 +_,14 @@
|
||||
@@ -1328,6 +_,14 @@
|
||||
|
||||
public void submitProfilerChartRenderState(List<ResultField> p_408565_, int p_410147_, int p_406156_, int p_407365_, int p_408180_) {
|
||||
this.guiRenderState.submitPicturesInPictureState(new GuiProfilerChartRenderState(p_408565_, p_410147_, p_406156_, p_407365_, p_408180_, this.scissorStack.peek()));
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/client/gui/components/AbstractButton.java
|
||||
+++ b/net/minecraft/client/gui/components/AbstractButton.java
|
||||
@@ -41,7 +_,7 @@
|
||||
this.getHeight(),
|
||||
ARGB.white(this.alpha)
|
||||
);
|
||||
- int i = ARGB.color(this.alpha, this.active ? -1 : -6250336);
|
||||
+ int i = getFGColor();
|
||||
this.renderString(p_281670_, minecraft.font, i);
|
||||
if (this.isHovered()) {
|
||||
p_281670_.requestCursor(this.isActive() ? CursorTypes.POINTING_HAND : CursorTypes.NOT_ALLOWED);
|
||||
@@ -1,17 +1,16 @@
|
||||
--- a/net/minecraft/client/gui/components/AbstractWidget.java
|
||||
+++ b/net/minecraft/client/gui/components/AbstractWidget.java
|
||||
@@ -238,6 +_,25 @@
|
||||
@@ -221,6 +_,23 @@
|
||||
this.focused = p_93693_;
|
||||
}
|
||||
|
||||
+ // Forge start
|
||||
+ public static final int UNSET_FG_COLOR = -1;
|
||||
+
|
||||
+ protected int packedFGColor = UNSET_FG_COLOR;
|
||||
+
|
||||
+ public int getFGColor() {
|
||||
+ if (packedFGColor != UNSET_FG_COLOR) return packedFGColor;
|
||||
+ return net.minecraft.util.ARGB.color(this.alpha, this.active ? -1 : -6250336); // White : Light Grey
|
||||
+ return this.active ? net.minecraft.util.CommonColors.WHITE : net.minecraft.util.CommonColors.LIGHT_GRAY;
|
||||
+ }
|
||||
+
|
||||
+ public void setFGColor(int color) {
|
||||
@@ -21,7 +20,6 @@
|
||||
+ public void clearFGColor() {
|
||||
+ this.packedFGColor = UNSET_FG_COLOR;
|
||||
+ }
|
||||
+ // Forge end
|
||||
+
|
||||
@Override
|
||||
public NarratableEntry.NarrationPriority narrationPriority() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/Button.java
|
||||
+++ b/net/minecraft/client/gui/components/Button.java
|
||||
@@ -32,6 +_,12 @@
|
||||
@@ -33,6 +_,12 @@
|
||||
this.createNarration = p_259552_;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
}
|
||||
|
||||
public Button build() {
|
||||
- Button button = new Button(this.x, this.y, this.width, this.height, this.message, this.onPress, this.createNarration);
|
||||
- Button button = new Button.Plain(this.x, this.y, this.width, this.height, this.message, this.onPress, this.createNarration);
|
||||
- button.setTooltip(this.tooltip);
|
||||
- return button;
|
||||
+ return build(Button::new);
|
||||
+ return build(Button.Plain::new);
|
||||
+ }
|
||||
+
|
||||
+ // Forge (GH-9238)
|
||||
@@ -29,3 +29,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +_,10 @@
|
||||
int p_455297_, int p_455388_, int p_459653_, int p_452847_, Component p_459347_, Button.OnPress p_453378_, Button.CreateNarration p_456163_
|
||||
) {
|
||||
super(p_455297_, p_455388_, p_459653_, p_452847_, p_459347_, p_453378_, p_456163_);
|
||||
+ }
|
||||
+
|
||||
+ protected Plain(Builder builder) {
|
||||
+ super(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/toasts/ToastManager.java
|
||||
+++ b/net/minecraft/client/gui/components/toasts/ToastManager.java
|
||||
@@ -146,6 +_,7 @@
|
||||
@@ -142,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void addToast(Toast p_360768_) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/render/GuiRenderer.java
|
||||
+++ b/net/minecraft/client/gui/render/GuiRenderer.java
|
||||
@@ -146,6 +_,7 @@
|
||||
@@ -138,6 +_,7 @@
|
||||
builder.put((Class<? extends PictureInPictureRenderState>)pictureinpicturerenderer.getRenderStateClass(), pictureinpicturerenderer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/ConnectScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/ConnectScreen.java
|
||||
@@ -103,6 +_,8 @@
|
||||
@@ -102,6 +_,8 @@
|
||||
}
|
||||
|
||||
if (optional.isEmpty()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/LoadingOverlay.java
|
||||
+++ b/net/minecraft/client/gui/screens/LoadingOverlay.java
|
||||
@@ -62,6 +_,8 @@
|
||||
@@ -63,6 +_,8 @@
|
||||
return p_169325_ & 16777215 | p_169326_ << 24;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@Override
|
||||
public void render(GuiGraphics p_281839_, int p_282704_, int p_283650_, float p_283394_) {
|
||||
int i = p_281839_.guiWidth();
|
||||
@@ -102,6 +_,7 @@
|
||||
@@ -103,6 +_,7 @@
|
||||
f2 = 1.0F;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
int l2 = (int)(p_281839_.guiWidth() * 0.5);
|
||||
int i1 = (int)(p_281839_.guiHeight() * 0.5);
|
||||
double d0 = Math.min(p_281839_.guiWidth() * 0.75, (double)p_281839_.guiHeight()) * 0.25;
|
||||
@@ -117,6 +_,7 @@
|
||||
@@ -118,6 +_,7 @@
|
||||
if (f < 1.0F) {
|
||||
this.drawProgressBar(p_281839_, i / 2 - k1, i2 - 5, i / 2 + k1, i2 + 5, 1.0F - Mth.clamp(f, 0.0F, 1.0F));
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
if (f >= 2.0F) {
|
||||
this.minecraft.setOverlay(null);
|
||||
@@ -126,6 +_,7 @@
|
||||
@@ -127,6 +_,7 @@
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.fadeOutStart == -1L && this.reload.isDone() && this.isReadyToFadeOut()) {
|
||||
@@ -33,11 +33,11 @@
|
||||
try {
|
||||
this.reload.checkExceptions();
|
||||
this.onFinish.accept(Optional.empty());
|
||||
@@ -133,7 +_,6 @@
|
||||
@@ -134,7 +_,6 @@
|
||||
this.onFinish.accept(Optional.of(throwable));
|
||||
}
|
||||
|
||||
- this.fadeOutStart = Util.getMillis();
|
||||
if (this.minecraft.screen != null) {
|
||||
Window window = this.minecraft.getWindow();
|
||||
this.minecraft.screen.init(this.minecraft, window.getGuiScaledWidth(), window.getGuiScaledHeight());
|
||||
this.minecraft.screen.init(window.getGuiScaledWidth(), window.getGuiScaledHeight());
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
@@ -103,6 +_,7 @@
|
||||
@@ -102,6 +_,7 @@
|
||||
} else {
|
||||
gridlayout$rowhelper.addChild(this.openScreenButton(PLAYER_REPORTING, () -> new SocialInteractionsScreen(this)));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/Screen.java
|
||||
+++ b/net/minecraft/client/gui/screens/Screen.java
|
||||
@@ -191,7 +_,7 @@
|
||||
@@ -194,7 +_,7 @@
|
||||
}
|
||||
|
||||
public void onClose() {
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
protected <T extends GuiEventListener & Renderable & NarratableEntry> T addRenderableWidget(T p_169406_) {
|
||||
@@ -343,8 +_,10 @@
|
||||
@@ -326,8 +_,10 @@
|
||||
this.width = p_96608_;
|
||||
this.height = p_96609_;
|
||||
if (!this.initialized) {
|
||||
@@ -20,7 +20,7 @@
|
||||
} else {
|
||||
this.repositionElements();
|
||||
}
|
||||
@@ -361,8 +_,10 @@
|
||||
@@ -344,8 +_,10 @@
|
||||
protected void rebuildWidgets() {
|
||||
this.clearWidgets();
|
||||
this.clearFocus();
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
protected void fadeWidgets(float p_409453_) {
|
||||
@@ -402,6 +_,8 @@
|
||||
@@ -385,6 +_,8 @@
|
||||
this.renderMenuBackground(p_283688_);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
this.minecraft.gui.renderDeferredSubtitles();
|
||||
}
|
||||
|
||||
@@ -484,6 +_,19 @@
|
||||
@@ -467,6 +_,19 @@
|
||||
}
|
||||
|
||||
public void onFilesDrop(List<Path> p_96591_) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/TitleScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/TitleScreen.java
|
||||
@@ -55,6 +_,7 @@
|
||||
@@ -53,6 +_,7 @@
|
||||
private boolean fading;
|
||||
private long fadeInStart;
|
||||
private final LogoRenderer logoRenderer;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public TitleScreen() {
|
||||
this(false);
|
||||
@@ -107,11 +_,15 @@
|
||||
@@ -105,11 +_,15 @@
|
||||
int j = this.width - i - 2;
|
||||
int k = 24;
|
||||
int l = this.height / 4 + 48;
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
l = this.createTestWorldButton(l, 24);
|
||||
SpriteIconButton spriteiconbutton = this.addRenderableWidget(
|
||||
@@ -178,7 +_,7 @@
|
||||
@@ -176,7 +_,7 @@
|
||||
}).bounds(this.width / 2 - 100, i = p_96764_ + p_96765_, 200, 20).tooltip(tooltip).build()).active = flag;
|
||||
this.addRenderableWidget(
|
||||
Button.builder(Component.translatable("menu.online"), p_325369_ -> this.minecraft.setScreen(new RealmsMainScreen(this)))
|
||||
@@ -33,11 +33,11 @@
|
||||
.tooltip(tooltip)
|
||||
.build()
|
||||
)
|
||||
@@ -298,9 +_,18 @@
|
||||
@@ -295,9 +_,18 @@
|
||||
s = s + I18n.get("menu.modded");
|
||||
}
|
||||
|
||||
- p_282860_.drawString(this.font, s, 2, this.height - 10, ARGB.color(f, -1));
|
||||
- p_282860_.drawString(this.font, s, 2, this.height - 10, ARGB.white(f));
|
||||
+ final float f_f = f;
|
||||
+ net.minecraftforge.internal.BrandingControl.forEachLine(true, true, (brd, brdline) ->
|
||||
+ p_282860_.drawString(this.font, brd, 2, this.height - ( 10 + brdline * (this.font.lineHeight + 1)), ARGB.color(f_f, -1))
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
|
||||
@@ -39,6 +_,7 @@
|
||||
@@ -40,6 +_,7 @@
|
||||
private int maxY = Integer.MIN_VALUE;
|
||||
private float fade;
|
||||
private boolean centered;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public AdvancementTab(
|
||||
Minecraft p_97145_, AdvancementsScreen p_97146_, AdvancementTabType p_97147_, int p_97148_, AdvancementNode p_297568_, DisplayInfo p_97150_
|
||||
@@ -55,6 +_,15 @@
|
||||
@@ -56,6 +_,15 @@
|
||||
this.addWidget(this.root, p_297568_.holder());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
public AdvancementTabType getType() {
|
||||
return this.type;
|
||||
}
|
||||
@@ -145,8 +_,8 @@
|
||||
@@ -150,8 +_,8 @@
|
||||
return null;
|
||||
} else {
|
||||
for (AdvancementTabType advancementtabtype : AdvancementTabType.values()) {
|
||||
|
||||
+8
-8
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
|
||||
@@ -53,6 +_,7 @@
|
||||
@Nullable
|
||||
private AdvancementTab selectedTab;
|
||||
@@ -52,6 +_,7 @@
|
||||
private final Map<AdvancementHolder, AdvancementTab> tabs = Maps.newLinkedHashMap();
|
||||
private @Nullable AdvancementTab selectedTab;
|
||||
private boolean isScrolling;
|
||||
+ private static int tabPage, maxPages;
|
||||
|
||||
public AdvancementsScreen(ClientAdvancements p_97340_) {
|
||||
this(p_97340_, null);
|
||||
@@ -66,6 +_,19 @@
|
||||
@@ -65,6 +_,19 @@
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
@@ -28,7 +28,7 @@
|
||||
this.layout.addTitleHeader(TITLE, this.font);
|
||||
this.tabs.clear();
|
||||
this.selectedTab = null;
|
||||
@@ -110,7 +_,7 @@
|
||||
@@ -109,7 +_,7 @@
|
||||
int j = (this.height - 140) / 2;
|
||||
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
@@ -37,12 +37,12 @@
|
||||
this.advancements.setSelectedTab(advancementtab.getRootNode().holder(), true);
|
||||
break;
|
||||
}
|
||||
@@ -185,10 +_,12 @@
|
||||
@@ -200,10 +_,12 @@
|
||||
p_283395_.blit(RenderPipelines.GUI_TEXTURED, WINDOW_LOCATION, p_281890_, p_282532_, 0.0F, 0.0F, 252, 140, 256, 256);
|
||||
if (this.tabs.size() > 1) {
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
+ if (advancementtab.getPage() == tabPage)
|
||||
advancementtab.drawTab(p_283395_, p_281890_, p_282532_, advancementtab == this.selectedTab);
|
||||
advancementtab.drawTab(p_283395_, p_281890_, p_282532_, p_451461_, p_451545_, advancementtab == this.selectedTab);
|
||||
}
|
||||
|
||||
for (AdvancementTab advancementtab1 : this.tabs.values()) {
|
||||
@@ -50,7 +50,7 @@
|
||||
advancementtab1.drawIcon(p_283395_, p_281890_, p_282532_);
|
||||
}
|
||||
}
|
||||
@@ -207,6 +_,7 @@
|
||||
@@ -222,6 +_,7 @@
|
||||
|
||||
if (this.tabs.size() > 1) {
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
|
||||
+13
-13
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/AbstractContainerScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/AbstractContainerScreen.java
|
||||
@@ -105,6 +_,7 @@
|
||||
@@ -102,6 +_,7 @@
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
super.render(p_409971_, p_409213_, p_408205_, p_408282_);
|
||||
@@ -8,7 +8,7 @@
|
||||
p_409971_.pose().pushMatrix();
|
||||
p_409971_.pose().translate(i, j);
|
||||
this.renderLabels(p_409971_, p_409213_, p_408205_);
|
||||
@@ -117,6 +_,8 @@
|
||||
@@ -114,6 +_,8 @@
|
||||
this.onStopHovering(slot);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
p_409971_.pose().popMatrix();
|
||||
}
|
||||
|
||||
@@ -200,7 +_,7 @@
|
||||
@@ -197,7 +_,7 @@
|
||||
ItemStack itemstack = this.hoveredSlot.getItem();
|
||||
if (this.menu.getCarried().isEmpty() || this.showTooltipWithItemInHand(itemstack)) {
|
||||
p_283594_.setTooltipForNextFrame(
|
||||
@@ -26,7 +26,7 @@
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -216,7 +_,8 @@
|
||||
@@ -213,7 +_,8 @@
|
||||
|
||||
private void renderFloatingItem(GuiGraphics p_282567_, ItemStack p_281330_, int p_281772_, int p_281689_, @Nullable String p_282568_) {
|
||||
p_282567_.renderItem(p_281330_, p_281772_, p_281689_);
|
||||
@@ -36,7 +36,7 @@
|
||||
}
|
||||
|
||||
protected void renderLabels(GuiGraphics p_281635_, int p_282681_, int p_283686_) {
|
||||
@@ -317,7 +_,8 @@
|
||||
@@ -313,7 +_,8 @@
|
||||
if (super.mouseClicked(p_427253_, p_427622_)) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -46,7 +46,7 @@
|
||||
Slot slot = this.getHoveredSlot(p_427253_.x(), p_427253_.y());
|
||||
this.doubleclick = this.lastClickSlot == slot && p_427622_;
|
||||
this.skipNextRelease = false;
|
||||
@@ -327,6 +_,7 @@
|
||||
@@ -323,6 +_,7 @@
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
boolean flag1 = this.hasClickedOutside(p_427253_.x(), p_427253_.y(), i, j);
|
||||
@@ -54,7 +54,7 @@
|
||||
int k = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
@@ -352,7 +_,7 @@
|
||||
@@ -348,7 +_,7 @@
|
||||
}
|
||||
} else if (!this.isQuickCrafting) {
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
@@ -63,7 +63,7 @@
|
||||
this.slotClicked(slot, k, p_427253_.button(), ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag2 = k != -999 && p_427253_.hasShiftDown();
|
||||
@@ -376,7 +_,7 @@
|
||||
@@ -372,7 +_,7 @@
|
||||
this.quickCraftingType = 0;
|
||||
} else if (p_427253_.button() == 1) {
|
||||
this.quickCraftingType = 1;
|
||||
@@ -72,7 +72,7 @@
|
||||
this.quickCraftingType = 2;
|
||||
}
|
||||
}
|
||||
@@ -453,10 +_,13 @@
|
||||
@@ -449,10 +_,13 @@
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(MouseButtonEvent p_430939_) {
|
||||
@@ -86,7 +86,7 @@
|
||||
int k = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
@@ -473,7 +_,7 @@
|
||||
@@ -469,7 +_,7 @@
|
||||
if (slot2 != null
|
||||
&& slot2.mayPickup(this.minecraft.player)
|
||||
&& slot2.hasItem()
|
||||
@@ -95,7 +95,7 @@
|
||||
&& AbstractContainerMenu.canItemQuickReplace(slot2, this.lastQuickMoved, true)) {
|
||||
this.slotClicked(slot2, slot2.index, p_430939_.button(), ClickType.QUICK_MOVE);
|
||||
}
|
||||
@@ -538,7 +_,7 @@
|
||||
@@ -534,7 +_,7 @@
|
||||
|
||||
this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(2, this.quickCraftingType), ClickType.QUICK_CRAFT);
|
||||
} else if (!this.menu.getCarried().isEmpty()) {
|
||||
@@ -104,7 +104,7 @@
|
||||
this.slotClicked(slot, k, p_430939_.button(), ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag1 = k != -999 && p_430939_.hasShiftDown();
|
||||
@@ -609,7 +_,7 @@
|
||||
@@ -605,7 +_,7 @@
|
||||
public boolean keyPressed(KeyEvent p_424324_) {
|
||||
if (super.keyPressed(p_424324_)) {
|
||||
return true;
|
||||
@@ -113,7 +113,7 @@
|
||||
this.onClose();
|
||||
return true;
|
||||
} else {
|
||||
@@ -688,6 +_,13 @@
|
||||
@@ -684,6 +_,13 @@
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
|
||||
@@ -116,6 +_,8 @@
|
||||
@@ -115,6 +_,8 @@
|
||||
private final Set<TagKey<Item>> visibleTags = new HashSet<>();
|
||||
private final boolean displayOperatorCreativeTab;
|
||||
private final EffectsInInventory effects;
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
public CreativeModeInventoryScreen(LocalPlayer p_344408_, FeatureFlagSet p_260074_, boolean p_259569_) {
|
||||
super(new CreativeModeInventoryScreen.ItemPickerMenu(p_344408_), p_344408_.getInventory(), CommonComponents.EMPTY);
|
||||
@@ -164,7 +_,7 @@
|
||||
@@ -163,7 +_,7 @@
|
||||
private void refreshCurrentTabContents(Collection<ItemStack> p_261591_) {
|
||||
int i = this.menu.getRowIndexForScroll(this.scrollOffs);
|
||||
this.menu.items.clear();
|
||||
@@ -18,7 +18,7 @@
|
||||
this.refreshSearchResults();
|
||||
} else {
|
||||
this.menu.items.addAll(p_261591_);
|
||||
@@ -332,6 +_,36 @@
|
||||
@@ -329,6 +_,36 @@
|
||||
protected void init() {
|
||||
if (this.minecraft.player.hasInfiniteMaterials()) {
|
||||
super.init();
|
||||
@@ -55,7 +55,7 @@
|
||||
this.searchBox = new EditBox(this.font, this.leftPos + 82, this.topPos + 6, 80, 9, Component.translatable("itemGroup.search"));
|
||||
this.searchBox.setMaxLength(50);
|
||||
this.searchBox.setBordered(false);
|
||||
@@ -378,7 +_,7 @@
|
||||
@@ -376,7 +_,7 @@
|
||||
public boolean charTyped(CharacterEvent p_424087_) {
|
||||
if (this.ignoreTextInput) {
|
||||
return false;
|
||||
@@ -64,7 +64,7 @@
|
||||
return false;
|
||||
} else {
|
||||
String s = this.searchBox.getValue();
|
||||
@@ -397,7 +_,7 @@
|
||||
@@ -395,7 +_,7 @@
|
||||
@Override
|
||||
public boolean keyPressed(KeyEvent p_429237_) {
|
||||
this.ignoreTextInput = false;
|
||||
@@ -73,7 +73,7 @@
|
||||
if (this.minecraft.options.keyChat.matches(p_429237_)) {
|
||||
this.ignoreTextInput = true;
|
||||
this.selectTab(CreativeModeTabs.searchTab());
|
||||
@@ -433,6 +_,7 @@
|
||||
@@ -431,6 +_,7 @@
|
||||
}
|
||||
|
||||
private void refreshSearchResults() {
|
||||
@@ -81,7 +81,7 @@
|
||||
this.menu.items.clear();
|
||||
this.visibleTags.clear();
|
||||
String s = this.searchBox.getValue();
|
||||
@@ -445,10 +_,10 @@
|
||||
@@ -443,10 +_,10 @@
|
||||
SearchTree<ItemStack> searchtree;
|
||||
if (s.startsWith("#")) {
|
||||
s = s.substring(1);
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
|
||||
this.menu.items.addAll(searchtree.search(s.toLowerCase(Locale.ROOT)));
|
||||
@@ -480,7 +_,8 @@
|
||||
@@ -478,7 +_,8 @@
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics p_283168_, int p_281774_, int p_281466_) {
|
||||
if (selectedTab.showTitle()) {
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +_,7 @@
|
||||
@@ -488,7 +_,7 @@
|
||||
double d0 = p_430803_.x() - this.leftPos;
|
||||
double d1 = p_430803_.y() - this.topPos;
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
if (this.checkTabClicked(creativemodetab, d0, d1)) {
|
||||
return true;
|
||||
}
|
||||
@@ -512,7 +_,7 @@
|
||||
@@ -510,7 +_,7 @@
|
||||
double d1 = p_423848_.y() - this.topPos;
|
||||
this.scrolling = false;
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
if (this.checkTabClicked(creativemodetab, d0, d1)) {
|
||||
this.selectTab(creativemodetab);
|
||||
return true;
|
||||
@@ -606,13 +_,15 @@
|
||||
@@ -604,13 +_,15 @@
|
||||
this.originalSlots = null;
|
||||
}
|
||||
|
||||
@@ -139,9 +139,9 @@
|
||||
|
||||
this.refreshSearchResults();
|
||||
} else {
|
||||
@@ -676,7 +_,14 @@
|
||||
@@ -673,7 +_,14 @@
|
||||
this.effects.render(p_283000_, p_281317_, p_282770_);
|
||||
super.render(p_283000_, p_281317_, p_282770_, p_281295_);
|
||||
this.effects.renderTooltip(p_283000_, p_281317_, p_282770_);
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ if (this.pages.size() != 1) {
|
||||
@@ -155,7 +155,7 @@
|
||||
if (this.checkTabHovering(p_283000_, creativemodetab, p_281317_, p_282770_)) {
|
||||
break;
|
||||
}
|
||||
@@ -700,7 +_,7 @@
|
||||
@@ -697,7 +_,7 @@
|
||||
public List<Component> getTooltipFromContainerItem(ItemStack p_281769_) {
|
||||
boolean flag = this.hoveredSlot != null && this.hoveredSlot instanceof CreativeModeInventoryScreen.CustomCreativeSlot;
|
||||
boolean flag1 = selectedTab.getType() == CreativeModeTab.Type.CATEGORY;
|
||||
@@ -164,7 +164,7 @@
|
||||
TooltipFlag.Default tooltipflag$default = this.minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL;
|
||||
TooltipFlag tooltipflag = flag ? tooltipflag$default.asCreative() : tooltipflag$default;
|
||||
List<Component> list = p_281769_.getTooltipLines(Item.TooltipContext.of(this.minecraft.level), this.minecraft.player, tooltipflag);
|
||||
@@ -721,7 +_,7 @@
|
||||
@@ -718,7 +_,7 @@
|
||||
int i = 1;
|
||||
|
||||
for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
@@ -173,24 +173,24 @@
|
||||
list1.add(i++, creativemodetab.getDisplayName().copy().withStyle(ChatFormatting.BLUE));
|
||||
}
|
||||
}
|
||||
@@ -732,7 +_,7 @@
|
||||
@@ -729,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics p_282663_, float p_282504_, int p_282089_, int p_282249_) {
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
|
||||
if (creativemodetab != selectedTab) {
|
||||
this.renderTabButton(p_282663_, creativemodetab);
|
||||
this.renderTabButton(p_282663_, p_282089_, p_282249_, creativemodetab);
|
||||
}
|
||||
@@ -748,6 +_,7 @@
|
||||
p_282663_.blitSprite(RenderPipelines.GUI_TEXTURED, resourcelocation, j, k + (int)((i - k - 17) * this.scrollOffs), 12, 15);
|
||||
@@ -749,6 +_,7 @@
|
||||
p_282663_.blitSprite(RenderPipelines.GUI_TEXTURED, identifier, j, k + (int)((i - k - 17) * this.scrollOffs), 12, 15);
|
||||
}
|
||||
|
||||
+ if (currentPage.getVisibleTabs().contains(selectedTab)) //Forge: only display tab selection when the selected tab is on the current page
|
||||
this.renderTabButton(p_282663_, selectedTab);
|
||||
this.renderTabButton(p_282663_, p_282089_, p_282249_, selectedTab);
|
||||
if (selectedTab.getType() == CreativeModeTab.Type.INVENTORY) {
|
||||
InventoryScreen.renderEntityInInventoryFollowsMouse(
|
||||
@@ -766,7 +_,7 @@
|
||||
@@ -767,7 +_,7 @@
|
||||
}
|
||||
|
||||
private int getTabX(CreativeModeTab p_260136_) {
|
||||
@@ -199,7 +199,7 @@
|
||||
int j = 27;
|
||||
int k = 27 * i;
|
||||
if (p_260136_.isAlignedRight()) {
|
||||
@@ -778,7 +_,7 @@
|
||||
@@ -779,7 +_,7 @@
|
||||
|
||||
private int getTabY(CreativeModeTab p_260181_) {
|
||||
int i = 0;
|
||||
@@ -208,9 +208,9 @@
|
||||
i -= 32;
|
||||
} else {
|
||||
i += this.imageHeight;
|
||||
@@ -806,8 +_,8 @@
|
||||
@@ -807,8 +_,8 @@
|
||||
|
||||
protected void renderTabButton(GuiGraphics p_283590_, CreativeModeTab p_283489_) {
|
||||
protected void renderTabButton(GuiGraphics p_283590_, int p_454271_, int p_455485_, CreativeModeTab p_283489_) {
|
||||
boolean flag = p_283489_ == selectedTab;
|
||||
- boolean flag1 = p_283489_.row() == CreativeModeTab.Row.TOP;
|
||||
- int i = p_283489_.column();
|
||||
@@ -218,16 +218,16 @@
|
||||
+ int i = currentPage.getColumn(p_283489_);
|
||||
int j = this.leftPos + this.getTabX(p_283489_);
|
||||
int k = this.topPos - (flag1 ? 28 : -(this.imageHeight - 4));
|
||||
ResourceLocation[] aresourcelocation;
|
||||
@@ -817,6 +_,7 @@
|
||||
aresourcelocation = flag ? SELECTED_BOTTOM_TABS : UNSELECTED_BOTTOM_TABS;
|
||||
Identifier[] aidentifier;
|
||||
@@ -822,6 +_,7 @@
|
||||
p_283590_.requestCursor(CursorTypes.POINTING_HAND);
|
||||
}
|
||||
|
||||
+ com.mojang.blaze3d.opengl.GlStateManager._enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
|
||||
p_283590_.blitSprite(RenderPipelines.GUI_TEXTURED, aresourcelocation[Mth.clamp(i, 0, aresourcelocation.length)], j, k, 26, 32);
|
||||
p_283590_.blitSprite(RenderPipelines.GUI_TEXTURED, aidentifier[Mth.clamp(i, 0, aidentifier.length)], j, k, 26, 32);
|
||||
int l = j + 13 - 8;
|
||||
int i1 = k + 16 - 8 + (flag1 ? 1 : -1);
|
||||
@@ -853,6 +_,14 @@
|
||||
@@ -858,6 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
static class CustomCreativeSlot extends Slot {
|
||||
public CustomCreativeSlot(Container p_98633_, int p_98634_, int p_98635_, int p_98636_) {
|
||||
@@ -1034,6 +_,22 @@
|
||||
@@ -1038,6 +_,22 @@
|
||||
@Override
|
||||
public boolean mayPickup(Player p_98665_) {
|
||||
return this.target.mayPickup(p_98665_);
|
||||
@@ -259,7 +259,7 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Slot setBackground(ResourceLocation sprite) {
|
||||
+ public Slot setBackground(Identifier sprite) {
|
||||
+ this.target.setBackground(sprite);
|
||||
+ return this;
|
||||
}
|
||||
|
||||
+16
-28
@@ -1,48 +1,36 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EffectsInInventory.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EffectsInInventory.java
|
||||
@@ -47,12 +_,16 @@
|
||||
int j = this.screen.width - i;
|
||||
Collection<MobEffectInstance> collection = this.minecraft.player.getActiveEffects();
|
||||
if (!collection.isEmpty() && j >= 32) {
|
||||
boolean flag = j >= 120;
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenEffectSize(this.screen, j, !flag, i);
|
||||
- int k = j >= 120 ? j - 7 : 32;
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenEffectSize(this.screen, j, j < 120, i);
|
||||
+ if (event == null) return;
|
||||
+ flag = !event.isCompact();
|
||||
+ int k = !event.isCompact() ? j - 7 : 32;
|
||||
+ i = event.getHorizontalOffset();
|
||||
int k = 33;
|
||||
int l = 33;
|
||||
if (collection.size() > 5) {
|
||||
k = 132 / (collection.size() - 1);
|
||||
l = 132 / (collection.size() - 1);
|
||||
}
|
||||
|
||||
- Iterable<MobEffectInstance> iterable = Ordering.natural().sortedCopy(collection);
|
||||
+ Iterable<MobEffectInstance> iterable = collection.stream().filter(net.minecraftforge.client.ForgeHooksClient::shouldRenderEffect).sorted().toList();
|
||||
this.renderBackgrounds(p_362146_, i, k, iterable, flag);
|
||||
this.renderIcons(p_362146_, i, k, iterable, flag);
|
||||
if (flag) {
|
||||
@@ -98,6 +_,11 @@
|
||||
int i = this.screen.topPos;
|
||||
this.renderEffects(p_456221_, collection, i, l, p_453611_, p_457243_, k);
|
||||
}
|
||||
}
|
||||
@@ -66,6 +_,11 @@
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : p_361981_) {
|
||||
for (MobEffectInstance mobeffectinstance : iterable) {
|
||||
boolean flag = mobeffectinstance.isAmbient();
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(mobeffectinstance);
|
||||
+ if (renderer.renderInventoryIcon(mobeffectinstance, this, p_367085_, p_367644_ + (p_368681_ ? 6 : 7), i, 0)) {
|
||||
+ i += p_367522_;
|
||||
+ continue;
|
||||
+ }
|
||||
Holder<MobEffect> holder = mobeffectinstance.getEffect();
|
||||
ResourceLocation resourcelocation = Gui.getMobEffectSprite(holder);
|
||||
p_367085_.blitSprite(RenderPipelines.GUI_TEXTURED, resourcelocation, p_367644_ + (p_368681_ ? 6 : 7), i + 7, 18, 18);
|
||||
@@ -109,6 +_,11 @@
|
||||
int i = this.screen.topPos;
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : p_365480_) {
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(mobeffectinstance);
|
||||
+ if (renderer.renderInventoryText(mobeffectinstance, this, p_361851_, p_367468_, i, 0)) {
|
||||
+ i += p_365556_;
|
||||
+ if (renderer.renderInventory(mobeffectinstance, this, p_362146_, p_370153_, i, 0)) {
|
||||
+ i += p_365612_;
|
||||
+ continue;
|
||||
+ }
|
||||
Component component = this.getEffectName(mobeffectinstance);
|
||||
p_361851_.drawString(this.screen.getFont(), component, p_367468_ + 10 + 18, i + 6, -1);
|
||||
Component component1 = MobEffectUtil.formatDuration(mobeffectinstance, 1.0F, this.minecraft.level.tickRateManager().tickrate());
|
||||
@@ -124,5 +_,9 @@
|
||||
int j = this.renderBackground(p_362146_, font, component, component1, p_370153_, i, flag, p_457235_);
|
||||
@@ -123,5 +_,9 @@
|
||||
}
|
||||
|
||||
return mutablecomponent;
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
|
||||
@@ -107,7 +_,7 @@
|
||||
@@ -108,7 +_,7 @@
|
||||
int l1 = 86 - this.font.width(s);
|
||||
FormattedText formattedtext = EnchantmentNames.getInstance().getRandomName(this.font, l1);
|
||||
int i2 = -9937334;
|
||||
@@ -9,7 +9,7 @@
|
||||
p_282430_.blitSprite(RenderPipelines.GUI_TEXTURED, ENCHANTMENT_SLOT_DISABLED_SPRITE, i1, j + 14 + 19 * l, 108, 19);
|
||||
p_282430_.blitSprite(RenderPipelines.GUI_TEXTURED, DISABLED_LEVEL_SPRITES[l], i1 + 1, j + 15 + 19 * l, 16, 16);
|
||||
p_282430_.drawWordWrap(this.font, formattedtext, j1, j + 16 + 19 * l, l1, ARGB.opaque((i2 & 16711422) >> 1), false);
|
||||
@@ -158,13 +_,16 @@
|
||||
@@ -160,13 +_,16 @@
|
||||
.registryAccess()
|
||||
.lookupOrThrow(Registries.ENCHANTMENT)
|
||||
.get(this.menu.enchantClue[j]);
|
||||
@@ -17,8 +17,8 @@
|
||||
+ {
|
||||
int l = this.menu.levelClue[j];
|
||||
int i1 = j + 1;
|
||||
- if (this.isHovering(60, 14 + 19 * j, 108, 17, p_282491_, p_281953_) && k > 0 && l >= 0 && optional != null) {
|
||||
+ if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)p_282491_, (double)p_281953_) && k > 0) {
|
||||
- if (this.isHovering(60, 14 + 19 * j, 108, 17, p_282491_, p_281953_) && k > 0 && l >= 0) {
|
||||
+ if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)p_282491_, (double)p_281953_) && l >= 0) {
|
||||
List<Component> list = Lists.newArrayList();
|
||||
- list.add(Component.translatable("container.enchant.clue", Enchantment.getFullname(optional.get(), l)).withStyle(ChatFormatting.WHITE));
|
||||
- if (!flag) {
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
private static final Vector3f TEXT_SCALE = new Vector3f(1.0F, 1.0F, 1.0F);
|
||||
private static final int TEXTURE_WIDTH = 16;
|
||||
private static final int TEXTURE_HEIGHT = 16;
|
||||
- private final ResourceLocation texture = ResourceLocation.withDefaultNamespace("textures/gui/hanging_signs/" + this.woodType.name() + ".png");
|
||||
+ private final ResourceLocation texture = ResourceLocation.parse(this.woodType.name() + ".png").withPrefix("textures/gui/hanging_signs/");
|
||||
- private final Identifier texture = Identifier.withDefaultNamespace("textures/gui/hanging_signs/" + this.woodType.name() + ".png");
|
||||
+ private final Identifier texture = Identifier.parse(this.woodType.name() + ".png").withPrefix("textures/gui/hanging_signs/");
|
||||
|
||||
public HangingSignEditScreen(SignBlockEntity p_278017_, boolean p_277942_, boolean p_277778_) {
|
||||
super(p_278017_, p_277942_, p_277778_, Component.translatable("hanging_sign.edit"));
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
|
||||
@@ -230,6 +_,14 @@
|
||||
@@ -236,6 +_,14 @@
|
||||
} else {
|
||||
p_281357_.renderItemDecorations(this.font, p_282046_, p_282403_, p_283601_, p_282046_.getCount() == 1 ? "1" : null);
|
||||
p_281357_.renderItemDecorations(this.font, p_283466_, p_282403_ + 14, p_283601_, p_283466_.getCount() == 1 ? "1" : null);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
@@ -363,6 +_,8 @@
|
||||
@@ -361,6 +_,8 @@
|
||||
p_425273_.setTooltipForNextFrame(Lists.transform(this.onlinePlayersTooltip, Component::getVisualOrderText), p_424268_, p_430737_);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/options/controls/KeyBindsList.java
|
||||
+++ b/net/minecraft/client/gui/screens/options/controls/KeyBindsList.java
|
||||
@@ -115,9 +_,10 @@
|
||||
@@ -116,9 +_,10 @@
|
||||
this.name = p_343976_;
|
||||
this.changeButton = Button.builder(p_343976_, p_342196_ -> {
|
||||
KeyBindsList.this.keyBindsScreen.selectedKey = p_343088_;
|
||||
@@ -12,7 +12,7 @@
|
||||
.createNarration(
|
||||
p_342179_ -> p_343088_.isUnbound()
|
||||
? Component.translatable("narrator.controls.unbound", p_343976_)
|
||||
@@ -125,7 +_,7 @@
|
||||
@@ -126,7 +_,7 @@
|
||||
)
|
||||
.build();
|
||||
this.resetButton = Button.builder(RESET_BUTTON_TITLE, p_357685_ -> {
|
||||
@@ -21,7 +21,7 @@
|
||||
KeyBindsList.this.resetMappingAndUpdateButtons();
|
||||
}).bounds(0, 0, 50, 20).createNarration(p_344192_ -> Component.translatable("narrator.controls.reset", p_343976_)).build();
|
||||
this.refreshEntry();
|
||||
@@ -166,7 +_,8 @@
|
||||
@@ -167,7 +_,8 @@
|
||||
MutableComponent mutablecomponent = Component.empty();
|
||||
if (!this.key.isUnbound()) {
|
||||
for (KeyMapping keymapping : KeyBindsList.this.minecraft.options.keyMappings) {
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/options/controls/KeyBindsScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/options/controls/KeyBindsScreen.java
|
||||
@@ -43,7 +_,7 @@
|
||||
@@ -42,7 +_,7 @@
|
||||
protected void addFooter() {
|
||||
this.resetButton = Button.builder(Component.translatable("controls.resetAll"), p_343640_ -> {
|
||||
for (KeyMapping keymapping : this.options.keyMappings) {
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
this.keyBindsList.resetMappingAndUpdateButtons();
|
||||
@@ -75,11 +_,12 @@
|
||||
@@ -74,11 +_,12 @@
|
||||
public boolean keyPressed(KeyEvent p_424487_) {
|
||||
if (this.selectedKey != null) {
|
||||
if (p_424487_.isEscape()) {
|
||||
@@ -24,7 +24,7 @@
|
||||
this.selectedKey = null;
|
||||
this.lastKeySelection = Util.getMillis();
|
||||
this.keyBindsList.resetMappingAndUpdateButtons();
|
||||
@@ -102,5 +_,18 @@
|
||||
@@ -101,5 +_,18 @@
|
||||
}
|
||||
|
||||
this.resetButton.active = flag;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/packs/TransferableSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/packs/TransferableSelectionList.java
|
||||
@@ -64,7 +_,7 @@
|
||||
@@ -65,7 +_,7 @@
|
||||
Component component = Component.empty().append(this.title).withStyle(ChatFormatting.UNDERLINE, ChatFormatting.BOLD);
|
||||
this.addEntry(new TransferableSelectionList.HeaderEntry(this.minecraft.font, component), (int)(9.0F * 1.5F));
|
||||
this.setSelected(null);
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/CreateWorldScreen.java
|
||||
@@ -171,6 +_,7 @@
|
||||
@@ -173,6 +_,7 @@
|
||||
WorldDataConfiguration worlddataconfiguration = SharedConstants.IS_RUNNING_IN_IDE
|
||||
? new WorldDataConfiguration(new DataPackConfig(List.of("vanilla", "tests"), List.of()), FeatureFlags.DEFAULT_FLAGS)
|
||||
: WorldDataConfiguration.DEFAULT;
|
||||
@@ -8,7 +8,7 @@
|
||||
WorldLoader.InitConfig worldloader$initconfig = createDefaultLoadConfig(packrepository, worlddataconfiguration);
|
||||
CompletableFuture<WorldCreationContext> completablefuture = WorldLoader.load(
|
||||
worldloader$initconfig,
|
||||
@@ -471,7 +_,7 @@
|
||||
@@ -472,7 +_,7 @@
|
||||
if (p_269627_) {
|
||||
p_270552_.accept(this.uiState.getSettings().dataConfiguration());
|
||||
} else {
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
},
|
||||
Component.translatable("dataPack.validation.failed"),
|
||||
@@ -585,6 +_,7 @@
|
||||
@@ -584,6 +_,7 @@
|
||||
if (path != null) {
|
||||
if (this.tempDataPackRepository == null) {
|
||||
this.tempDataPackRepository = ServerPacksSource.createPackRepository(path, this.packValidator);
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/WorldCreationUiState.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/WorldCreationUiState.java
|
||||
@@ -234,7 +_,7 @@
|
||||
@Nullable
|
||||
public PresetEditor getPresetEditor() {
|
||||
@@ -232,7 +_,7 @@
|
||||
|
||||
public @Nullable PresetEditor getPresetEditor() {
|
||||
Holder<WorldPreset> holder = this.getWorldType().preset();
|
||||
- return holder != null ? PresetEditor.EDITORS.get(holder.unwrapKey()) : null;
|
||||
+ return holder != null ? holder.unwrapKey().map(net.minecraftforge.client.PresetEditorManager::get).orElse(null) : null; // FORGE: redirect lookup to expanded map
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.java
|
||||
@@ -329,6 +_,8 @@
|
||||
@@ -331,6 +_,8 @@
|
||||
this.minecraft.setScreenAndShow(new GenericMessageScreen(Component.translatable("selectWorld.resource_load")));
|
||||
PackRepository packrepository = ServerPacksSource.createPackRepository(p_333651_);
|
||||
|
||||
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/client/gui/screens/worldselection/WorldSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/worldselection/WorldSelectionList.java
|
||||
@@ -79,6 +_,7 @@
|
||||
static final ResourceLocation JOIN_HIGHLIGHTED_SPRITE = ResourceLocation.withDefaultNamespace("world_list/join_highlighted");
|
||||
static final ResourceLocation JOIN_SPRITE = ResourceLocation.withDefaultNamespace("world_list/join");
|
||||
@@ -83,6 +_,7 @@
|
||||
static final Identifier JOIN_HIGHLIGHTED_SPRITE = Identifier.withDefaultNamespace("world_list/join_highlighted");
|
||||
static final Identifier JOIN_SPRITE = Identifier.withDefaultNamespace("world_list/join");
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
+ private static final ResourceLocation FORGE_EXPERIMENTAL_WARNING_ICON = ResourceLocation.fromNamespaceAndPath("forge","textures/gui/experimental_warning.png");
|
||||
+ private static final Identifier FORGE_EXPERIMENTAL_WARNING_ICON = Identifier.fromNamespaceAndPath("forge","textures/gui/experimental_warning.png");
|
||||
static final Component FROM_NEWER_TOOLTIP_1 = Component.translatable("selectWorld.tooltip.fromNewerVersion1").withStyle(ChatFormatting.RED);
|
||||
static final Component FROM_NEWER_TOOLTIP_2 = Component.translatable("selectWorld.tooltip.fromNewerVersion2").withStyle(ChatFormatting.RED);
|
||||
static final Component SNAPSHOT_TOOLTIP_1 = Component.translatable("selectWorld.tooltip.snapshot1").withStyle(ChatFormatting.GOLD);
|
||||
@@ -494,6 +_,19 @@
|
||||
@@ -489,6 +_,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
@Override
|
||||
public Component getNarration() {
|
||||
Component component = Component.translatable(
|
||||
@@ -520,6 +_,7 @@
|
||||
@@ -515,6 +_,7 @@
|
||||
this.infoText.setPosition(i, this.getContentY() + 9 + 9 + 3);
|
||||
this.infoText.render(p_424437_, p_425443_, p_425024_, p_424775_);
|
||||
p_424437_.blit(RenderPipelines.GUI_TEXTURED, this.icon.textureLocation(), this.getContentX(), this.getContentY(), 0.0F, 0.0F, 32, 32, 32, 32);
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
--- a/net/minecraft/client/model/HumanoidModel.java
|
||||
+++ b/net/minecraft/client/model/HumanoidModel.java
|
||||
@@ -290,6 +_,8 @@
|
||||
case BRUSH:
|
||||
this.rightArm.xRot = this.rightArm.xRot * 0.5F - (float) (Math.PI / 5);
|
||||
this.rightArm.yRot = 0.0F;
|
||||
@@ -308,6 +_,8 @@
|
||||
break;
|
||||
case SPEAR:
|
||||
SpearAnimations.thirdPersonHandUse(this.rightArm, this.head, true, p_362371_.getUseItemStackForArm(HumanoidArm.RIGHT), p_362371_);
|
||||
+ default:
|
||||
+ p_366231_.applyTransform(this, p_362371_, net.minecraft.world.entity.HumanoidArm.RIGHT);
|
||||
+ p_362371_.rightArmPose.applyTransform(this, p_362371_, net.minecraft.world.entity.HumanoidArm.RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +_,8 @@
|
||||
case BRUSH:
|
||||
this.leftArm.xRot = this.leftArm.xRot * 0.5F - (float) (Math.PI / 5);
|
||||
this.leftArm.yRot = 0.0F;
|
||||
@@ -355,6 +_,8 @@
|
||||
break;
|
||||
case SPEAR:
|
||||
SpearAnimations.thirdPersonHandUse(this.leftArm, this.head, false, p_363560_.getUseItemStackForArm(HumanoidArm.LEFT), p_363560_);
|
||||
+ default:
|
||||
+ p_370002_.applyTransform(this, p_363560_, net.minecraft.world.entity.HumanoidArm.LEFT);
|
||||
+ p_363560_.leftArmPose.applyTransform(this, p_363560_, net.minecraft.world.entity.HumanoidArm.LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +_,7 @@
|
||||
@@ -427,7 +_,7 @@
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
- public static enum ArmPose {
|
||||
+ public static enum ArmPose implements net.minecraftforge.common.IExtensibleEnum {
|
||||
EMPTY(false),
|
||||
ITEM(false),
|
||||
BLOCK(false),
|
||||
@@ -418,10 +_,28 @@
|
||||
|
||||
private ArmPose(final boolean p_102896_) {
|
||||
EMPTY(false, false),
|
||||
ITEM(false, false),
|
||||
BLOCK(false, false),
|
||||
@@ -453,10 +_,29 @@
|
||||
ArmPose(final boolean p_102896_, final boolean p_456170_) {
|
||||
this.twoHanded = p_102896_;
|
||||
this.affectsOffhandPose = p_456170_;
|
||||
+ this.forgeArmPose = null;
|
||||
}
|
||||
|
||||
@@ -41,18 +41,19 @@
|
||||
+ @javax.annotation.Nullable
|
||||
+ private final net.minecraftforge.client.IArmPoseTransformer forgeArmPose;
|
||||
+
|
||||
+ private ArmPose(boolean twoHanded, @javax.annotation.Nonnull net.minecraftforge.client.IArmPoseTransformer forgeArmPose) {
|
||||
+ private ArmPose(boolean twoHanded, boolean affectsOffhandPose, @javax.annotation.Nonnull net.minecraftforge.client.IArmPoseTransformer forgeArmPose) {
|
||||
+ this.twoHanded = twoHanded;
|
||||
+ this.affectsOffhandPose = affectsOffhandPose;
|
||||
+ com.google.common.base.Preconditions.checkNotNull(forgeArmPose, "Cannot create new ArmPose with null transformer!");
|
||||
+ this.forgeArmPose = forgeArmPose;
|
||||
+ }
|
||||
+
|
||||
+ public static ArmPose create(String name, boolean twoHanded, @javax.annotation.Nonnull net.minecraftforge.client.IArmPoseTransformer forgeArmPose) {
|
||||
+ public static ArmPose create(String name, boolean twoHanded, boolean affectsOffhandPose, @javax.annotation.Nonnull net.minecraftforge.client.IArmPoseTransformer forgeArmPose) {
|
||||
+ throw new IllegalStateException("Enum not extended");
|
||||
+ }
|
||||
+
|
||||
+ public <T extends HumanoidRenderState> void applyTransform(HumanoidModel<T> model, T state, net.minecraft.world.entity.HumanoidArm arm) {
|
||||
+ if (this.forgeArmPose != null) this.forgeArmPose.applyTransform(model, state, arm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean affectsOffhandPose() {
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/client/model/geom/LayerDefinitions.java
|
||||
+++ b/net/minecraft/client/model/geom/LayerDefinitions.java
|
||||
@@ -506,6 +_,7 @@
|
||||
builder.put(ModelLayers.createHangingSignModelName(p_374591_, hangingsignrenderer$attachmenttype), layerdefinition57);
|
||||
@@ -524,6 +_,7 @@
|
||||
builder.put(ModelLayers.createHangingSignModelName(p_374591_, hangingsignrenderer$attachmenttype), layerdefinition58);
|
||||
}
|
||||
});
|
||||
+ net.minecraftforge.client.ForgeHooksClient.loadLayerDefinitions(builder);
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
--- a/net/minecraft/client/model/geom/ModelLayers.java
|
||||
+++ b/net/minecraft/client/model/geom/ModelLayers.java
|
||||
@@ -328,15 +_,18 @@
|
||||
@@ -341,15 +_,18 @@
|
||||
}
|
||||
|
||||
public static ModelLayerLocation createStandingSignModelName(WoodType p_171292_) {
|
||||
- return createLocation("sign/standing/" + p_171292_.name(), "main");
|
||||
+ ResourceLocation location = ResourceLocation.parse(p_171292_.name());
|
||||
+ return new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath(location.getNamespace(), "sign/standing/" + location.getPath()), "main");
|
||||
+ Identifier location = Identifier.parse(p_171292_.name());
|
||||
+ return new ModelLayerLocation(Identifier.fromNamespaceAndPath(location.getNamespace(), "sign/standing/" + location.getPath()), "main");
|
||||
}
|
||||
|
||||
public static ModelLayerLocation createWallSignModelName(WoodType p_363532_) {
|
||||
- return createLocation("sign/wall/" + p_363532_.name(), "main");
|
||||
+ ResourceLocation location = ResourceLocation.parse(p_363532_.name());
|
||||
+ return new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath(location.getNamespace(), "sign/wall/" + location.getPath()), "main");
|
||||
+ Identifier location = Identifier.parse(p_363532_.name());
|
||||
+ return new ModelLayerLocation(Identifier.fromNamespaceAndPath(location.getNamespace(), "sign/wall/" + location.getPath()), "main");
|
||||
}
|
||||
|
||||
public static ModelLayerLocation createHangingSignModelName(WoodType p_252225_, HangingSignRenderer.AttachmentType p_378070_) {
|
||||
- return createLocation("hanging_sign/" + p_252225_.name() + "/" + p_378070_.getSerializedName(), "main");
|
||||
+ ResourceLocation location = ResourceLocation.parse(p_252225_.name());
|
||||
+ return new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath(location.getNamespace(), "hanging_sign/" + location.getPath() + "/" + p_378070_.getSerializedName()), "main");
|
||||
+ Identifier location = Identifier.parse(p_252225_.name());
|
||||
+ return new ModelLayerLocation(Identifier.fromNamespaceAndPath(location.getNamespace(), "hanging_sign/" + location.getPath() + "/" + p_378070_.getSerializedName()), "main");
|
||||
}
|
||||
|
||||
public static Stream<ModelLayerLocation> getKnownLocations() {
|
||||
@@ -8,7 +8,7 @@
|
||||
this.storage.drop(i, levelchunk);
|
||||
}
|
||||
}
|
||||
@@ -125,6 +_,7 @@
|
||||
@@ -123,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.level.onChunkLoaded(chunkpos);
|
||||
|
||||
Loaded 100 of 813 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user