mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 09:05:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bca349d64 | ||
|
|
7a44626d5e | ||
|
|
30ec79b19e | ||
|
|
0794e51f62 | ||
|
|
c86172db31 | ||
|
|
ee14c0c911 | ||
|
|
b3a4ac864f | ||
|
|
f9139a3002 | ||
|
|
784693b7e5 | ||
|
|
774048154f | ||
|
|
490e35ba8e | ||
|
|
667a164430 | ||
|
|
0434d67016 | ||
|
|
02229557ed | ||
|
|
79224a70e6 | ||
|
|
5c9c8ce539 | ||
|
|
c186c38113 | ||
|
|
1507717fae | ||
|
|
12c4233fac | ||
|
|
f331376d9d | ||
|
|
b5b5064a4f | ||
|
|
f4801960e7 | ||
|
|
68c60c17e5 | ||
|
|
4a5f977691 | ||
|
|
896cfb38a3 | ||
|
|
185273022c | ||
|
|
eb65e1db51 | ||
|
|
6a5c413a13 | ||
|
|
1b7b2b6ff1 | ||
|
|
cb290f23f5 | ||
|
|
6e8eaeeec9 | ||
|
|
56c41f3ca8 | ||
|
|
0084b8cf48 | ||
|
|
eb6c564ce4 | ||
|
|
618da273dc | ||
|
|
074c0cdfd6 |
No files matched your search
@@ -3,7 +3,6 @@
|
||||
*.patch text eol=lf
|
||||
*.java text eol=lf
|
||||
*.gradle text eol=crlf
|
||||
**/MANIFEST.MF text eol=crlf
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.exe binary
|
||||
|
||||
+12
-6
@@ -26,6 +26,7 @@
|
||||
/projects/mcp/
|
||||
/projects/clean/
|
||||
/projects/forge/
|
||||
#/patches/*
|
||||
|
||||
#occupational hazards
|
||||
/projects/**/build/
|
||||
@@ -34,15 +35,20 @@
|
||||
/projects/**/*.launch
|
||||
/repo/
|
||||
src/*/generated/**/.cache/
|
||||
|
||||
# Generated by gradle every import
|
||||
**/src/main/resources/META-INF/MANIFEST.MF
|
||||
/fmlloader/src/main/resources/forge_version.json
|
||||
|
||||
#Patch rejects
|
||||
#/patches-/
|
||||
#*.patch.rej
|
||||
#/projects/*/rejects/
|
||||
|
||||
# FML changelog
|
||||
changelog.txt
|
||||
*.py
|
||||
*.7z
|
||||
/logs/
|
||||
|
||||
/ForgeRoot.ipr
|
||||
/ForgeRoot.iws
|
||||
|
||||
# APT stuff
|
||||
/*/.gitignore
|
||||
/*/.factorypath
|
||||
/*/.apt_generated/
|
||||
+3
-19
@@ -3,7 +3,6 @@ package net.minecraftforge.forge.tasks
|
||||
import groovy.transform.CompileStatic
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
@@ -13,19 +12,13 @@ abstract class BytecodePredicateFinder extends BytecodeFinder {
|
||||
@Internal
|
||||
abstract Property<Closure<Boolean>> getPredicate()
|
||||
|
||||
private final Map<String, List<String>> matches = new TreeMap<>(Comparator.naturalOrder())
|
||||
private final Set<String> matches = new HashSet<>()
|
||||
|
||||
@Override
|
||||
protected process(ClassNode parent, MethodNode node) {
|
||||
for (final current : node.instructions) {
|
||||
if (predicate.get().call(parent, node, current)) {
|
||||
var methods = matches.compute(parent.name, { k, v -> v ?: new ArrayList<>() })
|
||||
|
||||
// only add non-synthetic methods
|
||||
if ((node.access & Opcodes.ACC_SYNTHETIC) == 0) {
|
||||
methods.add(node.name + node.desc)
|
||||
}
|
||||
|
||||
matches.add(parent.name)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -34,15 +27,6 @@ abstract class BytecodePredicateFinder extends BytecodeFinder {
|
||||
@Internal
|
||||
@Override
|
||||
protected Object getData() {
|
||||
var array = new ArrayList<Object>()
|
||||
matches.forEach { c, m ->
|
||||
{
|
||||
array.add(
|
||||
'class': c,
|
||||
'methods': m
|
||||
)
|
||||
}
|
||||
}
|
||||
return array ?: { throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.') }()
|
||||
return matches.toSorted(Comparator.<String>naturalOrder()) ?: {throw new RuntimeException('Failed to find any targets, please ensure that method names and descriptors are correct.')}()
|
||||
}
|
||||
}
|
||||
+18
-53
@@ -47,7 +47,6 @@ jarSigner.autoDetect('forge')
|
||||
applyPatches {
|
||||
level 'WARNING'
|
||||
failOnError = UPDATING != 'true'
|
||||
rejects = rootProject.layout.projectDirectory.dir('rejects').asFile
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -92,18 +91,18 @@ final String MAVEN_PATH = ext.MAVEN_PATH
|
||||
final String BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.2.0:fatjar'
|
||||
final String INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.4.3'
|
||||
final String FART = 'net.minecraftforge:ForgeAutoRenamingTool:1.0.6'
|
||||
final String S2S_TOOL = 'net.minecraftforge:Srg2Source:8.1.1:fatjar'
|
||||
final String S2S_TOOL = 'net.minecraftforge:Srg2Source:8.1.0:fatjar'
|
||||
|
||||
configurations {
|
||||
// Don't pull all libraries, if we're missing something, add it to the installer list so the installer knows to download it.
|
||||
bootstrap { transitive = false }
|
||||
installer {
|
||||
installer {
|
||||
extendsFrom(bootstrap)
|
||||
transitive = false
|
||||
transitive = false
|
||||
}
|
||||
installerextra {
|
||||
installerextra {
|
||||
extendsFrom(bootstrap)
|
||||
transitive = false
|
||||
transitive = false
|
||||
}
|
||||
api.extendsFrom(installer)
|
||||
}
|
||||
@@ -117,9 +116,9 @@ dependencies {
|
||||
bootstrap(libs.securemodules) // Has Union file system in it
|
||||
bootstrap(libs.unsafe) // Needed by securemodules
|
||||
bootstrap(libs.bundles.asm) // Needed by securemodules
|
||||
|
||||
|
||||
implementation(libs.jopt.simple)
|
||||
|
||||
|
||||
installer(libs.bootstrap)
|
||||
installer(libs.bootstrap.api) // Needed by securemodules
|
||||
installer(libs.accesstransformers)
|
||||
@@ -209,6 +208,7 @@ patcher {
|
||||
'--all',
|
||||
'--validate',
|
||||
'--output', rootProject.file('src/main/generated/'),
|
||||
'--validate',
|
||||
'--existing', sourceSets.main.resources.srcDirs[0],
|
||||
'--assetsDir', downloadAssets.output,
|
||||
'--assetIndex', "{asset_index}"
|
||||
@@ -226,31 +226,6 @@ patcher {
|
||||
'--assetsDir', downloadAssets.output,
|
||||
'--assetIndex', "{asset_index}"
|
||||
}
|
||||
|
||||
forge_client_data {
|
||||
args '--launchTarget', 'forge_dev_client_data',
|
||||
'--mod', 'forge',
|
||||
'--all',
|
||||
'--validate',
|
||||
'--output', rootProject.file('src/main/generated/'),
|
||||
'--existing', sourceSets.main.resources.srcDirs[0],
|
||||
'--assetsDir', downloadAssets.output,
|
||||
'--assetIndex', "{asset_index}"
|
||||
}
|
||||
|
||||
forge_client_data_test {
|
||||
source sourceSets.test
|
||||
args '--launchTarget', 'forge_dev',
|
||||
'--launchEntry', 'minecraft/net.minecraft.client.data.Main',
|
||||
'--launchData',
|
||||
'--mod', '.+',
|
||||
'--all',
|
||||
'--output', rootProject.file('src/test/generated/'),
|
||||
'--existing', sourceSets.main.resources.srcDirs[0],
|
||||
'--existing', sourceSets.test.resources.srcDirs[0],
|
||||
'--assetsDir', downloadAssets.output,
|
||||
'--assetIndex', "{asset_index}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,11 +267,11 @@ tasks.register('downloadCrowdin', Download) {
|
||||
tasks.userdevConfig.configure {
|
||||
configurations.installer.allDependencies.forEach {
|
||||
def dep = it.toString()
|
||||
if (it instanceof ProjectDependency)
|
||||
if (it instanceof ProjectDependency)
|
||||
dep = "net.minecraftforge:$it.dependencyProject.name:$it.dependencyProject.version"
|
||||
libraries.add(dep)
|
||||
}
|
||||
|
||||
|
||||
inject = '' // We don't have a userdev sourceset anymore. Empty as a gradle workaround...
|
||||
runs {
|
||||
client {
|
||||
@@ -308,13 +283,6 @@ tasks.userdevConfig.configure {
|
||||
args '--assetsDir', '{assets_root}'
|
||||
}
|
||||
|
||||
clientData {
|
||||
environment 'MCP_MAPPINGS', '{mcp_mappings}'
|
||||
args '--launchTarget', "forge_userdev_client_data"
|
||||
args '--assetIndex', '{asset_index}'
|
||||
args '--assetsDir', '{assets_root}'
|
||||
}
|
||||
|
||||
server {
|
||||
environment 'MCP_MAPPINGS', '{mcp_mappings}'
|
||||
property 'forge.enableGameTest', 'true'
|
||||
@@ -412,14 +380,14 @@ tasks.register('extractInheritance', ExtractInheritance) {
|
||||
}
|
||||
}
|
||||
tasks.register("findFinalizeSpawnTargets", BytecodePredicateFinder) {
|
||||
jar = createClientOfficial.output
|
||||
jar = createJoinedSRG.output
|
||||
output = rootProject.file('src/main/resources/coremods/finalize_spawn_targets.json')
|
||||
predicate = {
|
||||
parent, node, insn ->
|
||||
return 'net/minecraft/world/level/BaseSpawner' != parent.name // Ignore this class as we special case it.
|
||||
&& insn.getOpcode().equals(Opcodes.INVOKEVIRTUAL)
|
||||
&& insn.name == 'finalizeSpawn'
|
||||
&& insn.desc == '(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;';
|
||||
&& insn.name == 'm_6518_'
|
||||
&& insn.desc == '(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;';
|
||||
}
|
||||
}
|
||||
tasks.register('validateDeprecations', ValidateDeprecations) {
|
||||
@@ -524,7 +492,7 @@ tasks.register('serverShimJar', Jar) {
|
||||
from {
|
||||
zipTree(downloadServerShim.output).find { it.name == 'MANIFEST.MF' }
|
||||
}
|
||||
|
||||
|
||||
attributes('Class-Path': configurations.bootstrap.resolvedConfiguration.resolvedArtifacts.collect { "libraries/${Util.getMavenInfoFromDep(it).path}" }.join(' '))
|
||||
}
|
||||
archiveClassifier = 'shim'
|
||||
@@ -617,7 +585,7 @@ tasks.register('checkJarCompatibility', CheckJarCompatibility) {
|
||||
baseLibraries.from(project.tasks.named('createJoinedSRG').flatMap { it.output })
|
||||
|
||||
inputJar = project.tasks.named('reobfJar').flatMap { it.output }
|
||||
|
||||
|
||||
commonLibraries.from(project.configurations.minecraftImplementation)
|
||||
commonLibraries.from(project.configurations.installer)
|
||||
}
|
||||
@@ -638,11 +606,11 @@ tasks.register('launcherJson', LauncherJson).configure {
|
||||
|
||||
tasks.register('installerJson', InstallerJson) {
|
||||
icon = rootProject.file('icon.ico')
|
||||
|
||||
|
||||
// Json to install into the client's launcher
|
||||
dependsOn(launcherJson)
|
||||
input.from(launcherJson.output)
|
||||
|
||||
|
||||
// Download Official Mappings
|
||||
dependsOn(downloadClientMappings, downloadServerMappings)
|
||||
input.from(downloadClientMappings.output, downloadServerMappings.output)
|
||||
@@ -954,9 +922,6 @@ tasks.register('mdkZip', Zip) {
|
||||
rename 'gitignore\\.txt', '.gitignore'
|
||||
rename 'gitattributes\\.txt', '.gitattributes'
|
||||
}
|
||||
from(rootProject.file('src/test/java/com/example/examplemod/')) {
|
||||
into('src/main/java/com/example/examplemod/')
|
||||
}
|
||||
from(rootProject.file('src/test/generated/mdk_datagen/')) {
|
||||
into('src/main/resources/')
|
||||
exclude '**/.cache/'
|
||||
@@ -1090,7 +1055,7 @@ publishing {
|
||||
license gradleutils.pom.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ tasks.withType(JavaCompile).configureEach {
|
||||
dependsOn 'processResources' // Needed because we merge the output of this with the output of the compile task. And gradle detects downstream tasks using the output without a hard dep
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
options.warnings = false // Shutup deprecated for removal warnings
|
||||
options.forkOptions.jvmArgs += '-Xmx6G' // Needed to make compiling faster, and not run out of heap space in some cases.
|
||||
options.forkOptions.jvmArgs += '-Xmx3G' // Needed to make compiling faster, and not run out of heap space in some cases.
|
||||
}
|
||||
|
||||
// Merge the resources and classes into the same directory. We'll need to split them at runtime because
|
||||
|
||||
+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!
|
||||
|
||||
@@ -68,15 +68,13 @@ public interface IModLoadingState {
|
||||
* @return a transition task for this state
|
||||
* @see #buildTransition(Executor, Executor, ProgressMeter, Function, Function)
|
||||
*/
|
||||
default <T extends Event & IModBusEvent> Optional<CompletableFuture<Void>> buildTransition(
|
||||
final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar
|
||||
) {
|
||||
default <T extends Event & IModBusEvent>
|
||||
Optional<CompletableFuture<Void>> buildTransition(final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar) {
|
||||
return buildTransition(syncExecutor, parallelExecutor, progressBar,
|
||||
e -> CompletableFuture.completedFuture(null),
|
||||
e -> CompletableFuture.completedFuture(null)
|
||||
);
|
||||
e -> CompletableFuture.runAsync(() -> {}, e),
|
||||
e -> CompletableFuture.runAsync(() -> {}, e));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,8 @@ import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.progress.ProgressMeter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -16,67 +18,103 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public interface IModStateTransition {
|
||||
/** Magic value to allow me to optimize the futures list by ignoring the default value without making old methods nullable. */
|
||||
public static final BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> NULL_HOOK = (e, g) -> CompletableFuture.completedFuture(null);
|
||||
|
||||
static IModStateTransition buildNoopTransition() {
|
||||
return ModStateTransitionHelper.NOOP;
|
||||
return new NoopTransition();
|
||||
}
|
||||
|
||||
default CompletableFuture<Void> build(
|
||||
final String name,
|
||||
final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar,
|
||||
final Function<Executor, CompletableFuture<Void>> preSyncTask,
|
||||
final Function<Executor, CompletableFuture<Void>> postSyncTask
|
||||
) {
|
||||
return ModStateTransitionHelper.build(this, name, syncExecutor, parallelExecutor, progressBar, preSyncTask, postSyncTask);
|
||||
default <T extends Event & IModBusEvent>
|
||||
CompletableFuture<Void> build(final String name,
|
||||
final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar,
|
||||
final Function<Executor, CompletableFuture<Void>> preSyncTask,
|
||||
final Function<Executor, CompletableFuture<Void>> postSyncTask) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
|
||||
this.eventFunctionStream().get()
|
||||
.map(f -> (EventGenerator<T>) f)
|
||||
.reduce((head, tail) -> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, futures, progressBar, head, ModLoadingStage::currentState, tail))
|
||||
.ifPresent(last -> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, futures, progressBar, last, nextModLoadingStage(), null));
|
||||
|
||||
final CompletableFuture<Void> preSyncTaskCF = preSyncTask.apply(syncExecutor);
|
||||
final CompletableFuture<Void> eventDispatchCF = ModList.gather(futures).thenCompose(ModList::completableFutureFromExceptionList);
|
||||
final CompletableFuture<Void> postEventDispatchCF = preSyncTaskCF
|
||||
.thenApplyAsync(n -> {
|
||||
progressBar.label(progressBar.name() + ": dispatching "+name);
|
||||
return null;
|
||||
}, parallelExecutor)
|
||||
.thenComposeAsync(n -> eventDispatchCF, parallelExecutor)
|
||||
.thenApply(r -> {
|
||||
postSyncTask.apply(syncExecutor);
|
||||
return null;
|
||||
});
|
||||
return this.finalActivityGenerator().apply(syncExecutor, postEventDispatchCF);
|
||||
}
|
||||
|
||||
default BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextModLoadingStage() {
|
||||
return ModLoadingStage::nextState;
|
||||
}
|
||||
|
||||
/**
|
||||
* This used to allow you to fire multiple events during the transition. However, in doing so it would cause issues with the default
|
||||
* ModContainer's event handlers causing issues such as mod classes being constructed multiple times.
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
default Supplier<Stream<EventGenerator<?>>> eventFunctionStream() {
|
||||
return () -> Stream.ofNullable(eventFunction());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default <T extends Event & IModBusEvent> EventGenerator<T> eventFunction() {
|
||||
return null;
|
||||
private <T extends Event & IModBusEvent>
|
||||
EventGenerator<T> addCompletableFutureTaskForModDispatch(final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final List<CompletableFuture<Void>> completableFutures,
|
||||
final ProgressMeter progressBar,
|
||||
final EventGenerator<T> eventGenerator,
|
||||
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextState,
|
||||
final EventGenerator<T> nextGenerator) {
|
||||
final Executor selectedExecutor = threadSelector().apply(syncExecutor, parallelExecutor);
|
||||
|
||||
var preDispatchHook = (BiFunction<Executor, EventGenerator<T>, CompletableFuture<Void>>) preDispatchHook();
|
||||
completableFutures.add(preDispatchHook.apply(selectedExecutor, eventGenerator));
|
||||
|
||||
completableFutures.add(ModList.get().futureVisitor(eventGenerator, progressBar, nextState).apply(threadSelector().apply(syncExecutor, parallelExecutor)));
|
||||
|
||||
var postDispatchHook = (BiFunction<Executor, EventGenerator<T>, CompletableFuture<Void>>) postDispatchHook();
|
||||
completableFutures.add(postDispatchHook.apply(selectedExecutor, eventGenerator));
|
||||
|
||||
return nextGenerator;
|
||||
}
|
||||
|
||||
Supplier<Stream<EventGenerator<?>>> eventFunctionStream();
|
||||
ThreadSelector threadSelector();
|
||||
BiFunction<Executor, CompletableFuture<Void>, CompletableFuture<Void>> finalActivityGenerator();
|
||||
|
||||
/**
|
||||
* I think this was meant as a way to do some things for each mod container beforge/after the transition had been sent to the container.
|
||||
* However, the Future returned by this was never linked to the main transition future in any way. Which means that it was run
|
||||
* in parallel and couldn't guarantee the state of the ModContainer.
|
||||
* <p>
|
||||
* Plus all existing code that I could find returned a completedFuture, so I don't think anyone ever used this.
|
||||
* <p>
|
||||
* If I were to add this back it would be a CompletableFuture wrap(ModContainer, CompletableFuture)
|
||||
* <p>
|
||||
* Added magic value NULL_HOOK to allow me to optimize the futures list by ignoring the default value without making this method nullable.
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
default BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> preDispatchHook() { return NULL_HOOK; }
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
default BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> postDispatchHook() { return NULL_HOOK; }
|
||||
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> preDispatchHook();
|
||||
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> postDispatchHook();
|
||||
|
||||
interface EventGenerator<T extends Event & IModBusEvent> extends Function<ModContainer, T> {
|
||||
static <FN extends Event & IModBusEvent> EventGenerator<FN> fromFunction(Function<ModContainer, FN> fn) {
|
||||
return fn::apply;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record NoopTransition() implements IModStateTransition {
|
||||
|
||||
@Override
|
||||
public Supplier<Stream<EventGenerator<?>>> eventFunctionStream() {
|
||||
return Stream::of;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadSelector threadSelector() {
|
||||
return ThreadSelector.SYNC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Executor, CompletableFuture<Void>, CompletableFuture<Void>> finalActivityGenerator() {
|
||||
return (e, t) -> t.thenApplyAsync(Function.identity(), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> preDispatchHook() {
|
||||
return (t, f)-> CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> postDispatchHook() {
|
||||
return (t, f)-> CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,18 @@ import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.config.IConfigEvent;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.progress.ProgressMeter;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
@@ -30,8 +33,13 @@ import java.util.function.Supplier;
|
||||
* a mechanism by which we can wrap actual mod code so that the loader and other
|
||||
* facilities can treat mods at arms length.
|
||||
* </p>
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public abstract class ModContainer {
|
||||
|
||||
public abstract class ModContainer
|
||||
{
|
||||
protected final String modId;
|
||||
protected final String namespace;
|
||||
protected final IModInfo modInfo;
|
||||
@@ -40,14 +48,11 @@ public abstract class ModContainer {
|
||||
protected final Map<ModLoadingStage, Runnable> activityMap = new EnumMap<>(ModLoadingStage.class);
|
||||
protected final Map<Class<? extends IExtensionPoint<?>>, Supplier<?>> extensionPoints = new IdentityHashMap<>();
|
||||
protected final EnumMap<ModConfig.Type, ModConfig> configs = new EnumMap<>(ModConfig.Type.class);
|
||||
final Set<ModContainer> dependencies = new HashSet<>();
|
||||
/**
|
||||
* If you want to handle the event, override {@link #dispatchConfigEvent(IConfigEvent)}
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
protected Optional<Consumer<IConfigEvent>> configHandler = Optional.empty();
|
||||
|
||||
public ModContainer(IModInfo info) {
|
||||
public ModContainer(IModInfo info)
|
||||
{
|
||||
this.modId = info.getModId();
|
||||
// TODO: Currently not reading namespace from configuration..
|
||||
this.namespace = this.modId;
|
||||
@@ -77,35 +82,58 @@ public abstract class ModContainer {
|
||||
/**
|
||||
* Errored container state, used for filtering. Does nothing.
|
||||
*/
|
||||
ModContainer() {
|
||||
ModContainer()
|
||||
{
|
||||
this.modLoadingStage = ModLoadingStage.ERROR;
|
||||
modId = "BROKEN";
|
||||
namespace = "BROKEN";
|
||||
modInfo = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the modid for this mod
|
||||
*/
|
||||
public final String getModId() {
|
||||
public final String getModId()
|
||||
{
|
||||
return modId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resource prefix for the mod
|
||||
*/
|
||||
public final String getNamespace() {
|
||||
public final String getNamespace()
|
||||
{
|
||||
return namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current loading stage for this mod
|
||||
*/
|
||||
public ModLoadingStage getCurrentState() {
|
||||
public ModLoadingStage getCurrentState()
|
||||
{
|
||||
return modLoadingStage;
|
||||
}
|
||||
|
||||
public IModInfo getModInfo() {
|
||||
public static <T extends Event & IModBusEvent> CompletableFuture<Void> buildTransitionHandler(
|
||||
final ModContainer target,
|
||||
final IModStateTransition.EventGenerator<T> eventGenerator,
|
||||
final ProgressMeter progressBar,
|
||||
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChangeHandler,
|
||||
final Executor executor) {
|
||||
return CompletableFuture
|
||||
.runAsync(() -> {
|
||||
ModLoadingContext.get().setActiveContainer(target);
|
||||
target.activityMap.getOrDefault(target.modLoadingStage, ()->{}).run();
|
||||
target.acceptEvent(eventGenerator.apply(target));
|
||||
}, executor)
|
||||
.whenComplete((mc, exception) -> {
|
||||
target.modLoadingStage = stateChangeHandler.apply(target.modLoadingStage, exception);
|
||||
progressBar.increment();
|
||||
ModLoadingContext.get().setActiveContainer(null);
|
||||
});
|
||||
}
|
||||
|
||||
public IModInfo getModInfo()
|
||||
{
|
||||
return modInfo;
|
||||
}
|
||||
|
||||
@@ -114,7 +142,8 @@ public abstract class ModContainer {
|
||||
return Optional.ofNullable((T)extensionPoints.getOrDefault(point,()-> null).get());
|
||||
}
|
||||
|
||||
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension) {
|
||||
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension)
|
||||
{
|
||||
extensionPoints.put(point, extension);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.progress.ProgressMeter;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
@@ -12,15 +15,27 @@ import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import java.util.Collections;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -30,25 +45,27 @@ import java.util.stream.Stream;
|
||||
* Master list of all mods - game-side version. This is classloaded in the game scope and
|
||||
* can dispatch game level events as a result.
|
||||
*/
|
||||
public class ModList {
|
||||
public class ModList
|
||||
{
|
||||
//private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static ModList INSTANCE;
|
||||
private final List<IModFileInfo> modFiles;
|
||||
private final List<IModInfo> sortedList;
|
||||
private final Map<String, IModFileInfo> fileById;
|
||||
private final Map<String, ModFileInfo> fileById;
|
||||
private List<ModContainer> mods;
|
||||
private Map<String, ModContainer> indexedMods;
|
||||
private List<ModFileScanData> modFileScanData;
|
||||
private List<ModContainer> sortedContainers;
|
||||
|
||||
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList) {
|
||||
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 mod : file.getMods())
|
||||
byId.put(mod.getModId(), mod.getOwningFile());
|
||||
}
|
||||
this.fileById = Collections.unmodifiableMap(byId);
|
||||
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
|
||||
{
|
||||
this.modFiles = modFiles.stream().map(ModFile::getModFileInfo).map(ModFileInfo.class::cast).collect(Collectors.toList());
|
||||
this.sortedList = sortedList.stream().
|
||||
map(ModInfo.class::cast).
|
||||
collect(Collectors.toList());
|
||||
this.fileById = this.modFiles.stream().map(IModFileInfo::getMods).flatMap(Collection::stream).
|
||||
map(ModInfo.class::cast).
|
||||
collect(Collectors.toMap(ModInfo::getModId, ModInfo::getOwningFile));
|
||||
CrashReportCallables.registerCrashCallable("Mod List", this::crashReport);
|
||||
}
|
||||
|
||||
@@ -65,12 +82,12 @@ public class ModList {
|
||||
getModContainerState(mainMod.getModId()),
|
||||
((ModFileInfo)mf.getModFileInfo()).getCodeSigningFingerprint().orElse("NOSIGNATURE"));
|
||||
}
|
||||
|
||||
private String crashReport() {
|
||||
return "\n"+applyForEachModFile(this::fileToLine).collect(Collectors.joining("\n\t\t", "\t\t", ""));
|
||||
}
|
||||
|
||||
public static ModList of(List<ModFile> modFiles, List<ModInfo> sortedList) {
|
||||
public static ModList of(List<ModFile> modFiles, List<ModInfo> sortedList)
|
||||
{
|
||||
INSTANCE = new ModList(modFiles, sortedList);
|
||||
return INSTANCE;
|
||||
}
|
||||
@@ -79,47 +96,103 @@ public class ModList {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public List<IModFileInfo> getModFiles() {
|
||||
public List<IModFileInfo> getModFiles()
|
||||
{
|
||||
return modFiles;
|
||||
}
|
||||
|
||||
public IModFileInfo getModFileById(String modid) {
|
||||
public IModFileInfo getModFileById(String modid)
|
||||
{
|
||||
return this.fileById.get(modid);
|
||||
}
|
||||
|
||||
void setLoadedMods(final List<ModContainer> modContainers) {
|
||||
<T extends Event & IModBusEvent> Function<Executor, CompletableFuture<Void>> futureVisitor(
|
||||
final IModStateTransition.EventGenerator<T> eventGenerator,
|
||||
final ProgressMeter progressBar,
|
||||
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChange) {
|
||||
return executor -> gather(
|
||||
this.mods.stream()
|
||||
.map(mod -> ModContainer.buildTransitionHandler(mod, eventGenerator, progressBar, stateChange, executor))
|
||||
.toList()
|
||||
).thenComposeAsync(ModList::completableFutureFromExceptionList, executor);
|
||||
}
|
||||
static CompletionStage<Void> completableFutureFromExceptionList(List<? extends Map.Entry<?, Throwable>> t) {
|
||||
if (t.stream().noneMatch(e->e.getValue()!=null)) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
final List<Throwable> throwables = t.stream().filter(e -> e.getValue() != null).map(Map.Entry::getValue).toList();
|
||||
CompletableFuture<Void> cf = new CompletableFuture<>();
|
||||
final RuntimeException accumulator = new RuntimeException();
|
||||
cf.completeExceptionally(accumulator);
|
||||
for (Throwable exception : throwables) {
|
||||
if (exception instanceof CompletionException) {
|
||||
exception = exception.getCause();
|
||||
}
|
||||
if (exception.getSuppressed().length != 0) {
|
||||
for (Throwable throwable : exception.getSuppressed()) {
|
||||
accumulator.addSuppressed(throwable);
|
||||
}
|
||||
} else {
|
||||
accumulator.addSuppressed(exception);
|
||||
}
|
||||
}
|
||||
return cf;
|
||||
}
|
||||
}
|
||||
|
||||
static <V> CompletableFuture<List<Map.Entry<V, Throwable>>> gather(List<? extends CompletableFuture<? extends V>> futures) {
|
||||
List<Map.Entry<V, Throwable>> list = new ArrayList<>(futures.size());
|
||||
CompletableFuture<?>[] results = new CompletableFuture[futures.size()];
|
||||
for (var future : futures) {
|
||||
int i = list.size();
|
||||
list.add(null);
|
||||
results[i] = future.whenComplete((result, exception) -> list.set(i, new AbstractMap.SimpleImmutableEntry<>(result, exception)));
|
||||
}
|
||||
return CompletableFuture.allOf(results).handle((r, th)->null).thenApply(res -> list);
|
||||
}
|
||||
|
||||
void setLoadedMods(final List<ModContainer> modContainers)
|
||||
{
|
||||
this.mods = modContainers;
|
||||
this.sortedContainers = modContainers.stream().sorted(Comparator.comparingInt(c -> sortedList.indexOf(c.getModInfo()))).toList();
|
||||
this.sortedContainers = modContainers.stream().sorted(Comparator.comparingInt(c->sortedList.indexOf(c.getModInfo()))).toList();
|
||||
this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Optional<T> getModObjectById(String modId) {
|
||||
public <T> Optional<T> getModObjectById(String modId)
|
||||
{
|
||||
return getModContainerById(modId).map(ModContainer::getMod).map(o -> (T) o);
|
||||
}
|
||||
|
||||
public Optional<? extends ModContainer> getModContainerById(String modId) {
|
||||
public Optional<? extends ModContainer> getModContainerById(String modId)
|
||||
{
|
||||
return Optional.ofNullable(this.indexedMods.get(modId));
|
||||
}
|
||||
|
||||
public Optional<? extends ModContainer> getModContainerByObject(Object obj) {
|
||||
public Optional<? extends ModContainer> getModContainerByObject(Object obj)
|
||||
{
|
||||
return mods.stream().filter(mc -> mc.getMod() == obj).findFirst();
|
||||
}
|
||||
|
||||
public List<IModInfo> getMods() {
|
||||
public List<IModInfo> getMods()
|
||||
{
|
||||
return this.sortedList;
|
||||
}
|
||||
|
||||
public boolean isLoaded(String modTarget) {
|
||||
public boolean isLoaded(String modTarget)
|
||||
{
|
||||
return this.indexedMods.containsKey(modTarget);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
public int size()
|
||||
{
|
||||
return mods.size();
|
||||
}
|
||||
|
||||
public List<ModFileScanData> getAllScanData() {
|
||||
if (modFileScanData == null) {
|
||||
public List<ModFileScanData> getAllScanData()
|
||||
{
|
||||
if (modFileScanData == null)
|
||||
{
|
||||
modFileScanData = this.sortedList.stream().
|
||||
map(IModInfo::getOwningFile).
|
||||
filter(Objects::nonNull).
|
||||
@@ -132,7 +205,8 @@ public class ModList {
|
||||
|
||||
}
|
||||
|
||||
public void forEachModFile(Consumer<IModFile> fileConsumer) {
|
||||
public void forEachModFile(Consumer<IModFile> fileConsumer)
|
||||
{
|
||||
modFiles.stream().map(IModFileInfo::getFile).forEach(fileConsumer);
|
||||
}
|
||||
|
||||
@@ -148,11 +222,13 @@ public class ModList {
|
||||
this.sortedContainers.forEach(containerConsumer);
|
||||
}
|
||||
|
||||
public List<ModContainer> getLoadedMods() {
|
||||
return this.sortedContainers;
|
||||
}
|
||||
|
||||
public <T> Stream<T> applyForEachModContainer(Function<ModContainer, T> function) {
|
||||
return indexedMods.values().stream().map(function);
|
||||
}
|
||||
|
||||
private static class UncaughtModLoadingException extends ModLoadingException {
|
||||
public UncaughtModLoadingException(ModLoadingStage stage, Throwable originalException) {
|
||||
super(null, stage, "fml.modloading.uncaughterror", originalException);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
@@ -32,6 +33,8 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.CORE;
|
||||
import static net.minecraftforge.fml.Logging.LOADING;
|
||||
|
||||
@@ -71,7 +74,8 @@ import static net.minecraftforge.fml.Logging.LOADING;
|
||||
* and completes the mod loading sequence.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
public class ModLoader {
|
||||
public class ModLoader
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final LoadingModList loadingModList;
|
||||
|
||||
@@ -80,15 +84,17 @@ public class ModLoader {
|
||||
private final List<ModLoadingWarning> loadingWarnings;
|
||||
private final ModStateManager stateManager;
|
||||
private static boolean loadingStateValid;
|
||||
private final Consumer<String> statusConsumer = StartupNotificationManager.modLoaderConsumer().orElse(msg -> {});
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private final Optional<Consumer<String>> statusConsumer = StartupNotificationManager.modLoaderConsumer();
|
||||
private final Set<IModLoadingState> completedStates = new HashSet<>();
|
||||
private ModList modList;
|
||||
|
||||
private ModLoader() {
|
||||
private ModLoader()
|
||||
{
|
||||
this.loadingModList = FMLLoader.getLoadingModList();
|
||||
this.loadingExceptions = this.loadingModList.getErrors().stream()
|
||||
.flatMap(ModLoadingException::fromEarlyException)
|
||||
.toList();
|
||||
.collect(Collectors.toList());
|
||||
this.loadingWarnings = this.loadingModList.getBrokenFiles().stream()
|
||||
.map(file -> new ModLoadingWarning(null, ModLoadingStage.VALIDATE, InvalidModIdentifier.identifyJarProblem(file.getFilePath()).orElse("fml.modloading.brokenfile"), file.getFileName()))
|
||||
.collect(Collectors.toList());
|
||||
@@ -150,7 +156,7 @@ public class ModLoader {
|
||||
loadingModList.getMods());
|
||||
if (!this.loadingExceptions.isEmpty()) {
|
||||
LOGGER.fatal(CORE, "Error during pre-loading phase", loadingExceptions.getFirst());
|
||||
statusConsumer.accept("ERROR DURING MOD LOADING");
|
||||
statusConsumer.ifPresent(c->c.accept("ERROR DURING MOD LOADING"));
|
||||
modList.setLoadedMods(Collections.emptyList());
|
||||
loadingStateValid = false;
|
||||
throw new LoadingFailedException(loadingExceptions);
|
||||
@@ -163,7 +169,7 @@ public class ModLoader {
|
||||
|
||||
if (!failedBounds.isEmpty()) {
|
||||
LOGGER.fatal(CORE, "Failed to validate feature bounds for mods: {}", failedBounds);
|
||||
statusConsumer.accept("ERROR DURING MOD LOADING");
|
||||
statusConsumer.ifPresent(c->c.accept("ERROR DURING MOD LOADING"));
|
||||
modList.setLoadedMods(Collections.emptyList());
|
||||
loadingStateValid = false;
|
||||
throw new LoadingFailedException(failedBounds.stream()
|
||||
@@ -171,42 +177,19 @@ public class ModLoader {
|
||||
.toList());
|
||||
}
|
||||
|
||||
final var modContainers = new HashMap<String, ModContainer>();
|
||||
for (var file : loadingModList.getModFiles()) {
|
||||
var containers = this.buildMods(file.getFile());
|
||||
for (var container : containers)
|
||||
modContainers.put(container.getModId(), container);
|
||||
}
|
||||
|
||||
final List<ModContainer> modContainers = loadingModList.getModFiles().stream()
|
||||
.map(ModFileInfo::getFile)
|
||||
.map(this::buildMods)
|
||||
.flatMap(List::stream)
|
||||
.toList();
|
||||
if (!loadingExceptions.isEmpty()) {
|
||||
LOGGER.fatal(CORE, "Failed to initialize mod containers", loadingExceptions.getFirst());
|
||||
statusConsumer.accept("ERROR DURING MOD LOADING");
|
||||
statusConsumer.ifPresent(c->c.accept("ERROR DURING MOD LOADING"));
|
||||
modList.setLoadedMods(Collections.emptyList());
|
||||
loadingStateValid = false;
|
||||
throw new LoadingFailedException(loadingExceptions);
|
||||
}
|
||||
|
||||
// Gather all dependencies, so we can make sure they have finished their transition events before we fire ours
|
||||
for (var mod : modContainers.values()) {
|
||||
for (var dep : mod.getModInfo().getDependencies()) {
|
||||
var target = modContainers.get(dep.getModId());
|
||||
if (target == null)
|
||||
continue;
|
||||
|
||||
switch (dep.getOrdering()) {
|
||||
case AFTER:
|
||||
mod.dependencies.add(target);
|
||||
break;
|
||||
case BEFORE:
|
||||
target.dependencies.add(mod);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modList.setLoadedMods(modContainers.values().stream().toList());
|
||||
modList.setLoadedMods(modContainers);
|
||||
this.modList = modList;
|
||||
var stateList = stateManager.getStates(ModLoadingPhase.GATHER);
|
||||
var progress = StartupMessageManager.addProgressBar("Mod Gather", stateList.stream().mapToInt(mls -> mls.size().applyAsInt(this.modList)).sum());
|
||||
@@ -231,7 +214,7 @@ 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()));
|
||||
statusConsumer.ifPresent(c->c.accept(String.format("Mod loading complete - %d mods loaded", this.modList.size())));
|
||||
progress.complete();
|
||||
}
|
||||
|
||||
@@ -260,12 +243,10 @@ public class ModLoader {
|
||||
pb.complete();
|
||||
syncExecutor.drive(ticker);
|
||||
}
|
||||
|
||||
private void waitForTransition(final IModLoadingState state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker, final CompletableFuture<Void> transition) {
|
||||
while (!transition.isDone()) {
|
||||
syncExecutor.drive(ticker);
|
||||
}
|
||||
|
||||
try {
|
||||
transition.join();
|
||||
} catch (CompletionException e) {
|
||||
@@ -275,38 +256,36 @@ public class ModLoader {
|
||||
.anyMatch(obj -> !(obj instanceof ModLoadingException));
|
||||
if (hasNotModLoadingEx) {
|
||||
LOGGER.fatal("Encountered non-modloading exceptions!", e);
|
||||
statusConsumer.accept("ERROR DURING MOD LOADING");
|
||||
statusConsumer.ifPresent(c->c.accept("ERROR DURING MOD LOADING"));
|
||||
throw e;
|
||||
}
|
||||
|
||||
final List<ModLoadingException> modLoadingExceptions = Arrays.stream(t.getSuppressed())
|
||||
.filter(ModLoadingException.class::isInstance)
|
||||
.map(ModLoadingException.class::cast)
|
||||
.toList();
|
||||
.collect(Collectors.toList());
|
||||
LOGGER.fatal(LOADING,"Failed to complete lifecycle event {}, {} errors found", state.name(), modLoadingExceptions.size());
|
||||
statusConsumer.accept("ERROR DURING MOD LOADING");
|
||||
statusConsumer.ifPresent(c->c.accept("ERROR DURING MOD LOADING"));
|
||||
throw new LoadingFailedException(modLoadingExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ModContainer> buildMods(final IModFile modFile) {
|
||||
final Map<String, IModInfo> modInfoMap = new HashMap<>();
|
||||
for (var mod : modFile.getModFileInfo().getMods())
|
||||
modInfoMap.put(mod.getModId(), mod);
|
||||
private List<ModContainer> buildMods(final IModFile modFile)
|
||||
{
|
||||
final Map<String, IModInfo> modInfoMap = modFile.getModFileInfo().getMods().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
|
||||
|
||||
LOGGER.trace(LOADING, "ModContainer is {}", ModContainer.class.getClassLoader());
|
||||
final List<ModContainer> containers = new ArrayList<>();
|
||||
for (var entry : modFile.getScanResult().getTargets().entrySet()) {
|
||||
var container = buildModContainerFromTOML(modFile, modInfoMap, entry.getKey(), entry.getValue());
|
||||
if (container != null)
|
||||
containers.add(container);
|
||||
}
|
||||
|
||||
final List<ModContainer> containers = modFile.getScanResult().getTargets()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(e -> buildModContainerFromTOML(modFile, modInfoMap, e))
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
if (containers.size() != modInfoMap.size()) {
|
||||
var modIds = modInfoMap.values().stream().map(IModInfo::getModId).sorted().toList();
|
||||
var containerIds = containers.stream().map(c -> c != null ? c.getModId() : "(null)").sorted().toList();
|
||||
|
||||
LOGGER.fatal(LOADING, "File {} constructed {} mods: {}, but had {} mods specified: {}",
|
||||
LOGGER.fatal(LOADING,"File {} constructed {} mods: {}, but had {} mods specified: {}",
|
||||
modFile.getFilePath(),
|
||||
containers.size(), containerIds,
|
||||
modInfoMap.size(), modIds);
|
||||
@@ -321,15 +300,15 @@ public class ModLoader {
|
||||
|
||||
loadingExceptions.add(new ModLoadingException(null, ModLoadingStage.CONSTRUCT, "fml.modloading.missingclasses", null, modFile.getFilePath()));
|
||||
}
|
||||
|
||||
// remove errored mod containers
|
||||
return containers.stream().filter(mc -> mc.modLoadingStage != ModLoadingStage.ERROR).toList();
|
||||
}
|
||||
|
||||
private ModContainer buildModContainerFromTOML(final IModFile modFile, final Map<String, IModInfo> modInfoMap,
|
||||
final String modId, final IModLanguageProvider.IModLanguageLoader languageLoader
|
||||
) {
|
||||
private ModContainer buildModContainerFromTOML(final IModFile modFile, final Map<String, IModInfo> modInfoMap, final Map.Entry<String, ? extends IModLanguageProvider.IModLanguageLoader> idToProviderEntry) {
|
||||
try {
|
||||
final String modId = idToProviderEntry.getKey();
|
||||
final IModLanguageProvider.IModLanguageLoader languageLoader = idToProviderEntry.getValue();
|
||||
|
||||
IModInfo info = modInfoMap.get(modId);
|
||||
// throw a missing metadata error if there is no matching modid in the modInfoMap from the mods.toml file
|
||||
if (info == null)
|
||||
@@ -372,7 +351,6 @@ public class ModLoader {
|
||||
}
|
||||
ModList.get().forEachModInOrder(mc -> mc.acceptEvent(e));
|
||||
}
|
||||
|
||||
public <T extends Event & IModBusEvent> T postEventWithReturn(T e) {
|
||||
if (!loadingStateValid) {
|
||||
LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName());
|
||||
@@ -381,15 +359,9 @@ public class ModLoader {
|
||||
ModList.get().forEachModInOrder(mc -> mc.acceptEvent(e));
|
||||
return e;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public <T extends Event & IModBusEvent> void postEventWrapContainerInModOrder(T event) {
|
||||
postEventWithWrapInModOrder(event,
|
||||
(mc, e) -> ModLoadingContext.get().setActiveContainer(mc),
|
||||
(mc, e) -> ModLoadingContext.get().setActiveContainer(null)
|
||||
);
|
||||
postEventWithWrapInModOrder(event, (mc, e) -> ModLoadingContext.get().setActiveContainer(mc), (mc, e) -> ModLoadingContext.get().setActiveContainer(null));
|
||||
}
|
||||
|
||||
public <T extends Event & IModBusEvent> void postEventWithWrapInModOrder(T e, BiConsumer<ModContainer, T> pre, BiConsumer<ModContainer, T> post) {
|
||||
if (!loadingStateValid) {
|
||||
LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName());
|
||||
@@ -402,11 +374,13 @@ public class ModLoader {
|
||||
});
|
||||
}
|
||||
|
||||
public List<ModLoadingWarning> getWarnings() {
|
||||
public List<ModLoadingWarning> getWarnings()
|
||||
{
|
||||
return ImmutableList.copyOf(this.loadingWarnings);
|
||||
}
|
||||
|
||||
public void addWarning(ModLoadingWarning warning) {
|
||||
public void addWarning(ModLoadingWarning warning)
|
||||
{
|
||||
this.loadingWarnings.add(warning);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,15 +8,20 @@ package net.minecraftforge.fml;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.fml.config.IConfigSpec;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ModLoadingContext {
|
||||
public class ModLoadingContext
|
||||
{
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
|
||||
private ModContainer activeContainer;
|
||||
private Object languageExtension;
|
||||
private ModLoadingStage stage;
|
||||
|
||||
/**
|
||||
* @deprecated Use the context provided by your language loader in your mod's constructor
|
||||
|
||||
@@ -26,23 +26,19 @@ import java.util.function.ToIntFunction;
|
||||
* @param inlineRunnable an optional runnable, which runs before starting the transition from this state to the next
|
||||
* @param transition optional state transition information
|
||||
*/
|
||||
public record ModLoadingState(
|
||||
String name,
|
||||
String previous,
|
||||
Function<ModList, String> message,
|
||||
ToIntFunction<ModList> size,
|
||||
ModLoadingPhase phase,
|
||||
Optional<Consumer<ModList>> inlineRunnable,
|
||||
Optional<IModStateTransition> transition
|
||||
) implements IModLoadingState {
|
||||
public record ModLoadingState(String name, String previous,
|
||||
Function<ModList, String> message,
|
||||
ToIntFunction<ModList> size,
|
||||
ModLoadingPhase phase,
|
||||
Optional<Consumer<ModList>> inlineRunnable,
|
||||
Optional<IModStateTransition> transition) implements IModLoadingState {
|
||||
@Override
|
||||
public <T extends Event & IModBusEvent> Optional<CompletableFuture<Void>> buildTransition(
|
||||
final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar,
|
||||
final Function<Executor, CompletableFuture<Void>> preSyncTask,
|
||||
final Function<Executor, CompletableFuture<Void>> postSyncTask
|
||||
) {
|
||||
public <T extends Event & IModBusEvent>
|
||||
Optional<CompletableFuture<Void>> buildTransition(final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar,
|
||||
final Function<Executor, CompletableFuture<Void>> preSyncTask,
|
||||
final Function<Executor, CompletableFuture<Void>> postSyncTask) {
|
||||
var transition = this.transition.orElse(null);
|
||||
return transition == null
|
||||
? Optional.empty()
|
||||
@@ -56,12 +52,9 @@ public record ModLoadingState(
|
||||
* @param name the name of the state
|
||||
* @param previous the name of the immediately previous state to this state
|
||||
* @param phase the mod loading phase the state belongs to
|
||||
*
|
||||
* @deprecated Use the builder
|
||||
*/
|
||||
@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 -> "", f->0, phase, Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,13 +65,11 @@ public record ModLoadingState(
|
||||
* @param previous the name of the immediately previous state to this state
|
||||
* @param phase the mod loading phase the state belongs to
|
||||
* @param transition the state transition information
|
||||
*
|
||||
* @deprecated Use the builder
|
||||
* @return a mod loading state with state transition information and a default message
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
public static ModLoadingState withTransition(final String name, final String previous, final ModLoadingPhase phase,
|
||||
final IModStateTransition transition) {
|
||||
return of(name, phase).after(previous).withTransition(transition);
|
||||
return new ModLoadingState(name, previous, ml -> "Processing transition " + name, ModList::size, phase, Optional.empty(), Optional.of(transition));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,14 +81,11 @@ public record ModLoadingState(
|
||||
* @param phase the mod loading phase the state belongs to
|
||||
* @param transition the state transition information
|
||||
* @return a mod loading state with state transition information and a custom message
|
||||
*
|
||||
* @deprecated Use the builder
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
public static ModLoadingState withTransition(final String name, final String previous,
|
||||
final Function<ModList, String> message, final ModLoadingPhase phase,
|
||||
final IModStateTransition transition) {
|
||||
return of(name, phase).after(previous).message(message).withTransition(transition);
|
||||
return new ModLoadingState(name, previous, message, ModList::size, phase, Optional.empty(), Optional.of(transition));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,59 +97,9 @@ public record ModLoadingState(
|
||||
* @param phase the mod loading phase the state belongs to
|
||||
* @param inline an optional runnable, which runs before starting the transition from this state to the next
|
||||
* @return a mod loading state with an inline runnable and default message
|
||||
*
|
||||
* @deprecated Use the builder
|
||||
*/
|
||||
@Deprecated(since = "1.21.3", forRemoval = true)
|
||||
public static ModLoadingState withInline(final String name, final String previous, final ModLoadingPhase phase,
|
||||
final Consumer<ModList> inline) {
|
||||
return of(name, phase).after(previous).withInline(inline);
|
||||
}
|
||||
|
||||
public static Builder of(final String name, final ModLoadingPhase phase) {
|
||||
return new Builder(name, phase);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final String name;
|
||||
private final ModLoadingPhase phase;
|
||||
private String after;
|
||||
private Function<ModList, String> message = null;
|
||||
private ToIntFunction<ModList> size = null;
|
||||
|
||||
private Builder(final String name, final ModLoadingPhase phase) {
|
||||
this.name = name;
|
||||
this.phase = phase;
|
||||
}
|
||||
|
||||
public Builder after(final ModLoadingState value) { return after(value.name()); }
|
||||
public Builder after(final String value) {
|
||||
this.after = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder message(final String value) { return message(ml -> value); }
|
||||
public Builder message(final Function<ModList, String> value) {
|
||||
this.message = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder size(final int value) { return size(ml -> value); }
|
||||
public Builder size(final ToIntFunction<ModList> value) {
|
||||
this.size = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModLoadingState empty() {
|
||||
return new ModLoadingState(name, after, message != null ? message : ml -> "", size != null ? size : ml -> 0, phase, Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
public ModLoadingState withTransition(final IModStateTransition transition) {
|
||||
return new ModLoadingState(name, after, message != null ? message : ml -> "Processing transition " + name, size != null ? size : ModList::size, phase, Optional.empty(), Optional.of(transition));
|
||||
}
|
||||
|
||||
public ModLoadingState withInline(final Consumer<ModList> inline) {
|
||||
return new ModLoadingState(name, after, message != null ? message : ml -> "Processing work " + name, size != null ? size : ml -> 0, phase, Optional.of(inline), Optional.empty());
|
||||
}
|
||||
return new ModLoadingState(name, previous, ml -> "Processing work " + name, ml->0, phase, Optional.of(inline), Optional.empty());
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.IModStateTransition.EventGenerator;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.loading.progress.ProgressMeter;
|
||||
|
||||
@ApiStatus.Internal
|
||||
class ModStateTransitionHelper {
|
||||
static final IModStateTransition NOOP = new NoopTransition();
|
||||
record NoopTransition() implements IModStateTransition {
|
||||
@Override
|
||||
public ThreadSelector threadSelector() {
|
||||
return ThreadSelector.SYNC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Executor, CompletableFuture<Void>, CompletableFuture<Void>> finalActivityGenerator() {
|
||||
return (e, t) -> t.thenApplyAsync(Function.identity(), e);
|
||||
}
|
||||
}
|
||||
|
||||
static <V> CompletionStage<Void> completableFutureFromExceptionList(List<FutureResult<V>> t) {
|
||||
if (t.stream().noneMatch(e -> e.exception() != null)) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
final var throwables = t.stream().map(FutureResult::exception).filter(e -> e != null).toList();
|
||||
CompletableFuture<Void> cf = new CompletableFuture<>();
|
||||
final RuntimeException accumulator = new RuntimeException();
|
||||
cf.completeExceptionally(accumulator);
|
||||
for (Throwable exception : throwables) {
|
||||
if (exception instanceof CompletionException) {
|
||||
exception = exception.getCause();
|
||||
}
|
||||
if (exception.getSuppressed().length != 0) {
|
||||
for (Throwable throwable : exception.getSuppressed()) {
|
||||
accumulator.addSuppressed(throwable);
|
||||
}
|
||||
} else {
|
||||
accumulator.addSuppressed(exception);
|
||||
}
|
||||
}
|
||||
return cf;
|
||||
}
|
||||
}
|
||||
|
||||
record FutureResult<V>(V value, Throwable exception){}
|
||||
|
||||
static <V> CompletableFuture<List<FutureResult<V>>> gather(Collection<? extends CompletableFuture<? extends V>> futures) {
|
||||
var list = new ArrayList<FutureResult<V>>(futures.size());
|
||||
var results = new CompletableFuture[futures.size()];
|
||||
|
||||
for (var future : futures) {
|
||||
int i = list.size();
|
||||
list.add(null);
|
||||
results[i] = future.whenComplete((result, exception) -> list.set(i, new FutureResult<>(result, exception)));
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf(results).handle((r, th)->null).thenApply(res -> list);
|
||||
}
|
||||
|
||||
private static <T extends Event & IModBusEvent> void addCompletableFutureTaskForModDispatch(
|
||||
final IModStateTransition transition,
|
||||
final Executor executor,
|
||||
final List<CompletableFuture<Void>> completableFutures,
|
||||
final ProgressMeter progressBar,
|
||||
final EventGenerator<T> eventGenerator,
|
||||
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextState
|
||||
) {
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
var preDispatchHook = getHook(transition.preDispatchHook(), executor, eventGenerator);
|
||||
if (preDispatchHook != null)
|
||||
completableFutures.add(preDispatchHook);
|
||||
|
||||
var modFutures = new LinkedHashMap<String, CompletableFuture<Void>>();
|
||||
for (var mod : ModList.get().getLoadedMods()) {
|
||||
|
||||
CompletableFuture<Void> parent = null;
|
||||
if (mod.dependencies.isEmpty()) {
|
||||
parent = CompletableFuture.allOf();
|
||||
} else {
|
||||
var deps = new CompletableFuture[mod.dependencies.size()];
|
||||
int idx = 0;
|
||||
for (var depContainer : mod.dependencies) {
|
||||
var future = modFutures.get(depContainer.getModId());
|
||||
if (future == null)
|
||||
throw new IllegalStateException("Could not find dependency future " + depContainer.getModId() + " for " + mod.getModId());
|
||||
deps[idx++] = future;
|
||||
}
|
||||
parent = CompletableFuture.allOf(deps);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
var dispatch = parent
|
||||
.thenRunAsync(() -> {
|
||||
ModLoadingContext.get().setActiveContainer(mod);
|
||||
var handler = mod.activityMap.get(mod.modLoadingStage);
|
||||
if (handler != null)
|
||||
handler.run();
|
||||
mod.acceptEvent(eventGenerator.apply(mod));
|
||||
}, executor)
|
||||
.whenComplete((mc, exception) -> {
|
||||
mod.modLoadingStage = nextState.apply(mod.modLoadingStage, exception);
|
||||
progressBar.increment();
|
||||
ModLoadingContext.get().setActiveContainer(null);
|
||||
});
|
||||
|
||||
modFutures.put(mod.getModId(), dispatch);
|
||||
}
|
||||
|
||||
var dispatch = gather(modFutures.values()).thenComposeAsync(ModStateTransitionHelper::completableFutureFromExceptionList, executor);
|
||||
completableFutures.add(dispatch);
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
var postDispatchHook = getHook(transition.preDispatchHook(), executor, eventGenerator);
|
||||
if (postDispatchHook != null)
|
||||
completableFutures.add(postDispatchHook);
|
||||
}
|
||||
|
||||
private static <T extends Event & IModBusEvent> CompletableFuture<Void> getHook(BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> hook, Executor executor, EventGenerator<T> eventGenerator) {
|
||||
if (hook == null || hook == IModStateTransition.NULL_HOOK) return null;
|
||||
@SuppressWarnings("unchecked")
|
||||
var hookTyped = (BiFunction<Executor, EventGenerator<T>, CompletableFuture<Void>>)hook;
|
||||
return hookTyped.apply(executor, eventGenerator);
|
||||
}
|
||||
|
||||
static <T extends Event & IModBusEvent> CompletableFuture<Void> build(
|
||||
final IModStateTransition transition,
|
||||
final String name,
|
||||
final Executor syncExecutor,
|
||||
final Executor parallelExecutor,
|
||||
final ProgressMeter progressBar,
|
||||
final Function<Executor, CompletableFuture<Void>> preSyncTask,
|
||||
final Function<Executor, CompletableFuture<Void>> postSyncTask
|
||||
) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
final var executor = transition.threadSelector().apply(syncExecutor, parallelExecutor);
|
||||
|
||||
@SuppressWarnings({ "removal", "unchecked" })
|
||||
var events = transition.eventFunctionStream().get().map(f -> (EventGenerator<T>)f).toList();
|
||||
for (int x = 0; x < events.size(); x++) {
|
||||
var gen = events.get(x);
|
||||
BiFunction<ModLoadingStage, Throwable, ModLoadingStage> state = x == events.size() - 1
|
||||
? transition.nextModLoadingStage()
|
||||
: ModLoadingStage::currentState;
|
||||
addCompletableFutureTaskForModDispatch(transition, executor, futures, progressBar, gen, state);
|
||||
}
|
||||
|
||||
final CompletableFuture<Void> preSyncTaskCF = preSyncTask.apply(syncExecutor);
|
||||
final CompletableFuture<Void> eventDispatchCF = gather(futures).thenCompose(ModStateTransitionHelper::completableFutureFromExceptionList);
|
||||
final CompletableFuture<Void> postEventDispatchCF = preSyncTaskCF
|
||||
.thenApplyAsync(n -> {
|
||||
progressBar.label(progressBar.name() + ": dispatching " + name);
|
||||
return null;
|
||||
}, parallelExecutor)
|
||||
.thenComposeAsync(n -> eventDispatchCF, parallelExecutor)
|
||||
.thenApply(r -> {
|
||||
postSyncTask.apply(syncExecutor);
|
||||
return null;
|
||||
});
|
||||
return transition.finalActivityGenerator().apply(syncExecutor, postEventDispatchCF);
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -85,7 +85,6 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
private ScheduledFuture<?> initializationFuture;
|
||||
|
||||
private PerformanceInfo performanceInfo;
|
||||
@SuppressWarnings("unused")
|
||||
private ScheduledFuture<?> performanceTick;
|
||||
// The GL ID of the window. Used for all operations
|
||||
private long window;
|
||||
@@ -258,11 +257,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
for (var itr = this.elements.iterator(); itr.hasNext(); ) {
|
||||
var element = itr.next();
|
||||
if (!element.render(context, framecount))
|
||||
itr.remove();
|
||||
}
|
||||
this.elements.removeIf(element -> !element.render(context, framecount));
|
||||
if (animationTimerTrigger.compareAndSet(true, false)) // we only increment the framecount on a periodic basis
|
||||
framecount++;
|
||||
}
|
||||
@@ -493,6 +488,10 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
private void badWindowHandler(final int code, final long desc) {
|
||||
LOGGER.error("Got error from GLFW window init: "+code+ " "+MemoryUtil.memUTF8(desc));
|
||||
}
|
||||
|
||||
private void winResize(long window, int width, int height) {
|
||||
if (window == this.window && width != 0 && height != 0) {
|
||||
this.winWidth = width;
|
||||
@@ -641,6 +640,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
|
||||
|
||||
public void addMojangTexture(final int textureId) {
|
||||
this.elements.add(0, RenderElement.mojang(textureId, framecount));
|
||||
// this.elements.get(0).retire(framecount + 1);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
||||
@@ -84,6 +84,16 @@ public class RenderElement {
|
||||
|
||||
font.generateVerticesForTexts(10, context.scaledHeight() - texts.size() * font.lineSpacing() + font.descent() - 10, bb, texts.toArray(SimpleFont.DisplayText[]::new));
|
||||
}
|
||||
public static RenderElement monag() {
|
||||
return new RenderElement(RenderElement.initializeTexture("monagstudios.png", 45000, 4, (bb, ctx, sz, frame) -> {
|
||||
var size = 256;
|
||||
var x0 = (ctx.width() - 2 * size) / 2;
|
||||
var y0 = 64;
|
||||
QuadHelper.loadQuad(bb, x0, x0+size, y0, y0+size/2f, 0f, 1f, 0f, 0.5f, 0xFFFFFFFF);
|
||||
QuadHelper.loadQuad(bb, x0+size, x0+2*size, y0, y0+size/2f, 0f, 1f, 0.5f, 1f, 0xFFFFFFFF);
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
public static RenderElement mojang(final int textureId, final int frameStart) {
|
||||
return new RenderElement(()->(bb, ctx, frame) -> {
|
||||
|
||||
@@ -11,6 +11,8 @@ import org.lwjgl.stb.STBTTFontinfo;
|
||||
import org.lwjgl.stb.STBTTPackContext;
|
||||
import org.lwjgl.stb.STBTTPackRange;
|
||||
import org.lwjgl.stb.STBTTPackedchar;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
+1
-21
@@ -5,7 +5,6 @@ plugins {
|
||||
id 'maven-publish'
|
||||
id 'net.minecraftforge.licenser'
|
||||
id 'net.minecraftforge.gradleutils'
|
||||
alias(libs.plugins.apt)
|
||||
}
|
||||
|
||||
apply from: rootProject.file('build_shared.gradle')
|
||||
@@ -37,7 +36,6 @@ dependencies {
|
||||
implementation(libs.terminalconsoleappender)
|
||||
implementation(libs.jimfs)
|
||||
|
||||
// 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)
|
||||
annotationProcessor(libs.bundles.log4j)
|
||||
|
||||
@@ -87,7 +85,7 @@ publishing {
|
||||
license PomUtils.Licenses.LGPLv2_1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
maven gradleutils.publishingForgeMaven
|
||||
}
|
||||
@@ -104,23 +102,5 @@ tasks.register('writeForgeVersionJson') {
|
||||
}
|
||||
|
||||
tasks.named('generateResources').configure {
|
||||
dependsOn('eclipseJdt')
|
||||
dependsOn('eclipseJdtApt')
|
||||
dependsOn('eclipseFactorypath')
|
||||
dependsOn('writeForgeVersionJson')
|
||||
}
|
||||
|
||||
eclipse {
|
||||
classpath {
|
||||
// We need to set the default output directory for the log4j annotation processor
|
||||
// Ideally we'd just set the value, but the eclipse plugin deduplicates the output directories
|
||||
// So we have to do a hacky whenMerged
|
||||
//defaultOutputDir = file('bin/main')
|
||||
file.whenMerged {
|
||||
entries.each { entry ->
|
||||
if (entry.kind == 'output' && entry.hasProperty('path'))
|
||||
entry.path = 'bin/main'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,14 @@
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class BackgroundWaiter {
|
||||
private static final ExecutorService runner = Executors.newSingleThreadExecutor();
|
||||
|
||||
public static void runAndTick(Runnable r, Runnable tick) {
|
||||
var runner = Executors.newSingleThreadExecutor();
|
||||
ImmediateWindowHandler.updateProgress("Loading bootstrap resources");
|
||||
final Future<?> work = runner.submit(r);
|
||||
do {
|
||||
|
||||
@@ -54,6 +54,9 @@ public class FMLLoader {
|
||||
LOGGER.debug(CORE, "Detected version data : {}", versionInfo);
|
||||
LOGGER.debug(CORE, "FML {} loading", LauncherVersion.getVersion());
|
||||
|
||||
// Allows us to communicate properties with other services through ModLauncher
|
||||
setupBlackboardKeys();
|
||||
|
||||
checkPackage(ITransformationService.class, "4.0", "ModLauncher");
|
||||
accessTransformer = getPlugin(env, "accesstransformer", "1.0", "AccessTransformer");
|
||||
/*eventBus =*/ getPlugin(env, "eventbus", "1.0", "EventBus");
|
||||
@@ -118,6 +121,12 @@ public class FMLLoader {
|
||||
return providers.get(0);
|
||||
}
|
||||
|
||||
private static void setupBlackboardKeys() {
|
||||
LOGGER.debug(CORE, "Requesting CoreMods to not apply the fix for ASMAPI.findFirstInstructionBefore by default");
|
||||
var blackboardKey = TypesafeMap.Key.getOrCreate(Launcher.INSTANCE.blackboard(), "coremods.use_old_findFirstInstructionBefore", Boolean.class);
|
||||
Launcher.INSTANCE.blackboard().<Boolean>computeIfAbsent(blackboardKey, k -> true);
|
||||
}
|
||||
|
||||
static void setupLaunchHandler(final IEnvironment environment, final Map<String, Object> arguments) {
|
||||
final String launchTarget = environment.getProperty(IEnvironment.Keys.LAUNCHTARGET.get()).orElse("MISSING");
|
||||
arguments.put("launchTarget", launchTarget);
|
||||
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.fml.loading;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import cpw.mods.modlauncher.api.*;
|
||||
import joptsimple.OptionSpecBuilder;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.forgespi.Environment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -18,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
|
||||
|
||||
public class FMLServiceProvider implements ITransformationService {
|
||||
|
||||
@@ -5,25 +5,31 @@
|
||||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Master list of all mods <em>in the loading context. This class cannot refer outside the
|
||||
* loading package</em>
|
||||
*/
|
||||
public class LoadingModList {
|
||||
public class LoadingModList
|
||||
{
|
||||
private static LoadingModList INSTANCE;
|
||||
private final List<ModFileInfo> modFiles;
|
||||
private final List<ModInfo> sortedList;
|
||||
@@ -31,14 +37,15 @@ public class LoadingModList {
|
||||
private final List<EarlyLoadingException> preLoadErrors;
|
||||
private List<IModFile> brokenFiles;
|
||||
|
||||
private LoadingModList(final List<ModFile> modFiles, final List<ModInfo> sortedList) {
|
||||
private LoadingModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
|
||||
{
|
||||
this.modFiles = modFiles.stream()
|
||||
.map(ModFile::getModFileInfo)
|
||||
.map(ModFileInfo.class::cast)
|
||||
.toList();
|
||||
.collect(Collectors.toList());
|
||||
this.sortedList = sortedList.stream()
|
||||
.map(ModInfo.class::cast)
|
||||
.toList();
|
||||
.collect(Collectors.toList());
|
||||
this.fileById = this.modFiles.stream()
|
||||
.map(ModFileInfo::getMods)
|
||||
.flatMap(Collection::stream)
|
||||
@@ -47,18 +54,21 @@ public class LoadingModList {
|
||||
this.preLoadErrors = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static LoadingModList of(List<ModFile> modFiles, List<ModInfo> sortedList, final EarlyLoadingException earlyLoadingException) {
|
||||
public static LoadingModList of(List<ModFile> modFiles, List<ModInfo> sortedList, final EarlyLoadingException earlyLoadingException)
|
||||
{
|
||||
INSTANCE = new LoadingModList(modFiles, sortedList);
|
||||
if (earlyLoadingException != null)
|
||||
{
|
||||
INSTANCE.preLoadErrors.add(earlyLoadingException);
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static LoadingModList get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void addCoreMods() {
|
||||
public void addCoreMods()
|
||||
{
|
||||
modFiles.stream()
|
||||
.map(ModFileInfo::getFile)
|
||||
.map(ModFile::getCoreMods)
|
||||
@@ -66,7 +76,8 @@ public class LoadingModList {
|
||||
.forEach(FMLLoader.getCoreModProvider()::addCoreMod);
|
||||
}
|
||||
|
||||
public void addAccessTransformers() {
|
||||
public void addAccessTransformers()
|
||||
{
|
||||
for (ModFileInfo modFile : modFiles) {
|
||||
ModFile mod = modFile.getFile();
|
||||
var at = mod.getAccessTransformer().orElse(null);
|
||||
@@ -76,18 +87,21 @@ public class LoadingModList {
|
||||
}
|
||||
}
|
||||
|
||||
public void addForScanning(BackgroundScanHandler backgroundScanHandler) {
|
||||
public void addForScanning(BackgroundScanHandler backgroundScanHandler)
|
||||
{
|
||||
backgroundScanHandler.setLoadingModList(this);
|
||||
modFiles.stream()
|
||||
.map(ModFileInfo::getFile)
|
||||
.forEach(backgroundScanHandler::submitForScanning);
|
||||
}
|
||||
|
||||
public List<ModFileInfo> getModFiles() {
|
||||
public List<ModFileInfo> getModFiles()
|
||||
{
|
||||
return modFiles;
|
||||
}
|
||||
|
||||
public Path findResource(final String className) {
|
||||
public Path findResource(final String className)
|
||||
{
|
||||
for (ModFileInfo mf : modFiles) {
|
||||
final Path resource = mf.getFile().findResource(className);
|
||||
if (Files.exists(resource)) return resource;
|
||||
@@ -95,11 +109,55 @@ public class LoadingModList {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModFileInfo getModFileById(String modid) {
|
||||
public Enumeration<URL> findAllURLsForResource(final String resName) {
|
||||
final String resourceName;
|
||||
// strip a leading slash
|
||||
if (resName.startsWith("/")) {
|
||||
resourceName = resName.substring(1);
|
||||
} else {
|
||||
resourceName = resName;
|
||||
}
|
||||
return new Enumeration<URL>() {
|
||||
private final Iterator<ModFileInfo> modFileIterator = modFiles.iterator();
|
||||
private URL next;
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
if (next!=null) return true;
|
||||
next = findNextURL();
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL nextElement() {
|
||||
if (next == null) {
|
||||
next = findNextURL();
|
||||
if (next == null) throw new NoSuchElementException();
|
||||
}
|
||||
URL result = next;
|
||||
next = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
private URL findNextURL() {
|
||||
while (modFileIterator.hasNext()) {
|
||||
final ModFileInfo next = modFileIterator.next();
|
||||
final Path resource = next.getFile().findResource(resourceName);
|
||||
if (Files.exists(resource)) {
|
||||
return LamdbaExceptionUtils.uncheck(()->new URL("modjar://" + next.getMods().get(0).getModId() + "/" + resourceName));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ModFileInfo getModFileById(String modid)
|
||||
{
|
||||
return this.fileById.get(modid);
|
||||
}
|
||||
|
||||
public List<ModInfo> getMods() {
|
||||
public List<ModInfo> getMods()
|
||||
{
|
||||
return this.sortedList;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ package net.minecraftforge.fml.loading;
|
||||
import com.google.common.graph.GraphBuilder;
|
||||
import com.google.common.graph.MutableGraph;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.forgespi.language.IModInfo.ModVersion;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.fml.loading.EarlyLoadingException.ExceptionData;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
@@ -20,250 +20,235 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.*;
|
||||
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||
|
||||
public class ModSorter {
|
||||
public class ModSorter
|
||||
{
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final UniqueModListBuilder uniqueModListBuilder;
|
||||
private List<ModFile> modFiles;
|
||||
private List<ModInfo> sortedList;
|
||||
private Map<String, IModInfo> modIdNameLookup;
|
||||
private List<ModFile> systemMods;
|
||||
|
||||
private record State(List<ModFile> files, List<ModInfo> mods) {}
|
||||
|
||||
private ModSorter() {}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static LoadingModList sort(List<ModFile> mods, final List<ExceptionData> errors) {
|
||||
State systemMods = detectSystemMods(mods);
|
||||
List<ModFile> modFiles;
|
||||
private ModSorter(final List<ModFile> modFiles)
|
||||
{
|
||||
this.uniqueModListBuilder = new UniqueModListBuilder(modFiles);
|
||||
}
|
||||
|
||||
public static LoadingModList sort(List<ModFile> mods, final List<ExceptionData> errors)
|
||||
{
|
||||
final ModSorter ms = new ModSorter(mods);
|
||||
try {
|
||||
modFiles = new UniqueModListBuilder(mods).buildUniqueList().modFiles();
|
||||
ms.buildUniqueList();
|
||||
} catch (EarlyLoadingException e) {
|
||||
// We cannot build any list with duped mods. We have to abort immediately and report it
|
||||
// Note this will never actually throw an error because the duplicate checks are done in ModDiscovererer before we get to this phase
|
||||
// So all this is really doing is wasting time.
|
||||
// But i'm leaving it here until I rewrite all of cpw's mod loading code because its such a clusterfuck.
|
||||
return LoadingModList.of(systemMods.files(), systemMods.mods(), e);
|
||||
return LoadingModList.of(ms.systemMods, ms.systemMods.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).toList(), e);
|
||||
}
|
||||
|
||||
var named = new HashMap<String, ModInfo>();
|
||||
for (var file : modFiles) {
|
||||
for (var info : file.getModInfos())
|
||||
named.put(info.getModId(), (ModInfo)info);
|
||||
}
|
||||
|
||||
// try and validate dependencies
|
||||
final List<ExceptionData> failedList = Stream.concat(verifyDependencyVersions(modFiles).stream(), errors.stream()).toList();
|
||||
|
||||
final List<ExceptionData> failedList = Stream.concat(ms.verifyDependencyVersions().stream(), errors.stream()).toList();
|
||||
// if we miss one or the other, we abort now
|
||||
if (!failedList.isEmpty()) {
|
||||
return LoadingModList.of(systemMods.files(), systemMods.mods(), new EarlyLoadingException("failure to validate mod list", null, failedList));
|
||||
return LoadingModList.of(ms.systemMods, ms.systemMods.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).toList(), new EarlyLoadingException("failure to validate mod list", null, failedList));
|
||||
} else {
|
||||
// Otherwise, lets try and sort the modlist and proceed
|
||||
EarlyLoadingException earlyLoadingException = null;
|
||||
try {
|
||||
var sorted = sort(modFiles, named);
|
||||
return LoadingModList.of(sorted.files(), sorted.mods(), null);
|
||||
ms.sort();
|
||||
} catch (EarlyLoadingException e) {
|
||||
// The only exception that can happen here is a cyclic exception, but fall back to system mods so we can display the nice screen.
|
||||
return LoadingModList.of(systemMods.files(), systemMods.mods(), e);
|
||||
earlyLoadingException = e;
|
||||
}
|
||||
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
|
||||
}
|
||||
}
|
||||
|
||||
private static State sort(final List<ModFile> modFiles, final Map<String, ModInfo> named) {
|
||||
final MutableGraph<ModInfo> graph = GraphBuilder.directed().build();
|
||||
private void sort()
|
||||
{
|
||||
// lambdas are identity based, so sorting them is impossible unless you hold reference to them
|
||||
final MutableGraph<ModFileInfo> graph = GraphBuilder.directed().build();
|
||||
AtomicInteger counter = new AtomicInteger();
|
||||
Map<ModFileInfo, Integer> infos = modFiles.stream()
|
||||
.map(ModFile::getModFileInfo)
|
||||
.filter(ModFileInfo.class::isInstance)
|
||||
.map(ModFileInfo.class::cast)
|
||||
.collect(toMap(Function.identity(), e -> counter.incrementAndGet()));
|
||||
infos.keySet().forEach(graph::addNode);
|
||||
modFiles.stream()
|
||||
.map(ModFile::getModInfos)
|
||||
.flatMap(List::stream)
|
||||
.map(IModInfo::getDependencies)
|
||||
.<IModInfo.ModVersion>flatMap(List::stream)
|
||||
.forEach(dep -> addDependency(graph, dep));
|
||||
|
||||
int counter = 0;
|
||||
var infos = new HashMap<ModInfo, Integer>();
|
||||
for (var file : modFiles) {
|
||||
if (file.getModFileInfo() instanceof ModFileInfo info) {
|
||||
for (var imod : info.getMods()) {
|
||||
var mod = (ModInfo)imod;
|
||||
infos.put(mod, counter++);
|
||||
graph.addNode(mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var file : modFiles) {
|
||||
for (var info : file.getModInfos()) {
|
||||
for (var dep : info.getDependencies()) {
|
||||
// Ordering isn't effected by sides, should it be?
|
||||
//if (!dep.getSide().isCorrectSide())
|
||||
// continue;
|
||||
|
||||
var target = named.get(dep.getModId());
|
||||
|
||||
// soft dep that doesn't exist. No edge required.
|
||||
if (target == null)
|
||||
continue;
|
||||
|
||||
var self = (ModInfo)dep.getOwner();
|
||||
|
||||
switch (dep.getOrdering()) {
|
||||
case BEFORE -> graph.putEdge(self, target);
|
||||
case AFTER -> graph.putEdge(target, self);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<ModInfo> sorted;
|
||||
try {
|
||||
final List<ModFileInfo> sorted;
|
||||
try
|
||||
{
|
||||
sorted = TopologicalSort.topologicalSort(graph, Comparator.comparing(infos::get));
|
||||
} catch (CyclePresentException e) {
|
||||
Set<Set<ModInfo>> cycles = e.getCycles();
|
||||
var buf = new StringBuilder();
|
||||
buf.append("Mod Sorting failed - Detected Cycles: \n");
|
||||
|
||||
var dataList = new ArrayList<ExceptionData>();
|
||||
for (var cycle : cycles) {
|
||||
buf.append("\tCycle:\n");
|
||||
for (var mod : cycle) {
|
||||
var modDeps = new StringBuilder()
|
||||
.append(mod.getModId())
|
||||
.append(' ')
|
||||
.append(mod.getDependencies().stream()
|
||||
.filter(v -> cycle.stream().anyMatch(m -> m.getModId().equals(v.getModId())))
|
||||
.map(dep -> dep.getOrdering().name() + " " + dep.getModId())
|
||||
.collect(Collectors.joining(", "))
|
||||
);
|
||||
dataList.add(new ExceptionData("fml.modloading.cycle", modDeps.toString()));
|
||||
buf.append("\t\tMod: ").append(modDeps.toString()).append('\n');
|
||||
}
|
||||
}
|
||||
catch (CyclePresentException e)
|
||||
{
|
||||
Set<Set<ModFileInfo>> cycles = e.getCycles();
|
||||
if (LOGGER.isErrorEnabled(LOADING))
|
||||
{
|
||||
LOGGER.error(LOADING, "Mod Sorting failed.\nDetected Cycles: {}\n", cycles);
|
||||
}
|
||||
|
||||
LOGGER.error(LOADING, buf.toString());
|
||||
|
||||
var dataList = cycles.stream()
|
||||
.flatMap(Set::stream)
|
||||
.<IModInfo>mapMulti((mf,c)->mf.getMods().forEach(c))
|
||||
.map(IModInfo::getModId)
|
||||
.map(list -> new ExceptionData("fml.modloading.cycle", list))
|
||||
.toList();
|
||||
throw new EarlyLoadingException("Sorting error", e, dataList);
|
||||
}
|
||||
|
||||
var files = new LinkedHashSet<ModFile>();
|
||||
var list = new ArrayList<ModInfo>();
|
||||
|
||||
for (var mod : sorted) {
|
||||
files.add(mod.getOwningFile().getFile());
|
||||
list.add(mod);
|
||||
}
|
||||
|
||||
return new State(files.stream().toList(), list);
|
||||
this.sortedList = sorted.stream()
|
||||
.map(ModFileInfo::getMods)
|
||||
.flatMap(List::stream)
|
||||
.map(ModInfo.class::cast)
|
||||
.collect(toList());
|
||||
this.modFiles = sorted.stream()
|
||||
.map(ModFileInfo::getFile)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
private static State detectSystemMods(final List<ModFile> modFiles) {
|
||||
private void addDependency(MutableGraph<ModFileInfo> topoGraph, IModInfo.ModVersion dep)
|
||||
{
|
||||
final IModInfo targetModInfo = modIdNameLookup.get(dep.getModId());
|
||||
// soft dep that doesn't exist. Just return. No edge required.
|
||||
if (targetModInfo == null || !(targetModInfo.getOwningFile() instanceof final ModFileInfo target)) return;
|
||||
|
||||
final ModFileInfo self = (ModFileInfo)dep.getOwner().getOwningFile();
|
||||
if (self == target)
|
||||
return; // in case a jar has two mods that have dependencies between
|
||||
|
||||
switch (dep.getOrdering()) {
|
||||
case BEFORE -> topoGraph.putEdge(self, target);
|
||||
case AFTER -> topoGraph.putEdge(target, self);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildUniqueList()
|
||||
{
|
||||
final UniqueModListBuilder.UniqueModListData uniqueModListData = uniqueModListBuilder.buildUniqueList();
|
||||
|
||||
this.modFiles = uniqueModListData.modFiles();
|
||||
|
||||
detectSystemMods(uniqueModListData.modFilesByFirstId());
|
||||
|
||||
modIdNameLookup = uniqueModListData.modFilesByFirstId().entrySet().stream()
|
||||
.filter(e -> !e.getValue().get(0).getModInfos().isEmpty())
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
e -> e.getValue().get(0).getModInfos().get(0)
|
||||
));
|
||||
}
|
||||
|
||||
private void detectSystemMods(final Map<String, List<ModFile>> modFilesByFirstId) {
|
||||
// Capture system mods (ex. MC, Forge) here, so we can keep them for later
|
||||
var systemMods = List.of("minecraft", "forge");
|
||||
LOGGER.debug("Configured system mods: {}", systemMods);
|
||||
|
||||
var mods = new ArrayList<ModInfo>();
|
||||
var files = new ArrayList<ModFile>();
|
||||
this.systemMods = new ArrayList<>();
|
||||
for (var systemMod : systemMods) {
|
||||
var mod = findMod(modFiles, systemMod);
|
||||
if (mod == null)
|
||||
var container = modFilesByFirstId.get(systemMod);
|
||||
if (container != null && !container.isEmpty()) {
|
||||
LOGGER.debug("Found system mod: {}", systemMod);
|
||||
this.systemMods.add(container.getFirst());
|
||||
} else {
|
||||
throw new IllegalStateException("Failed to find system mod: " + systemMod);
|
||||
|
||||
LOGGER.debug("Found system mod: {}", systemMod);
|
||||
mods.add(mod.info());
|
||||
files.add(mod.file());
|
||||
}
|
||||
|
||||
return new State(files, mods);
|
||||
}
|
||||
|
||||
private record ModPair(ModFile file, ModInfo info) {}
|
||||
private static ModPair findMod(final List<ModFile> modFiles, String name) {
|
||||
for (var file : modFiles) {
|
||||
for (var mod : file.getModFileInfo().getMods()) {
|
||||
if (name.equals(mod.getModId()))
|
||||
return new ModPair(file, (ModInfo)mod);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<ExceptionData> verifyDependencyVersions(final List<ModFile> files) {
|
||||
final var modVersions = new HashMap<String, ArtifactVersion>();
|
||||
final var modRequirements = new HashSet<ModVersion>();
|
||||
int mandatoryRequired = 0;
|
||||
private List<EarlyLoadingException.ExceptionData> verifyDependencyVersions()
|
||||
{
|
||||
final var modVersions = modFiles.stream()
|
||||
.map(ModFile::getModInfos)
|
||||
.flatMap(List::stream)
|
||||
.collect(toMap(IModInfo::getModId, IModInfo::getVersion));
|
||||
|
||||
for (var file : files) {
|
||||
for (var info : file.getModInfos()) {
|
||||
modVersions.put(info.getModId(), info.getVersion());
|
||||
for (var dep : info.getDependencies()) {
|
||||
if (dep.getSide().isCorrectSide()) {
|
||||
if (modRequirements.add(dep) && dep.isMandatory())
|
||||
mandatoryRequired++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final var modVersionDependencies = modFiles.stream()
|
||||
.map(ModFile::getModInfos)
|
||||
.flatMap(List::stream)
|
||||
.collect(groupingBy(Function.identity(), flatMapping(e -> e.getDependencies().stream(), toList())));
|
||||
|
||||
final var modRequirements = modVersionDependencies.values().stream()
|
||||
.<IModInfo.ModVersion>flatMap(List::stream)
|
||||
.filter(mv -> mv.getSide().isCorrectSide())
|
||||
.collect(toSet());
|
||||
|
||||
final long mandatoryRequired = modRequirements.stream().filter(IModInfo.ModVersion::isMandatory).count();
|
||||
LOGGER.debug(LOADING, "Found {} mod requirements ({} mandatory, {} optional)", modRequirements.size(), mandatoryRequired, modRequirements.size() - mandatoryRequired);
|
||||
final var missingVersions = modRequirements.stream()
|
||||
.filter(mv -> (mv.isMandatory() || modVersions.containsKey(mv.getModId())) && !modVersionContained(mv, modVersions))
|
||||
.collect(toSet());
|
||||
final long mandatoryMissing = missingVersions.stream().filter(IModInfo.ModVersion::isMandatory).count();
|
||||
LOGGER.debug(LOADING, "Found {} mod requirements missing ({} mandatory, {} optional)", missingVersions.size(), mandatoryMissing, missingVersions.size() - mandatoryMissing);
|
||||
|
||||
final var missingMandatory = new HashSet<ModVersion>();
|
||||
final var missingOptional = new HashSet<ModVersion>();
|
||||
if (!missingVersions.isEmpty()) {
|
||||
if (mandatoryMissing > 0) {
|
||||
LOGGER.error(
|
||||
LOADING,
|
||||
"Missing or unsupported mandatory dependencies:\n{}",
|
||||
missingVersions.stream()
|
||||
.filter(IModInfo.ModVersion::isMandatory)
|
||||
.map(ver -> formatDependencyError(ver, modVersions))
|
||||
.collect(Collectors.joining("\n"))
|
||||
);
|
||||
}
|
||||
if (missingVersions.size() - mandatoryMissing > 0) {
|
||||
LOGGER.error(
|
||||
LOADING,
|
||||
"Unsupported installed optional dependencies:\n{}",
|
||||
missingVersions.stream()
|
||||
.filter(ver -> !ver.isMandatory())
|
||||
.map(ver -> formatDependencyError(ver, modVersions))
|
||||
.collect(Collectors.joining("\n"))
|
||||
);
|
||||
}
|
||||
|
||||
for (var dep : modRequirements) {
|
||||
var modId = dep.getModId();
|
||||
var existing = modVersions.get(modId);
|
||||
|
||||
if (!dep.isMandatory() && existing == null)
|
||||
continue;
|
||||
|
||||
var range = dep.getVersionRange();
|
||||
if (existing != null && (range.containsVersion(existing) || "0.0NONE".equals(existing.toString())))
|
||||
continue;
|
||||
|
||||
if (!VersionSupportMatrix.testVersionSupportMatrix(range, modId, "mod"))
|
||||
(dep.isMandatory() ? missingMandatory : missingOptional).add(dep);
|
||||
return missingVersions.stream()
|
||||
.map(mv -> new ExceptionData(mv.isMandatory() ? "fml.modloading.missingdependency" : "fml.modloading.missingdependency.optional",
|
||||
mv.getOwner(), mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
|
||||
modVersions.getOrDefault(mv.getModId(), new DefaultArtifactVersion("null"))))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
LOGGER.debug(LOADING, "Found {} mod requirements missing ({} mandatory, {} optional)", missingMandatory.size() + missingOptional.size(), missingMandatory.size(), missingOptional.size());
|
||||
|
||||
var ret = new ArrayList<ExceptionData>();
|
||||
|
||||
if (!missingMandatory.isEmpty()) {
|
||||
LOGGER.error(LOADING, "Missing or unsupported mandatory dependencies:\n{}", formatDependencyError(missingMandatory, modVersions));
|
||||
for (var mv : missingMandatory)
|
||||
ret.add(data(mv, modVersions, "fml.modloading.missingdependency"));
|
||||
}
|
||||
|
||||
if (!missingOptional.isEmpty()) {
|
||||
LOGGER.error(LOADING, "Unsupported installed optional dependencies:\n{}", formatDependencyError(missingMandatory, modVersions));
|
||||
for (var mv : missingMandatory)
|
||||
ret.add(data(mv, modVersions, "fml.modloading.missingdependency.optional"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static String formatDependencyError(Collection<ModVersion> missing, Map<String, ArtifactVersion> modVersions) {
|
||||
var ret = new ArrayList<String>();
|
||||
for (var dep : missing) {
|
||||
var installed = modVersions.get(dep.getModId());
|
||||
ret.add(String.format(
|
||||
private static String formatDependencyError(IModInfo.ModVersion dependency, Map<String, ArtifactVersion> modVersions)
|
||||
{
|
||||
ArtifactVersion installed = modVersions.get(dependency.getModId());
|
||||
return String.format(
|
||||
"\tMod ID: '%s', Requested by: '%s', Expected range: '%s', Actual version: '%s'",
|
||||
dep.getModId(),
|
||||
dep.getOwner().getModId(),
|
||||
dep.getVersionRange(),
|
||||
dependency.getModId(),
|
||||
dependency.getOwner().getModId(),
|
||||
dependency.getVersionRange(),
|
||||
installed != null ? installed.toString() : "[MISSING]"
|
||||
));
|
||||
}
|
||||
return String.join("\n", ret);
|
||||
);
|
||||
}
|
||||
|
||||
private static final ArtifactVersion NULL_VERSION = new DefaultArtifactVersion("null");
|
||||
private static ExceptionData data(ModVersion mv, Map<String, ArtifactVersion> modVersions, String key) {
|
||||
return new ExceptionData(key, mv.getOwner(), mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(), modVersions.getOrDefault(mv.getModId(), NULL_VERSION));
|
||||
private static boolean modVersionContained(IModInfo.ModVersion mv, Map<String, ArtifactVersion> modVersions) {
|
||||
var modId = mv.getModId();
|
||||
var range = mv.getVersionRange();
|
||||
if (modVersions.containsKey(modId)
|
||||
&& (range.containsVersion(modVersions.get(modId)) || modVersions.get(modId).toString().equals("0.0NONE")))
|
||||
return true;
|
||||
|
||||
return VersionSupportMatrix.testVersionSupportMatrix(mv.getVersionRange(), mv.getModId(), "mod");
|
||||
}
|
||||
}
|
||||
@@ -40,21 +40,6 @@ public class RuntimeDistCleaner implements ILaunchPluginService {
|
||||
return "runtimedistcleaner";
|
||||
}
|
||||
|
||||
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
|
||||
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
|
||||
|
||||
@Override
|
||||
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
|
||||
if (isEmpty)
|
||||
return NAY;
|
||||
|
||||
String internalName = classType.getInternalName();
|
||||
if (internalName.startsWith("net/minecraftforge/"))
|
||||
return NAY;
|
||||
|
||||
return YAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) {
|
||||
var changed = false;
|
||||
@@ -213,6 +198,21 @@ public class RuntimeDistCleaner implements ILaunchPluginService {
|
||||
};
|
||||
}
|
||||
|
||||
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
|
||||
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
|
||||
|
||||
@Override
|
||||
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
|
||||
if (isEmpty)
|
||||
return NAY;
|
||||
|
||||
String internalName = classType.getInternalName();
|
||||
if (internalName.startsWith("net/minecraftforge/"))
|
||||
return NAY;
|
||||
|
||||
return YAY;
|
||||
}
|
||||
|
||||
private static class LambdaGatherer extends MethodVisitor {
|
||||
private static final Handle META_FACTORY = new Handle(Opcodes.H_INVOKESTATIC,
|
||||
"java/lang/invoke/LambdaMetafactory", "metafactory",
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.mojang.logging.LogUtils;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -24,18 +23,16 @@ import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
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 {
|
||||
public class UniqueModListBuilder
|
||||
{
|
||||
private final static Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
private final List<ModFile> modFiles;
|
||||
|
||||
public UniqueModListBuilder(final List<ModFile> modFiles) {
|
||||
this.modFiles = modFiles;
|
||||
}
|
||||
public UniqueModListBuilder(final List<ModFile> modFiles) {this.modFiles = modFiles;}
|
||||
|
||||
public UniqueModListData buildUniqueList() {
|
||||
public UniqueModListData buildUniqueList()
|
||||
{
|
||||
List<ModFile> uniqueModList;
|
||||
List<ModFile> uniqueLibListWithVersion;
|
||||
|
||||
@@ -142,4 +139,5 @@ public class UniqueModListBuilder {
|
||||
}
|
||||
|
||||
public record UniqueModListData(List<ModFile> modFiles, Map<String, List<ModFile>> modFilesByFirstId) {}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,9 @@ import org.apache.logging.log4j.util.PerformanceSensitive;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A wrapper for {@link HighlightConverter} that auto-disables ANSI when the terminal doesn't support it.
|
||||
|
||||
+1
@@ -9,6 +9,7 @@ import cpw.mods.modlauncher.api.LamdbaExceptionUtils.Supplier_WithExceptions;
|
||||
import net.minecraftforge.fml.loading.StringUtils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -68,7 +68,6 @@ public class ModDiscoverer {
|
||||
}
|
||||
}
|
||||
|
||||
@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<>();
|
||||
|
||||
+1
@@ -17,6 +17,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
@@ -81,10 +81,6 @@ class ArgumentList {
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
public boolean has(String key) {
|
||||
return this.values.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean hasValue(String key) {
|
||||
return getOrDefault(key, null) != null;
|
||||
}
|
||||
|
||||
+4
-30
@@ -22,10 +22,6 @@ abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
super(type, prefix);
|
||||
}
|
||||
|
||||
protected CommonDevLaunchHandler(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override public String getNaming() { return "mcp"; }
|
||||
@Override public boolean isProduction() { return false; }
|
||||
|
||||
@@ -33,35 +29,13 @@ abstract class CommonDevLaunchHandler extends CommonLaunchHandler {
|
||||
protected String[] preLaunch(String[] arguments, ModuleLayer layer) {
|
||||
super.preLaunch(arguments, layer);
|
||||
|
||||
var args = ArgumentList.from(arguments);
|
||||
|
||||
if (this.module == null) {
|
||||
var entry = args.get("launchEntry");
|
||||
if (entry == null)
|
||||
throw new IllegalArgumentException("When using " + this.name() + " launch target you must specify a --launchEntry argument");
|
||||
|
||||
args.remove("launchEntry");
|
||||
|
||||
int idx = entry.indexOf('/');
|
||||
if (idx == -1) {
|
||||
this.module = "minecraft";
|
||||
this.main = entry;
|
||||
} else {
|
||||
this.module = entry.substring(0, idx);
|
||||
this.main = entry.substring(idx + 1);
|
||||
}
|
||||
|
||||
if (args.has("launchData")) {
|
||||
args.remove("launchData");
|
||||
this.isData = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getDist().isDedicatedServer())
|
||||
return args.getArguments();
|
||||
return arguments;
|
||||
|
||||
if (isData())
|
||||
return args.getArguments();
|
||||
return arguments;
|
||||
|
||||
var args = ArgumentList.from(arguments);
|
||||
|
||||
String username = args.get("username");
|
||||
if (username != null) { // Replace '#' placeholders with random numbers
|
||||
|
||||
+8
-19
@@ -29,27 +29,17 @@ import java.util.List;
|
||||
public abstract class CommonLaunchHandler implements ILaunchHandlerService {
|
||||
protected static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
private final String name;
|
||||
protected Dist dist = Dist.CLIENT;
|
||||
protected boolean isData = false;
|
||||
protected String module;
|
||||
protected String main;
|
||||
protected final LaunchType type;
|
||||
private final String prefix;
|
||||
|
||||
protected CommonLaunchHandler(LaunchType type, String prefix) {
|
||||
this(prefix + type.name());
|
||||
this.dist = type.dist();
|
||||
this.isData = type.data();
|
||||
this.module = type.module();
|
||||
this.main = type.main();
|
||||
this.type = type;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
protected CommonLaunchHandler(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override public String name() { return this.name; }
|
||||
public Dist getDist() { return this.dist; }
|
||||
public boolean isData() { return this.isData; }
|
||||
@Override public String name() { return this.prefix + this.type.name(); }
|
||||
public Dist getDist() { return this.type.dist(); }
|
||||
public boolean isData() { return this.type.data(); }
|
||||
public boolean isProduction() { return false; }
|
||||
public abstract String getNaming();
|
||||
|
||||
@@ -76,12 +66,11 @@ public abstract class CommonLaunchHandler implements ILaunchHandlerService {
|
||||
}
|
||||
|
||||
protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) {
|
||||
return () -> runTarget(this.module, this.main, arguments, gameLayer);
|
||||
return () -> runTarget(this.type.module(), this.type.main(), arguments, gameLayer);
|
||||
}
|
||||
|
||||
protected record LaunchType(String name, String module, String main, Dist dist, boolean data) {};
|
||||
protected static final LaunchType CLIENT = new LaunchType("client", "minecraft", "net.minecraft.client.main.Main", Dist.CLIENT, false);
|
||||
protected static final LaunchType CLIENT_DATA = new LaunchType("client_data", "minecraft", "net.minecraft.client.data.Main", Dist.CLIENT, true);
|
||||
protected static final LaunchType DATA = new LaunchType("data", "minecraft", "net.minecraft.data.Main", Dist.CLIENT, true);
|
||||
protected static final LaunchType SERVER = new LaunchType("server", "minecraft", "net.minecraft.server.Main", Dist.DEDICATED_SERVER, false);
|
||||
protected static final LaunchType SERVER_GAMETEST = new LaunchType("server_gametest", "net.minecraftforge.forge", "net.minecraftforge.gametest.GameTestMain", Dist.DEDICATED_SERVER, false);
|
||||
|
||||
+4
-18
@@ -14,14 +14,12 @@ sealed abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
super(type, "forge_dev_");
|
||||
}
|
||||
|
||||
private ForgeDevLaunchHandler(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Path> getMinecraftPaths() {
|
||||
// The client extra jar is on the classpath we can try locating it using the .mcassetsroot which vanilla uses for loading data
|
||||
var extra = getPathFromResource("assets/.mcassetsroot");
|
||||
|
||||
// The extra jar is on the classpath, so try and pull it out of the legacy classpath
|
||||
var legacyCP = findClassPath();
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra");
|
||||
// Minecraft is an exploded directory, so find it.
|
||||
var minecraft = getPathFromResource("net/minecraft/client/Minecraft.class");
|
||||
var forge = getPathFromResource("net/minecraftforge/common/MinecraftForge.class");
|
||||
@@ -41,12 +39,6 @@ sealed abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ClientData extends ForgeDevLaunchHandler {
|
||||
public ClientData() {
|
||||
super(CLIENT_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Data extends ForgeDevLaunchHandler {
|
||||
public Data() {
|
||||
super(DATA);
|
||||
@@ -64,10 +56,4 @@ sealed abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler {
|
||||
super(SERVER_GAMETEST);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Custom extends ForgeDevLaunchHandler {
|
||||
public Custom() {
|
||||
super("forge_dev");
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-17
@@ -8,18 +8,17 @@ package net.minecraftforge.fml.loading.targets;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
|
||||
@ApiStatus.Internal
|
||||
sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
|
||||
private ForgeUserdevLaunchHandler(LaunchType type) {
|
||||
super(type, "forge_userdev_");
|
||||
}
|
||||
|
||||
private ForgeUserdevLaunchHandler(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Path> getMinecraftPaths() {
|
||||
var legacyCP = findClassPath();
|
||||
@@ -27,7 +26,7 @@ sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
|
||||
|
||||
// Minecraft is extra jar {resources} + forge jar {patches}
|
||||
// The MC extra and forge jars are on the classpath, so try and pull them out
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra"); // This should be "client-" + vers.mcAndMCPVersion() + "-extra" but FG6 qwerks
|
||||
var extra = findJarOnClasspath(legacyCP, "client-extra");
|
||||
var forge = findJarOnClasspath(legacyCP, "forge-" + vers.mcAndForgeVersion());
|
||||
// We need to filter the forge jar to just MC code
|
||||
var minecraft = CommonDevLaunchHandler.getMinecraftOnly(extra, forge);
|
||||
@@ -40,12 +39,6 @@ sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ClientData extends ForgeUserdevLaunchHandler {
|
||||
public ClientData() {
|
||||
super(CLIENT_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Data extends ForgeUserdevLaunchHandler {
|
||||
public Data() {
|
||||
super(DATA);
|
||||
@@ -63,10 +56,4 @@ sealed abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler {
|
||||
super(SERVER_GAMETEST);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Custom extends ForgeUserdevLaunchHandler {
|
||||
public Custom() {
|
||||
super("forge_userdev");
|
||||
}
|
||||
}
|
||||
}
|
||||
-4
@@ -4,16 +4,12 @@ net.minecraftforge.fml.loading.targets.ForgeProdLaunchHandler$Server
|
||||
|
||||
# Mod Developers
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Client
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$ClientData
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Custom
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Data
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Server
|
||||
net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$ServerGameTest
|
||||
|
||||
#Working on Forge itself
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Client
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$ClientData
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Custom
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Data
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Server
|
||||
net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$ServerGameTest
|
||||
@@ -4,7 +4,7 @@
|
||||
SPDX-License-Identifier: LGPL-2.1-only
|
||||
-->
|
||||
|
||||
<Configuration status="warn" shutdownHook="disable">
|
||||
<Configuration status="warn" packages="net.minecrell.terminalconsole,net.minecrell.terminalconsole.util,com.mojang.util,cpw.mods.modlauncher.log,net.minecraftforge.fml.loading.log4j" shutdownHook="disable">
|
||||
<filters>
|
||||
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
|
||||
<MarkerFilter marker="NETWORK_PACKETS" onMatch="${sys:forge.logging.marker.networking:-DENY}" onMismatch="NEUTRAL"/>
|
||||
|
||||
+7
-7
@@ -1,17 +1,17 @@
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx6G
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
org.gradle.parallel=true
|
||||
|
||||
JAVA_VERSION=21
|
||||
MC_VERSION=1.21.5
|
||||
MC_VERSION=1.21.1
|
||||
MC_NEXT_VERSION=1.22
|
||||
MCP_VERSION=20250325.155543
|
||||
MCP_VERSION=20240808.132146
|
||||
MAPPING_CHANNEL=official
|
||||
MAPPING_VERSION=1.21.5
|
||||
MAPPING_VERSION=1.21.1
|
||||
|
||||
# Set to true before the first build of a new MC version, so we don't do compatibility checks
|
||||
// Set to true before the first build of a new MC version, so we don't do compatibility checks
|
||||
CHECK_COMPATIBILITY=false
|
||||
# Set to true to allow for fuzzy patching. Useful during updateing
|
||||
UPDATING=false
|
||||
// Set to true to allow for fuzzy patching. Useful during updateing
|
||||
UPDATING=false
|
||||
+2
-11
@@ -13,7 +13,6 @@ import net.minecraftforge.eventbus.api.IEventListener;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModLoadingException;
|
||||
import net.minecraftforge.fml.ModLoadingStage;
|
||||
import net.minecraftforge.fml.config.IConfigEvent;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
@@ -30,6 +29,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.jar.Attributes;
|
||||
|
||||
public class FMLModContainer extends ModContainer {
|
||||
@@ -47,6 +47,7 @@ public class FMLModContainer extends ModContainer {
|
||||
this.scanResults = modFileScanResults;
|
||||
activityMap.put(ModLoadingStage.CONSTRUCT, this::constructMod);
|
||||
this.eventBus = BusBuilder.builder().setExceptionHandler(FMLModContainer::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).useModLauncher().build();
|
||||
this.configHandler = Optional.of(ce->this.eventBus.post(ce.self()));
|
||||
this.contextExtension = () -> context;
|
||||
try {
|
||||
var moduleName = info.getOwningFile().moduleName();
|
||||
@@ -188,14 +189,4 @@ public class FMLModContainer extends ModContainer {
|
||||
throw new ModLoadingException(modInfo, modLoadingStage, "fml.modloading.errorduringevent", t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchConfigEvent(IConfigEvent event) {
|
||||
this.eventBus.post(event.self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FMLModContainer[" + this.getModInfo().getModId() + ", " + this.getClass().getName() + "]";
|
||||
}
|
||||
}
|
||||
+7
-3
@@ -8,6 +8,7 @@ import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -15,7 +16,8 @@ import java.util.stream.Collectors;
|
||||
// An example config class. This is not required, but it's a good idea to have one to keep your config organized.
|
||||
// Demonstrates how to use Forge's config APIs
|
||||
@Mod.EventBusSubscriber(modid = ExampleMod.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public class Config {
|
||||
public class Config
|
||||
{
|
||||
private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder();
|
||||
|
||||
private static final ForgeConfigSpec.BooleanValue LOG_DIRT_BLOCK = BUILDER
|
||||
@@ -42,12 +44,14 @@ public class Config {
|
||||
public static String magicNumberIntroduction;
|
||||
public static Set<Item> items;
|
||||
|
||||
private static boolean validateItemName(final Object obj) {
|
||||
private static boolean validateItemName(final Object obj)
|
||||
{
|
||||
return obj instanceof final String itemName && ForgeRegistries.ITEMS.containsKey(ResourceLocation.tryParse(itemName));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
static void onLoad(final ModConfigEvent event) {
|
||||
static void onLoad(final ModConfigEvent event)
|
||||
{
|
||||
logDirtBlock = LOG_DIRT_BLOCK.get();
|
||||
magicNumber = MAGIC_NUMBER.get();
|
||||
magicNumberIntroduction = MAGIC_NUMBER_INTRODUCTION.get();
|
||||
+18
-27
@@ -30,7 +30,8 @@ import org.slf4j.Logger;
|
||||
|
||||
// The value here should match an entry in the META-INF/mods.toml file
|
||||
@Mod(ExampleMod.MODID)
|
||||
public class ExampleMod {
|
||||
public class ExampleMod
|
||||
{
|
||||
// Define mod id in a common place for everything to reference
|
||||
public static final String MODID = "examplemod";
|
||||
// Directly reference a slf4j logger
|
||||
@@ -43,29 +44,13 @@ public class ExampleMod {
|
||||
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID);
|
||||
|
||||
// Creates a new Block with the id "examplemod:example_block", combining the namespace and path
|
||||
public static final RegistryObject<Block> EXAMPLE_BLOCK = BLOCKS.register("example_block",
|
||||
() -> new Block(BlockBehaviour.Properties.of()
|
||||
.setId(BLOCKS.key("example_block"))
|
||||
.mapColor(MapColor.STONE)
|
||||
)
|
||||
);
|
||||
public static final RegistryObject<Block> EXAMPLE_BLOCK = BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.STONE)));
|
||||
// Creates a new BlockItem with the id "examplemod:example_block", combining the namespace and path
|
||||
public static final RegistryObject<Item> EXAMPLE_BLOCK_ITEM = ITEMS.register("example_block",
|
||||
() -> new BlockItem(EXAMPLE_BLOCK.get(), new Item.Properties().setId(ITEMS.key("example_block")))
|
||||
);
|
||||
public static final RegistryObject<Item> EXAMPLE_BLOCK_ITEM = ITEMS.register("example_block", () -> new BlockItem(EXAMPLE_BLOCK.get(), new Item.Properties()));
|
||||
|
||||
// Creates a new food item with the id "examplemod:example_id", nutrition 1 and saturation 2
|
||||
public static final RegistryObject<Item> EXAMPLE_ITEM = ITEMS.register("example_item",
|
||||
() -> new Item(new Item.Properties()
|
||||
.setId(ITEMS.key("example_item"))
|
||||
.food(new FoodProperties.Builder()
|
||||
.alwaysEdible()
|
||||
.nutrition(1)
|
||||
.saturationModifier(2f)
|
||||
.build()
|
||||
)
|
||||
)
|
||||
);
|
||||
public static final RegistryObject<Item> EXAMPLE_ITEM = ITEMS.register("example_item", () -> new Item(new Item.Properties().food(new FoodProperties.Builder()
|
||||
.alwaysEdible().nutrition(1).saturationModifier(2f).build())));
|
||||
|
||||
// Creates a creative tab with the id "examplemod:example_tab" for the example item, that is placed after the combat tab
|
||||
public static final RegistryObject<CreativeModeTab> EXAMPLE_TAB = CREATIVE_MODE_TABS.register("example_tab", () -> CreativeModeTab.builder()
|
||||
@@ -75,7 +60,8 @@ public class ExampleMod {
|
||||
output.accept(EXAMPLE_ITEM.get()); // Add the example item to the tab. For your own tabs, this method is preferred over the event
|
||||
}).build());
|
||||
|
||||
public ExampleMod(FMLJavaModLoadingContext context) {
|
||||
public ExampleMod(FMLJavaModLoadingContext context)
|
||||
{
|
||||
IEventBus modEventBus = context.getModEventBus();
|
||||
|
||||
// Register the commonSetup method for modloading
|
||||
@@ -98,7 +84,8 @@ public class ExampleMod {
|
||||
context.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
|
||||
}
|
||||
|
||||
private void commonSetup(final FMLCommonSetupEvent event) {
|
||||
private void commonSetup(final FMLCommonSetupEvent event)
|
||||
{
|
||||
// Some common setup code
|
||||
LOGGER.info("HELLO FROM COMMON SETUP");
|
||||
|
||||
@@ -111,23 +98,27 @@ public class ExampleMod {
|
||||
}
|
||||
|
||||
// Add the example block item to the building blocks tab
|
||||
private void addCreative(BuildCreativeModeTabContentsEvent event) {
|
||||
private void addCreative(BuildCreativeModeTabContentsEvent event)
|
||||
{
|
||||
if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS)
|
||||
event.accept(EXAMPLE_BLOCK_ITEM);
|
||||
}
|
||||
|
||||
// You can use SubscribeEvent and let the Event Bus discover methods to call
|
||||
@SubscribeEvent
|
||||
public void onServerStarting(ServerStartingEvent event) {
|
||||
public void onServerStarting(ServerStartingEvent event)
|
||||
{
|
||||
// Do something when the server starts
|
||||
LOGGER.info("HELLO from server starting");
|
||||
}
|
||||
|
||||
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
|
||||
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
||||
public static class ClientModEvents {
|
||||
public static class ClientModEvents
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void onClientSetup(FMLClientSetupEvent event) {
|
||||
public static void onClientSetup(FMLClientSetupEvent event)
|
||||
{
|
||||
// Some client setup code
|
||||
LOGGER.info("HELLO FROM CLIENT SETUP");
|
||||
LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName());
|
||||
@@ -1,12 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlCommandEncoder.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlCommandEncoder.java
|
||||
@@ -109,6 +_,9 @@
|
||||
GlStateManager._colorMask(true, true, true, true);
|
||||
GlStateManager._clear(16384);
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, 0, 0);
|
||||
+ // Forge: if using stencil, clear it as well (3553 = GlConst.GL_TEXTURE_2D)
|
||||
+ if (p_394273_.isStencilEnabled())
|
||||
+ GlStateManager._glFramebufferTexture2D(GlConst.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, GlConst.GL_TEXTURE_2D, 0, 0);
|
||||
GlStateManager._glBindFramebuffer(36160, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlDebug.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlDebug.java
|
||||
@@ -23,6 +_,14 @@
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class GlDebug {
|
||||
+ /**
|
||||
+ * TODO: [Forge][Rendering][VEN] Expose this in the configs
|
||||
+ * <p>
|
||||
+ * Will enable synchronous OpenGL debug logging, which means the message will be sent from the call that
|
||||
+ * would have caused the error. Additionally, enables printing a stacktrace when and where this occurs.
|
||||
+ */
|
||||
+ private static final boolean PRINT_STACKTRACE_ON_ERROR = Boolean.getBoolean("forge.printGLStackOnError");
|
||||
+
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int CIRCULAR_LOG_SIZE = 10;
|
||||
private final Queue<GlDebug.LogEntry> MESSAGE_BUFFER = EvictingQueue.create(10);
|
||||
@@ -105,6 +_,8 @@
|
||||
}
|
||||
|
||||
LOGGER.info("OpenGL debug message: {}", gldebug$logentry);
|
||||
+ // TODO: [VEN] Trim the stack trace
|
||||
+ if (PRINT_STACKTRACE_ON_ERROR) LOGGER.info("Trace: ", new Throwable("GlDebug"));
|
||||
}
|
||||
|
||||
public List<String> getLastOpenGlDebugMessages() {
|
||||
@@ -121,6 +_,7 @@
|
||||
|
||||
@Nullable
|
||||
public static GlDebug enableDebugCallback(int p_394351_, boolean p_393026_, Set<String> p_393339_) {
|
||||
+ p_393026_ |= PRINT_STACKTRACE_ON_ERROR;
|
||||
if (p_394351_ <= 0) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -1,53 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlDevice.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlDevice.java
|
||||
@@ -80,11 +_,25 @@
|
||||
|
||||
@Override
|
||||
public GpuTexture createTexture(@Nullable Supplier<String> p_397830_, TextureFormat p_394839_, int p_394481_, int p_391831_, int p_395609_) {
|
||||
- return this.createTexture(this.debugLabels.exists() && p_397830_ != null ? p_397830_.get() : null, p_394839_, p_394481_, p_391831_, p_395609_);
|
||||
+ return this.createTexture(p_397830_, p_394839_, p_394481_, p_391831_, p_395609_, false);
|
||||
+ }
|
||||
+
|
||||
+ /** @see GpuDevice#createTexture(Supplier, TextureFormat, int, int, int, boolean) */
|
||||
+ @Override
|
||||
+ public GpuTexture createTexture(@Nullable Supplier<String> p_397830_, TextureFormat p_394839_, int p_394481_, int p_391831_, int p_395609_, boolean stencil) {
|
||||
+ return this.createTexture(this.debugLabels.exists() && p_397830_ != null ? p_397830_.get() : null, p_394839_, p_394481_, p_391831_, p_395609_, stencil);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GpuTexture createTexture(@Nullable String p_394142_, TextureFormat p_394951_, int p_395535_, int p_393944_, int p_392329_) {
|
||||
+ return this.createTexture(p_394142_, p_394951_, p_395535_, p_393944_, p_392329_, false);
|
||||
+ }
|
||||
+
|
||||
+ /** @see GpuDevice#createTexture(String, TextureFormat, int, int, int, boolean) */
|
||||
+ @Override
|
||||
+ public GpuTexture createTexture(@Nullable String p_394142_, TextureFormat p_394951_, int p_395535_, int p_393944_, int p_392329_, boolean stencil) {
|
||||
+ // Forge: stencil rendering is only for depth
|
||||
+ stencil &= p_394951_.hasDepthAspect();
|
||||
if (p_392329_ < 1) {
|
||||
throw new IllegalArgumentException("mipLevels must be at least 1");
|
||||
} else {
|
||||
@@ -106,11 +_,14 @@
|
||||
GlStateManager._texImage2D(
|
||||
3553,
|
||||
j,
|
||||
+ stencil ? org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8 :
|
||||
GlConst.toGlInternalId(p_394951_),
|
||||
p_395535_ >> j,
|
||||
p_393944_ >> j,
|
||||
0,
|
||||
+ stencil ? org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL :
|
||||
GlConst.toGlExternalId(p_394951_),
|
||||
+ stencil ? org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV :
|
||||
GlConst.toGlType(p_394951_),
|
||||
null
|
||||
);
|
||||
@@ -122,7 +_,7 @@
|
||||
} else if (k != 0) {
|
||||
throw new IllegalStateException("OpenGL error " + k);
|
||||
} else {
|
||||
- GlTexture gltexture = new GlTexture(p_394142_, p_394951_, p_395535_, p_393944_, p_392329_, i);
|
||||
+ GlTexture gltexture = new GlTexture(p_394142_, p_394951_, p_395535_, p_393944_, p_392329_, i, stencil);
|
||||
this.debugLabels.applyLabel(gltexture);
|
||||
return gltexture;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlStateManager.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlStateManager.java
|
||||
@@ -90,6 +_,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ public static boolean _isBlendEnabled() {
|
||||
+ RenderSystem.assertOnRenderThread();
|
||||
+ return BLEND.mode.enabled;
|
||||
+ }
|
||||
+
|
||||
public static void _disableBlend() {
|
||||
RenderSystem.assertOnRenderThread();
|
||||
BLEND.mode.disable();
|
||||
@@ -411,9 +_,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Stores the last values sent into glMultiTexCoord2f */
|
||||
+ public static float lastBrightnessX = 0.0f;
|
||||
+ public static float lastBrightnessY = 0.0f;
|
||||
+
|
||||
public static void _texParameter(int p_393876_, int p_397998_, int p_396741_) {
|
||||
RenderSystem.assertOnRenderThread();
|
||||
GL11.glTexParameteri(p_393876_, p_397998_, p_396741_);
|
||||
+ if (p_393876_ == GL13.GL_TEXTURE1) {
|
||||
+ lastBrightnessX = p_397998_;
|
||||
+ lastBrightnessY = p_396741_;
|
||||
+ }
|
||||
}
|
||||
|
||||
public static int _getTexLevelParameter(int p_393352_, int p_397204_, int p_396319_) {
|
||||
@@ -1,32 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlTexture.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlTexture.java
|
||||
@@ -18,8 +_,13 @@
|
||||
protected boolean modesDirty = true;
|
||||
|
||||
protected GlTexture(String p_393950_, TextureFormat p_392837_, int p_394590_, int p_391379_, int p_391947_, int p_396659_) {
|
||||
+ this(p_393950_, p_392837_, p_394590_, p_391379_, p_391947_, p_396659_, false);
|
||||
+ }
|
||||
+
|
||||
+ protected GlTexture(String p_393950_, TextureFormat p_392837_, int p_394590_, int p_391379_, int p_391947_, int p_396659_, boolean stencil) {
|
||||
super(p_393950_, p_392837_, p_394590_, p_391379_, p_391947_);
|
||||
this.id = p_396659_;
|
||||
+ this.stencilEnabled = stencil;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,5 +_,15 @@
|
||||
public void setTextureFilter(FilterMode p_394977_, FilterMode p_397175_, boolean p_393558_) {
|
||||
super.setTextureFilter(p_394977_, p_397175_, p_393558_);
|
||||
this.modesDirty = true;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* FORGE START */
|
||||
+
|
||||
+ private final boolean stencilEnabled;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isStencilEnabled() {
|
||||
+ return this.stencilEnabled;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,35 @@
|
||||
--- a/com/mojang/blaze3d/pipeline/RenderTarget.java
|
||||
+++ b/com/mojang/blaze3d/pipeline/RenderTarget.java
|
||||
@@ -75,7 +_,7 @@
|
||||
this.width = p_83951_;
|
||||
this.height = p_83952_;
|
||||
if (this.useDepth) {
|
||||
- this.depthTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", TextureFormat.DEPTH32, p_83951_, p_83952_, 1);
|
||||
+ this.depthTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", TextureFormat.DEPTH32, p_83951_, p_83952_, 1, this.stencilEnabled);
|
||||
this.depthTexture.setTextureFilter(FilterMode.NEAREST, false);
|
||||
this.depthTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE);
|
||||
@@ -104,7 +_,10 @@
|
||||
GlStateManager._texParameter(3553, 34892, 0);
|
||||
GlStateManager._texParameter(3553, 10242, 33071);
|
||||
GlStateManager._texParameter(3553, 10243, 33071);
|
||||
+ if (!stencilEnabled)
|
||||
GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, null);
|
||||
+ else
|
||||
+ GlStateManager._texImage2D(3553, 0, org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8, this.width, this.height, 0, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL, org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV, null);
|
||||
}
|
||||
@@ -134,5 +_,26 @@
|
||||
@Nullable
|
||||
public GpuTexture getDepthTexture() {
|
||||
return this.depthTexture;
|
||||
|
||||
this.setFilterMode(9728, true);
|
||||
@@ -114,8 +_,13 @@
|
||||
GlStateManager._texImage2D(3553, 0, 32856, this.width, this.height, 0, 6408, 5121, null);
|
||||
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.colorTextureId, 0);
|
||||
- if (this.useDepth) {
|
||||
+ if (this.useDepth && !stencilEnabled) {
|
||||
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0);
|
||||
+ } else if(this.useDepth && net.minecraftforge.common.ForgeConfig.CLIENT.useCombinedDepthStencilAttachment.get()) {
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
|
||||
+ } else if (this.useDepth) {
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_ATTACHMENT, 3553, this.depthBufferId, 0);
|
||||
+ GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
|
||||
}
|
||||
|
||||
this.checkStatus();
|
||||
@@ -257,5 +_,26 @@
|
||||
|
||||
public int getDepthTextureId() {
|
||||
return this.depthBufferId;
|
||||
+ }
|
||||
+
|
||||
+ private boolean stencilEnabled = false;
|
||||
@@ -25,7 +42,7 @@
|
||||
+ public void enableStencil() {
|
||||
+ if (stencilEnabled) return;
|
||||
+ stencilEnabled = true;
|
||||
+ this.resize(viewWidth, viewHeight);
|
||||
+ this.resize(viewWidth, viewHeight, net.minecraft.client.Minecraft.ON_OSX);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/com/mojang/blaze3d/platform/GlStateManager.java
|
||||
+++ b/com/mojang/blaze3d/platform/GlStateManager.java
|
||||
@@ -493,9 +_,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Stores the last values sent into glMultiTexCoord2f */
|
||||
+ public static float lastBrightnessX = 0.0f;
|
||||
+ public static float lastBrightnessY = 0.0f;
|
||||
+
|
||||
public static void _texParameter(int p_84161_, int p_84162_, float p_84163_) {
|
||||
RenderSystem.assertOnRenderThreadOrInit();
|
||||
GL11.glTexParameterf(p_84161_, p_84162_, p_84163_);
|
||||
+ if (p_84161_ == GL13.GL_TEXTURE1) {
|
||||
+ lastBrightnessX = p_84162_;
|
||||
+ lastBrightnessY = p_84163_;
|
||||
+ }
|
||||
}
|
||||
|
||||
public static void _texParameter(int p_84332_, int p_84333_, int p_84334_) {
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/platform/Window.java
|
||||
+++ b/com/mojang/blaze3d/platform/Window.java
|
||||
@@ -88,7 +_,8 @@
|
||||
@@ -84,7 +_,8 @@
|
||||
GLFW.glfwWindowHint(139267, 2);
|
||||
GLFW.glfwWindowHint(139272, 204801);
|
||||
GLFW.glfwWindowHint(139270, 1);
|
||||
@@ -10,15 +10,15 @@
|
||||
if (monitor != null) {
|
||||
VideoMode videomode = monitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
|
||||
this.windowedX = this.x = monitor.getX() + videomode.getWidth() / 2 - this.width / 2;
|
||||
@@ -100,6 +_,7 @@
|
||||
@@ -96,6 +_,7 @@
|
||||
this.windowedX = this.x = aint1[0];
|
||||
this.windowedY = this.y = aint[0];
|
||||
}
|
||||
+ }
|
||||
|
||||
this.setMode();
|
||||
this.refreshFramebufferSize();
|
||||
@@ -266,6 +_,9 @@
|
||||
GLFW.glfwMakeContextCurrent(this.window);
|
||||
GL.createCapabilities();
|
||||
@@ -254,6 +_,9 @@
|
||||
GLFW.glfwGetFramebufferSize(this.window, aint, aint1);
|
||||
this.framebufferWidth = aint[0] > 0 ? aint[0] : 1;
|
||||
this.framebufferHeight = aint1[0] > 0 ? aint1[0] : 1;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/systems/GpuDevice.java
|
||||
+++ b/com/mojang/blaze3d/systems/GpuDevice.java
|
||||
@@ -25,7 +_,17 @@
|
||||
|
||||
GpuTexture createTexture(@Nullable Supplier<String> p_394357_, TextureFormat p_395807_, int p_395623_, int p_395802_, int p_396157_);
|
||||
|
||||
+ /** Forge: same as {@link #createTexture(Supplier, TextureFormat, int, int, int)} but with stencil support */
|
||||
+ default GpuTexture createTexture(@Nullable Supplier<String> p_394357_, TextureFormat p_395807_, int p_395623_, int p_395802_, int p_396157_, boolean stencil) {
|
||||
+ return this.createTexture(p_394357_, p_395807_, p_395623_, p_395802_, p_396157_);
|
||||
+ }
|
||||
+
|
||||
GpuTexture createTexture(@Nullable String p_391798_, TextureFormat p_393333_, int p_391800_, int p_395600_, int p_394065_);
|
||||
+
|
||||
+ /** Forge: same as {@link #createTexture(String, TextureFormat, int, int, int)} but with stencil support */
|
||||
+ default GpuTexture createTexture(@Nullable String p_391798_, TextureFormat p_393333_, int p_391800_, int p_395600_, int p_394065_, boolean stencil) {
|
||||
+ return this.createTexture(p_391798_, p_393333_, p_391800_, p_395600_, p_394065_);
|
||||
+ }
|
||||
|
||||
GpuBuffer createBuffer(@Nullable Supplier<String> p_395215_, BufferType p_392847_, BufferUsage p_391478_, int p_397054_);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/com/mojang/blaze3d/textures/GpuTexture.java
|
||||
+++ b/com/mojang/blaze3d/textures/GpuTexture.java
|
||||
@@ -6,7 +_,7 @@
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@DontObfuscate
|
||||
-public abstract class GpuTexture implements AutoCloseable {
|
||||
+public abstract class GpuTexture implements AutoCloseable, net.minecraftforge.client.extensions.IForgeGpuTexture {
|
||||
private final TextureFormat format;
|
||||
private final int width;
|
||||
private final int height;
|
||||
@@ -1,11 +1,11 @@
|
||||
--- a/com/mojang/blaze3d/vertex/PoseStack.java
|
||||
+++ b/com/mojang/blaze3d/vertex/PoseStack.java
|
||||
@@ -15,7 +_,7 @@
|
||||
import org.joml.Vector3fc;
|
||||
@@ -13,7 +_,7 @@
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class PoseStack {
|
||||
+public class PoseStack implements net.minecraftforge.client.extensions.IForgePoseStack {
|
||||
private final List<PoseStack.Pose> poses = new ArrayList<>(16);
|
||||
private int lastIndex;
|
||||
|
||||
private final Deque<PoseStack.Pose> poseStack = Util.make(Queues.newArrayDeque(), p_85848_ -> {
|
||||
Matrix4f matrix4f = new Matrix4f();
|
||||
Matrix3f matrix3f = new Matrix3f();
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/com/mojang/blaze3d/vertex/SheetedDecalTextureGenerator.java
|
||||
+++ b/com/mojang/blaze3d/vertex/SheetedDecalTextureGenerator.java
|
||||
@@ -62,7 +_,7 @@
|
||||
public VertexConsumer setNormal(float p_344306_, float p_342091_, float p_344579_) {
|
||||
this.delegate.setNormal(p_344306_, p_342091_, p_344579_);
|
||||
Vector3f vector3f = this.normalInversePose.transform(p_344306_, p_342091_, p_344579_, this.normal);
|
||||
- Direction direction = Direction.getNearest(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
+ Direction direction = net.minecraftforge.client.ForgeHooksClient.getNearestStable(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
Vector3f vector3f1 = this.cameraInversePose.transformPosition(this.x, this.y, this.z, this.worldPos);
|
||||
vector3f1.rotateY((float) Math.PI);
|
||||
vector3f1.rotateX((float) (-Math.PI / 2));
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/vertex/VertexConsumer.java
|
||||
+++ b/com/mojang/blaze3d/vertex/VertexConsumer.java
|
||||
@@ -13,7 +_,7 @@
|
||||
@@ -12,7 +_,7 @@
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -9,15 +9,16 @@
|
||||
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_);
|
||||
@@ -133,9 +_,11 @@
|
||||
@@ -135,10 +_,11 @@
|
||||
}
|
||||
|
||||
int j1 = ARGB.color(k, (int)f3, (int)f4, (int)f5);
|
||||
int k1 = LightTexture.lightCoordsWithEmission(p_331444_[i1], l);
|
||||
+ k1 = applyBakedLighting(k1, bytebuffer);
|
||||
int i1 = FastColor.ARGB32.color(k, (int)f3, (int)f4, (int)f5);
|
||||
- int j1 = p_331444_[l];
|
||||
+ int j1 = applyBakedLighting(p_331444_[l], 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());
|
||||
this.addVertex(vector3f1.x(), vector3f1.y(), vector3f1.z(), i1, f10, f9, p_85993_, j1, vector3f.x(), vector3f.y(), vector3f.z());
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
--- a/com/mojang/blaze3d/vertex/VertexFormat.java
|
||||
+++ b/com/mojang/blaze3d/vertex/VertexFormat.java
|
||||
@@ -20,7 +_,7 @@
|
||||
@@ -13,7 +_,7 @@
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@DontObfuscate
|
||||
-public class VertexFormat {
|
||||
+public class VertexFormat implements net.minecraftforge.client.extensions.IForgeVertexFormat {
|
||||
public static final int UNKNOWN_ELEMENT = -1;
|
||||
private final List<VertexFormatElement> elements;
|
||||
private final List<String> names;
|
||||
@@ -31,6 +_,7 @@
|
||||
private GpuBuffer immediateDrawVertexBuffer;
|
||||
@@ -22,6 +_,7 @@
|
||||
private final int[] offsetsByElement = new int[32];
|
||||
@Nullable
|
||||
private GpuBuffer immediateDrawIndexBuffer;
|
||||
private VertexBuffer immediateDrawVertexBuffer;
|
||||
+ 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 @@
|
||||
@@ -34,6 +_,11 @@
|
||||
int j = vertexformatelement != null ? p_343616_.indexOf(vertexformatelement) : -1;
|
||||
this.offsetsByElement[i] = j != -1 ? p_345522_.getInt(j) : -1;
|
||||
}
|
||||
@@ -29,13 +29,13 @@
|
||||
}
|
||||
|
||||
public static VertexFormat.Builder builder() {
|
||||
@@ -146,6 +_,9 @@
|
||||
@@ -158,6 +_,9 @@
|
||||
|
||||
return this.immediateDrawIndexBuffer;
|
||||
return vertexbuffer;
|
||||
}
|
||||
+
|
||||
+ public ImmutableMap<String, VertexFormatElement> getElementMapping() { return elementMapping; }
|
||||
+ public int getOffset(int index) { return offsetsByElement[index]; }
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@DontObfuscate
|
||||
public static class Builder {
|
||||
@@ -1,15 +1,15 @@
|
||||
--- a/com/mojang/math/Transformation.java
|
||||
+++ b/com/mojang/math/Transformation.java
|
||||
@@ -14,7 +_,7 @@
|
||||
@@ -13,7 +_,7 @@
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
-public final class Transformation {
|
||||
+public final class Transformation implements net.minecraftforge.common.extensions.IForgeTransformation {
|
||||
private final Matrix4fc matrix;
|
||||
private final Matrix4f matrix;
|
||||
public static final Codec<Transformation> CODEC = RecordCodecBuilder.create(
|
||||
p_269604_ -> p_269604_.group(
|
||||
@@ -174,5 +_,19 @@
|
||||
@@ -169,5 +_,19 @@
|
||||
vector3f1.lerp(p_175938_.getScale(), p_175939_);
|
||||
quaternionf1.slerp(p_175938_.getRightRotation(), p_175939_);
|
||||
return new Transformation(vector3f, quaternionf, vector3f1, quaternionf1);
|
||||
|
||||
@@ -34,4 +34,4 @@
|
||||
+ this.stackTrace = t.getStackTrace();
|
||||
}
|
||||
|
||||
public static void populateBlockDetails(CrashReportCategory p_178951_, LevelHeightAccessor p_178952_, BlockPos p_178953_, BlockState p_178954_) {
|
||||
public static void populateBlockDetails(CrashReportCategory p_178951_, LevelHeightAccessor p_178952_, BlockPos p_178953_, @Nullable BlockState p_178954_) {
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/Util.java
|
||||
+++ b/net/minecraft/Util.java
|
||||
@@ -268,7 +_,7 @@
|
||||
@@ -267,7 +_,7 @@
|
||||
.getSchema(DataFixUtils.makeKey(SharedConstants.getCurrentVersion().getDataVersion().getVersion()))
|
||||
.getChoiceType(p_137552_, p_137553_);
|
||||
} catch (IllegalArgumentException illegalargumentexception) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/advancements/Advancement.java
|
||||
+++ b/net/minecraft/advancements/Advancement.java
|
||||
@@ -226,7 +_,11 @@
|
||||
@@ -214,7 +_,11 @@
|
||||
}
|
||||
|
||||
public AdvancementHolder save(Consumer<AdvancementHolder> p_138390_, String p_138391_) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Camera.java
|
||||
+++ b/net/minecraft/client/Camera.java
|
||||
@@ -118,9 +_,13 @@
|
||||
@@ -105,9 +_,13 @@
|
||||
}
|
||||
|
||||
protected void setRotation(float p_90573_, float p_90574_) {
|
||||
@@ -15,7 +15,7 @@
|
||||
FORWARDS.rotate(this.rotation, this.forwards);
|
||||
UP.rotate(this.rotation, this.up);
|
||||
LEFT.rotate(this.rotation, this.left);
|
||||
@@ -236,6 +_,13 @@
|
||||
@@ -223,6 +_,13 @@
|
||||
|
||||
public float getPartialTickTime() {
|
||||
return this.partialTickTime;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/client/ClientRecipeBook.java
|
||||
+++ b/net/minecraft/client/ClientRecipeBook.java
|
||||
@@ -65,7 +_,7 @@
|
||||
Recipe<?> recipe = recipeholder.value();
|
||||
if (!recipe.isSpecial() && !recipe.isIncomplete()) {
|
||||
RecipeBookCategories recipebookcategories = getCategory(recipeholder);
|
||||
- String s = recipe.getGroup();
|
||||
+ String s = recipe.getGroup().isEmpty() ? recipeholder.id().toString() : recipe.getGroup(); // FORGE: Group value defaults to the recipe's ID if the recipe's explicit group is empty.
|
||||
if (s.isEmpty()) {
|
||||
map.computeIfAbsent(recipebookcategories, p_90645_ -> Lists.newArrayList()).add(ImmutableList.of(recipeholder));
|
||||
} else {
|
||||
@@ -125,6 +_,8 @@
|
||||
} else if (recipetype == RecipeType.SMITHING) {
|
||||
return RecipeBookCategories.SMITHING;
|
||||
} else {
|
||||
+ var categories = net.minecraftforge.client.RecipeBookManager.findCategories((RecipeType)recipetype, p_299041_);
|
||||
+ if (categories != null) return categories;
|
||||
LOGGER.warn(
|
||||
"Unknown recipe category: {}/{}",
|
||||
LogUtils.defer(() -> BuiltInRegistries.RECIPE_TYPE.getKey(recipe.getType())),
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/KeyMapping.java
|
||||
+++ b/net/minecraft/client/KeyMapping.java
|
||||
@@ -15,9 +_,9 @@
|
||||
@@ -14,9 +_,9 @@
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -12,7 +12,7 @@
|
||||
private static final Set<String> CATEGORIES = Sets.newHashSet();
|
||||
public static final String CATEGORY_MOVEMENT = "key.categories.movement";
|
||||
public static final String CATEGORY_MISC = "key.categories.misc";
|
||||
@@ -43,14 +_,14 @@
|
||||
@@ -42,14 +_,14 @@
|
||||
private int clickCount;
|
||||
|
||||
public static void click(InputConstants.Key p_90836_) {
|
||||
@@ -29,7 +29,7 @@
|
||||
if (keymapping != null) {
|
||||
keymapping.setDown(p_90839_);
|
||||
}
|
||||
@@ -101,7 +_,7 @@
|
||||
@@ -100,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean isDown() {
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
@@ -137,7 +_,16 @@
|
||||
@@ -136,7 +_,16 @@
|
||||
public int compareTo(KeyMapping p_90841_) {
|
||||
return this.category.equals(p_90841_.category)
|
||||
? I18n.get(this.name).compareTo(I18n.get(p_90841_.name))
|
||||
@@ -56,7 +56,7 @@
|
||||
}
|
||||
|
||||
public static Supplier<Component> createNameSupplier(String p_90843_) {
|
||||
@@ -146,6 +_,20 @@
|
||||
@@ -145,6 +_,20 @@
|
||||
}
|
||||
|
||||
public boolean same(KeyMapping p_90851_) {
|
||||
@@ -77,7 +77,7 @@
|
||||
return this.key.equals(p_90851_.key);
|
||||
}
|
||||
|
||||
@@ -164,11 +_,13 @@
|
||||
@@ -163,11 +_,13 @@
|
||||
}
|
||||
|
||||
public Component getTranslatedKeyMessage() {
|
||||
@@ -92,10 +92,10 @@
|
||||
}
|
||||
|
||||
public String saveString() {
|
||||
@@ -182,5 +_,88 @@
|
||||
@Nullable
|
||||
public static KeyMapping get(String p_378660_) {
|
||||
return ALL.get(p_378660_);
|
||||
@@ -176,5 +_,88 @@
|
||||
|
||||
public void setDown(boolean p_90846_) {
|
||||
this.isDown = p_90846_;
|
||||
+ }
|
||||
+
|
||||
+ private net.minecraftforge.client.settings.KeyModifier keyModifierDefault = net.minecraftforge.client.settings.KeyModifier.NONE;
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
--- a/net/minecraft/client/KeyboardHandler.java
|
||||
+++ b/net/minecraft/client/KeyboardHandler.java
|
||||
@@ -431,12 +_,12 @@
|
||||
if (screen != null) {
|
||||
try {
|
||||
if (p_90897_ != 1 && p_90897_ != 2) {
|
||||
- if (p_90897_ == 0 && screen.keyReleased(p_90895_, p_90896_, p_90898_)) {
|
||||
+ if (p_90897_ == 0 && net.minecraftforge.client.ForgeHooksClient.onScreenKeyReleased(screen, p_90895_, p_90896_, p_90898_)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -405,9 +_,9 @@
|
||||
Screen.wrapScreenError(() -> {
|
||||
if (p_90897_ == 1 || p_90897_ == 2) {
|
||||
screen.afterKeyboardAction();
|
||||
- if (screen.keyPressed(p_90895_, p_90896_, p_90898_)) {
|
||||
+ if (net.minecraftforge.client.ForgeHooksClient.onScreenKeyPressed(screen, p_90895_, p_90896_, p_90898_)) {
|
||||
return;
|
||||
}
|
||||
- aboolean[0] = screen.keyPressed(p_90895_, p_90896_, p_90898_);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenKeyPressed(aboolean, screen, p_90895_, p_90896_, p_90898_);
|
||||
} else if (p_90897_ == 0) {
|
||||
- aboolean[0] = screen.keyReleased(p_90895_, p_90896_, p_90898_);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenKeyReleased(aboolean, screen, p_90895_, p_90896_, p_90898_);
|
||||
}
|
||||
@@ -495,6 +_,7 @@
|
||||
}, "keyPressed event handler", screen.getClass().getCanonicalName());
|
||||
if (aboolean[0]) {
|
||||
@@ -476,20 +_,21 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,17 +20,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,10 +_,10 @@
|
||||
if (screen != null && this.minecraft.getOverlay() == null) {
|
||||
try {
|
||||
if (Character.isBmpCodePoint(p_90891_)) {
|
||||
- screen.charTyped((char)p_90891_, p_90892_);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenCharTyped(screen, (char)p_90891_, p_90892_);
|
||||
} else if (Character.isValidCodePoint(p_90891_)) {
|
||||
- screen.charTyped(Character.highSurrogate(p_90891_), p_90892_);
|
||||
- screen.charTyped(Character.lowSurrogate(p_90891_), p_90892_);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenCharTyped(screen, Character.highSurrogate(p_90891_), p_90892_);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenCharTyped(screen, Character.lowSurrogate(p_90891_), p_90892_);
|
||||
private void charTyped(long p_90890_, int p_90891_, int p_90892_) {
|
||||
if (p_90890_ == this.minecraft.getWindow().getWindow()) {
|
||||
- GuiEventListener guieventlistener = this.minecraft.screen;
|
||||
+ Screen guieventlistener = this.minecraft.screen;
|
||||
if (guieventlistener != null && this.minecraft.getOverlay() == null) {
|
||||
if (Character.charCount(p_90891_) == 1) {
|
||||
Screen.wrapScreenError(
|
||||
- () -> guieventlistener.charTyped((char)p_90891_, p_90892_), "charTyped event handler", guieventlistener.getClass().getCanonicalName()
|
||||
+ () -> net.minecraftforge.client.ForgeHooksClient.onScreenCharTyped(guieventlistener, (char)p_90891_, p_90892_), "charTyped event handler", guieventlistener.getClass().getCanonicalName()
|
||||
);
|
||||
} else {
|
||||
for (char c0 : Character.toChars(p_90891_)) {
|
||||
- Screen.wrapScreenError(() -> guieventlistener.charTyped(c0, p_90892_), "charTyped event handler", guieventlistener.getClass().getCanonicalName());
|
||||
+ Screen.wrapScreenError(() -> net.minecraftforge.client.ForgeHooksClient.onScreenCharTyped(guieventlistener, c0, p_90892_), "charTyped event handler", guieventlistener.getClass().getCanonicalName());
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "charTyped event handler");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/Minecraft.java
|
||||
+++ b/net/minecraft/client/Minecraft.java
|
||||
@@ -248,7 +_,7 @@
|
||||
@@ -254,7 +_,7 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -9,7 +9,7 @@
|
||||
static Minecraft instance;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final boolean ON_OSX = Util.getPlatform() == Util.OS.OSX;
|
||||
@@ -426,7 +_,6 @@
|
||||
@@ -431,7 +_,6 @@
|
||||
}
|
||||
}, Util.nonCriticalIoPool());
|
||||
LOGGER.info("Setting user: {}", this.user.getName());
|
||||
@@ -17,35 +17,39 @@
|
||||
this.demo = p_91084_.game.demo;
|
||||
this.allowsMultiplayer = !p_91084_.game.disableMultiplayer;
|
||||
this.allowsChat = !p_91084_.game.disableChat;
|
||||
@@ -478,10 +_,9 @@
|
||||
LOGGER.error("Couldn't set icon", (Throwable)ioexception);
|
||||
@@ -468,15 +_,15 @@
|
||||
}
|
||||
|
||||
this.window.setFramerateLimit(this.options.framerateLimit().get());
|
||||
+ // FORGE: Move mouse and keyboard handler setup further below
|
||||
this.mouseHandler = new MouseHandler(this);
|
||||
- this.mouseHandler.setup(this.window.getWindow());
|
||||
this.keyboardHandler = new KeyboardHandler(this);
|
||||
- this.keyboardHandler.setup(this.window.getWindow());
|
||||
RenderSystem.initRenderer(
|
||||
this.window.getWindow(),
|
||||
this.options.glDebugVerbosity,
|
||||
@@ -492,6 +_,7 @@
|
||||
LOGGER.info("Using optional rendering extensions: {}", String.join(", ", RenderSystem.getDevice().getEnabledExtensions()));
|
||||
RenderSystem.initRenderer(this.options.glDebugVerbosity, false);
|
||||
this.mainRenderTarget = new MainTarget(this.window.getWidth(), this.window.getHeight());
|
||||
this.mainRenderTarget.setClearColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
this.mainRenderTarget.clear(ON_OSX);
|
||||
this.resourceManager = new ReloadableResourceManager(PackType.CLIENT_RESOURCES);
|
||||
+ net.minecraftforge.client.loading.ClientModLoader.begin(this, this.resourcePackRepository, this.resourceManager);
|
||||
this.resourcePackRepository.reload();
|
||||
this.options.loadSelectedResourcePacks(this.resourcePackRepository);
|
||||
this.languageManager = new LanguageManager(this.options.languageCode, p_340763_ -> {
|
||||
@@ -570,6 +_,7 @@
|
||||
this.blockEntityRenderDispatcher = new BlockEntityRenderDispatcher(this.font, this.modelManager.entityModels(), this.blockRenderer, this.itemModelResolver, this.itemRenderer, this.entityRenderDispatcher);
|
||||
this.resourceManager.registerReloadListener(this.blockEntityRenderDispatcher);
|
||||
@@ -540,6 +_,7 @@
|
||||
this.entityRenderDispatcher = new EntityRenderDispatcher(this, this.textureManager, this.itemRenderer, this.blockRenderer, this.font, this.options, this.entityModels);
|
||||
this.resourceManager.registerReloadListener(this.entityRenderDispatcher);
|
||||
this.particleEngine = new ParticleEngine(this.level, this.textureManager);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onRegisterParticleProviders(this.particleEngine);
|
||||
this.resourceManager.registerReloadListener(this.particleEngine);
|
||||
this.paintingTextures = new PaintingTextureManager(this.textureManager);
|
||||
this.resourceManager.registerReloadListener(this.paintingTextures);
|
||||
@@ -585,6 +_,9 @@
|
||||
@@ -552,11 +_,15 @@
|
||||
this.gameRenderer = new GameRenderer(this, this.entityRenderDispatcher.getItemInHandRenderer(), this.resourceManager, this.renderBuffers);
|
||||
this.resourceManager.registerReloadListener(this.gameRenderer.createReloadListener());
|
||||
this.levelRenderer = new LevelRenderer(this, this.entityRenderDispatcher, this.blockEntityRenderDispatcher, this.renderBuffers);
|
||||
+ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.RenderLevelStageEvent.RegisterStageEvent());
|
||||
this.resourceManager.registerReloadListener(this.levelRenderer);
|
||||
this.gpuWarnlistManager = new GpuWarnlistManager();
|
||||
this.resourceManager.registerReloadListener(this.gpuWarnlistManager);
|
||||
this.resourceManager.registerReloadListener(this.regionalCompliancies);
|
||||
this.gui = new Gui(this);
|
||||
@@ -53,17 +57,17 @@
|
||||
+ this.mouseHandler.setup(this.window.getWindow());
|
||||
+ this.keyboardHandler.setup(this.window.getWindow());
|
||||
this.debugRenderer = new DebugRenderer(this);
|
||||
RealmsClient realmsclient = RealmsClient.getOrCreate(this);
|
||||
RealmsClient realmsclient = RealmsClient.create(this);
|
||||
this.realmsDataFetcher = new RealmsDataFetcher(realmsclient);
|
||||
@@ -618,6 +_,7 @@
|
||||
}
|
||||
@@ -580,6 +_,7 @@
|
||||
this.options.fullscreen().set(this.window.isFullscreen());
|
||||
}
|
||||
|
||||
+ net.minecraftforge.client.ForgeHooksClient.initClientHooks(this, this.resourceManager);
|
||||
this.window.updateVsync(this.options.enableVsync().get());
|
||||
this.window.updateRawMouseInput(this.options.rawMouseInput().get());
|
||||
this.window.setDefaultErrorCallback();
|
||||
@@ -639,16 +_,17 @@
|
||||
@@ -600,16 +_,17 @@
|
||||
GameLoadTimesEvent.INSTANCE.beginStep(TelemetryProperty.LOAD_TIME_LOADING_OVERLAY_MS);
|
||||
Minecraft.GameLoadCookie minecraft$gameloadcookie = new Minecraft.GameLoadCookie(realmsclient, p_91084_.quickPlay);
|
||||
this.setOverlay(
|
||||
@@ -71,20 +75,20 @@
|
||||
- this, reloadinstance, p_296164_ -> Util.ifElse(p_296164_, 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), () -> {
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
this.selfTest();
|
||||
}
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
this.selfTest();
|
||||
}
|
||||
|
||||
this.reloadStateTracker.finishReload();
|
||||
this.onResourceLoadFinished(minecraft$gameloadcookie);
|
||||
+ net.minecraftforge.client.loading.ClientModLoader.completeModLoading();
|
||||
}), false
|
||||
this.reloadStateTracker.finishReload();
|
||||
this.onResourceLoadFinished(minecraft$gameloadcookie);
|
||||
+ net.minecraftforge.client.loading.ClientModLoader.completeModLoading();
|
||||
}), false
|
||||
- )
|
||||
+ ).get()
|
||||
);
|
||||
this.quickPlayLog = QuickPlayLog.of(p_91084_.quickPlay.path());
|
||||
this.framerateLimitTracker = new FramerateLimitTracker(this.options, this);
|
||||
@@ -746,6 +_,7 @@
|
||||
}
|
||||
@@ -698,6 +_,7 @@
|
||||
StringBuilder stringbuilder = new StringBuilder("Minecraft");
|
||||
if (checkModStatus().shouldReportAsModified()) {
|
||||
stringbuilder.append("*");
|
||||
@@ -92,7 +96,7 @@
|
||||
}
|
||||
|
||||
stringbuilder.append(" ");
|
||||
@@ -769,6 +_,8 @@
|
||||
@@ -721,6 +_,8 @@
|
||||
}
|
||||
|
||||
private UserApiService createUserApiService(YggdrasilAuthenticationService p_193586_, GameConfig p_193587_) {
|
||||
@@ -101,7 +105,7 @@
|
||||
return p_193587_.user.user.getType() != User.Type.MSA
|
||||
? UserApiService.OFFLINE
|
||||
: p_193586_.createUserApiService(p_193587_.user.user.getAccessToken());
|
||||
@@ -779,7 +_,7 @@
|
||||
@@ -731,7 +_,7 @@
|
||||
}
|
||||
|
||||
private void rollbackResourcePacks(Throwable p_91240_, @Nullable Minecraft.GameLoadCookie p_299515_) {
|
||||
@@ -110,7 +114,7 @@
|
||||
this.clearResourcePacksOnError(p_91240_, null, p_299515_);
|
||||
} else {
|
||||
Util.throwAsRuntime(p_91240_);
|
||||
@@ -1065,12 +_,6 @@
|
||||
@@ -991,12 +_,6 @@
|
||||
LOGGER.error("setScreen called from non-game thread");
|
||||
}
|
||||
|
||||
@@ -123,7 +127,7 @@
|
||||
if (p_91153_ == null && this.clientLevelTeardownInProgress) {
|
||||
throw new IllegalStateException("Trying to return to in-game GUI during disconnection");
|
||||
} else {
|
||||
@@ -1084,6 +_,23 @@
|
||||
@@ -1010,6 +_,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,40 +151,40 @@
|
||||
this.screen = p_91153_;
|
||||
if (this.screen != null) {
|
||||
this.screen.added();
|
||||
@@ -1168,6 +_,7 @@
|
||||
@@ -1088,6 +_,7 @@
|
||||
this.resourceManager.close();
|
||||
FreeTypeUtil.destroy();
|
||||
Util.shutdownExecutors();
|
||||
RenderSystem.getDevice().close();
|
||||
+ net.minecraftforge.fml.config.ConfigTracker.INSTANCE.forceUnload();
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Shutdown failure!", throwable);
|
||||
throw throwable;
|
||||
@@ -1237,9 +_,11 @@
|
||||
@@ -1155,9 +_,11 @@
|
||||
this.mouseHandler.handleAccumulatedMovement();
|
||||
profilerfiller.pop();
|
||||
this.profiler.pop();
|
||||
if (!this.noRender) {
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickStart(this.deltaTracker);
|
||||
profilerfiller.popPush("gameRenderer");
|
||||
this.gameRenderer.render(this.deltaTracker, p_91384_);
|
||||
profilerfiller.pop();
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickEnd(this.deltaTracker);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickStart(this.timer);
|
||||
this.profiler.popPush("gameRenderer");
|
||||
this.gameRenderer.render(this.timer, p_91384_);
|
||||
this.profiler.pop();
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTickEnd(this.timer);
|
||||
}
|
||||
|
||||
profilerfiller.push("blit");
|
||||
@@ -1363,10 +_,12 @@
|
||||
this.window.setGuiScale(i);
|
||||
if (this.fpsPieResults != null) {
|
||||
@@ -1283,10 +_,12 @@
|
||||
this.window.setGuiScale((double)i);
|
||||
if (this.screen != null) {
|
||||
this.screen.resize(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
+ net.minecraftforge.client.ForgeHooksClient.resizeGuiLayers(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
|
||||
}
|
||||
|
||||
RenderTarget rendertarget = this.getMainRenderTarget();
|
||||
rendertarget.resize(this.window.getWidth(), this.window.getHeight());
|
||||
rendertarget.resize(this.window.getWidth(), this.window.getHeight(), ON_OSX);
|
||||
+ if (this.gameRenderer != null)
|
||||
this.gameRenderer.resize(this.window.getWidth(), this.window.getHeight());
|
||||
this.mouseHandler.setIgnoreFirstMove();
|
||||
}
|
||||
@@ -1504,6 +_,7 @@
|
||||
@@ -1554,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -188,7 +192,7 @@
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@@ -1532,10 +_,18 @@
|
||||
@@ -1582,10 +_,18 @@
|
||||
if (p_91387_ && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
@@ -210,7 +214,7 @@
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
}
|
||||
@@ -1563,6 +_,8 @@
|
||||
@@ -1613,6 +_,8 @@
|
||||
return false;
|
||||
} else {
|
||||
boolean flag = false;
|
||||
@@ -219,7 +223,7 @@
|
||||
switch (this.hitResult.getType()) {
|
||||
case ENTITY:
|
||||
this.gameMode.attack(this.player, ((EntityHitResult)this.hitResult).getEntity());
|
||||
@@ -1570,7 +_,7 @@
|
||||
@@ -1620,7 +_,7 @@
|
||||
case BLOCK:
|
||||
BlockHitResult blockhitresult = (BlockHitResult)this.hitResult;
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
@@ -228,7 +232,7 @@
|
||||
this.gameMode.startDestroyBlock(blockpos, blockhitresult.getDirection());
|
||||
if (this.level.getBlockState(blockpos).isAir()) {
|
||||
flag = true;
|
||||
@@ -1583,8 +_,10 @@
|
||||
@@ -1633,8 +_,10 @@
|
||||
}
|
||||
|
||||
this.player.resetAttackStrengthTicker();
|
||||
@@ -239,7 +243,7 @@
|
||||
this.player.swing(InteractionHand.MAIN_HAND);
|
||||
return flag;
|
||||
}
|
||||
@@ -1600,6 +_,12 @@
|
||||
@@ -1650,6 +_,12 @@
|
||||
}
|
||||
|
||||
for (InteractionHand interactionhand : InteractionHand.values()) {
|
||||
@@ -252,68 +256,68 @@
|
||||
ItemStack itemstack = this.player.getItemInHand(interactionhand);
|
||||
if (!itemstack.isItemEnabled(this.level.enabledFeatures())) {
|
||||
return;
|
||||
@@ -1620,7 +_,7 @@
|
||||
@@ -1670,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()) {
|
||||
if (interactionresult.consumesAction()) {
|
||||
- if (interactionresult.shouldSwing()) {
|
||||
+ if (interactionresult.shouldSwing() && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(interactionhand);
|
||||
}
|
||||
|
||||
@@ -1632,7 +_,7 @@
|
||||
@@ -1682,7 +_,7 @@
|
||||
int i = itemstack.getCount();
|
||||
InteractionResult interactionresult1 = this.gameMode.useItemOn(this.player, interactionhand, blockhitresult);
|
||||
if (interactionresult1 instanceof InteractionResult.Success interactionresult$success) {
|
||||
- if (interactionresult$success.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
+ if (interactionresult$success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
|
||||
if (interactionresult1.consumesAction()) {
|
||||
- if (interactionresult1.shouldSwing()) {
|
||||
+ if (interactionresult1.shouldSwing() && inputEvent.shouldSwingHand()) {
|
||||
this.player.swing(interactionhand);
|
||||
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.player.hasInfiniteMaterials())) {
|
||||
if (!itemstack.isEmpty() && (itemstack.getCount() != i || this.gameMode.hasInfiniteItems())) {
|
||||
this.gameRenderer.itemInHandRenderer.itemUsed(interactionhand);
|
||||
@@ -1648,6 +_,9 @@
|
||||
@@ -1698,6 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (itemstack.isEmpty() && (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS))
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onRightClickEmpty(this.player, interactionhand);
|
||||
+
|
||||
if (!itemstack.isEmpty()
|
||||
&& this.gameMode.useItem(this.player, interactionhand) instanceof InteractionResult.Success interactionresult$success1) {
|
||||
if (interactionresult$success1.swingSource() == InteractionResult.SwingSource.CLIENT) {
|
||||
@@ -1677,6 +_,8 @@
|
||||
if (!itemstack.isEmpty()) {
|
||||
InteractionResult interactionresult2 = this.gameMode.useItem(this.player, interactionhand);
|
||||
if (interactionresult2.consumesAction()) {
|
||||
@@ -1728,6 +_,8 @@
|
||||
this.rightClickDelay--;
|
||||
}
|
||||
|
||||
ProfilerFiller profilerfiller = Profiler.get();
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPreClientTick();
|
||||
+
|
||||
profilerfiller.push("gui");
|
||||
this.profiler.push("gui");
|
||||
this.chatListener.tick();
|
||||
this.gui.tick(this.pause);
|
||||
@@ -1766,6 +_,7 @@
|
||||
@@ -1811,6 +_,7 @@
|
||||
|
||||
this.tutorial.tick();
|
||||
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPreLevelTick(this.level, () -> true);
|
||||
try {
|
||||
this.level.tick(() -> true);
|
||||
} catch (Throwable throwable1) {
|
||||
@@ -1779,6 +_,7 @@
|
||||
} catch (Throwable throwable) {
|
||||
@@ -1824,6 +_,7 @@
|
||||
|
||||
throw new ReportedException(crashreport1);
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPostLevelTick(this.level, () -> true);
|
||||
}
|
||||
|
||||
profilerfiller.popPush("animateTick");
|
||||
@@ -1803,6 +_,7 @@
|
||||
profilerfiller.popPush("keyboard");
|
||||
this.profiler.popPush("animateTick");
|
||||
@@ -1843,6 +_,7 @@
|
||||
this.profiler.popPush("keyboard");
|
||||
this.keyboardHandler.tick();
|
||||
profilerfiller.pop();
|
||||
this.profiler.pop();
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPostClientTick();
|
||||
}
|
||||
|
||||
private boolean isLevelRunningNormally() {
|
||||
@@ -2003,6 +_,7 @@
|
||||
@@ -2043,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void setLevel(ClientLevel p_91157_, ReceivingLevelScreen.Reason p_335893_) {
|
||||
@@ -321,7 +325,7 @@
|
||||
this.updateScreenAndTick(new ReceivingLevelScreen(() -> false, p_335893_));
|
||||
this.level = p_91157_;
|
||||
this.updateLevelInEngines(p_91157_);
|
||||
@@ -2040,6 +_,7 @@
|
||||
@@ -2080,6 +_,7 @@
|
||||
IntegratedServer integratedserver = this.singleplayerServer;
|
||||
this.singleplayerServer = null;
|
||||
this.gameRenderer.resetData();
|
||||
@@ -329,15 +333,15 @@
|
||||
this.gameMode = null;
|
||||
this.narrator.clear();
|
||||
this.clientLevelTeardownInProgress = true;
|
||||
@@ -2047,6 +_,7 @@
|
||||
@@ -2087,6 +_,7 @@
|
||||
try {
|
||||
this.updateScreenAndTick(p_335030_);
|
||||
if (this.level != null) {
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onLevelUnload(this.level);
|
||||
if (integratedserver != null) {
|
||||
ProfilerFiller profilerfiller = Profiler.get();
|
||||
profilerfiller.push("waitForServer");
|
||||
@@ -2060,6 +_,7 @@
|
||||
this.profiler.push("waitForServer");
|
||||
|
||||
@@ -2099,6 +_,7 @@
|
||||
|
||||
this.gui.onDisconnected();
|
||||
this.isLocalServer = false;
|
||||
@@ -345,11 +349,40 @@
|
||||
}
|
||||
|
||||
this.level = null;
|
||||
@@ -2207,6 +_,7 @@
|
||||
@@ -2245,6 +_,7 @@
|
||||
|
||||
private void pickBlock() {
|
||||
if (this.hitResult != null && this.hitResult.getType() != HitResult.Type.MISS) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onClickInput(2, this.options.keyPickItem, InteractionHand.MAIN_HAND).isCanceled()) return;
|
||||
boolean flag = Screen.hasControlDown();
|
||||
switch (this.hitResult) {
|
||||
case BlockHitResult blockhitresult:
|
||||
boolean flag = this.player.getAbilities().instabuild;
|
||||
BlockEntity blockentity = null;
|
||||
HitResult.Type hitresult$type = this.hitResult.getType();
|
||||
@@ -2257,7 +_,7 @@
|
||||
}
|
||||
|
||||
Block block = blockstate.getBlock();
|
||||
- itemstack = block.getCloneItemStack(this.level, blockpos, blockstate);
|
||||
+ itemstack = blockstate.getCloneItemStack(this.hitResult, this.level, blockpos, this.player);
|
||||
if (itemstack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -2271,7 +_,7 @@
|
||||
}
|
||||
|
||||
Entity entity = ((EntityHitResult)this.hitResult).getEntity();
|
||||
- itemstack = entity.getPickResult();
|
||||
+ itemstack = entity.getPickedResult(this.hitResult);
|
||||
if (itemstack == null) {
|
||||
return;
|
||||
}
|
||||
@@ -2855,6 +_,10 @@
|
||||
@Nullable
|
||||
public static String getLauncherBrand() {
|
||||
return System.getProperty("minecraft.launcher.brand");
|
||||
+ }
|
||||
+
|
||||
+ public ItemColors getItemColors() {
|
||||
+ return this.itemColors;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -1,68 +1,62 @@
|
||||
--- a/net/minecraft/client/MouseHandler.java
|
||||
+++ b/net/minecraft/client/MouseHandler.java
|
||||
@@ -90,6 +_,7 @@
|
||||
@@ -79,6 +_,7 @@
|
||||
this.activeButton = -1;
|
||||
}
|
||||
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPre(p_91532_, p_91533_, p_91534_)) return;
|
||||
boolean[] aboolean = new boolean[]{false};
|
||||
if (this.minecraft.getOverlay() == null) {
|
||||
if (this.minecraft.screen == null) {
|
||||
if (!this.mouseGrabbed && flag) {
|
||||
@@ -103,7 +_,7 @@
|
||||
@@ -91,9 +_,9 @@
|
||||
Screen screen = this.minecraft.screen;
|
||||
if (flag) {
|
||||
screen.afterMouseAction();
|
||||
|
||||
try {
|
||||
- if (screen.mouseClicked(d0, d1, i)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseClicked(screen, d0, d1, i)) {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable throwable1) {
|
||||
@@ -116,7 +_,7 @@
|
||||
}
|
||||
- Screen.wrapScreenError(() -> aboolean[0] = screen.mouseClicked(d0, d1, i), "mouseClicked event handler", screen.getClass().getCanonicalName());
|
||||
+ Screen.wrapScreenError(() -> net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseClicked(aboolean, screen, d0, d1, i), "mouseClicked event handler", screen.getClass().getCanonicalName());
|
||||
} else {
|
||||
try {
|
||||
- if (screen.mouseReleased(d0, d1, i)) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseReleased(screen, d0, d1, i)) {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
@@ -150,6 +_,7 @@
|
||||
- Screen.wrapScreenError(() -> aboolean[0] = screen.mouseReleased(d0, d1, i), "mouseReleased event handler", screen.getClass().getCanonicalName());
|
||||
+ Screen.wrapScreenError(() -> net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseReleased(aboolean, screen, d0, d1, i), "mouseReleased event handler", screen.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(p_91532_, p_91533_, p_91534_);
|
||||
}
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseButtonPost(p_91532_, p_91533_, p_91534_);
|
||||
}
|
||||
|
||||
public void fillMousePositionDetails(CrashReportCategory p_398230_, Window p_398216_) {
|
||||
@@ -189,7 +_,9 @@
|
||||
@@ -129,7 +_,9 @@
|
||||
if (this.minecraft.screen != null) {
|
||||
double d3 = this.getScaledXPos(this.minecraft.getWindow());
|
||||
double d4 = this.getScaledYPos(this.minecraft.getWindow());
|
||||
double d3 = this.xpos * (double)this.minecraft.getWindow().getGuiScaledWidth() / (double)this.minecraft.getWindow().getScreenWidth();
|
||||
double d4 = this.ypos * (double)this.minecraft.getWindow().getGuiScaledHeight() / (double)this.minecraft.getWindow().getScreenHeight();
|
||||
- this.minecraft.screen.mouseScrolled(d3, d4, d1, d2);
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPre(this.minecraft.screen, d3, d4, d1, d2)) return;
|
||||
+ if (this.minecraft.screen.mouseScrolled(d3, d4, d1, d2)) return;
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenMouseScrollPost(this.minecraft.screen, d3, d4, d1, d2);
|
||||
this.minecraft.screen.afterMouseAction();
|
||||
} else if (this.minecraft.player != null) {
|
||||
Vector2i vector2i = this.scrollWheelHandler.onMouseScroll(d1, d2);
|
||||
@@ -198,6 +_,7 @@
|
||||
}
|
||||
|
||||
int i = vector2i.y == 0 ? -vector2i.x : vector2i.y;
|
||||
if (this.accumulatedScrollX != 0.0 && Math.signum(d1) != Math.signum(this.accumulatedScrollX)) {
|
||||
@@ -151,6 +_,7 @@
|
||||
this.accumulatedScrollX -= (double)j;
|
||||
this.accumulatedScrollY -= (double)i;
|
||||
int k = i == 0 ? -j : i;
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onMouseScroll(this, d1, d2)) return;
|
||||
if (this.minecraft.player.isSpectator()) {
|
||||
if (this.minecraft.gui.getSpectatorGui().isMenuActive()) {
|
||||
this.minecraft.gui.getSpectatorGui().onMouseScrolled(-i);
|
||||
@@ -303,7 +_,7 @@
|
||||
double d5 = getScaledYPos(window, this.accumulatedDY);
|
||||
this.minecraft.gui.getSpectatorGui().onMouseScrolled(-k);
|
||||
@@ -236,7 +_,7 @@
|
||||
if (this.activeButton != -1 && this.mousePressedTime > 0.0) {
|
||||
double d4 = this.accumulatedDX * (double)this.minecraft.getWindow().getGuiScaledWidth() / (double)this.minecraft.getWindow().getScreenWidth();
|
||||
double d5 = this.accumulatedDY * (double)this.minecraft.getWindow().getGuiScaledHeight() / (double)this.minecraft.getWindow().getScreenHeight();
|
||||
- Screen.wrapScreenError(() -> screen.mouseDragged(d2, d3, this.activeButton, d4, d5), "mouseDragged event handler", screen.getClass().getCanonicalName());
|
||||
+ Screen.wrapScreenError(() -> net.minecraftforge.client.ForgeHooksClient.onScreenMouseDrag(screen, d2, d3, this.activeButton, d4, d5), "mouseDragged event handler", screen.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
try {
|
||||
- screen.mouseDragged(d2, d3, this.activeButton, d4, d5);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onScreenMouseDrag(screen, d2, d3, this.activeButton, d4, d5);
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport1 = CrashReport.forThrowable(throwable, "mouseDragged event handler");
|
||||
screen.fillCrashDetails(crashreport1);
|
||||
@@ -393,6 +_,14 @@
|
||||
screen.afterMouseMove();
|
||||
@@ -303,6 +_,14 @@
|
||||
|
||||
public double ypos() {
|
||||
return this.ypos;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/client/Options.java
|
||||
+++ b/net/minecraft/client/Options.java
|
||||
@@ -668,7 +_,8 @@
|
||||
@@ -681,7 +_,8 @@
|
||||
},
|
||||
new OptionInstance.LazyEnum<>(
|
||||
() -> Stream.concat(Stream.of(""), Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().stream()).toList(),
|
||||
- p_232011_ -> Minecraft.getInstance().isRunning() && p_232011_ != "" && !Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().contains(p_232011_)
|
||||
+ // FORGE: fix incorrect string comparison - PR #8767
|
||||
+ p_232011_ -> Minecraft.getInstance().isRunning() && (p_232011_ == null || !p_232011_.isEmpty()) && !Minecraft.getInstance().getSoundManager().getAvailableSoundDevices().contains(p_232011_)
|
||||
? Optional.empty()
|
||||
: Optional.of(p_232011_),
|
||||
? Optional.empty()
|
||||
: Optional.of(p_232011_),
|
||||
Codec.STRING
|
||||
@@ -1050,6 +_,7 @@
|
||||
}
|
||||
@@ -18,10 +18,10 @@
|
||||
this.minecraft = p_92138_;
|
||||
this.optionsFile = new File(p_92139_, "options.txt");
|
||||
boolean flag = Runtime.getRuntime().maxMemory() >= 1000000000L;
|
||||
@@ -1181,12 +_,22 @@
|
||||
@@ -1184,12 +_,22 @@
|
||||
p_168428_.process("telemetryOptInExtra", this.telemetryOptInExtra);
|
||||
this.onboardAccessibility = p_168428_.process("onboardAccessibility", this.onboardAccessibility);
|
||||
p_168428_.process("menuBackgroundBlurriness", this.menuBackgroundBlurriness);
|
||||
this.startedCleanly = p_168428_.process("startedCleanly", this.startedCleanly);
|
||||
+ processOptionsForge(p_168428_);
|
||||
+ }
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1204,6 +_,10 @@
|
||||
@@ -1207,6 +_,10 @@
|
||||
}
|
||||
|
||||
public void load() {
|
||||
@@ -53,8 +53,8 @@
|
||||
try {
|
||||
if (!this.optionsFile.exists()) {
|
||||
return;
|
||||
@@ -1228,7 +_,8 @@
|
||||
this.graphicsMode.set(isTrue(optional.get()) ? GraphicsStatus.FANCY : GraphicsStatus.FAST);
|
||||
@@ -1234,7 +_,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- this.processOptions(
|
||||
@@ -62,14 +62,14 @@
|
||||
+ processor.accept(
|
||||
new Options.FieldAccess() {
|
||||
@Nullable
|
||||
private String getValue(String p_394210_) {
|
||||
@@ -1433,6 +_,7 @@
|
||||
private String getValueOrNull(String p_168459_) {
|
||||
@@ -1428,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void broadcastOptions() {
|
||||
+ if (net.minecraftforge.client.loading.ClientModLoader.isLoading()) return; //Don't save settings before mods add keybindigns and the like to prevent them from being deleted.
|
||||
if (this.minecraft.player != null) {
|
||||
this.minecraft.player.connection.broadcastClientInformation(this.buildPlayerInformation());
|
||||
this.minecraft.player.connection.send(new ServerboundClientInformationPacket(this.buildPlayerInformation()));
|
||||
}
|
||||
@@ -1546,6 +_,23 @@
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
--- a/net/minecraft/client/RecipeBookCategories.java
|
||||
+++ b/net/minecraft/client/RecipeBookCategories.java
|
||||
@@ -12,7 +_,7 @@
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public enum RecipeBookCategories {
|
||||
+public enum RecipeBookCategories implements net.minecraftforge.common.IExtensibleEnum {
|
||||
CRAFTING_SEARCH(new ItemStack(Items.COMPASS)),
|
||||
CRAFTING_BUILDING_BLOCKS(new ItemStack(Blocks.BRICKS)),
|
||||
CRAFTING_REDSTONE(new ItemStack(Items.REDSTONE)),
|
||||
@@ -38,7 +_,7 @@
|
||||
public static final List<RecipeBookCategories> CRAFTING_CATEGORIES = ImmutableList.of(
|
||||
CRAFTING_SEARCH, CRAFTING_EQUIPMENT, CRAFTING_BUILDING_BLOCKS, CRAFTING_MISC, CRAFTING_REDSTONE
|
||||
);
|
||||
- public static final Map<RecipeBookCategories, List<RecipeBookCategories>> AGGREGATE_CATEGORIES = ImmutableMap.of(
|
||||
+ public static final Map<RecipeBookCategories, List<RecipeBookCategories>> AGGREGATE_CATEGORIES = net.minecraftforge.client.RecipeBookManager.getAggregateCategories(ImmutableMap.of(
|
||||
CRAFTING_SEARCH,
|
||||
ImmutableList.of(CRAFTING_EQUIPMENT, CRAFTING_BUILDING_BLOCKS, CRAFTING_MISC, CRAFTING_REDSTONE),
|
||||
FURNACE_SEARCH,
|
||||
@@ -47,7 +_,7 @@
|
||||
ImmutableList.of(BLAST_FURNACE_BLOCKS, BLAST_FURNACE_MISC),
|
||||
SMOKER_SEARCH,
|
||||
ImmutableList.of(SMOKER_FOOD)
|
||||
- );
|
||||
+ ));
|
||||
private final List<ItemStack> itemIcons;
|
||||
|
||||
private RecipeBookCategories(final ItemStack... p_92267_) {
|
||||
@@ -60,10 +_,15 @@
|
||||
case FURNACE -> FURNACE_CATEGORIES;
|
||||
case BLAST_FURNACE -> BLAST_FURNACE_CATEGORIES;
|
||||
case SMOKER -> SMOKER_CATEGORIES;
|
||||
+ default -> net.minecraftforge.client.RecipeBookManager.getCustomCategoriesOrEmpty(p_92270_);
|
||||
};
|
||||
}
|
||||
|
||||
public List<ItemStack> getIconItems() {
|
||||
return this.itemIcons;
|
||||
+ }
|
||||
+
|
||||
+ public static RecipeBookCategories create(String name, ItemStack... icons) {
|
||||
+ throw new IllegalStateException("Enum not extended");
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,30 @@
|
||||
--- a/net/minecraft/client/Screenshot.java
|
||||
+++ b/net/minecraft/client/Screenshot.java
|
||||
@@ -43,6 +_,13 @@
|
||||
file2 = new File(file1, p_92297_);
|
||||
}
|
||||
@@ -54,14 +_,24 @@
|
||||
file2 = new File(file1, p_92307_);
|
||||
}
|
||||
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenshot(p_389141_, file2);
|
||||
+ if (event.isCanceled()) {
|
||||
+ p_92301_.accept(event.getCancelMessage());
|
||||
+ return;
|
||||
+ }
|
||||
+ final File target = event.getScreenshotFile();
|
||||
+ var event = net.minecraftforge.client.event.ForgeEventFactoryClient.onScreenshot(nativeimage, file2);
|
||||
+ if (event.isCanceled()) {
|
||||
+ p_92311_.accept(event.getCancelMessage());
|
||||
+ return;
|
||||
+ }
|
||||
+ final File target = event.getScreenshotFile();
|
||||
+
|
||||
Util.ioPool()
|
||||
.execute(
|
||||
() -> {
|
||||
@@ -50,10 +_,13 @@
|
||||
NativeImage $$4x = p_389141_;
|
||||
|
||||
try {
|
||||
- p_389141_.writeToFile(file2);
|
||||
- Component component = Component.literal(file2.getName())
|
||||
+ p_389141_.writeToFile(target);
|
||||
+ Component component = Component.literal(target.getName())
|
||||
.withStyle(ChatFormatting.UNDERLINE)
|
||||
.withStyle(p_389149_ -> p_389149_.withClickEvent(new ClickEvent.OpenFile(file2.getAbsoluteFile())));
|
||||
+ if (event.getResultMessage() != null)
|
||||
+ p_92301_.accept(event.getResultMessage());
|
||||
+ else
|
||||
p_92301_.accept(Component.translatable("screenshot.success", component));
|
||||
} catch (Throwable throwable1) {
|
||||
if (p_389141_ != null) {
|
||||
Util.ioPool()
|
||||
.execute(
|
||||
() -> {
|
||||
try {
|
||||
- nativeimage.writeToFile(file2);
|
||||
- Component component = Component.literal(file2.getName())
|
||||
+ nativeimage.writeToFile(target);
|
||||
+ Component component = Component.literal(target.getName())
|
||||
.withStyle(ChatFormatting.UNDERLINE)
|
||||
- .withStyle(p_168608_ -> p_168608_.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, file2.getAbsolutePath())));
|
||||
+ .withStyle(p_168608_ -> p_168608_.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, target.getAbsolutePath())));
|
||||
+ if (event.getResultMessage() != null)
|
||||
+ p_92311_.accept(event.getResultMessage());
|
||||
+ else
|
||||
p_92311_.accept(Component.translatable("screenshot.success", component));
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Couldn't save screenshot", (Throwable)exception);
|
||||
@@ -1,16 +1,16 @@
|
||||
--- a/net/minecraft/client/color/block/BlockColors.java
|
||||
+++ b/net/minecraft/client/color/block/BlockColors.java
|
||||
@@ -30,7 +_,8 @@
|
||||
@@ -29,7 +_,8 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class BlockColors {
|
||||
private static final int DEFAULT = -1;
|
||||
public static final int LILY_PAD_IN_WORLD = -14647248;
|
||||
public static final int LILY_PAD_DEFAULT = -9321636;
|
||||
- private final IdMapper<BlockColor> blockColors = new IdMapper<>(32);
|
||||
+ // Forge: Use registry delegate as non-Vanilla block ids are not constant
|
||||
+ private final java.util.Map<net.minecraft.core.Holder.Reference<Block>, BlockColor> blockColors = new java.util.HashMap<>(32);
|
||||
private final Map<Block, Set<Property<?>>> coloringStates = Maps.newHashMap();
|
||||
|
||||
public static BlockColors createDefault() {
|
||||
@@ -95,11 +_,12 @@
|
||||
@@ -91,11 +_,12 @@
|
||||
}, Blocks.MELON_STEM, Blocks.PUMPKIN_STEM);
|
||||
blockcolors.addColoringState(StemBlock.AGE, Blocks.MELON_STEM, Blocks.PUMPKIN_STEM);
|
||||
blockcolors.register((p_92596_, p_92597_, p_92598_, p_92599_) -> p_92597_ != null && p_92598_ != null ? -14647248 : -9321636, Blocks.LILY_PAD);
|
||||
@@ -24,7 +24,7 @@
|
||||
if (blockcolor != null) {
|
||||
return blockcolor.getColor(p_92583_, null, null, 0);
|
||||
} else {
|
||||
@@ -109,13 +_,15 @@
|
||||
@@ -105,13 +_,15 @@
|
||||
}
|
||||
|
||||
public int getColor(BlockState p_92578_, @Nullable BlockAndTintGetter p_92579_, @Nullable BlockPos p_92580_, int p_92581_) {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
--- a/net/minecraft/client/color/item/ItemColors.java
|
||||
+++ b/net/minecraft/client/color/item/ItemColors.java
|
||||
@@ -26,7 +_,8 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class ItemColors {
|
||||
private static final int DEFAULT = -1;
|
||||
- private final IdMapper<ItemColor> itemColors = new IdMapper<>(32);
|
||||
+ // Forge: Use registry delegate as non-Vanilla item ids are not constant
|
||||
+ private final java.util.Map<net.minecraft.core.Holder.Reference<Item>, ItemColor> itemColors = new java.util.HashMap<>(32);
|
||||
|
||||
public static ItemColors createDefault(BlockColors p_92684_) {
|
||||
ItemColors itemcolors = new ItemColors();
|
||||
@@ -105,17 +_,20 @@
|
||||
: FastColor.ARGB32.opaque(p_325310_.getOrDefault(DataComponents.MAP_COLOR, MapItemColor.DEFAULT).rgb()),
|
||||
Items.FILLED_MAP
|
||||
);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onItemColorsInit(itemcolors, p_92684_);
|
||||
return itemcolors;
|
||||
}
|
||||
|
||||
public int getColor(ItemStack p_92677_, int p_92678_) {
|
||||
- ItemColor itemcolor = this.itemColors.byId(BuiltInRegistries.ITEM.getId(p_92677_.getItem()));
|
||||
+ ItemColor itemcolor = this.itemColors.get(net.minecraftforge.registries.ForgeRegistries.ITEMS.getDelegateOrThrow(p_92677_.getItem()));
|
||||
return itemcolor == null ? -1 : itemcolor.getColor(p_92677_, p_92678_);
|
||||
}
|
||||
|
||||
+ /** @deprecated Register via {@link net.minecraftforge.client.event.RegisterColorHandlersEvent.Item} */
|
||||
+ @Deprecated
|
||||
public void register(ItemColor p_92690_, ItemLike... p_92691_) {
|
||||
for (ItemLike itemlike : p_92691_) {
|
||||
- this.itemColors.addMapping(p_92690_, Item.getId(itemlike.asItem()));
|
||||
+ this.itemColors.put(net.minecraftforge.registries.ForgeRegistries.ITEMS.getDelegateOrThrow(itemlike.asItem()), p_92690_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
--- a/net/minecraft/client/data/Main.java
|
||||
+++ b/net/minecraft/client/data/Main.java
|
||||
@@ -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");
|
||||
+ OptionSpec<String> inputSpec = optionparser.accepts("input", "Input folder").withRequiredArg();
|
||||
+ var loader = net.minecraftforge.data.loading.DatagenModLoader.setup(optionparser, true);
|
||||
OptionSet optionset = optionparser.parse(p_375526_);
|
||||
- if (!optionset.has(optionspec) && optionset.hasOptions()) {
|
||||
+ if (!optionset.has(optionspec) && optionset.hasOptions() && loader.hasArgs(optionset)) {
|
||||
+ var input = optionset.valuesOf(inputSpec).stream().map(Paths::get).toList();
|
||||
Path path = Paths.get(optionspec3.value(optionset));
|
||||
boolean flag = optionset.has(optionspec2);
|
||||
boolean flag1 = flag || optionset.has(optionspec1);
|
||||
Bootstrap.bootStrap();
|
||||
ClientBootstrap.bootstrap();
|
||||
+ if (!loader.run(optionset, path, input, flag, flag1, flag, flag, false))
|
||||
+ return;
|
||||
DataGenerator datagenerator = new DataGenerator(path, SharedConstants.getCurrentVersion(), true);
|
||||
addClientProviders(datagenerator, flag1);
|
||||
datagenerator.run();
|
||||
@@ -1,12 +0,0 @@
|
||||
--- a/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
+++ b/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
@@ -852,6 +_,9 @@
|
||||
this.declareCustomModelItem(Items.COD);
|
||||
this.declareCustomModelItem(Items.FEATHER);
|
||||
this.declareCustomModelItem(Items.LEAD);
|
||||
+ // moved from validate to here, because it's just vanilla default blocks
|
||||
+ if (this.itemModelOutput instanceof ModelProvider.ItemInfoCollector collector)
|
||||
+ collector.generateDefaultBlockModels();
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -1,111 +0,0 @@
|
||||
--- a/net/minecraft/client/data/models/ModelProvider.java
|
||||
+++ b/net/minecraft/client/data/models/ModelProvider.java
|
||||
@@ -45,11 +_,11 @@
|
||||
|
||||
@Override
|
||||
public CompletableFuture<?> run(CachedOutput p_376268_) {
|
||||
- ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector();
|
||||
- ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector();
|
||||
+ ModelProvider.ItemInfoCollector modelprovider$iteminfocollector = new ModelProvider.ItemInfoCollector(this::getKnownItems);
|
||||
+ ModelProvider.BlockStateGeneratorCollector modelprovider$blockstategeneratorcollector = new ModelProvider.BlockStateGeneratorCollector(this::getKnownBlocks);
|
||||
ModelProvider.SimpleModelCollector modelprovider$simplemodelcollector = new ModelProvider.SimpleModelCollector();
|
||||
- new BlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
- new ItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
+ getBlockModelGenerators(modelprovider$blockstategeneratorcollector, modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
+ getItemModelGenerators(modelprovider$iteminfocollector, modelprovider$simplemodelcollector).run();
|
||||
modelprovider$blockstategeneratorcollector.validate();
|
||||
modelprovider$iteminfocollector.finalizeAndValidate();
|
||||
return CompletableFuture.allOf(
|
||||
@@ -59,6 +_,22 @@
|
||||
);
|
||||
}
|
||||
|
||||
+ protected Stream<Block> getKnownBlocks() {
|
||||
+ return BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().location().getNamespace()));
|
||||
+ }
|
||||
+
|
||||
+ protected Stream<Item> getKnownItems() {
|
||||
+ return BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().location().getNamespace()));
|
||||
+ }
|
||||
+
|
||||
+ protected BlockModelGenerators getBlockModelGenerators(BlockStateGeneratorCollector blocks, ItemInfoCollector items, SimpleModelCollector models) {
|
||||
+ return new BlockModelGenerators(blocks, items, models);
|
||||
+ }
|
||||
+
|
||||
+ protected ItemModelGenerators getItemModelGenerators(ItemInfoCollector items, SimpleModelCollector models) {
|
||||
+ return new ItemModelGenerators(items, models);
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public final String getName() {
|
||||
return "Model Definitions";
|
||||
@@ -67,6 +_,15 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class BlockStateGeneratorCollector implements Consumer<BlockModelDefinitionGenerator> {
|
||||
private final Map<Block, BlockModelDefinitionGenerator> generators = new HashMap<>();
|
||||
+ private final Supplier<Stream<Block>> known;
|
||||
+
|
||||
+ public BlockStateGeneratorCollector() {
|
||||
+ this(() -> BuiltInRegistries.BLOCK.stream().filter(block -> "minecraft".equals(block.builtInRegistryHolder().key().location().getNamespace())));
|
||||
+ }
|
||||
+
|
||||
+ public BlockStateGeneratorCollector(Supplier<Stream<Block>> known) {
|
||||
+ this.known = known;
|
||||
+ }
|
||||
|
||||
public void accept(BlockModelDefinitionGenerator p_393399_) {
|
||||
Block block = p_393399_.block();
|
||||
@@ -77,7 +_,7 @@
|
||||
}
|
||||
|
||||
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())
|
||||
.toList();
|
||||
@@ -97,6 +_,15 @@
|
||||
public static class ItemInfoCollector implements ItemModelOutput {
|
||||
private final Map<Item, ClientItem> itemInfos = new HashMap<>();
|
||||
private final Map<Item, Item> copies = new HashMap<>();
|
||||
+ private final Supplier<Stream<Item>> known;
|
||||
+
|
||||
+ public ItemInfoCollector() {
|
||||
+ this(() -> BuiltInRegistries.ITEM.stream().filter(item -> "minecraft".equals(item.builtInRegistryHolder().key().location().getNamespace())));
|
||||
+ }
|
||||
+
|
||||
+ public ItemInfoCollector(Supplier<Stream<Item>> known) {
|
||||
+ this.known = known;
|
||||
+ }
|
||||
|
||||
@Override
|
||||
public void accept(Item p_376450_, ItemModel.Unbaked p_378513_) {
|
||||
@@ -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)) {
|
||||
@@ -124,6 +_,8 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
+ }
|
||||
+ public void finalizeAndValidate() {
|
||||
this.copies.forEach((p_376289_, p_375718_) -> {
|
||||
ClientItem clientitem = this.itemInfos.get(p_375718_);
|
||||
if (clientitem == null) {
|
||||
@@ -132,8 +_,8 @@
|
||||
this.register(p_376289_, clientitem);
|
||||
}
|
||||
});
|
||||
- List<ResourceLocation> list = BuiltInRegistries.ITEM
|
||||
- .listElements()
|
||||
+ List<ResourceLocation> list = known.get()
|
||||
+ .map(item -> item.builtInRegistryHolder())
|
||||
.filter(p_377225_ -> !this.itemInfos.containsKey(p_377225_.value()))
|
||||
.map(p_378591_ -> p_378591_.key().location())
|
||||
.toList();
|
||||
@@ -1,11 +1,20 @@
|
||||
--- a/net/minecraft/client/gui/Font.java
|
||||
+++ b/net/minecraft/client/gui/Font.java
|
||||
@@ -32,7 +_,7 @@
|
||||
import org.joml.Matrix4f;
|
||||
@@ -31,7 +_,7 @@
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class Font {
|
||||
+public class Font implements net.minecraftforge.client.extensions.IForgeFont {
|
||||
private static final float EFFECT_DEPTH = 0.01F;
|
||||
public static final float SHADOW_DEPTH = 0.03F;
|
||||
public static final int NO_SHADOW = 0;
|
||||
private static final Vector3f SHADOW_OFFSET = new Vector3f(0.0F, 0.0F, 0.03F);
|
||||
public static final int ALPHA_CUTOFF = 8;
|
||||
@@ -322,6 +_,8 @@
|
||||
public StringSplitter getSplitter() {
|
||||
return this.splitter;
|
||||
}
|
||||
+
|
||||
+ @Override public Font self() { return this; }
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static enum DisplayMode {
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/Gui.java
|
||||
+++ b/net/minecraft/client/gui/Gui.java
|
||||
@@ -148,7 +_,7 @@
|
||||
@@ -131,7 +_,7 @@
|
||||
public float vignetteBrightness = 1.0F;
|
||||
private int toolHighlightTimer;
|
||||
private ItemStack lastToolHighlight = ItemStack.EMPTY;
|
||||
@@ -9,32 +9,32 @@
|
||||
private final SubtitleOverlay subtitleOverlay;
|
||||
private final SpectatorGui spectatorGui;
|
||||
private final PlayerTabOverlay tabList;
|
||||
@@ -347,7 +_,7 @@
|
||||
@@ -318,7 +_,7 @@
|
||||
Window window = this.minecraft.getWindow();
|
||||
int i = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window));
|
||||
int j = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window));
|
||||
int i = Mth.floor(this.minecraft.mouseHandler.xpos() * (double)window.getGuiScaledWidth() / (double)window.getScreenWidth());
|
||||
int j = Mth.floor(this.minecraft.mouseHandler.ypos() * (double)window.getGuiScaledHeight() / (double)window.getScreenHeight());
|
||||
- this.chat.render(p_329202_, this.tickCount, i, j, false);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeChatEvent(p_329202_, this.chat, window, i, j, this.tickCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,6 +_,8 @@
|
||||
@@ -434,6 +_,8 @@
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : Ordering.natural().reverse().sortedCopy(collection)) {
|
||||
Holder<MobEffect> holder = mobeffectinstance.getEffect();
|
||||
+ var renderer = net.minecraftforge.client.extensions.common.IClientMobEffectExtensions.of(mobeffectinstance);
|
||||
+ if (!renderer.isVisibleInGui(mobeffectinstance)) continue;
|
||||
if (mobeffectinstance.showIcon()) {
|
||||
int k = p_282812_.guiWidth();
|
||||
int l = 1;
|
||||
@@ -475,6 +_,7 @@
|
||||
int i = p_282812_.guiWidth();
|
||||
int j = 1;
|
||||
@@ -463,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (renderer.renderGuiIcon(mobeffectinstance, this, p_282812_, k, l, 0, f)) continue;
|
||||
+ if (renderer.renderGuiIcon(mobeffectinstance, this, p_282812_, i, j, 0, f)) continue;
|
||||
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.get(holder);
|
||||
int l1 = k;
|
||||
int k1 = l;
|
||||
int l1 = i;
|
||||
int i1 = j;
|
||||
@@ -625,6 +_,10 @@
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
+ }
|
||||
+
|
||||
+ public void renderSelectedItemName(GuiGraphics p_283501_, int yShift) {
|
||||
Profiler.get().push("selectedItemName");
|
||||
this.minecraft.getProfiler().push("selectedItemName");
|
||||
if (this.toolHighlightTimer > 0 && !this.lastToolHighlight.isEmpty()) {
|
||||
MutableComponent mutablecomponent = Component.empty().append(this.lastToolHighlight.getHoverName()).withStyle(this.lastToolHighlight.getRarity().color());
|
||||
@@ -632,9 +_,13 @@
|
||||
@@ -66,13 +66,13 @@
|
||||
}
|
||||
|
||||
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, FastColor.ARGB32.color(l, -1));
|
||||
+ p_283501_.drawStringWithBackdrop(font, highlightTip, j, k, i, FastColor.ARGB32.color(l, -1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,7 +_,7 @@
|
||||
ItemStack itemstack = this.minecraft.player.getInventory().getSelectedItem();
|
||||
@@ -1146,7 +_,7 @@
|
||||
ItemStack itemstack = this.minecraft.player.getInventory().getSelected();
|
||||
if (itemstack.isEmpty()) {
|
||||
this.toolHighlightTimer = 0;
|
||||
- } else if (this.lastToolHighlight.isEmpty() || !itemstack.is(this.lastToolHighlight.getItem()) || !itemstack.getHoverName().equals(this.lastToolHighlight.getHoverName())) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/GuiGraphics.java
|
||||
+++ b/net/minecraft/client/gui/GuiGraphics.java
|
||||
@@ -52,7 +_,7 @@
|
||||
@@ -56,7 +_,7 @@
|
||||
import org.joml.Vector2ic;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -9,7 +9,7 @@
|
||||
public static final float MAX_GUI_Z = 10000.0F;
|
||||
public static final float MIN_GUI_Z = -10000.0F;
|
||||
private static final int EXTRA_SPACE_AFTER_FIRST_TOOLTIP_LINE = 2;
|
||||
@@ -229,6 +_,11 @@
|
||||
@@ -268,6 +_,11 @@
|
||||
}
|
||||
|
||||
public int drawString(Font p_283343_, @Nullable String p_281896_, int p_283569_, int p_283418_, int p_281560_, boolean p_282130_) {
|
||||
@@ -18,10 +18,10 @@
|
||||
+
|
||||
+ // Forge: Add float variant for x,y coordinates
|
||||
+ public int drawString(Font p_283343_, @Nullable String p_281896_, float p_283569_, float p_283418_, int p_281560_, boolean p_282130_) {
|
||||
return p_281896_ == null
|
||||
? 0
|
||||
: p_283343_.drawInBatch(
|
||||
@@ -250,6 +_,11 @@
|
||||
if (p_281896_ == null) {
|
||||
return 0;
|
||||
} else {
|
||||
@@ -294,6 +_,11 @@
|
||||
}
|
||||
|
||||
public int drawString(Font p_282636_, FormattedCharSequence p_281596_, int p_281586_, int p_282816_, int p_281743_, boolean p_282394_) {
|
||||
@@ -30,10 +30,10 @@
|
||||
+
|
||||
+ // Forge: Add float variant for x,y coordinates
|
||||
+ public int drawString(Font p_282636_, FormattedCharSequence p_281596_, float p_281586_, float p_282816_, int p_281743_, boolean p_282394_) {
|
||||
return p_282636_.drawInBatch(
|
||||
p_281596_, p_281586_, p_282816_, p_281743_, p_282394_, this.pose.last().pose(), this.bufferSource, Font.DisplayMode.NORMAL, 0, 15728880
|
||||
);
|
||||
@@ -850,6 +_,7 @@
|
||||
int i = p_282636_.drawInBatch(
|
||||
p_281596_,
|
||||
(float)p_281586_,
|
||||
@@ -864,6 +_,7 @@
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item");
|
||||
CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered");
|
||||
crashreportcategory.setDetail("Item Type", () -> String.valueOf(p_281675_.getItem()));
|
||||
@@ -41,9 +41,9 @@
|
||||
crashreportcategory.setDetail("Item Components", () -> String.valueOf(p_281675_.getComponents()));
|
||||
crashreportcategory.setDetail("Item Foil", () -> String.valueOf(p_281675_.hasFoil()));
|
||||
throw new ReportedException(crashreport);
|
||||
@@ -870,13 +_,24 @@
|
||||
this.renderItemCount(p_282005_, p_283349_, p_282641_, p_282146_, p_282803_);
|
||||
this.renderItemCooldown(p_283349_, p_282641_, p_282146_);
|
||||
@@ -904,16 +_,26 @@
|
||||
}
|
||||
|
||||
this.pose.popPose();
|
||||
+ net.minecraftforge.client.ItemDecoratorHandler.of(p_283349_).render(this, p_282005_, p_283349_, p_282641_, p_282146_);
|
||||
}
|
||||
@@ -53,56 +53,50 @@
|
||||
|
||||
public void renderTooltip(Font p_282308_, ItemStack p_282781_, int p_282687_, int p_282292_) {
|
||||
+ this.tooltipStack = p_282781_;
|
||||
this.renderTooltip(
|
||||
p_282308_, Screen.getTooltipFromItem(this.minecraft, p_282781_), p_282781_.getTooltipImage(), p_282687_, p_282292_, p_282781_.get(DataComponents.TOOLTIP_STYLE)
|
||||
);
|
||||
this.renderTooltip(p_282308_, Screen.getTooltipFromItem(this.minecraft, p_282781_), p_282781_.getTooltipImage(), p_282687_, p_282292_);
|
||||
+ this.tooltipStack = ItemStack.EMPTY;
|
||||
+ }
|
||||
+
|
||||
+ public void renderTooltip(Font font, List<Component> textComponents, Optional<TooltipComponent> tooltipComponent, ItemStack stack, int mouseX, int mouseY) {
|
||||
+ this.tooltipStack = stack;
|
||||
+ this.renderTooltip(font, textComponents, tooltipComponent, mouseX, mouseY, stack.get(DataComponents.TOOLTIP_STYLE));
|
||||
+ this.renderTooltip(font, textComponents, tooltipComponent, mouseX, mouseY);
|
||||
+ this.tooltipStack = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public void renderTooltip(Font p_283128_, List<Component> p_282716_, Optional<TooltipComponent> p_281682_, int p_283678_, int p_281696_) {
|
||||
@@ -886,8 +_,7 @@
|
||||
public void renderTooltip(
|
||||
Font p_362491_, List<Component> p_368544_, Optional<TooltipComponent> p_362815_, int p_366300_, int p_368952_, @Nullable ResourceLocation p_368469_
|
||||
) {
|
||||
- List<ClientTooltipComponent> list = p_368544_.stream().map(Component::getVisualOrderText).map(ClientTooltipComponent::create).collect(Util.toMutableList());
|
||||
- p_362815_.ifPresent(p_325321_ -> list.add(list.isEmpty() ? 0 : 1, ClientTooltipComponent.create(p_325321_)));
|
||||
+ List<ClientTooltipComponent> list = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, p_368544_, p_362815_, p_366300_, guiWidth(), guiHeight(), p_362491_);
|
||||
this.renderTooltipInternal(p_362491_, list, p_366300_, p_368952_, DefaultTooltipPositioner.INSTANCE, p_368469_);
|
||||
- List<ClientTooltipComponent> list = p_282716_.stream().map(Component::getVisualOrderText).map(ClientTooltipComponent::create).collect(Util.toMutableList());
|
||||
- p_281682_.ifPresent(p_325321_ -> list.add(list.isEmpty() ? 0 : 1, ClientTooltipComponent.create(p_325321_)));
|
||||
+ List<ClientTooltipComponent> list = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, p_282716_, p_281682_, p_283678_, guiWidth(), guiHeight(), p_283128_);
|
||||
this.renderTooltipInternal(p_283128_, list, p_283678_, p_281696_, DefaultTooltipPositioner.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -900,7 +_,22 @@
|
||||
@@ -922,7 +_,22 @@
|
||||
}
|
||||
|
||||
public void renderComponentTooltip(Font p_282739_, List<Component> p_281832_, int p_282191_, int p_282446_) {
|
||||
- this.renderComponentTooltip(p_282739_, p_281832_, p_282191_, p_282446_, null);
|
||||
- this.renderTooltip(p_282739_, Lists.transform(p_281832_, Component::getVisualOrderText), p_282191_, p_282446_);
|
||||
+ List<ClientTooltipComponent> components = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(this.tooltipStack, p_281832_, p_282191_, guiWidth(), guiHeight(), p_282739_);
|
||||
+ this.renderTooltipInternal(p_282739_, components, p_282191_, p_282446_, DefaultTooltipPositioner.INSTANCE, null);
|
||||
+ this.renderTooltipInternal(p_282739_, components, p_282191_, p_282446_, DefaultTooltipPositioner.INSTANCE);
|
||||
+ }
|
||||
+
|
||||
+ public void renderComponentTooltip(Font font, List<? extends net.minecraft.network.chat.FormattedText> tooltips, int mouseX, int mouseY, ItemStack stack) {
|
||||
+ this.tooltipStack = stack;
|
||||
+ List<ClientTooltipComponent> components = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponents(stack, tooltips, mouseX, guiWidth(), guiHeight(), font);
|
||||
+ this.renderTooltipInternal(font, components, mouseX, mouseY, DefaultTooltipPositioner.INSTANCE, null);
|
||||
+ this.renderTooltipInternal(font, components, mouseX, mouseY, DefaultTooltipPositioner.INSTANCE);
|
||||
+ this.tooltipStack = ItemStack.EMPTY;
|
||||
+ }
|
||||
+
|
||||
+ public void renderComponentTooltipFromElements(Font font, List<com.mojang.datafixers.util.Either<FormattedText, TooltipComponent>> elements, int mouseX, int mouseY, ItemStack stack) {
|
||||
+ this.tooltipStack = stack;
|
||||
+ List<ClientTooltipComponent> components = net.minecraftforge.client.ForgeHooksClient.gatherTooltipComponentsFromElements(stack, elements, mouseX, guiWidth(), guiHeight(), font);
|
||||
+ this.renderTooltipInternal(font, components, mouseX, mouseY, DefaultTooltipPositioner.INSTANCE, null);
|
||||
+ this.renderTooltipInternal(font, components, mouseX, mouseY, DefaultTooltipPositioner.INSTANCE);
|
||||
+ this.tooltipStack = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public void renderComponentTooltip(Font p_369090_, List<Component> p_365405_, int p_368143_, int p_366244_, @Nullable ResourceLocation p_364763_) {
|
||||
@@ -942,11 +_,13 @@
|
||||
@Nullable ResourceLocation p_368234_
|
||||
) {
|
||||
public void renderTooltip(Font p_282192_, List<? extends FormattedCharSequence> p_282297_, int p_281680_, int p_283325_) {
|
||||
@@ -941,11 +_,13 @@
|
||||
|
||||
private void renderTooltipInternal(Font p_282675_, List<ClientTooltipComponent> p_282615_, int p_283230_, int p_283417_, ClientTooltipPositioner p_282442_) {
|
||||
if (!p_282615_.isEmpty()) {
|
||||
+ var preEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipPre(this.tooltipStack, this, p_283230_, p_283417_, guiWidth(), guiHeight(), p_282615_, p_282675_, p_282442_);
|
||||
+ if (preEvent.isCanceled()) return;
|
||||
@@ -115,19 +109,21 @@
|
||||
if (k > i) {
|
||||
i = k;
|
||||
}
|
||||
@@ -956,18 +_,19 @@
|
||||
@@ -955,18 +_,21 @@
|
||||
|
||||
int i2 = i;
|
||||
int j2 = j;
|
||||
- Vector2ic vector2ic = p_282442_.positionTooltip(this.guiWidth(), this.guiHeight(), p_283230_, p_283417_, i, j);
|
||||
- Vector2ic vector2ic = p_282442_.positionTooltip(this.guiWidth(), this.guiHeight(), p_283230_, p_283417_, i2, j2);
|
||||
+ Vector2ic vector2ic = p_282442_.positionTooltip(this.guiWidth(), this.guiHeight(), preEvent.getX(), preEvent.getY(), i2, j2);
|
||||
int l = vector2ic.x();
|
||||
int i1 = vector2ic.y();
|
||||
this.pose.pushPose();
|
||||
int j1 = 400;
|
||||
- TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, 400, p_368234_);
|
||||
+ var background_event = net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTooltipBackground(this.tooltipStack, this, l, i1, preEvent.getFont(), p_282615_, p_368234_);
|
||||
+ TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, 400, background_event.getBackground());
|
||||
- this.drawManaged(() -> TooltipRenderUtil.renderTooltipBackground(this, l, i1, i2, j2, 400));
|
||||
+ this.drawManaged(() -> {
|
||||
+ var colorEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipColor(this.tooltipStack, this, l, i1, preEvent.getFont(), p_282615_);
|
||||
+ TooltipRenderUtil.renderTooltipBackground(this, l, i1, i2, j2, 400, colorEvent.getBackgroundStart(), colorEvent.getBackgroundEnd(), colorEvent.getBorderStart(), colorEvent.getBorderEnd());
|
||||
+ });
|
||||
this.pose.translate(0.0F, 0.0F, 400.0F);
|
||||
int k1 = i1;
|
||||
|
||||
@@ -135,26 +131,15 @@
|
||||
ClientTooltipComponent clienttooltipcomponent1 = p_282615_.get(l1);
|
||||
- clienttooltipcomponent1.renderText(p_282675_, l, k1, this.pose.last().pose(), this.bufferSource);
|
||||
+ clienttooltipcomponent1.renderText(preEvent.getFont(), l, k1, this.pose.last().pose(), this.bufferSource);
|
||||
k1 += clienttooltipcomponent1.getHeight(p_282675_) + (l1 == 0 ? 2 : 0);
|
||||
k1 += clienttooltipcomponent1.getHeight() + (l1 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -975,7 +_,7 @@
|
||||
@@ -974,7 +_,7 @@
|
||||
|
||||
for (int k2 = 0; k2 < p_282615_.size(); k2++) {
|
||||
ClientTooltipComponent clienttooltipcomponent2 = p_282615_.get(k2);
|
||||
- clienttooltipcomponent2.renderImage(p_282675_, l, k1, i2, j2, this);
|
||||
+ clienttooltipcomponent2.renderImage(preEvent.getFont(), l, k1, i2, j2, this);
|
||||
k1 += clienttooltipcomponent2.getHeight(p_282675_) + (k2 == 0 ? 2 : 0);
|
||||
- clienttooltipcomponent2.renderImage(p_282675_, l, k1, this);
|
||||
+ clienttooltipcomponent2.renderImage(preEvent.getFont(), l, k1, this);
|
||||
k1 += clienttooltipcomponent2.getHeight() + (k2 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -1030,6 +_,10 @@
|
||||
default:
|
||||
}
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ public MultiBufferSource.BufferSource getBufferSource() {
|
||||
+ return this.bufferSource;
|
||||
}
|
||||
|
||||
public void drawSpecial(Consumer<MultiBufferSource> p_367429_) {
|
||||
@@ -1,9 +1,9 @@
|
||||
--- a/net/minecraft/client/gui/components/AbstractButton.java
|
||||
+++ b/net/minecraft/client/gui/components/AbstractButton.java
|
||||
@@ -39,7 +_,7 @@
|
||||
this.getHeight(),
|
||||
ARGB.white(this.alpha)
|
||||
);
|
||||
@@ -34,7 +_,7 @@
|
||||
RenderSystem.enableDepthTest();
|
||||
p_281670_.blitSprite(SPRITES.get(this.active, this.isHoveredOrFocused()), this.getX(), this.getY(), this.getWidth(), this.getHeight());
|
||||
p_281670_.setColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
- int i = this.active ? 16777215 : 10526880;
|
||||
+ int i = getFGColor();
|
||||
this.renderString(p_281670_, minecraft.font, i | Mth.ceil(this.alpha * 255.0F) << 24);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/AbstractWidget.java
|
||||
+++ b/net/minecraft/client/gui/components/AbstractWidget.java
|
||||
@@ -250,6 +_,25 @@
|
||||
@@ -255,6 +_,25 @@
|
||||
this.focused = p_93693_;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/BossHealthOverlay.java
|
||||
+++ b/net/minecraft/client/gui/components/BossHealthOverlay.java
|
||||
@@ -66,13 +_,16 @@
|
||||
@@ -63,13 +_,16 @@
|
||||
|
||||
for (LerpingBossEvent lerpingbossevent : this.events.values()) {
|
||||
int k = i / 2 - 91;
|
||||
|
||||
+34
-35
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/components/DebugScreenOverlay.java
|
||||
+++ b/net/minecraft/client/gui/components/DebugScreenOverlay.java
|
||||
@@ -134,9 +_,9 @@
|
||||
@@ -101,9 +_,9 @@
|
||||
@Nullable
|
||||
private CompletableFuture<LevelChunk> serverChunk;
|
||||
private boolean renderDebug;
|
||||
@@ -13,54 +13,53 @@
|
||||
private final LocalSampleLogger frameTimeLogger = new LocalSampleLogger(1);
|
||||
private final LocalSampleLogger tickTimeLogger = new LocalSampleLogger(TpsDebugDimensions.values().length);
|
||||
private final LocalSampleLogger pingLogger = new LocalSampleLogger(1);
|
||||
@@ -179,14 +_,18 @@
|
||||
@@ -129,14 +_,18 @@
|
||||
this.clientChunk = null;
|
||||
}
|
||||
|
||||
- public void render(GuiGraphics p_281427_) {
|
||||
- ProfilerFiller profilerfiller = Profiler.get();
|
||||
- profilerfiller.push("debug");
|
||||
- this.minecraft.getProfiler().push("debug");
|
||||
+ protected void update() {
|
||||
Entity entity = this.minecraft.getCameraEntity();
|
||||
this.block = entity.pick(20.0, 0.0F, false);
|
||||
this.liquid = entity.pick(20.0, 0.0F, true);
|
||||
- p_281427_.drawManaged(() -> {
|
||||
+ }
|
||||
+
|
||||
+ protected void drawText(ProfilerFiller profilerfiller, GuiGraphics p_281427_) {
|
||||
this.drawGameInformation(p_281427_);
|
||||
this.drawSystemInformation(p_281427_);
|
||||
+ protected void drawText(GuiGraphics p_281427_) {
|
||||
this.drawGameInformation(p_281427_);
|
||||
this.drawSystemInformation(p_281427_);
|
||||
+ }
|
||||
+
|
||||
+ protected void drawFPSCharts(ProfilerFiller profilerfiller, GuiGraphics p_281427_) {
|
||||
this.profilerPieChart.setBottomOffset(10);
|
||||
if (this.renderFpsCharts) {
|
||||
int i = p_281427_.guiWidth();
|
||||
@@ -199,7 +_,9 @@
|
||||
|
||||
this.profilerPieChart.setBottomOffset(this.tpsChart.getFullHeight());
|
||||
}
|
||||
+ protected void drawFPSCharts(GuiGraphics p_281427_) {
|
||||
if (this.renderFpsCharts) {
|
||||
int i = p_281427_.guiWidth();
|
||||
int j = i / 2;
|
||||
@@ -146,7 +_,9 @@
|
||||
this.tpsChart.drawChart(p_281427_, i - k, k);
|
||||
}
|
||||
}
|
||||
+ }
|
||||
|
||||
+ protected void drawNetworkCharts(ProfilerFiller profilerfiller, GuiGraphics p_281427_) {
|
||||
if (this.renderNetworkCharts) {
|
||||
int l = p_281427_.guiWidth();
|
||||
int i1 = l / 2;
|
||||
@@ -215,12 +_,22 @@
|
||||
try (Zone zone = profilerfiller.zone("profilerPie")) {
|
||||
this.profilerPieChart.render(p_281427_);
|
||||
}
|
||||
+ protected void drawNetworkCharts(GuiGraphics p_281427_) {
|
||||
if (this.renderNetworkCharts) {
|
||||
int l = p_281427_.guiWidth();
|
||||
int i1 = l / 2;
|
||||
@@ -157,12 +_,21 @@
|
||||
int j1 = this.pingChart.getWidth(i1);
|
||||
this.pingChart.drawChart(p_281427_, l - j1, j1);
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ public void render(GuiGraphics p_281427_) {
|
||||
+ ProfilerFiller profilerfiller = Profiler.get();
|
||||
+ profilerfiller.push("debug");
|
||||
+ this.minecraft.getProfiler().push("debug");
|
||||
+ this.update();
|
||||
+
|
||||
+ this.drawText(profilerfiller, p_281427_);
|
||||
+ this.drawFPSCharts(profilerfiller, p_281427_);
|
||||
+ this.drawNetworkCharts(profilerfiller, p_281427_);
|
||||
|
||||
profilerfiller.pop();
|
||||
+ p_281427_.drawManaged(() -> {
|
||||
+ this.drawText(p_281427_);
|
||||
+ this.drawFPSCharts(p_281427_);
|
||||
+ this.drawNetworkCharts(p_281427_);
|
||||
});
|
||||
this.minecraft.getProfiler().pop();
|
||||
}
|
||||
|
||||
- protected void drawGameInformation(GuiGraphics p_281525_) {
|
||||
@@ -70,7 +69,7 @@
|
||||
list.add("");
|
||||
boolean flag = this.minecraft.getSingleplayerServer() != null;
|
||||
list.add(
|
||||
@@ -234,11 +_,18 @@
|
||||
@@ -176,11 +_,18 @@
|
||||
+ (this.renderNetworkCharts ? " visible" : " hidden")
|
||||
);
|
||||
list.add("For help: press F3 + Q");
|
||||
@@ -80,17 +79,17 @@
|
||||
+ protected void drawGameInformation(GuiGraphics p_281525_) {
|
||||
+ List<String> list = this.getGameInformation();
|
||||
+ list.addAll(this.getOverlayHelp());
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeDebugEvent(p_281525_, minecraft.getWindow(), minecraft.getDeltaTracker().getRealtimeDeltaTicks(), list, true);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeDebugEvent(p_281525_, minecraft.getWindow(), minecraft.getTimer().getRealtimeDeltaTicks(), list, true);
|
||||
+ this.renderLines(p_281525_, list, true);
|
||||
}
|
||||
|
||||
protected void drawSystemInformation(GuiGraphics p_281261_) {
|
||||
List<String> list = this.getSystemInformation();
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeDebugEvent(p_281261_, minecraft.getWindow(), minecraft.getDeltaTracker().getRealtimeDeltaTicks(), list, false);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCustomizeDebugEvent(p_281261_, minecraft.getWindow(), minecraft.getTimer().getRealtimeDeltaTicks(), list, false);
|
||||
this.renderLines(p_281261_, list, false);
|
||||
}
|
||||
|
||||
@@ -592,6 +_,7 @@
|
||||
@@ -529,6 +_,7 @@
|
||||
list.add("");
|
||||
list.add(ChatFormatting.UNDERLINE + "Targeted Entity");
|
||||
list.add(String.valueOf(BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType())));
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/client/gui/components/toasts/ToastComponent.java
|
||||
+++ b/net/minecraft/client/gui/components/toasts/ToastComponent.java
|
||||
@@ -97,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void addToast(Toast p_94923_) {
|
||||
+ if (net.minecraftforge.client.ForgeHooksClient.onToastAdd(p_94923_)) return;
|
||||
this.queued.add(p_94923_);
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
--- a/net/minecraft/client/gui/components/toasts/ToastManager.java
|
||||
+++ b/net/minecraft/client/gui/components/toasts/ToastManager.java
|
||||
@@ -127,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void addToast(Toast p_360768_) {
|
||||
+ if (net.minecraftforge.client.event.ForgeEventFactoryClient.onToastAdd(p_360768_)) return;
|
||||
this.queued.add(p_360768_);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/LoadingOverlay.java
|
||||
+++ b/net/minecraft/client/gui/screens/LoadingOverlay.java
|
||||
@@ -61,6 +_,8 @@
|
||||
return p_169325_ & 16777215 | p_169326_ << 24;
|
||||
}
|
||||
|
||||
+ protected boolean renderContents(GuiGraphics gui, float alpha) { return true; }
|
||||
+
|
||||
@Override
|
||||
public void render(GuiGraphics p_281839_, int p_282704_, int p_283650_, float p_283394_) {
|
||||
int i = p_281839_.guiWidth();
|
||||
@@ -95,6 +_,7 @@
|
||||
f2 = 1.0F;
|
||||
}
|
||||
|
||||
+ if (renderContents(p_281839_, f2)) {
|
||||
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;
|
||||
@@ -110,12 +_,14 @@
|
||||
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));
|
||||
}
|
||||
+ }
|
||||
|
||||
if (f >= 2.0F) {
|
||||
this.minecraft.setOverlay(null);
|
||||
@@ -131,6 +_,7 @@
|
||||
}
|
||||
|
||||
if (this.fadeOutStart == -1L && this.reload.isDone() && (!this.fadeIn || f1 >= 2.0F)) {
|
||||
@@ -32,7 +8,7 @@
|
||||
try {
|
||||
this.reload.checkExceptions();
|
||||
this.onFinish.accept(Optional.empty());
|
||||
@@ -123,7 +_,6 @@
|
||||
@@ -138,7 +_,6 @@
|
||||
this.onFinish.accept(Optional.of(throwable));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
@@ -95,6 +_,7 @@
|
||||
@@ -94,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
|
||||
@@ -197,7 +_,7 @@
|
||||
@@ -201,7 +_,7 @@
|
||||
}
|
||||
|
||||
public void onClose() {
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
protected <T extends GuiEventListener & Renderable & NarratableEntry> T addRenderableWidget(T p_169406_) {
|
||||
@@ -311,8 +_,10 @@
|
||||
@@ -312,8 +_,10 @@
|
||||
this.width = p_96608_;
|
||||
this.height = p_96609_;
|
||||
if (!this.initialized) {
|
||||
@@ -20,7 +20,7 @@
|
||||
} else {
|
||||
this.repositionElements();
|
||||
}
|
||||
@@ -325,8 +_,10 @@
|
||||
@@ -326,8 +_,10 @@
|
||||
protected void rebuildWidgets() {
|
||||
this.clearWidgets();
|
||||
this.clearFocus();
|
||||
@@ -31,15 +31,15 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -353,6 +_,7 @@
|
||||
@@ -354,6 +_,7 @@
|
||||
|
||||
this.renderBlurredBackground();
|
||||
this.renderBlurredBackground(p_297268_);
|
||||
this.renderMenuBackground(p_283688_);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderScreenBackground(this, p_283688_);
|
||||
}
|
||||
|
||||
protected void renderBlurredBackground() {
|
||||
@@ -453,6 +_,19 @@
|
||||
protected void renderBlurredBackground(float p_336041_) {
|
||||
@@ -463,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
|
||||
@@ -58,6 +_,7 @@
|
||||
@@ -60,6 +_,7 @@
|
||||
private boolean fading;
|
||||
private long fadeInStart;
|
||||
private final LogoRenderer logoRenderer;
|
||||
@@ -8,32 +8,32 @@
|
||||
|
||||
public TitleScreen() {
|
||||
this(false);
|
||||
@@ -111,11 +_,15 @@
|
||||
@@ -115,11 +_,15 @@
|
||||
int j = this.width - i - 2;
|
||||
int k = 24;
|
||||
int l = this.height / 4 + 48;
|
||||
+ Button modButton = null;
|
||||
if (this.minecraft.isDemo()) {
|
||||
l = this.createDemoMenuOptions(l, 24);
|
||||
this.createDemoMenuOptions(l, 24);
|
||||
} else {
|
||||
l = this.createNormalMenuOptions(l, 24);
|
||||
this.createNormalMenuOptions(l, 24);
|
||||
+ modButton = this.addRenderableWidget(Button.builder(Component.translatable("fml.menu.mods"), button -> this.minecraft.setScreen(new net.minecraftforge.client.gui.ModListScreen(this)))
|
||||
+ .pos(this.width / 2 - 100, l).size(98, 20).build());
|
||||
+ .pos(this.width / 2 - 100, l + 24 * 2).size(98, 20).build());
|
||||
}
|
||||
+ modUpdateNotification = net.minecraftforge.client.gui.TitleScreenModUpdateIndicator.init(this, modButton);
|
||||
|
||||
l = this.createTestWorldButton(l, 24);
|
||||
SpriteIconButton spriteiconbutton = this.addRenderableWidget(
|
||||
@@ -180,7 +_,7 @@
|
||||
}).bounds(this.width / 2 - 100, i = p_96764_ + p_96765_, 200, 20).tooltip(tooltip).build()).active = flag;
|
||||
CommonButtons.language(
|
||||
@@ -170,7 +_,7 @@
|
||||
}).bounds(this.width / 2 - 100, p_96764_ + p_96765_ * 1, 200, 20).tooltip(tooltip).build()).active = flag;
|
||||
this.addRenderableWidget(
|
||||
Button.builder(Component.translatable("menu.online"), p_325369_ -> this.minecraft.setScreen(new RealmsMainScreen(this)))
|
||||
- .bounds(this.width / 2 - 100, p_96764_ = i + p_96765_, 200, 20)
|
||||
+ .bounds(this.width / 2 + 2, p_96764_ = i + p_96765_, 98, 20)
|
||||
- .bounds(this.width / 2 - 100, p_96764_ + p_96765_ * 2, 200, 20)
|
||||
+ .bounds(this.width / 2 + 2, p_96764_ + p_96765_ * 2, 98, 20)
|
||||
.tooltip(tooltip)
|
||||
.build()
|
||||
)
|
||||
@@ -289,6 +_,7 @@
|
||||
@@ -276,6 +_,7 @@
|
||||
if ((i & -67108864) != 0) {
|
||||
super.render(p_282860_, p_281753_, p_283539_, p_282628_);
|
||||
this.logoRenderer.renderLogo(p_282860_, this.width, f);
|
||||
@@ -41,7 +41,7 @@
|
||||
if (this.splash != null && !this.minecraft.options.hideSplashTexts().get()) {
|
||||
this.splash.render(p_282860_, this.width, this.font, i);
|
||||
}
|
||||
@@ -304,10 +_,18 @@
|
||||
@@ -291,11 +_,19 @@
|
||||
s = s + I18n.get("menu.modded");
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
+ );
|
||||
+
|
||||
if (this.realmsNotificationsEnabled() && f >= 1.0F) {
|
||||
RenderSystem.enableDepthTest();
|
||||
this.realmsNotificationsScreen.render(p_282860_, p_281753_, p_283539_, p_282628_);
|
||||
}
|
||||
+ if (f >= 1.0f) this.modUpdateNotification.render(p_282860_, p_281753_, p_283539_, p_282628_);
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
|
||||
@@ -39,6 +_,7 @@
|
||||
@@ -37,6 +_,7 @@
|
||||
private int maxY = Integer.MIN_VALUE;
|
||||
private float fade;
|
||||
private boolean centered;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public AdvancementTab(
|
||||
Minecraft p_97145_, AdvancementsScreen p_97146_, AdvancementTabType p_97147_, int p_97148_, AdvancementNode p_297568_, DisplayInfo p_97150_
|
||||
@@ -55,6 +_,15 @@
|
||||
@@ -53,6 +_,15 @@
|
||||
this.addWidget(this.root, p_297568_.holder());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
public AdvancementTabType getType() {
|
||||
return this.type;
|
||||
}
|
||||
@@ -148,8 +_,8 @@
|
||||
@@ -146,8 +_,8 @@
|
||||
return null;
|
||||
} else {
|
||||
for (AdvancementTabType advancementtabtype : AdvancementTabType.values()) {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTabType.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTabType.java
|
||||
@@ -70,6 +_,7 @@
|
||||
@@ -69,6 +_,7 @@
|
||||
5
|
||||
);
|
||||
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementsScreen.java
|
||||
@@ -51,6 +_,7 @@
|
||||
@@ -49,6 +_,7 @@
|
||||
@Nullable
|
||||
private AdvancementTab selectedTab;
|
||||
private boolean isScrolling;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public AdvancementsScreen(ClientAdvancements p_97340_) {
|
||||
this(p_97340_, null);
|
||||
@@ -64,6 +_,19 @@
|
||||
@@ -62,6 +_,19 @@
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
@@ -28,7 +28,7 @@
|
||||
this.layout.addTitleHeader(TITLE, this.font);
|
||||
this.tabs.clear();
|
||||
this.selectedTab = null;
|
||||
@@ -108,7 +_,7 @@
|
||||
@@ -106,7 +_,7 @@
|
||||
int j = (this.height - 140) / 2;
|
||||
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
@@ -37,8 +37,8 @@
|
||||
this.advancements.setSelectedTab(advancementtab.getRootNode().holder(), true);
|
||||
break;
|
||||
}
|
||||
@@ -181,10 +_,12 @@
|
||||
p_283395_.blit(RenderType::guiTextured, WINDOW_LOCATION, p_281890_, p_282532_, 0.0F, 0.0F, 252, 140, 256, 256);
|
||||
@@ -180,10 +_,12 @@
|
||||
p_283395_.blit(WINDOW_LOCATION, p_281890_, p_282532_, 0, 0, 252, 140);
|
||||
if (this.tabs.size() > 1) {
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
+ if (advancementtab.getPage() == tabPage)
|
||||
@@ -50,11 +50,11 @@
|
||||
advancementtab1.drawIcon(p_283395_, p_281890_, p_282532_);
|
||||
}
|
||||
}
|
||||
@@ -202,6 +_,7 @@
|
||||
@@ -203,6 +_,7 @@
|
||||
|
||||
if (this.tabs.size() > 1) {
|
||||
for (AdvancementTab advancementtab : this.tabs.values()) {
|
||||
+ if (advancementtab.getPage() == tabPage)
|
||||
if (advancementtab.isMouseOver(p_281519_, p_283371_, p_283556_, p_282458_)) {
|
||||
if (advancementtab.isMouseOver(p_281519_, p_283371_, (double)p_283556_, (double)p_282458_)) {
|
||||
p_282784_.renderTooltip(this.font, advancementtab.getTitle(), p_283556_, p_282458_);
|
||||
}
|
||||
+57
-34
@@ -1,32 +1,49 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/AbstractContainerScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/AbstractContainerScreen.java
|
||||
@@ -106,6 +_,7 @@
|
||||
@@ -92,6 +_,7 @@
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
super.render(p_283479_, p_283661_, p_281248_, p_281886_);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onContainerRenderBackground(this, p_283479_, p_283661_, p_281248_);
|
||||
RenderSystem.disableDepthTest();
|
||||
p_283479_.pose().pushPose();
|
||||
p_283479_.pose().translate(i, j, 0.0F);
|
||||
Slot slot = this.hoveredSlot;
|
||||
@@ -117,6 +_,8 @@
|
||||
this.onStopHovering(slot);
|
||||
}
|
||||
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onContainerRenderForeground(this, p_283479_, p_283661_, p_281248_);
|
||||
+
|
||||
this.renderLabels(p_283479_, p_283661_, p_281248_);
|
||||
ItemStack itemstack = this.draggingItem.isEmpty() ? this.menu.getCarried() : this.draggingItem;
|
||||
if (!itemstack.isEmpty()) {
|
||||
@@ -197,7 +_,7 @@
|
||||
ItemStack itemstack = this.hoveredSlot.getItem();
|
||||
if (this.menu.getCarried().isEmpty() || this.showTooltipWithItemInHand(itemstack)) {
|
||||
p_283594_.renderTooltip(
|
||||
- this.font, this.getTooltipFromContainerItem(itemstack), itemstack.getTooltipImage(), p_282171_, p_281909_, itemstack.get(DataComponents.TOOLTIP_STYLE)
|
||||
+ this.font, this.getTooltipFromContainerItem(itemstack), itemstack.getTooltipImage(), itemstack, p_282171_, p_281909_
|
||||
);
|
||||
p_283479_.pose().translate((float)i, (float)j, 0.0F);
|
||||
@@ -108,12 +_,13 @@
|
||||
int l = slot.x;
|
||||
int i1 = slot.y;
|
||||
if (this.hoveredSlot.isHighlightable()) {
|
||||
- renderSlotHighlight(p_283479_, l, i1, 0);
|
||||
+ renderSlotHighlight(p_283479_, l, i1, 0, getSlotColor(k));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +_,8 @@
|
||||
|
||||
this.renderLabels(p_283479_, p_283661_, p_281248_);
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onContainerRenderForeground(this, p_283479_, p_283661_, p_281248_);
|
||||
ItemStack itemstack = this.draggingItem.isEmpty() ? this.menu.getCarried() : this.draggingItem;
|
||||
if (!itemstack.isEmpty()) {
|
||||
int l1 = 8;
|
||||
@@ -156,13 +_,17 @@
|
||||
}
|
||||
|
||||
public static void renderSlotHighlight(GuiGraphics p_283692_, int p_281453_, int p_281915_, int p_283504_) {
|
||||
- p_283692_.fillGradient(RenderType.guiOverlay(), p_281453_, p_281915_, p_281453_ + 16, p_281915_ + 16, -2130706433, -2130706433, p_283504_);
|
||||
+ renderSlotHighlight(p_283692_, p_281453_, p_281915_, p_283504_, -2130706433);
|
||||
+ }
|
||||
+
|
||||
+ public static void renderSlotHighlight(GuiGraphics p_283692_, int p_281453_, int p_281915_, int p_283504_, int color) {
|
||||
+ p_283692_.fillGradient(RenderType.guiOverlay(), p_281453_, p_281915_, p_281453_ + 16, p_281915_ + 16, color, color, p_283504_);
|
||||
}
|
||||
|
||||
protected void renderTooltip(GuiGraphics p_283594_, int p_282171_, int p_281909_) {
|
||||
if (this.menu.getCarried().isEmpty() && this.hoveredSlot != null && this.hoveredSlot.hasItem()) {
|
||||
ItemStack itemstack = this.hoveredSlot.getItem();
|
||||
- p_283594_.renderTooltip(this.font, this.getTooltipFromContainerItem(itemstack), itemstack.getTooltipImage(), p_282171_, p_281909_);
|
||||
+ p_283594_.renderTooltip(this.font, this.getTooltipFromContainerItem(itemstack), itemstack.getTooltipImage(), itemstack, p_282171_, p_281909_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +_,8 @@
|
||||
p_282567_.pose().pushPose();
|
||||
p_282567_.pose().translate(0.0F, 0.0F, 232.0F);
|
||||
p_282567_.renderItem(p_281330_, p_281772_, p_281689_);
|
||||
@@ -36,17 +53,17 @@
|
||||
p_282567_.pose().popPose();
|
||||
}
|
||||
|
||||
@@ -321,7 +_,8 @@
|
||||
@@ -282,7 +_,8 @@
|
||||
if (super.mouseClicked(p_97748_, p_97749_, p_97750_)) {
|
||||
return true;
|
||||
} else {
|
||||
- boolean flag = this.minecraft.options.keyPickItem.matchesMouse(p_97750_) && this.minecraft.player.hasInfiniteMaterials();
|
||||
- boolean flag = this.minecraft.options.keyPickItem.matchesMouse(p_97750_) && this.minecraft.gameMode.hasInfiniteItems();
|
||||
+ InputConstants.Key mouseKey = InputConstants.Type.MOUSE.getOrCreate(p_97750_);
|
||||
+ boolean flag = this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey);
|
||||
Slot slot = this.getHoveredSlot(p_97748_, p_97749_);
|
||||
Slot slot = this.findSlot(p_97748_, p_97749_);
|
||||
long i = Util.getMillis();
|
||||
this.doubleclick = this.lastClickSlot == slot && i - this.lastClickTime < 250L && this.lastClickButton == p_97750_;
|
||||
@@ -332,6 +_,7 @@
|
||||
@@ -293,6 +_,7 @@
|
||||
int j = this.leftPos;
|
||||
int k = this.topPos;
|
||||
boolean flag1 = this.hasClickedOutside(p_97748_, p_97749_, j, k, p_97750_);
|
||||
@@ -54,7 +71,7 @@
|
||||
int l = -1;
|
||||
if (slot != null) {
|
||||
l = slot.index;
|
||||
@@ -357,7 +_,7 @@
|
||||
@@ -318,7 +_,7 @@
|
||||
}
|
||||
} else if (!this.isQuickCrafting) {
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
@@ -63,7 +80,7 @@
|
||||
this.slotClicked(slot, l, p_97750_, ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag2 = l != -999
|
||||
@@ -385,7 +_,7 @@
|
||||
@@ -346,7 +_,7 @@
|
||||
this.quickCraftingType = 0;
|
||||
} else if (p_97750_ == 1) {
|
||||
this.quickCraftingType = 1;
|
||||
@@ -72,12 +89,12 @@
|
||||
this.quickCraftingType = 2;
|
||||
}
|
||||
}
|
||||
@@ -461,10 +_,13 @@
|
||||
@@ -425,10 +_,13 @@
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double p_97812_, double p_97813_, int p_97814_) {
|
||||
+ super.mouseReleased(p_97812_, p_97813_, p_97814_); //Forge, Call parent to release buttons
|
||||
Slot slot = this.getHoveredSlot(p_97812_, p_97813_);
|
||||
Slot slot = this.findSlot(p_97812_, p_97813_);
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
boolean flag = this.hasClickedOutside(p_97812_, p_97813_, i, j, p_97814_);
|
||||
@@ -86,7 +103,7 @@
|
||||
int k = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
@@ -481,7 +_,7 @@
|
||||
@@ -445,7 +_,7 @@
|
||||
if (slot2 != null
|
||||
&& slot2.mayPickup(this.minecraft.player)
|
||||
&& slot2.hasItem()
|
||||
@@ -95,7 +112,7 @@
|
||||
&& AbstractContainerMenu.canItemQuickReplace(slot2, this.lastQuickMoved, true)) {
|
||||
this.slotClicked(slot2, slot2.index, p_97814_, ClickType.QUICK_MOVE);
|
||||
}
|
||||
@@ -545,7 +_,7 @@
|
||||
@@ -509,7 +_,7 @@
|
||||
|
||||
this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(2, this.quickCraftingType), ClickType.QUICK_CRAFT);
|
||||
} else if (!this.menu.getCarried().isEmpty()) {
|
||||
@@ -104,7 +121,7 @@
|
||||
this.slotClicked(slot, k, p_97814_, ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag1 = k != -999
|
||||
@@ -622,9 +_,10 @@
|
||||
@@ -568,9 +_,10 @@
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int p_97765_, int p_97766_, int p_97767_) {
|
||||
@@ -116,10 +133,11 @@
|
||||
this.onClose();
|
||||
return true;
|
||||
} else {
|
||||
@@ -698,4 +_,11 @@
|
||||
|
||||
@@ -639,5 +_,17 @@
|
||||
public void onClose() {
|
||||
this.minecraft.player.closeContainer();
|
||||
super.onClose();
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ @org.jetbrains.annotations.Nullable
|
||||
+ public Slot getSlotUnderMouse() { return this.hoveredSlot; }
|
||||
@@ -127,4 +145,9 @@
|
||||
+ public int getGuiTop() { return topPos; }
|
||||
+ public int getXSize() { return imageWidth; }
|
||||
+ public int getYSize() { return imageHeight; }
|
||||
+
|
||||
+ protected int slotColor = -2130706433;
|
||||
+ public int getSlotColor(int index) {
|
||||
+ return slotColor;
|
||||
}
|
||||
}
|
||||
+44
-36
@@ -1,15 +1,15 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
|
||||
@@ -114,6 +_,8 @@
|
||||
@@ -112,6 +_,8 @@
|
||||
private boolean hasClickedOutside;
|
||||
private final Set<TagKey<Item>> visibleTags = new HashSet<>();
|
||||
private final boolean displayOperatorCreativeTab;
|
||||
private final EffectsInInventory effects;
|
||||
+ private final List<net.minecraftforge.client.gui.CreativeTabsScreenPage> pages = new java.util.ArrayList<>();
|
||||
+ private net.minecraftforge.client.gui.CreativeTabsScreenPage currentPage = new net.minecraftforge.client.gui.CreativeTabsScreenPage(new java.util.ArrayList<>());
|
||||
|
||||
public CreativeModeInventoryScreen(LocalPlayer p_344408_, FeatureFlagSet p_260074_, boolean p_259569_) {
|
||||
super(new CreativeModeInventoryScreen.ItemPickerMenu(p_344408_), p_344408_.getInventory(), CommonComponents.EMPTY);
|
||||
@@ -162,7 +_,7 @@
|
||||
@@ -159,7 +_,7 @@
|
||||
private void refreshCurrentTabContents(Collection<ItemStack> p_261591_) {
|
||||
int i = this.menu.getRowIndexForScroll(this.scrollOffs);
|
||||
this.menu.items.clear();
|
||||
@@ -18,9 +18,9 @@
|
||||
this.refreshSearchResults();
|
||||
} else {
|
||||
this.menu.items.addAll(p_261591_);
|
||||
@@ -330,6 +_,35 @@
|
||||
@@ -322,6 +_,35 @@
|
||||
protected void init() {
|
||||
if (this.minecraft.player.hasInfiniteMaterials()) {
|
||||
if (this.minecraft.gameMode.hasInfiniteItems()) {
|
||||
super.init();
|
||||
+ this.pages.clear();
|
||||
+ int tabIndex = 0;
|
||||
@@ -54,7 +54,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);
|
||||
@@ -376,7 +_,7 @@
|
||||
@@ -368,7 +_,7 @@
|
||||
public boolean charTyped(char p_98521_, int p_98522_) {
|
||||
if (this.ignoreTextInput) {
|
||||
return false;
|
||||
@@ -63,7 +63,7 @@
|
||||
return false;
|
||||
} else {
|
||||
String s = this.searchBox.getValue();
|
||||
@@ -395,7 +_,7 @@
|
||||
@@ -387,7 +_,7 @@
|
||||
@Override
|
||||
public boolean keyPressed(int p_98547_, int p_98548_, int p_98549_) {
|
||||
this.ignoreTextInput = false;
|
||||
@@ -72,7 +72,7 @@
|
||||
if (this.minecraft.options.keyChat.matches(p_98547_, p_98548_)) {
|
||||
this.ignoreTextInput = true;
|
||||
this.selectTab(CreativeModeTabs.searchTab());
|
||||
@@ -431,6 +_,7 @@
|
||||
@@ -423,6 +_,7 @@
|
||||
}
|
||||
|
||||
private void refreshSearchResults() {
|
||||
@@ -80,7 +80,7 @@
|
||||
this.menu.items.clear();
|
||||
this.visibleTags.clear();
|
||||
String s = this.searchBox.getValue();
|
||||
@@ -443,10 +_,10 @@
|
||||
@@ -435,10 +_,10 @@
|
||||
SearchTree<ItemStack> searchtree;
|
||||
if (s.startsWith("#")) {
|
||||
s = s.substring(1);
|
||||
@@ -93,27 +93,27 @@
|
||||
}
|
||||
|
||||
this.menu.items.addAll(searchtree.search(s.toLowerCase(Locale.ROOT)));
|
||||
@@ -478,7 +_,8 @@
|
||||
@@ -466,7 +_,8 @@
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics p_283168_, int p_281774_, int p_281466_) {
|
||||
if (selectedTab.showTitle()) {
|
||||
- p_283168_.drawString(this.font, selectedTab.getDisplayName(), 8, 6, 4210752, false);
|
||||
+ com.mojang.blaze3d.opengl.GlStateManager._disableBlend();
|
||||
+ com.mojang.blaze3d.systems.RenderSystem.disableBlend();
|
||||
+ p_283168_.drawString(this.font, selectedTab.getDisplayName(), 8, 6, selectedTab.getLabelColor(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,7 +_,7 @@
|
||||
double d0 = p_98531_ - this.leftPos;
|
||||
double d1 = p_98532_ - this.topPos;
|
||||
@@ -476,7 +_,7 @@
|
||||
double d0 = p_98531_ - (double)this.leftPos;
|
||||
double d1 = p_98532_ - (double)this.topPos;
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ for (CreativeModeTab creativemodetab : currentPage.getVisibleTabs()) {
|
||||
if (this.checkTabClicked(creativemodetab, d0, d1)) {
|
||||
return true;
|
||||
}
|
||||
@@ -510,7 +_,7 @@
|
||||
double d1 = p_98623_ - this.topPos;
|
||||
@@ -498,7 +_,7 @@
|
||||
double d1 = p_98623_ - (double)this.topPos;
|
||||
this.scrolling = false;
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
@@ -121,7 +121,15 @@
|
||||
if (this.checkTabClicked(creativemodetab, d0, d1)) {
|
||||
this.selectTab(creativemodetab);
|
||||
return true;
|
||||
@@ -604,13 +_,15 @@
|
||||
@@ -516,6 +_,7 @@
|
||||
private void selectTab(CreativeModeTab p_98561_) {
|
||||
CreativeModeTab creativemodetab = selectedTab;
|
||||
selectedTab = p_98561_;
|
||||
+ slotColor = p_98561_.getSlotColor();
|
||||
this.quickCraftSlots.clear();
|
||||
this.menu.items.clear();
|
||||
this.clearDraggingState();
|
||||
@@ -592,13 +_,15 @@
|
||||
this.originalSlots = null;
|
||||
}
|
||||
|
||||
@@ -138,9 +146,9 @@
|
||||
|
||||
this.refreshSearchResults();
|
||||
} else {
|
||||
@@ -673,7 +_,15 @@
|
||||
@@ -661,7 +_,15 @@
|
||||
public void render(GuiGraphics p_283000_, int p_281317_, int p_282770_, float p_281295_) {
|
||||
super.render(p_283000_, p_281317_, p_282770_, p_281295_);
|
||||
this.effects.render(p_283000_, p_281317_, p_282770_, p_281295_);
|
||||
|
||||
- for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
+ if (this.pages.size() != 1) {
|
||||
@@ -155,7 +163,7 @@
|
||||
if (this.checkTabHovering(p_283000_, creativemodetab, p_281317_, p_282770_)) {
|
||||
break;
|
||||
}
|
||||
@@ -685,6 +_,7 @@
|
||||
@@ -673,6 +_,7 @@
|
||||
p_283000_.renderTooltip(this.font, TRASH_SLOT_TOOLTIP, p_281317_, p_282770_);
|
||||
}
|
||||
|
||||
@@ -163,7 +171,7 @@
|
||||
this.renderTooltip(p_283000_, p_281317_, p_282770_);
|
||||
}
|
||||
|
||||
@@ -697,7 +_,7 @@
|
||||
@@ -680,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;
|
||||
@@ -172,16 +180,16 @@
|
||||
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);
|
||||
@@ -718,7 +_,7 @@
|
||||
@@ -699,7 +_,7 @@
|
||||
int i = 1;
|
||||
|
||||
for (CreativeModeTab creativemodetab : CreativeModeTabs.tabs()) {
|
||||
- if (creativemodetab.getType() != CreativeModeTab.Type.SEARCH && creativemodetab.contains(p_281769_)) {
|
||||
+ if (creativemodetab.hasSearchBar() && creativemodetab.contains(p_281769_)) {
|
||||
+ if (!creativemodetab.hasSearchBar() && creativemodetab.contains(p_281769_)) {
|
||||
list1.add(i++, creativemodetab.getDisplayName().copy().withStyle(ChatFormatting.BLUE));
|
||||
}
|
||||
}
|
||||
@@ -729,7 +_,7 @@
|
||||
@@ -710,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics p_282663_, float p_282504_, int p_282089_, int p_282249_) {
|
||||
@@ -190,15 +198,15 @@
|
||||
if (creativemodetab != selectedTab) {
|
||||
this.renderTabButton(p_282663_, creativemodetab);
|
||||
}
|
||||
@@ -745,6 +_,7 @@
|
||||
p_282663_.blitSprite(RenderType::guiTextured, resourcelocation, j, k + (int)((i - k - 17) * this.scrollOffs), 12, 15);
|
||||
@@ -726,6 +_,7 @@
|
||||
p_282663_.blitSprite(resourcelocation, j, k + (int)((float)(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);
|
||||
if (selectedTab.getType() == CreativeModeTab.Type.INVENTORY) {
|
||||
InventoryScreen.renderEntityInInventoryFollowsMouse(
|
||||
@@ -763,7 +_,7 @@
|
||||
@@ -744,7 +_,7 @@
|
||||
}
|
||||
|
||||
private int getTabX(CreativeModeTab p_260136_) {
|
||||
@@ -207,7 +215,7 @@
|
||||
int j = 27;
|
||||
int k = 27 * i;
|
||||
if (p_260136_.isAlignedRight()) {
|
||||
@@ -775,7 +_,7 @@
|
||||
@@ -756,7 +_,7 @@
|
||||
|
||||
private int getTabY(CreativeModeTab p_260181_) {
|
||||
int i = 0;
|
||||
@@ -216,7 +224,7 @@
|
||||
i -= 32;
|
||||
} else {
|
||||
i += this.imageHeight;
|
||||
@@ -803,8 +_,8 @@
|
||||
@@ -784,8 +_,8 @@
|
||||
|
||||
protected void renderTabButton(GuiGraphics p_283590_, CreativeModeTab p_283489_) {
|
||||
boolean flag = p_283489_ == selectedTab;
|
||||
@@ -227,15 +235,15 @@
|
||||
int j = this.leftPos + this.getTabX(p_283489_);
|
||||
int k = this.topPos - (flag1 ? 28 : -(this.imageHeight - 4));
|
||||
ResourceLocation[] aresourcelocation;
|
||||
@@ -814,6 +_,7 @@
|
||||
@@ -795,6 +_,7 @@
|
||||
aresourcelocation = flag ? SELECTED_BOTTOM_TABS : UNSELECTED_BOTTOM_TABS;
|
||||
}
|
||||
|
||||
+ com.mojang.blaze3d.opengl.GlStateManager._enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
|
||||
p_283590_.blitSprite(RenderType::guiTextured, aresourcelocation[Mth.clamp(i, 0, aresourcelocation.length)], j, k, 26, 32);
|
||||
+ com.mojang.blaze3d.systems.RenderSystem.enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
|
||||
p_283590_.blitSprite(aresourcelocation[Mth.clamp(i, 0, aresourcelocation.length)], j, k, 26, 32);
|
||||
p_283590_.pose().pushPose();
|
||||
p_283590_.pose().translate(0.0F, 0.0F, 100.0F);
|
||||
@@ -855,6 +_,14 @@
|
||||
@@ -836,6 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +258,7 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
static class CustomCreativeSlot extends Slot {
|
||||
public CustomCreativeSlot(Container p_98633_, int p_98634_, int p_98635_, int p_98636_) {
|
||||
@@ -1036,6 +_,22 @@
|
||||
@@ -1020,6 +_,22 @@
|
||||
@Override
|
||||
public boolean mayPickup(Player p_98665_) {
|
||||
return this.target.mayPickup(p_98665_);
|
||||
@@ -267,8 +275,8 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Slot setBackground(ResourceLocation sprite) {
|
||||
+ this.target.setBackground(sprite);
|
||||
+ public Slot setBackground(ResourceLocation atlas, ResourceLocation sprite) {
|
||||
+ this.target.setBackground(atlas, sprite);
|
||||
+ return this;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-28
@@ -1,10 +1,10 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EffectsInInventory.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EffectsInInventory.java
|
||||
@@ -48,12 +_,16 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EffectRenderingInventoryScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EffectRenderingInventoryScreen.java
|
||||
@@ -47,12 +_,16 @@
|
||||
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);
|
||||
+ var event = net.minecraftforge.client.ForgeHooksClient.onScreenPotionSize(this, j, !flag, i);
|
||||
+ if (event.isCanceled()) return;
|
||||
+ flag = !event.isCompact();
|
||||
+ i = event.getHorizontalOffset();
|
||||
@@ -15,40 +15,30 @@
|
||||
|
||||
- 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);
|
||||
this.renderBackgrounds(p_281945_, i, k, iterable, flag);
|
||||
this.renderIcons(p_281945_, i, k, iterable, flag);
|
||||
if (flag) {
|
||||
@@ -99,6 +_,11 @@
|
||||
int i = this.screen.topPos;
|
||||
@@ -98,6 +_,11 @@
|
||||
int i = this.topPos;
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : p_361981_) {
|
||||
for (MobEffectInstance mobeffectinstance : p_282642_) {
|
||||
+ 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_;
|
||||
+ if (renderer.renderInventoryIcon(mobeffectinstance, this, p_282745_, p_282521_ + (p_281536_ ? 6 : 7), i, 0)) {
|
||||
+ i += p_282291_;
|
||||
+ continue;
|
||||
+ }
|
||||
Holder<MobEffect> holder = mobeffectinstance.getEffect();
|
||||
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.get(holder);
|
||||
p_367085_.blitSprite(RenderType::guiTextured, textureatlassprite, p_367644_ + (p_368681_ ? 6 : 7), i + 7, 18, 18);
|
||||
@@ -110,6 +_,11 @@
|
||||
int i = this.screen.topPos;
|
||||
p_282745_.blit(p_282521_ + (p_281536_ ? 6 : 7), i + 7, 0, 18, 18, textureatlassprite);
|
||||
@@ -109,6 +_,11 @@
|
||||
int i = this.topPos;
|
||||
|
||||
for (MobEffectInstance mobeffectinstance : p_365480_) {
|
||||
for (MobEffectInstance mobeffectinstance : p_281986_) {
|
||||
+ 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.renderInventoryText(mobeffectinstance, this, p_281462_, p_283484_, i, 0)) {
|
||||
+ i += p_282057_;
|
||||
+ continue;
|
||||
+ }
|
||||
Component component = this.getEffectName(mobeffectinstance);
|
||||
p_361851_.drawString(this.screen.getFont(), component, p_367468_ + 10 + 18, i + 6, 16777215);
|
||||
p_281462_.drawString(this.font, component, p_283484_ + 10 + 18, i + 6, 16777215);
|
||||
Component component1 = MobEffectUtil.formatDuration(mobeffectinstance, 1.0F, this.minecraft.level.tickRateManager().tickrate());
|
||||
@@ -125,5 +_,9 @@
|
||||
}
|
||||
|
||||
return mutablecomponent;
|
||||
+ }
|
||||
+
|
||||
+ public AbstractContainerScreen<?> getScreen() {
|
||||
+ return this.screen;
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -1,23 +1,23 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/EnchantmentScreen.java
|
||||
@@ -109,7 +_,7 @@
|
||||
@@ -111,7 +_,7 @@
|
||||
int l1 = 86 - this.font.width(s);
|
||||
FormattedText formattedtext = EnchantmentNames.getInstance().getRandomName(this.font, l1);
|
||||
int i2 = 6839882;
|
||||
- if ((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.hasInfiniteMaterials()) {
|
||||
+ if (((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.hasInfiniteMaterials()) || this.menu.enchantClue[l] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels{
|
||||
p_282430_.blitSprite(RenderType::guiTextured, ENCHANTMENT_SLOT_DISABLED_SPRITE, i1, j + 14 + 19 * l, 108, 19);
|
||||
p_282430_.blitSprite(RenderType::guiTextured, DISABLED_LEVEL_SPRITES[l], i1 + 1, j + 15 + 19 * l, 16, 16);
|
||||
p_282430_.drawWordWrap(this.font, formattedtext, j1, j + 16 + 19 * l, l1, (i2 & 16711422) >> 1, false);
|
||||
@@ -175,13 +_,16 @@
|
||||
- if ((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.getAbilities().instabuild) {
|
||||
+ if (((k < l + 1 || this.minecraft.player.experienceLevel < k1) && !this.minecraft.player.getAbilities().instabuild) || this.menu.enchantClue[l] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels{
|
||||
RenderSystem.enableBlend();
|
||||
p_282430_.blitSprite(ENCHANTMENT_SLOT_DISABLED_SPRITE, i1, j + 14 + 19 * l, 108, 19);
|
||||
p_282430_.blitSprite(DISABLED_LEVEL_SPRITES[l], i1 + 1, j + 15 + 19 * l, 16, 16);
|
||||
@@ -177,13 +_,16 @@
|
||||
.registryAccess()
|
||||
.lookupOrThrow(Registries.ENCHANTMENT)
|
||||
.get(this.menu.enchantClue[j]);
|
||||
.registryOrThrow(Registries.ENCHANTMENT)
|
||||
.getHolder(this.menu.enchantClue[j]);
|
||||
- if (!optional.isEmpty()) {
|
||||
+ {
|
||||
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 && l >= 0 && optional != null) {
|
||||
+ if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)p_282491_, (double)p_281953_) && k > 0) {
|
||||
List<Component> list = Lists.newArrayList();
|
||||
- list.add(Component.translatable("container.enchant.clue", Enchantment.getFullname(optional.get(), l)).withStyle(ChatFormatting.WHITE));
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/HangingSignEditScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/HangingSignEditScreen.java
|
||||
@@ -16,7 +_,7 @@
|
||||
@@ -15,7 +_,7 @@
|
||||
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;
|
||||
|
||||
+4
-5
@@ -1,17 +1,16 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
|
||||
@@ -232,6 +_,14 @@
|
||||
@@ -234,7 +_,12 @@
|
||||
p_281357_.renderItemDecorations(this.font, p_283466_, p_282403_, p_283601_);
|
||||
} 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);
|
||||
+ /*
|
||||
- p_281357_.renderItemDecorations(this.font, p_283466_, p_282403_ + 14, p_283601_, p_283466_.getCount() == 1 ? "1" : null);
|
||||
+ // Forge: fixes Forge-8806, code for count rendering taken from GuiGraphics#renderGuiItemDecorations
|
||||
+ p_281357_.pose().pushPose();
|
||||
+ p_281357_.pose().translate(0.0F, 0.0F, 200.0F);
|
||||
+ String count = p_283466_.getCount() == 1 ? "1" : String.valueOf(p_283466_.getCount());
|
||||
+ font.drawInBatch(count, (float) (p_282403_ + 14) + 19 - 2 - font.width(count), (float)p_283601_ + 6 + 3, 0xFFFFFF, true, p_281357_.pose().last().pose(), p_281357_.bufferSource(), net.minecraft.client.gui.Font.DisplayMode.NORMAL, 0, 15728880, false);
|
||||
+ p_281357_.pose().popPose();
|
||||
+ */
|
||||
p_281357_.pose().pushPose();
|
||||
p_281357_.pose().translate(0.0F, 0.0F, 300.0F);
|
||||
p_281357_.blitSprite(RenderType::guiTextured, DISCOUNT_STRIKETHRUOGH_SPRITE, p_282403_ + 7, p_283601_ + 12, 9, 2);
|
||||
p_281357_.blitSprite(DISCOUNT_STRIKETHRUOGH_SPRITE, p_282403_ + 7, p_283601_ + 12, 0, 9, 2);
|
||||
+8
-8
@@ -1,11 +1,11 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipComponent.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipComponent.java
|
||||
@@ -22,7 +_,7 @@
|
||||
case ClientActivePlayersTooltip.ActivePlayersTooltip clientactiveplayerstooltip$activeplayerstooltip -> new ClientActivePlayersTooltip(
|
||||
clientactiveplayerstooltip$activeplayerstooltip
|
||||
);
|
||||
- default -> throw new IllegalArgumentException("Unknown TooltipComponent");
|
||||
+ default -> net.minecraftforge.client.gui.ClientTooltipComponentManager.createClientTooltipComponent(p_169951_);
|
||||
});
|
||||
@@ -22,6 +_,8 @@
|
||||
} else if (p_169951_ instanceof ClientActivePlayersTooltip.ActivePlayersTooltip clientactiveplayerstooltip$activeplayerstooltip) {
|
||||
return new ClientActivePlayersTooltip(clientactiveplayerstooltip$activeplayerstooltip);
|
||||
} else {
|
||||
+ ClientTooltipComponent result = net.minecraftforge.client.gui.ClientTooltipComponentManager.createClientTooltipComponent(p_169951_);
|
||||
+ if (result != null) return result;
|
||||
throw new IllegalArgumentException("Unknown TooltipComponent");
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
--- a/net/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil.java
|
||||
+++ b/net/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil.java
|
||||
@@ -17,16 +_,21 @@
|
||||
private static final int BORDER_COLOR_BOTTOM = 1344798847;
|
||||
|
||||
public static void renderTooltipBackground(GuiGraphics p_282666_, int p_281901_, int p_281846_, int p_281559_, int p_283336_, int p_283422_) {
|
||||
+ renderTooltipBackground(p_282666_, p_281901_, p_281846_, p_281559_, p_283336_, p_283422_, BACKGROUND_COLOR, BACKGROUND_COLOR, BORDER_COLOR_TOP, BORDER_COLOR_BOTTOM);
|
||||
+ }
|
||||
+
|
||||
+ // Forge: Allow specifying colors for the inner border gradient and a gradient instead of a single color for the background and outer border
|
||||
+ public static void renderTooltipBackground(GuiGraphics p_282666_, int p_281901_, int p_281846_, int p_281559_, int p_283336_, int p_283422_, int backgroundTop, int backgroundBottom, int borderTop, int borderBottom) {
|
||||
int i = p_281901_ - 3;
|
||||
int j = p_281846_ - 3;
|
||||
int k = p_281559_ + 3 + 3;
|
||||
int l = p_283336_ + 3 + 3;
|
||||
- renderHorizontalLine(p_282666_, i, j - 1, k, p_283422_, -267386864);
|
||||
- renderHorizontalLine(p_282666_, i, j + l, k, p_283422_, -267386864);
|
||||
- renderRectangle(p_282666_, i, j, k, l, p_283422_, -267386864);
|
||||
- renderVerticalLine(p_282666_, i - 1, j, l, p_283422_, -267386864);
|
||||
- renderVerticalLine(p_282666_, i + k, j, l, p_283422_, -267386864);
|
||||
- renderFrameGradient(p_282666_, i, j + 1, k, l, p_283422_, 1347420415, 1344798847);
|
||||
+ renderHorizontalLine(p_282666_, i, j - 1, k, p_283422_, backgroundTop);
|
||||
+ renderHorizontalLine(p_282666_, i, j + l, k, p_283422_, backgroundBottom);
|
||||
+ renderRectangleGradient(p_282666_, i, j, k, l, p_283422_, backgroundTop, backgroundBottom);
|
||||
+ renderVerticalLineGradient(p_282666_, i - 1, j, l, p_283422_, backgroundTop, backgroundBottom);
|
||||
+ renderVerticalLineGradient(p_282666_, i + k, j, l, p_283422_, backgroundTop, backgroundBottom);
|
||||
+ renderFrameGradient(p_282666_, i, j + 1, k, l, p_283422_, borderTop, borderBottom);
|
||||
}
|
||||
|
||||
private static void renderFrameGradient(
|
||||
@@ -52,5 +_,9 @@
|
||||
|
||||
private static void renderRectangle(GuiGraphics p_281392_, int p_282294_, int p_283353_, int p_282640_, int p_281964_, int p_283211_, int p_282349_) {
|
||||
p_281392_.fill(p_282294_, p_283353_, p_282294_ + p_282640_, p_283353_ + p_281964_, p_283211_, p_282349_);
|
||||
+ }
|
||||
+
|
||||
+ private static void renderRectangleGradient(GuiGraphics p_281392_, int p_282294_, int p_283353_, int p_282640_, int p_281964_, int p_283211_, int p_282349_, int colorTo) {
|
||||
+ p_281392_.fillGradient(p_282294_, p_283353_, p_282294_ + p_282640_, p_283353_ + p_281964_, p_283211_, p_282349_, colorTo);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
+++ b/net/minecraft/client/gui/screens/multiplayer/ServerSelectionList.java
|
||||
@@ -371,6 +_,8 @@
|
||||
@@ -372,6 +_,8 @@
|
||||
this.screen.setTooltipForNextRenderPass(Lists.transform(this.onlinePlayersTooltip, Component::getVisualOrderText));
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -1,6 +1,18 @@
|
||||
--- a/net/minecraft/client/gui/screens/options/controls/KeyBindsList.java
|
||||
+++ b/net/minecraft/client/gui/screens/options/controls/KeyBindsList.java
|
||||
@@ -148,9 +_,10 @@
|
||||
@@ -69,6 +_,11 @@
|
||||
return 340;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ protected int getScrollbarPosition() {
|
||||
+ return super.getScrollbarPosition() + 20;
|
||||
+ }
|
||||
+
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class CategoryEntry extends KeyBindsList.Entry {
|
||||
final Component name;
|
||||
@@ -153,9 +_,10 @@
|
||||
this.name = p_343976_;
|
||||
this.changeButton = Button.builder(p_343976_, p_342196_ -> {
|
||||
KeyBindsList.this.keyBindsScreen.selectedKey = p_343088_;
|
||||
@@ -11,17 +23,16 @@
|
||||
+ .bounds(0, 0, 75 + 20 /* Forge: Add space */, 20)
|
||||
.createNarration(
|
||||
p_342179_ -> p_343088_.isUnbound()
|
||||
? Component.translatable("narrator.controls.unbound", p_343976_)
|
||||
@@ -158,7 +_,7 @@
|
||||
? Component.translatable("narrator.controls.unbound", p_343976_)
|
||||
@@ -163,6 +_,7 @@
|
||||
)
|
||||
.build();
|
||||
this.resetButton = Button.builder(RESET_BUTTON_TITLE, p_357685_ -> {
|
||||
- p_343088_.setKey(p_343088_.getDefaultKey());
|
||||
this.resetButton = Button.builder(RESET_BUTTON_TITLE, p_343650_ -> {
|
||||
+ this.key.setToDefault();
|
||||
KeyBindsList.this.minecraft.options.setKey(p_343088_, p_343088_.getDefaultKey());
|
||||
KeyBindsList.this.resetMappingAndUpdateButtons();
|
||||
}).bounds(0, 0, 50, 20).createNarration(p_344192_ -> Component.translatable("narrator.controls.reset", p_343976_)).build();
|
||||
this.refreshEntry();
|
||||
@@ -210,7 +_,7 @@
|
||||
@@ -215,7 +_,7 @@
|
||||
MutableComponent mutablecomponent = Component.empty();
|
||||
if (!this.key.isUnbound()) {
|
||||
for (KeyMapping keymapping : KeyBindsList.this.minecraft.options.keyMappings) {
|
||||
|
||||
+3
-3
@@ -9,15 +9,15 @@
|
||||
}
|
||||
|
||||
this.keyBindsList.resetMappingAndUpdateButtons();
|
||||
@@ -73,11 +_,12 @@
|
||||
@@ -73,11 +_,14 @@
|
||||
public boolean keyPressed(int p_342715_, int p_342862_, int p_345515_) {
|
||||
if (this.selectedKey != null) {
|
||||
if (p_342715_ == 256) {
|
||||
- this.selectedKey.setKey(InputConstants.UNKNOWN);
|
||||
+ this.selectedKey.setKeyModifierAndCode(null, InputConstants.UNKNOWN);
|
||||
this.options.setKey(this.selectedKey, InputConstants.UNKNOWN);
|
||||
} else {
|
||||
- this.selectedKey.setKey(InputConstants.getKey(p_342715_, p_342862_));
|
||||
+ this.selectedKey.setKeyModifierAndCode(null, InputConstants.getKey(p_342715_, p_342862_));
|
||||
this.options.setKey(this.selectedKey, InputConstants.getKey(p_342715_, p_342862_));
|
||||
}
|
||||
|
||||
+ if (p_342715_ == 256 || !net.minecraftforge.client.settings.KeyModifier.isKeyCodeModifier(this.selectedKey.getKey()))
|
||||
|
||||
+2
-2
@@ -6,6 +6,6 @@
|
||||
p_100014_.setSelected(null);
|
||||
- p_100015_.forEach(
|
||||
+ p_100015_.filter(PackSelectionModel.Entry::notHidden).forEach(
|
||||
p_389318_ -> {
|
||||
p_340813_ -> {
|
||||
TransferableSelectionList.PackEntry transferableselectionlist$packentry1 = new TransferableSelectionList.PackEntry(
|
||||
this.minecraft, p_100014_, p_389318_
|
||||
this.minecraft, p_100014_, p_340813_
|
||||
Loaded 100 of 1145 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user