mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 09:05:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef0e7bc17f | ||
|
|
ec7a098f81 | ||
|
|
ff25961a05 | ||
|
|
c999a2d4eb | ||
|
|
ce79df9716 | ||
|
|
eae9b9145d | ||
|
|
7f56986027 | ||
|
|
c6874bce67 | ||
|
|
aa11175f41 | ||
|
|
2730559ff3 | ||
|
|
e80c3402b7 | ||
|
|
837c259668 | ||
|
|
2e48910b4c | ||
|
|
70dd556db6 | ||
|
|
e44a558f37 | ||
|
|
1e154cbe3e | ||
|
|
d5c5df1b64 | ||
|
|
5e75de5eb7 | ||
|
|
ddb1e52e99 | ||
|
|
9e55363e2c | ||
|
|
219abfed22 | ||
|
|
6915753b5a | ||
|
|
1527738ddc | ||
|
|
18c806f1d0 | ||
|
|
47f7c68ed5 |
No files matched your search
+2
-3
@@ -4,7 +4,7 @@ import net.minecraftforge.gradleutils.PomUtils
|
||||
plugins {
|
||||
id 'net.minecraftforge.licenser' version '1.0.1'
|
||||
id 'com.github.ben-manes.versions' version '0.46.0'
|
||||
id 'net.minecraftforge.gradleutils' version '[2.3.0,2.4.0)'
|
||||
id 'net.minecraftforge.gradleutils' version '[2.6.4,2.7)'
|
||||
id 'eclipse'
|
||||
id 'de.undercouch.download' version '5.4.0'
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.22,6.2)' apply false
|
||||
@@ -16,8 +16,7 @@ plugins {
|
||||
Util.init() //Init all our extension methods!
|
||||
|
||||
ext {
|
||||
GIT_INFO = gradleutils.gitInfo
|
||||
VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, '[0-9]', MC_VERSION)
|
||||
VERSION = gitversion.getMCTagOffsetBranch(MC_VERSION)
|
||||
FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.ow2.asm:asm:9.7'
|
||||
implementation 'org.ow2.asm:asm-tree:9.7'
|
||||
implementation 'org.ow2.asm:asm:9.8'
|
||||
implementation 'org.ow2.asm:asm-tree:9.8'
|
||||
implementation 'net.minecraftforge:srgutils:0.5.10'
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
|
||||
+3
-3
@@ -71,7 +71,7 @@ sourceSets {
|
||||
}
|
||||
}
|
||||
|
||||
final String SPEC_VERSION = gradleutils.gitInfo.tag
|
||||
final String SPEC_VERSION = gitversion.info.tag
|
||||
|
||||
// The new versioning sceme is <MCVersion>-<ForgeMC>.<RB>.<CommitsSinceRB>
|
||||
// ForgeMC is a unique identifier for every MC version we have supported.
|
||||
@@ -148,7 +148,7 @@ dependencies {
|
||||
runtimeOnly(libs.bootstrap)
|
||||
runtimeOnly(libs.bootstrap.dev)
|
||||
|
||||
//annotationProcessor(libs.eventbus.validator)
|
||||
annotationProcessor(libs.eventbus.validator)
|
||||
}
|
||||
|
||||
tasks.named('extractRangeMap').configure {
|
||||
@@ -168,7 +168,7 @@ patcher {
|
||||
|
||||
runs {
|
||||
forge_client {
|
||||
property 'eventbus.checkTypesOnDispatch', 'true'
|
||||
property 'eventbus.api.strictRuntimeChecks', 'true'
|
||||
property 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll'
|
||||
|
||||
args '--launchTarget', 'forge_dev_client',
|
||||
|
||||
+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!
|
||||
|
||||
@@ -39,14 +39,13 @@ import java.util.jar.Manifest;
|
||||
public class ModFile implements IModFile {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final String jarVersion;
|
||||
private final ModFileFactory.ModFileInfoParser parser;
|
||||
private Map<String, Object> fileProperties;
|
||||
private List<IModLanguageProvider> loaders;
|
||||
private Throwable scanError;
|
||||
private final SecureJar jar;
|
||||
private final Type modFileType;
|
||||
private final IModProvider provider;
|
||||
private IModFileInfo modFileInfo;
|
||||
private final IModFileInfo modFileInfo;
|
||||
private ModFileScanData fileModFileScanData;
|
||||
private CompletableFuture<ModFileScanData> futureScanResult;
|
||||
private List<CoreModFile> coreMods;
|
||||
@@ -62,12 +61,11 @@ public class ModFile implements IModFile {
|
||||
public ModFile(final SecureJar jar, final IModProvider provider, final ModFileFactory.ModFileInfoParser parser, String type) {
|
||||
this.provider = provider;
|
||||
this.jar = jar;
|
||||
this.parser = parser;
|
||||
|
||||
var manifest = this.jar.moduleDataProvider().getManifest();
|
||||
modFileType = Type.valueOf(type);
|
||||
jarVersion = Optional.ofNullable(manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION)).orElse("0.0NONE");
|
||||
this.modFileInfo = ModFileParser.readModList(this, this.parser);
|
||||
this.modFileInfo = ModFileParser.readModList(this, parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +97,6 @@ public class ModFile implements IModFile {
|
||||
}
|
||||
|
||||
public boolean identifyMods() {
|
||||
this.modFileInfo = ModFileParser.readModList(this, this.parser);
|
||||
if (this.modFileInfo == null) return this.getType() != Type.MOD;
|
||||
LOGGER.debug(LogMarkers.LOADING,"Loading mod file {} with languages {}", this.getFilePath(), this.modFileInfo.requiredLanguageLoaders());
|
||||
this.coreMods = ModFileParser.getCoreMods(this);
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ public abstract class CommonLaunchHandler implements ILaunchHandlerService {
|
||||
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);
|
||||
protected static final LaunchType SERVER_GAMETEST = new LaunchType("server_gametest", "minecraft", "net.minecraft.gametest.Main", Dist.DEDICATED_SERVER, false);
|
||||
|
||||
protected void runTarget(String module, String target, final String[] arguments, final ModuleLayer layer) throws Throwable {
|
||||
var mod = layer.findModule(module).orElse(null);
|
||||
|
||||
@@ -96,14 +96,14 @@ public final class ForgeDevLocator extends AbstractModProvider implements IModLo
|
||||
|
||||
// Find resource directories for every mod in this group
|
||||
var paths = new LinkedHashSet<Path>();
|
||||
for (var modid : modids) {
|
||||
for (var modid : modids.stream().sorted().toList()) {
|
||||
var rsc = path.resolve(modid);
|
||||
if (Files.exists(rsc))
|
||||
paths.add(rsc);
|
||||
}
|
||||
|
||||
var root = memory.getPath(modids.iterator().next()); // use the first modid as our root
|
||||
buildModsToml(paths, modids, root);
|
||||
buildModsToml(paths, modids, root, pkg.startsWith("net/minecraftforge/debug/client/"));
|
||||
buildPackMeta(paths, root);
|
||||
moveModuleInfo(paths, root);
|
||||
|
||||
@@ -187,7 +187,7 @@ public final class ForgeDevLocator extends AbstractModProvider implements IModLo
|
||||
}
|
||||
|
||||
// Builds or update the mods.toml file for all @Mods in this package
|
||||
private static void buildModsToml(Set<Path> resources, Set<String> modids, Path root) {
|
||||
private static void buildModsToml(Set<Path> resources, Set<String> modids, Path root, boolean clientOnly) {
|
||||
var toml = resources.stream()
|
||||
.map(p -> p.resolve(MODS_TOML))
|
||||
.filter(Files::exists)
|
||||
@@ -205,7 +205,8 @@ public final class ForgeDevLocator extends AbstractModProvider implements IModLo
|
||||
var defaults = Map.of(
|
||||
"modLoader", "javafml",
|
||||
"loaderVersion", "[0,)",
|
||||
"license", "Doesnt fucking matter"
|
||||
"license", "Doesnt fucking matter",
|
||||
"clientSideOnly", clientOnly
|
||||
);
|
||||
|
||||
for (var key : defaults.keySet()) {
|
||||
|
||||
+3
-3
@@ -5,11 +5,11 @@ org.gradle.daemon=false
|
||||
org.gradle.parallel=true
|
||||
|
||||
JAVA_VERSION=21
|
||||
MC_VERSION=1.21.6
|
||||
MC_VERSION=1.21.8
|
||||
MC_NEXT_VERSION=1.22
|
||||
MCP_VERSION=20250618.020446
|
||||
MCP_VERSION=20250717.105350
|
||||
MAPPING_CHANNEL=official
|
||||
MAPPING_VERSION=1.21.6
|
||||
MAPPING_VERSION=1.21.8
|
||||
|
||||
# Set to true before the first build of a new MC version, so we don't do compatibility checks
|
||||
CHECK_COMPATIBILITY=false
|
||||
|
||||
+7
-2
@@ -152,6 +152,9 @@ public class AutomaticEventSubscriber {
|
||||
if (!Modifier.isStatic(method.getModifiers()))
|
||||
continue;
|
||||
|
||||
if (method.isSynthetic())
|
||||
continue; // EventBus#89
|
||||
|
||||
int paramCount = method.getParameterCount();
|
||||
if (paramCount == 0 || paramCount > 2)
|
||||
continue;
|
||||
@@ -187,8 +190,10 @@ public class AutomaticEventSubscriber {
|
||||
public static void registerStrict(BusGroup busGroup, Class<?> listenerClass) {
|
||||
Class<? extends Event> firstValidListenerEventType = null;
|
||||
|
||||
Method[] declaredMethods = listenerClass.getDeclaredMethods();
|
||||
if (declaredMethods.length == 0) {
|
||||
List<Method> declaredMethods = Arrays.stream(listenerClass.getDeclaredMethods())
|
||||
.filter(Predicate.not(Method::isSynthetic)) // EventBus#89
|
||||
.toList();
|
||||
if (declaredMethods.isEmpty()) {
|
||||
var errMsg = "No declared methods found in " + listenerClass.getName();
|
||||
var superClass = listenerClass.getSuperclass();
|
||||
if (superClass != null && superClass != Record.class && superClass != Enum.class) {
|
||||
|
||||
+1
-3
@@ -8,8 +8,6 @@ package net.minecraftforge.fml.mclanguageprovider;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MinecraftModContainer extends ModContainer {
|
||||
private static final String MCMODINSTANCE = "minecraft, the mod";
|
||||
|
||||
@@ -20,7 +18,7 @@ public class MinecraftModContainer extends ModContainer {
|
||||
|
||||
@Override
|
||||
public boolean matches(final Object mod) {
|
||||
return Objects.equals(mod, MCMODINSTANCE);
|
||||
return MCMODINSTANCE.equals(mod);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-3
@@ -10,7 +10,6 @@ import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
@@ -20,7 +19,7 @@ import java.util.function.Supplier;
|
||||
import static net.minecraftforge.fml.Logging.LOADING;
|
||||
|
||||
public class MinecraftModLanguageProvider implements IModLanguageProvider {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "minecraft";
|
||||
@@ -45,7 +44,7 @@ public class MinecraftModLanguageProvider implements IModLanguageProvider {
|
||||
final Class<?> mcModClass = Class.forName(getClass().getModule(), "net.minecraftforge.fml.mclanguageprovider.MinecraftModContainer");
|
||||
return (T)mcModClass.getConstructor(IModInfo.class).newInstance(info);
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
LOGGER.fatal(LOADING,"Unable to load MinecraftModContainer, wut?", e);
|
||||
LogManager.getLogger().fatal(LOADING, "Unable to load MinecraftModContainer, wut?", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ dependencies {
|
||||
// Forge 1.21.6+ uses EventBus 7, which shifts most of its runtime validation to compile-time via an annotation processor
|
||||
// to improve performance in production environments. This line is required to enable said compile-time validation
|
||||
// in your development environment, helping you catch issues early.
|
||||
annotationProcessor 'net.minecraftforge:eventbus-validator:7.0-beta.7'
|
||||
annotationProcessor 'net.minecraftforge:eventbus-validator:7.0-beta.10'
|
||||
|
||||
// Example mod dependency with JEI
|
||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/blaze3d/opengl/GlDevice.java
|
||||
+++ b/com/mojang/blaze3d/opengl/GlDevice.java
|
||||
@@ -88,8 +_,15 @@
|
||||
@@ -89,8 +_,15 @@
|
||||
public GpuTexture createTexture(
|
||||
@Nullable Supplier<String> p_397830_, int p_394481_, TextureFormat p_394839_, int p_391831_, int p_395609_, int p_407582_, int p_408928_
|
||||
) {
|
||||
@@ -17,7 +17,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,6 +_,15 @@
|
||||
@@ -98,6 +_,15 @@
|
||||
public GpuTexture createTexture(
|
||||
@Nullable String p_394142_, int p_395535_, TextureFormat p_394951_, int p_393944_, int p_392329_, int p_408015_, int p_406483_
|
||||
) {
|
||||
@@ -33,7 +33,7 @@
|
||||
if (p_406483_ < 1) {
|
||||
throw new IllegalArgumentException("mipLevels must be at least 1");
|
||||
} else if (p_408015_ < 1) {
|
||||
@@ -147,11 +_,14 @@
|
||||
@@ -148,11 +_,14 @@
|
||||
GlStateManager._texImage2D(
|
||||
k,
|
||||
l,
|
||||
@@ -48,7 +48,7 @@
|
||||
GlConst.toGlType(p_394951_),
|
||||
null
|
||||
);
|
||||
@@ -162,11 +_,14 @@
|
||||
@@ -163,11 +_,14 @@
|
||||
GlStateManager._texImage2D(
|
||||
j,
|
||||
i1,
|
||||
@@ -63,7 +63,7 @@
|
||||
GlConst.toGlType(p_394951_),
|
||||
null
|
||||
);
|
||||
@@ -179,7 +_,7 @@
|
||||
@@ -180,7 +_,7 @@
|
||||
} else if (j1 != 0) {
|
||||
throw new IllegalStateException("OpenGL error " + j1);
|
||||
} else {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
--- a/com/mojang/blaze3d/vertex/VertexFormat.java
|
||||
+++ b/com/mojang/blaze3d/vertex/VertexFormat.java
|
||||
@@ -18,7 +_,7 @@
|
||||
@@ -21,7 +_,7 @@
|
||||
|
||||
@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;
|
||||
@@ -29,6 +_,7 @@
|
||||
private static final boolean USE_STAGING_BUFFER_WORKAROUND = Util.getPlatform() == Util.OS.WINDOWS && Util.isAarch64();
|
||||
@Nullable
|
||||
@@ -35,6 +_,7 @@
|
||||
private GpuBuffer immediateDrawVertexBuffer;
|
||||
@Nullable
|
||||
private GpuBuffer immediateDrawIndexBuffer;
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
VertexFormat(List<VertexFormatElement> p_343616_, List<String> p_345241_, IntList p_345522_, int p_344162_) {
|
||||
this.elements = p_343616_;
|
||||
@@ -41,6 +_,11 @@
|
||||
@@ -47,6 +_,11 @@
|
||||
int j = vertexformatelement != null ? p_343616_.indexOf(vertexformatelement) : -1;
|
||||
this.offsetsByElement[i] = j != -1 ? p_345522_.getInt(j) : -1;
|
||||
}
|
||||
@@ -29,8 +29,8 @@
|
||||
}
|
||||
|
||||
public static VertexFormat.Builder builder() {
|
||||
@@ -138,6 +_,9 @@
|
||||
|
||||
@@ -169,6 +_,9 @@
|
||||
);
|
||||
return this.immediateDrawIndexBuffer;
|
||||
}
|
||||
+
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
+++ b/net/minecraft/client/data/models/ItemModelGenerators.java
|
||||
@@ -870,6 +_,9 @@
|
||||
@@ -871,6 +_,9 @@
|
||||
this.declareCustomModelItem(Items.COD);
|
||||
this.declareCustomModelItem(Items.FEATHER);
|
||||
this.declareCustomModelItem(Items.LEAD);
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
-public class Font {
|
||||
+public class Font implements net.minecraftforge.client.extensions.IForgeFont {
|
||||
private static final float EFFECT_DEPTH = 0.001F;
|
||||
private static final float OVER_EFFECT_DEPTH = 0.001F;
|
||||
private static final float UNDER_EFFECT_DEPTH = -0.001F;
|
||||
private static final float EFFECT_DEPTH = 0.01F;
|
||||
private static final float OVER_EFFECT_DEPTH = 0.01F;
|
||||
private static final float UNDER_EFFECT_DEPTH = -0.01F;
|
||||
@@ -9,6 +9,25 @@
|
||||
private final SubtitleOverlay subtitleOverlay;
|
||||
private final SpectatorGui spectatorGui;
|
||||
private final PlayerTabOverlay tabList;
|
||||
@@ -194,6 +_,7 @@
|
||||
() -> new JumpableVehicleBarRenderer(p_330021_)
|
||||
);
|
||||
this.resetTitleTimes();
|
||||
+ net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.init(this, p_330021_);
|
||||
}
|
||||
|
||||
public void resetTitleTimes() {
|
||||
@@ -204,6 +_,10 @@
|
||||
|
||||
public void render(GuiGraphics p_282884_, DeltaTracker p_342095_) {
|
||||
if (this.minecraft.screen == null || !(this.minecraft.screen instanceof ReceivingLevelScreen)) {
|
||||
+ if (Boolean.valueOf(true)) {
|
||||
+ net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.beginRender(p_282884_, p_342095_);
|
||||
+ return;
|
||||
+ }
|
||||
if (!this.minecraft.options.hideGui) {
|
||||
this.renderCameraOverlays(p_282884_, p_342095_);
|
||||
this.renderCrosshair(p_282884_, p_342095_);
|
||||
@@ -377,7 +_,7 @@
|
||||
int i = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window));
|
||||
int j = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window));
|
||||
@@ -38,7 +57,7 @@
|
||||
@@ -598,6 +_,10 @@
|
||||
}
|
||||
|
||||
private void renderSelectedItemName(GuiGraphics p_283501_) {
|
||||
public void renderSelectedItemName(GuiGraphics p_283501_) {
|
||||
+ renderSelectedItemName(p_283501_, 0);
|
||||
+ }
|
||||
+
|
||||
@@ -71,7 +90,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1148,7 +_,7 @@
|
||||
@@ -1146,7 +_,7 @@
|
||||
ItemStack itemstack = this.minecraft.player.getInventory().getSelectedItem();
|
||||
if (itemstack.isEmpty()) {
|
||||
this.toolHighlightTimer = 0;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
private static final int EXTRA_SPACE_AFTER_FIRST_TOOLTIP_LINE = 2;
|
||||
private final Minecraft minecraft;
|
||||
private final Matrix3x2fStack pose;
|
||||
@@ -870,6 +_,7 @@
|
||||
@@ -875,6 +_,7 @@
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item");
|
||||
CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered");
|
||||
crashreportcategory.setDetail("Item Type", () -> String.valueOf(p_283653_.getItem()));
|
||||
@@ -17,7 +17,7 @@
|
||||
crashreportcategory.setDetail("Item Components", () -> String.valueOf(p_283653_.getComponents()));
|
||||
crashreportcategory.setDetail("Item Foil", () -> String.valueOf(p_283653_.hasFoil()));
|
||||
throw new ReportedException(crashreport);
|
||||
@@ -888,6 +_,7 @@
|
||||
@@ -893,6 +_,7 @@
|
||||
this.renderItemCooldown(p_283349_, p_282641_, p_282146_);
|
||||
this.renderItemCount(p_282005_, p_283349_, p_282641_, p_282146_, p_282803_);
|
||||
this.pose.popMatrix();
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -899,21 +_,30 @@
|
||||
@@ -904,21 +_,30 @@
|
||||
this.setTooltipForNextFrame(this.minecraft.font, p_407686_, DefaultTooltipPositioner.INSTANCE, p_410475_, p_407139_, false);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
this.setTooltipForNextFrameInternal(p_407847_, list, p_409369_, p_407472_, DefaultTooltipPositioner.INSTANCE, p_410303_, false);
|
||||
}
|
||||
|
||||
@@ -926,7 +_,22 @@
|
||||
@@ -931,7 +_,22 @@
|
||||
}
|
||||
|
||||
public void setComponentTooltipForNextFrame(Font p_406239_, List<Component> p_410275_, int p_410594_, int p_409343_) {
|
||||
@@ -82,7 +82,7 @@
|
||||
}
|
||||
|
||||
public void setComponentTooltipForNextFrame(Font p_408650_, List<Component> p_407512_, int p_406019_, int p_408123_, @Nullable ResourceLocation p_409993_) {
|
||||
@@ -989,11 +_,13 @@
|
||||
@@ -994,11 +_,13 @@
|
||||
ClientTooltipPositioner p_409451_,
|
||||
@Nullable ResourceLocation p_409298_
|
||||
) {
|
||||
@@ -97,7 +97,7 @@
|
||||
if (k > i) {
|
||||
i = k;
|
||||
}
|
||||
@@ -1003,16 +_,17 @@
|
||||
@@ -1008,16 +_,17 @@
|
||||
|
||||
int l1 = i;
|
||||
int i2 = j;
|
||||
@@ -118,7 +118,7 @@
|
||||
j1 += clienttooltipcomponent1.getHeight(p_283128_) + (k1 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -1020,7 +_,7 @@
|
||||
@@ -1025,7 +_,7 @@
|
||||
|
||||
for (int j2 = 0; j2 < p_282716_.size(); j2++) {
|
||||
ClientTooltipComponent clienttooltipcomponent2 = p_282716_.get(j2);
|
||||
@@ -127,3 +127,18 @@
|
||||
j1 += clienttooltipcomponent2.getHeight(p_283128_) + (j2 == 0 ? 2 : 0);
|
||||
}
|
||||
|
||||
@@ -1222,6 +_,14 @@
|
||||
|
||||
public void submitProfilerChartRenderState(List<ResultField> p_408565_, int p_410147_, int p_406156_, int p_407365_, int p_408180_) {
|
||||
this.guiRenderState.submitPicturesInPictureState(new GuiProfilerChartRenderState(p_408565_, p_410147_, p_406156_, p_407365_, p_408180_, this.scissorStack.peek()));
|
||||
+ }
|
||||
+
|
||||
+ public GuiRenderState getRenderState() {
|
||||
+ return this.guiRenderState;
|
||||
+ }
|
||||
+
|
||||
+ public GuiGraphics.ScissorStack getScissorStack() {
|
||||
+ return this.scissorStack;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/client/gui/render/GuiRenderer.java
|
||||
+++ b/net/minecraft/client/gui/render/GuiRenderer.java
|
||||
@@ -134,6 +_,7 @@
|
||||
builder.put((Class<? extends PictureInPictureRenderState>)pictureinpicturerenderer.getRenderStateClass(), pictureinpicturerenderer);
|
||||
}
|
||||
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onRegisterPictureInPictureRenderers(p_410565_, p_410441_, builder);
|
||||
this.pictureInPictureRenderers = builder.buildOrThrow();
|
||||
}
|
||||
|
||||
@@ -71,3 +71,11 @@
|
||||
SignableCommand<ClientSuggestionProvider> signablecommand = SignableCommand.of(this.commands.parse(p_250092_, this.suggestionsProvider));
|
||||
if (signablecommand.arguments().isEmpty()) {
|
||||
this.send(new ServerboundChatCommandPacket(p_250092_));
|
||||
@@ -2641,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void sendUnattendedCommand(String p_407213_, @Nullable Screen p_406262_) {
|
||||
+ if (net.minecraftforge.client.ClientCommandHandler.runCommand(p_407213_)) return;
|
||||
switch (this.verifyCommand(p_407213_)) {
|
||||
case NO_ISSUES:
|
||||
this.send(new ServerboundChatCommandPacket(p_407213_));
|
||||
@@ -9,6 +9,14 @@
|
||||
@Nullable
|
||||
private ClientLevel level;
|
||||
private final SectionOcclusionGraph sectionOcclusionGraph = new SectionOcclusionGraph();
|
||||
@@ -161,6 +_,7 @@
|
||||
this.entityRenderDispatcher = p_234246_;
|
||||
this.blockEntityRenderDispatcher = p_234247_;
|
||||
this.renderBuffers = p_234248_;
|
||||
+ net.minecraftforge.client.event.ForgeEventFactoryClient.onInitLevelRenderer();
|
||||
}
|
||||
|
||||
public void tickParticles(Camera p_369538_) {
|
||||
@@ -480,7 +_,7 @@
|
||||
postchain1.addToFrame(framegraphbuilder, i, j, this.targets);
|
||||
}
|
||||
@@ -18,6 +26,14 @@
|
||||
CloudStatus cloudstatus = this.minecraft.options.getCloudsType();
|
||||
if (cloudstatus != CloudStatus.OFF) {
|
||||
Optional<Integer> optional = this.level.dimensionType().cloudHeight();
|
||||
@@ -497,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.addLateDebugPass(framegraphbuilder, vec3, p_407881_);
|
||||
+ net.minecraftforge.client.FramePassManager.insertForgePasses(framegraphbuilder, targets); // Forge: Modded passes are inserted here.
|
||||
profilerfiller.popPush("framegraph");
|
||||
framegraphbuilder.execute(p_367325_, new FrameGraphBuilder.Inspector() {
|
||||
@Override
|
||||
@@ -577,7 +_,7 @@
|
||||
multibuffersource$buffersource.endLastBatch();
|
||||
this.checkPoseStack(posestack);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/renderer/texture/TextureAtlas.java
|
||||
+++ b/net/minecraft/client/renderer/texture/TextureAtlas.java
|
||||
@@ -88,6 +_,7 @@
|
||||
@@ -91,6 +_,7 @@
|
||||
this.sprites = List.copyOf(list);
|
||||
this.animatedTextures = List.copyOf(list1);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,5 +_,10 @@
|
||||
@@ -168,5 +_,10 @@
|
||||
|
||||
int getHeight() {
|
||||
return this.height;
|
||||
|
||||
@@ -37,16 +37,15 @@
|
||||
if (contextchain != null) {
|
||||
executeCommandInContext(
|
||||
commandsourcestack,
|
||||
@@ -395,8 +_,11 @@
|
||||
public void sendCommands(ServerPlayer p_82096_) {
|
||||
@@ -396,7 +_,10 @@
|
||||
Map<CommandNode<CommandSourceStack>, CommandNode<CommandSourceStack>> map = new HashMap<>();
|
||||
RootCommandNode<CommandSourceStack> rootcommandnode = new RootCommandNode<>();
|
||||
+ // FORGE: Clean any modded command content if the client is vanilla
|
||||
+ rootcommandnode = net.minecraftforge.server.command.CommandHelper.filterCommandList(p_82096_.connection.getConnection(), rootcommandnode);
|
||||
map.put(this.dispatcher.getRoot(), rootcommandnode);
|
||||
- fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, p_82096_.createCommandSourceStack(), map);
|
||||
+ // FORGE: Use our own command node merging method to handle redirect nodes properly, see issue #7551
|
||||
+ net.minecraftforge.server.command.CommandHelper.mergeCommandNode(this.dispatcher.getRoot(), rootcommandnode, map, p_82096_.createCommandSourceStack(), ctx -> 0, suggest -> suggest);
|
||||
+ // FORGE: Clean any modded command content if the client is vanilla
|
||||
+ rootcommandnode = net.minecraftforge.server.command.CommandHelper.filterCommandList(p_82096_.connection.getConnection(), rootcommandnode);
|
||||
p_82096_.connection.send(new ClientboundCommandsPacket(rootcommandnode, COMMAND_NODE_INSPECTOR));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/commands/SharedSuggestionProvider.java
|
||||
+++ b/net/minecraft/commands/SharedSuggestionProvider.java
|
||||
@@ -98,7 +_,7 @@
|
||||
p_82948_.accept(t);
|
||||
}
|
||||
} else if (matchesSubStr(p_82946_, resourcelocation.getNamespace())
|
||||
- || resourcelocation.getNamespace().equals("minecraft") && matchesSubStr(p_82946_, resourcelocation.getPath())) {
|
||||
+ || matchesSubStr(p_82946_, resourcelocation.getPath())) { // Forge: Removed "minecraft" namespace requirement for path searching to allow modded path suggestions to show up
|
||||
p_82948_.accept(t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/gametest/Main.java
|
||||
+++ b/net/minecraft/gametest/Main.java
|
||||
@@ -7,6 +_,8 @@
|
||||
public class Main {
|
||||
@DontObfuscate
|
||||
public static void main(String[] p_393417_) throws Exception {
|
||||
+ System.setProperty("forge.enableGameTest", "true");
|
||||
+ System.setProperty("forge.gameTestServer", "true");
|
||||
SharedConstants.tryDetectVersion();
|
||||
GameTestMainUtil.runGameTestServer(p_393417_, p_393535_ -> {});
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/gametest/framework/GameTestMainUtil.java
|
||||
+++ b/net/minecraft/gametest/framework/GameTestMainUtil.java
|
||||
@@ -69,6 +_,7 @@
|
||||
|
||||
Bootstrap.bootStrap();
|
||||
Util.startTimerHackThread();
|
||||
+ net.minecraftforge.server.loading.ServerModLoader.load();
|
||||
String s = optionset.valueOf(universe);
|
||||
createOrResetDir(s);
|
||||
p_393652_.accept(s);
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
public void handleBlockBreakAction(BlockPos p_215120_, ServerboundPlayerActionPacket.Action p_215121_, Direction p_215122_, int p_215123_, int p_215124_) {
|
||||
+ var event = net.minecraftforge.event.ForgeEventFactory.onLeftClickBlock(player, p_215120_, p_215122_, p_215121_);
|
||||
+ if (event == null || !this.isCreative()) {
|
||||
+ if (event == null) {
|
||||
+ return;
|
||||
+ }
|
||||
if (!this.player.canInteractWithBlock(p_215120_, 1.0)) {
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java
|
||||
@@ -84,7 +_,7 @@
|
||||
@@ -83,7 +_,7 @@
|
||||
this.timeInOverworld = 0;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
this.playConvertedSound();
|
||||
this.finishConversion(p_360786_);
|
||||
}
|
||||
@@ -103,7 +_,10 @@
|
||||
@@ -102,7 +_,10 @@
|
||||
this.convertTo(
|
||||
EntityType.ZOMBIFIED_PIGLIN,
|
||||
ConversionParams.single(this, true, true),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -321,7 +_,7 @@
|
||||
@@ -320,7 +_,7 @@
|
||||
@Override
|
||||
public InteractionResult mobInteract(Player p_35472_, InteractionHand p_35473_) {
|
||||
ItemStack itemstack = p_35472_.getItemInHand(p_35473_);
|
||||
@@ -9,7 +9,7 @@
|
||||
return super.mobInteract(p_35472_, p_35473_);
|
||||
} else if (this.isBaby()) {
|
||||
this.setUnhappy();
|
||||
@@ -767,7 +_,7 @@
|
||||
@@ -766,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public void thunderHit(ServerLevel p_35409_, LightningBolt p_35410_) {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
private Vec3 calculateHaltTrackSpeed(Vec3 p_364212_, BlockState p_362846_) {
|
||||
- if (p_362846_.is(Blocks.POWERED_RAIL) && !p_362846_.getValue(PoweredRailBlock.POWERED)) {
|
||||
+ if (p_362846_.getBlock() instanceof PoweredRailBlock && !p_362846_.getValue(PoweredRailBlock.POWERED)) {
|
||||
+ if (p_362846_.getBlock() instanceof PoweredRailBlock powered && !powered.isActivatorRail() && !p_362846_.getValue(PoweredRailBlock.POWERED)) {
|
||||
return p_364212_.length() < 0.03 ? Vec3.ZERO : p_364212_.scale(0.5);
|
||||
} else {
|
||||
return p_364212_;
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
private Vec3 calculateBoostTrackSpeed(Vec3 p_366761_, BlockPos p_361866_, BlockState p_368734_) {
|
||||
- if (p_368734_.is(Blocks.POWERED_RAIL) && p_368734_.getValue(PoweredRailBlock.POWERED)) {
|
||||
+ if (p_368734_.getBlock() instanceof PoweredRailBlock && p_368734_.getValue(PoweredRailBlock.POWERED)) {
|
||||
+ if (p_368734_.getBlock() instanceof PoweredRailBlock powered && !powered.isActivatorRail() && p_368734_.getValue(PoweredRailBlock.POWERED)) {
|
||||
if (p_366761_.length() > 0.01) {
|
||||
return p_366761_.normalize().scale(p_366761_.length() + 0.06);
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
boolean flag1 = false;
|
||||
- if (blockstate.is(Blocks.POWERED_RAIL)) {
|
||||
+ BaseRailBlock baserailblock = (BaseRailBlock)blockstate.getBlock();
|
||||
+ if (blockstate.getBlock() instanceof PoweredRailBlock) {
|
||||
+ if (blockstate.getBlock() instanceof PoweredRailBlock powered && !powered.isActivatorRail()) {
|
||||
flag = blockstate.getValue(PoweredRailBlock.POWERED);
|
||||
flag1 = !flag;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/item/Items.java
|
||||
+++ b/net/minecraft/world/item/Items.java
|
||||
@@ -2152,7 +_,25 @@
|
||||
@@ -2155,7 +_,25 @@
|
||||
}
|
||||
|
||||
public static Item registerBlock(Block p_252092_, Block... p_248886_) {
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
for (Block block : p_248886_) {
|
||||
Item.BY_BLOCK.put(block, item);
|
||||
@@ -2191,10 +_,6 @@
|
||||
@@ -2194,10 +_,6 @@
|
||||
|
||||
public static Item registerItem(ResourceKey<Item> p_364577_, Function<Item.Properties, Item> p_366144_, Item.Properties p_369845_) {
|
||||
Item item = p_366144_.apply(p_369845_.setId(p_364577_));
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
protected boolean isSameRailWithPower(Level p_55226_, BlockPos p_55227_, boolean p_55228_, int p_55229_, RailShape p_55230_) {
|
||||
BlockState blockstate = p_55226_.getBlockState(p_55227_);
|
||||
- if (!blockstate.is(this)) {
|
||||
+ if (!(blockstate.getBlock() instanceof PoweredRailBlock other)) {
|
||||
+ if (!(blockstate.getBlock() instanceof PoweredRailBlock other) || this.isActivatorRail() != other.isActivatorRail()) {
|
||||
return false;
|
||||
} else {
|
||||
- RailShape railshape = blockstate.getValue(SHAPE);
|
||||
|
||||
+11
-11
@@ -10,7 +10,7 @@ buildscript {
|
||||
dependencies {
|
||||
classpath('com.google.code.gson:gson') {
|
||||
version {
|
||||
strictly '2.10.1'
|
||||
strictly '2.11.0'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,8 @@ dependencyResolutionManagement {
|
||||
library('accesstransformers', 'net.minecraftforge:accesstransformers:8.2.2')
|
||||
library('coremods', 'net.minecraftforge:coremods:5.2.6')
|
||||
library('nashorn', 'org.openjdk.nashorn:nashorn-core:15.4') // Needed by coremods, because the JRE no longer ships JS
|
||||
library('eventbus', 'net.minecraftforge:eventbus:7.0-beta.7')
|
||||
library('eventbus-validator', 'net.minecraftforge:eventbus-validator:7.0-beta.7')
|
||||
library('eventbus', 'net.minecraftforge:eventbus:7.0-beta.11')
|
||||
library('eventbus-validator', 'net.minecraftforge:eventbus-validator:7.0-beta.11')
|
||||
library('mergetool-api', 'net.minecraftforge:mergetool-api:1.0')
|
||||
|
||||
library('mixin', 'org.spongepowered:mixin:0.8.7')
|
||||
@@ -53,7 +53,7 @@ dependencyResolutionManagement {
|
||||
library('bootstrap-shim', 'net.minecraftforge', 'bootstrap-shim').versionRef('bootstrap')
|
||||
|
||||
// ASM it's used for so many of our hacks
|
||||
version('asm', '9.7.1')
|
||||
version('asm', '9.8')
|
||||
library('asm', 'org.ow2.asm', 'asm' ).versionRef('asm')
|
||||
library('asm-tree', 'org.ow2.asm', 'asm-tree' ).versionRef('asm')
|
||||
library('asm-util', 'org.ow2.asm', 'asm-util' ).versionRef('asm')
|
||||
@@ -84,19 +84,19 @@ dependencyResolutionManagement {
|
||||
|
||||
// These are libraries shipped by the MC launcher, try and keep them in sync with the manifest
|
||||
// but honestly if we don't it just means we ship them as normal libraries by adding them to the installer config in the forge project
|
||||
library('gson', 'com.google.code.gson:gson:2.10.1')
|
||||
library('guava', 'com.google.guava:guava:32.1.2-jre')
|
||||
library('failureaccess', 'com.google.guava:failureaccess:1.0.1')
|
||||
library('gson', 'com.google.code.gson:gson:2.11.0')
|
||||
library('guava', 'com.google.guava:guava:33.3.1-jre')
|
||||
library('failureaccess', 'com.google.guava:failureaccess:1.0.2')
|
||||
|
||||
version('log4j', '2.22.1')
|
||||
version('log4j', '2.24.3')
|
||||
library('log4j-api', 'org.apache.logging.log4j', 'log4j-api' ).versionRef('log4j')
|
||||
library('log4j-core', 'org.apache.logging.log4j', 'log4j-core').versionRef('log4j')
|
||||
bundle('log4j', ['log4j-api', 'log4j-core'])
|
||||
|
||||
library('apache-commons', 'org.apache.commons:commons-lang3:3.14.0')
|
||||
library('mojang-logging', 'com.mojang:logging:1.2.7')
|
||||
library('apache-commons', 'org.apache.commons:commons-lang3:3.17.0')
|
||||
library('mojang-logging', 'com.mojang:logging:1.5.10')
|
||||
library('jopt-simple', 'net.sf.jopt-simple:jopt-simple:5.0.4')
|
||||
library('commons-io', 'commons-io:commons-io:2.15.1')
|
||||
library('commons-io', 'commons-io:commons-io:2.17.0')
|
||||
|
||||
version('lwjgl', '3.3.3')
|
||||
library('lwjgl', 'org.lwjgl', 'lwjgl' ).versionRef('lwjgl')
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
"description": {
|
||||
"translate": "pack.forge.description"
|
||||
},
|
||||
"pack_format": 80
|
||||
"pack_format": 81
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.client.color.block.BlockTintCache;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
@@ -13,22 +12,23 @@ import net.minecraftforge.client.event.RegisterColorHandlersEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Manager for custom {@link ColorResolver} instances, collected via {@link RegisterColorHandlersEvent.ColorResolvers}.
|
||||
*/
|
||||
public final class ColorResolverManager
|
||||
{
|
||||
public final class ColorResolverManager {
|
||||
private ColorResolverManager() {}
|
||||
|
||||
private static ImmutableList<ColorResolver> colorResolvers;
|
||||
private static List<ColorResolver> colorResolvers;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void init()
|
||||
{
|
||||
ImmutableList.Builder<ColorResolver> builder = ImmutableList.builder();
|
||||
public static void init() {
|
||||
var builder = new ArrayList<ColorResolver>();
|
||||
ModLoader.get().postEvent(new RegisterColorHandlersEvent.ColorResolvers(builder));
|
||||
colorResolvers = builder.build();
|
||||
colorResolvers = List.copyOf(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,15 +37,9 @@ public final class ColorResolverManager
|
||||
* @param level the level to use
|
||||
* @param target the map to populate
|
||||
*/
|
||||
public static void registerBlockTintCaches(ClientLevel level, Map<ColorResolver, BlockTintCache> target)
|
||||
{
|
||||
for (var resolver : colorResolvers)
|
||||
{
|
||||
public static void registerBlockTintCaches(ClientLevel level, Map<ColorResolver, BlockTintCache> target) {
|
||||
for (var resolver : colorResolvers) {
|
||||
target.put(resolver, new BlockTintCache(pos -> level.calculateBlockTint(pos, resolver)));
|
||||
}
|
||||
}
|
||||
|
||||
private ColorResolverManager()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.client.renderer.DimensionSpecialEffects;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;
|
||||
@@ -22,7 +21,9 @@ import java.util.Map;
|
||||
* Provides a lookup by dimension type.
|
||||
*/
|
||||
public final class DimensionSpecialEffectsManager {
|
||||
private static ImmutableMap<ResourceLocation, DimensionSpecialEffects> EFFECTS;
|
||||
private DimensionSpecialEffectsManager() {}
|
||||
|
||||
private static Map<ResourceLocation, DimensionSpecialEffects> EFFECTS;
|
||||
private static DimensionSpecialEffects DEFAULT_EFFECTS;
|
||||
|
||||
/**
|
||||
@@ -38,7 +39,7 @@ public final class DimensionSpecialEffectsManager {
|
||||
DEFAULT_EFFECTS = preRegisterVanillaEffects(effects);
|
||||
var event = new RegisterDimensionSpecialEffectsEvent(effects);
|
||||
ModLoader.get().postEventWrapContainerInModOrder(event);
|
||||
EFFECTS = ImmutableMap.copyOf(effects);
|
||||
EFFECTS = Map.copyOf(effects);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,6 +54,4 @@ public final class DimensionSpecialEffectsManager {
|
||||
effects.put(BuiltinDimensionTypes.END_EFFECTS, new DimensionSpecialEffects.EndEffects());
|
||||
return overworldEffects;
|
||||
}
|
||||
|
||||
private DimensionSpecialEffectsManager() { }
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraftforge.client.event.RegisterEntitySpectatorShadersEvent;
|
||||
@@ -21,29 +20,24 @@ import java.util.Map;
|
||||
* <p>
|
||||
* Provides a lookup.
|
||||
*/
|
||||
public final class EntitySpectatorShaderManager
|
||||
{
|
||||
public final class EntitySpectatorShaderManager {
|
||||
private EntitySpectatorShaderManager() {}
|
||||
|
||||
private static Map<EntityType<?>, ResourceLocation> SHADERS;
|
||||
|
||||
/**
|
||||
* Finds the path to the spectator mode shader used for the specified entity type, or null if none is registered.
|
||||
*/
|
||||
@Nullable
|
||||
public static ResourceLocation get(EntityType<?> entityType)
|
||||
{
|
||||
public static ResourceLocation get(EntityType<?> entityType) {
|
||||
return SHADERS.get(entityType);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void init()
|
||||
{
|
||||
public static void init() {
|
||||
var shaders = new HashMap<EntityType<?>, ResourceLocation>();
|
||||
var event = new RegisterEntitySpectatorShadersEvent(shaders);
|
||||
ModLoader.get().postEventWrapContainerInModOrder(event);
|
||||
SHADERS = ImmutableMap.copyOf(shaders);
|
||||
}
|
||||
|
||||
private EntitySpectatorShaderManager()
|
||||
{
|
||||
SHADERS = Map.copyOf(shaders);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@ import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.ChatComponent;
|
||||
import net.minecraft.client.gui.components.LerpingBossEvent;
|
||||
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
||||
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
|
||||
import net.minecraft.client.gui.screens.ConfirmScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
|
||||
@@ -96,6 +98,7 @@ import net.minecraftforge.client.event.ClientChatEvent;
|
||||
import net.minecraftforge.client.event.ClientChatReceivedEvent;
|
||||
import net.minecraftforge.client.event.ClientPauseChangeEvent;
|
||||
import net.minecraftforge.client.event.ClientPlayerChangeGameTypeEvent;
|
||||
import net.minecraftforge.client.event.RegisterPictureInPictureRendererEvent;
|
||||
import net.minecraftforge.client.event.SystemMessageReceivedEvent;
|
||||
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.minecraftforge.client.event.EntityRenderersEvent;
|
||||
@@ -151,6 +154,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -596,6 +600,12 @@ public class ForgeHooksClient {
|
||||
ModLoader.get().postEvent(new RegisterKeyMappingsEvent(options));
|
||||
}
|
||||
|
||||
public static void onRegisterPictureInPictureRenderers(List<PictureInPictureRenderer<?>> renderers,
|
||||
MultiBufferSource.BufferSource bufferSource,
|
||||
ImmutableMap.Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder) {
|
||||
RegisterPictureInPictureRendererEvent.BUS.post(new RegisterPictureInPictureRendererEvent(renderers, bufferSource, builder));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Component onClientChat(ChatType.Bound boundChatType, Component message, UUID sender) {
|
||||
ClientChatReceivedEvent event = new ClientChatReceivedEvent(boundChatType, message, sender);
|
||||
@@ -874,4 +884,8 @@ public class ForgeHooksClient {
|
||||
return parent.compute(p_395456_);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addFramePass(ResourceLocation rl, FramePassManager.PassDefinition definition) {
|
||||
FramePassManager.addPass(rl, definition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
|
||||
import com.mojang.blaze3d.framegraph.FramePass;
|
||||
import net.minecraft.client.renderer.LevelTargetBundle;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FramePassManager {
|
||||
private static final List<PassInfo> addedPasses = new ArrayList<>();
|
||||
|
||||
protected static void addPass(ResourceLocation name, PassDefinition pass) {
|
||||
if (addedPasses.stream().noneMatch(info -> info.name.equals(name.toString()))) {
|
||||
addedPasses.add(new PassInfo(name.toString(), pass));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot create a frame pass with a duplicate name: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Pass order is determined automatically within FrameGraphBuilder. It's unclear what must be done to guarantee ordering.
|
||||
@ApiStatus.Internal
|
||||
public static void insertForgePasses(FrameGraphBuilder graphBuilder, LevelTargetBundle bundle) {
|
||||
for (PassInfo info : addedPasses) {
|
||||
FramePass pass = graphBuilder.addPass(info.name);
|
||||
PassDefinition forgePass = info.pass;
|
||||
forgePass.targets(bundle, pass);
|
||||
pass.executes(forgePass::executes);
|
||||
}
|
||||
}
|
||||
|
||||
public interface PassDefinition {
|
||||
void targets(LevelTargetBundle bundle, FramePass pass);
|
||||
void executes();
|
||||
}
|
||||
|
||||
private record PassInfo(String name, PassDefinition pass){}
|
||||
}
|
||||
@@ -16,16 +16,14 @@ import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||
import net.minecraftforge.client.event.RegisterPresetEditorsEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
|
||||
public final class PresetEditorManager
|
||||
{
|
||||
public final class PresetEditorManager {
|
||||
private PresetEditorManager() {} // Utility class
|
||||
|
||||
private static Map<ResourceKey<WorldPreset>, PresetEditor> editors = Map.of();
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@ApiStatus.Internal
|
||||
static void init()
|
||||
{
|
||||
static void init() {
|
||||
// Start with the vanilla entries
|
||||
Map<ResourceKey<WorldPreset>, PresetEditor> gatheredEditors = new HashMap<>();
|
||||
// Vanilla's map uses Optional<ResourceKey>s as its keys.
|
||||
@@ -41,7 +39,7 @@ public final class PresetEditorManager
|
||||
RegisterPresetEditorsEvent event = new RegisterPresetEditorsEvent(gatheredEditors);
|
||||
ModLoader.get().postEventWrapContainerInModOrder(event);
|
||||
|
||||
editors = gatheredEditors;
|
||||
editors = Map.copyOf(gatheredEditors);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,8 +48,7 @@ public final class PresetEditorManager
|
||||
* @param key ResourceKey for the specified WorldPreset/PresetEditor.
|
||||
*/
|
||||
@Nullable
|
||||
public static PresetEditor get(ResourceKey<WorldPreset> key)
|
||||
{
|
||||
public static PresetEditor get(ResourceKey<WorldPreset> key) {
|
||||
return editors.get(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.FramePassManager;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Fired after all vanilla frame passes are added into the pass list.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain net.minecraftforge.common.MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain net.minecraftforge.fml.LogicalSide#CLIENT logical client}.
|
||||
*/
|
||||
@NullMarked
|
||||
public record AddFramePassEvent() implements RecordEvent {
|
||||
public static final EventBus<AddFramePassEvent> BUS = EventBus.create(AddFramePassEvent.class);
|
||||
/**
|
||||
* Adds a frame pass to pass list.
|
||||
* Create a new {@linkplain FramePassManager.PassDefinition} to handle render targets and render code.
|
||||
*
|
||||
* @param rl Resource location for frame pass name. Use RLs to avoid duplicate names.
|
||||
* @param definition see usages of {@linkplain com.mojang.blaze3d.framegraph.FramePass} in {@linkplain net.minecraft.client.renderer.LevelRenderer}
|
||||
* @throws IllegalArgumentException If the name is a duplicate.
|
||||
*/
|
||||
public void addPass(ResourceLocation rl, FramePassManager.PassDefinition definition) {
|
||||
ForgeHooksClient.addFramePass(rl, definition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import net.minecraftforge.client.gui.overlay.ForgeLayeredDraw;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Fired when the {@linkplain ForgeLayeredDraw#VANILLA_ROOT}'s order is resolved during{@link ForgeLayeredDraw#resolveLayers().
|
||||
* This can be used to add additional or move gui layers and entire layer stacks as needed.
|
||||
*
|
||||
* <p> This event is fired on the {@linkplain IModBusEvent mod event bus},
|
||||
* only on the {@linkplain net.minecraftforge.fml.LogicalSide logical client}.</p>
|
||||
*
|
||||
* @param getLayedDraw The provided {@linkplain ForgeLayeredDraw#instance}. By default will be {@linkplain ForgeLayeredDraw#VANILLA_ROOT}.
|
||||
*/
|
||||
@NullMarked
|
||||
public record AddGuiOverlayLayersEvent(ForgeLayeredDraw getLayeredDraw) implements IModBusEvent, SelfDestructing, RecordEvent {
|
||||
@ApiStatus.Internal
|
||||
public AddGuiOverlayLayersEvent {}
|
||||
|
||||
public static EventBus<AddGuiOverlayLayersEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, AddGuiOverlayLayersEvent.class);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
@@ -60,12 +61,10 @@ public abstract sealed class EntityRenderersEvent implements IModBusEvent {
|
||||
/**
|
||||
* Fired for registering layer definitions at the appropriate time.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static final class RegisterLayerDefinitions extends EntityRenderersEvent {
|
||||
public static final class RegisterLayerDefinitions extends EntityRenderersEvent implements SelfDestructing {
|
||||
public static EventBus<RegisterLayerDefinitions> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterLayerDefinitions.class);
|
||||
}
|
||||
@@ -92,12 +91,10 @@ public abstract sealed class EntityRenderersEvent implements IModBusEvent {
|
||||
* For registering entity renderer layers to existing entity renderers (whether vanilla or registered through this
|
||||
* event), listen for the {@link AddLayers} event instead.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static final class RegisterRenderers extends EntityRenderersEvent {
|
||||
public static final class RegisterRenderers extends EntityRenderersEvent implements SelfDestructing {
|
||||
public static EventBus<RegisterRenderers> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterRenderers.class);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraftforge.client.FramePassManager;
|
||||
import net.minecraftforge.client.gui.overlay.ForgeLayeredDraw;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.Result;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
@@ -283,4 +285,12 @@ public final class ForgeEventFactoryClient {
|
||||
// This is on the mod bus because it happens during the initial texture reload, which is while the Forge bus is shut down.
|
||||
return fireModBus(new ModelEvent.RegisterModelStateDefinitions());
|
||||
}
|
||||
|
||||
public static void onInitLevelRenderer() {
|
||||
AddFramePassEvent.BUS.post(new AddFramePassEvent());
|
||||
}
|
||||
|
||||
public static void onComputeLayerOrder(ForgeLayeredDraw layeredDraw) {
|
||||
fireModBus(new AddGuiOverlayLayersEvent(layeredDraw));
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -11,6 +11,7 @@ import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraftforge.event.AddReloadListenerEvent;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
@@ -22,12 +23,10 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
*
|
||||
* <p>For registering reload listeners on the server-side resource manager, see {@link AddReloadListenerEvent}.</p>
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterClientReloadListenersEvent implements IModBusEvent {
|
||||
public final class RegisterClientReloadListenersEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterClientReloadListenersEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterClientReloadListenersEvent.class);
|
||||
}
|
||||
|
||||
+2
-3
@@ -9,6 +9,7 @@ import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent
|
||||
import net.minecraft.world.inventory.tooltip.TooltipComponent;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
@@ -21,12 +22,10 @@ import java.util.function.Function;
|
||||
* Allows users to register custom {@link net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent}
|
||||
* factories for their {@link net.minecraft.world.inventory.tooltip.TooltipComponent} types.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterClientTooltipComponentFactoriesEvent implements IModBusEvent {
|
||||
public final class RegisterClientTooltipComponentFactoriesEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterClientTooltipComponentFactoriesEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterClientTooltipComponentFactoriesEvent.class);
|
||||
}
|
||||
|
||||
@@ -12,10 +12,14 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Fired for registering block and item color handlers at the appropriate time.
|
||||
@@ -76,15 +80,16 @@ public abstract sealed class RegisterColorHandlersEvent implements IModBusEvent
|
||||
* Allows registration of custom {@link ColorResolver} implementations to be used with
|
||||
* {@link net.minecraft.world.level.BlockAndTintGetter#getBlockTint(BlockPos, ColorResolver)}.
|
||||
*/
|
||||
public static final class ColorResolvers extends RegisterColorHandlersEvent {
|
||||
@NullMarked
|
||||
public static final class ColorResolvers extends RegisterColorHandlersEvent implements SelfDestructing {
|
||||
public static EventBus<ColorResolvers> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, ColorResolvers.class);
|
||||
}
|
||||
|
||||
private final ImmutableList.Builder<ColorResolver> builder;
|
||||
private final ArrayList<ColorResolver> builder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ColorResolvers(ImmutableList.Builder<ColorResolver> builder) {
|
||||
public ColorResolvers(ArrayList<ColorResolver> builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -9,22 +9,23 @@ import net.minecraft.client.renderer.DimensionSpecialEffects;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Allows users to register custom {@link DimensionSpecialEffects} for their dimensions.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterDimensionSpecialEffectsEvent implements IModBusEvent {
|
||||
@NullMarked
|
||||
public final class RegisterDimensionSpecialEffectsEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterDimensionSpecialEffectsEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterDimensionSpecialEffectsEvent.class);
|
||||
}
|
||||
|
||||
+4
-3
@@ -9,10 +9,12 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -20,12 +22,11 @@ import java.util.Map;
|
||||
* Allows users to register custom shaders to be used when the player spectates a certain kind of entity.
|
||||
* Vanilla examples of this are the green effect for creepers and the invert effect for endermen.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterEntitySpectatorShadersEvent implements IModBusEvent {
|
||||
@NullMarked
|
||||
public final class RegisterEntitySpectatorShadersEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterEntitySpectatorShadersEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterEntitySpectatorShadersEvent.class);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.minecraftforge.client.IItemDecorator;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
@@ -23,12 +24,10 @@ import java.util.Map;
|
||||
/**
|
||||
* Allows users to register custom {@linkplain IItemDecorator IItemDecorator} to Items.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancelable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterItemDecorationsEvent implements IModBusEvent {
|
||||
public final class RegisterItemDecorationsEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterItemDecorationsEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterItemDecorationsEvent.class);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Options;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
@@ -18,12 +19,10 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
/**
|
||||
* Allows users to register custom {@link net.minecraft.client.KeyMapping key mappings}.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterKeyMappingsEvent implements IModBusEvent {
|
||||
public final class RegisterKeyMappingsEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterKeyMappingsEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterKeyMappingsEvent.class);
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
||||
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used for registering custom picture in picture renderers.
|
||||
* <p>
|
||||
* Fired at the beginning of the loading screen when starting minecraft.
|
||||
* Cannot be used to replace vanilla picture in picture renderers.
|
||||
* This event is fired only on the {@linkplain LogicalSide#CLIENT logical client}
|
||||
*/
|
||||
public final class RegisterPictureInPictureRendererEvent extends MutableEvent implements SelfDestructing {
|
||||
public static final EventBus<RegisterPictureInPictureRendererEvent> BUS = EventBus.create(RegisterPictureInPictureRendererEvent.class);
|
||||
|
||||
private final List<PictureInPictureRenderer<?>> renderers;
|
||||
private final MultiBufferSource.BufferSource bufferSource;
|
||||
private final ImmutableMap.Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RegisterPictureInPictureRendererEvent(List<PictureInPictureRenderer<?>> renderers, MultiBufferSource.BufferSource bufferSource, ImmutableMap.Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder) {
|
||||
this.renderers = renderers;
|
||||
this.bufferSource = bufferSource;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public MultiBufferSource.BufferSource getBufferSource() {
|
||||
return bufferSource;
|
||||
}
|
||||
|
||||
public void register(PictureInPictureRenderer<?> renderer) {
|
||||
var seen = HashSet.newHashSet(renderers.size());
|
||||
for (var r : renderers)
|
||||
seen.add(r.getRenderStateClass());
|
||||
var key = renderer.getRenderStateClass();
|
||||
if (seen.add(key))
|
||||
this.builder.put(key, renderer);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -24,12 +25,10 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
/**
|
||||
* <p>Event for registering {@link PresetEditor} screen factories for world presets.</p>
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterPresetEditorsEvent implements IModBusEvent {
|
||||
public final class RegisterPresetEditorsEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterPresetEditorsEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterPresetEditorsEvent.class);
|
||||
}
|
||||
|
||||
+2
-3
@@ -12,6 +12,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.textures.ITextureAtlasSpriteLoader;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
@@ -21,12 +22,10 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
/**
|
||||
* Allows users to register custom {@link ITextureAtlasSpriteLoader texture atlas sprite loaders}.
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public final class RegisterTextureAtlasSpriteLoadersEvent implements IModBusEvent {
|
||||
public final class RegisterTextureAtlasSpriteLoadersEvent implements SelfDestructing, IModBusEvent {
|
||||
public static EventBus<RegisterTextureAtlasSpriteLoadersEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, RegisterTextureAtlasSpriteLoadersEvent.class);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,8 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -21,48 +20,24 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
* and can be used to replace the rendering of the player's arm, such as for rendering armor on the arm or outright
|
||||
* replacing the arm with armor.
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If this event is cancelled, then the arm will not be rendered.</p>
|
||||
* <p>This event is {@linkplain Cancellable cancellable}. If this event is cancelled, then the arm will not be rendered.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
* <p>This event is fired only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*
|
||||
* @param getPoseStack The pose stack used for rendering
|
||||
* @param getMultiBufferSource The source of rendering buffers
|
||||
* @param getArm The arm being rendered
|
||||
*/
|
||||
public final class RenderArmEvent extends MutableEvent implements Cancellable {
|
||||
public record RenderArmEvent(
|
||||
PoseStack getPoseStack,
|
||||
MultiBufferSource getMultiBufferSource,
|
||||
int getPackedLight,
|
||||
HumanoidArm getArm
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<RenderArmEvent> BUS = CancellableEventBus.create(RenderArmEvent.class);
|
||||
|
||||
private final PoseStack poseStack;
|
||||
private final MultiBufferSource multiBufferSource;
|
||||
private final int packedLight;
|
||||
private final HumanoidArm arm;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RenderArmEvent(PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight, HumanoidArm arm) {
|
||||
this.poseStack = poseStack;
|
||||
this.multiBufferSource = multiBufferSource;
|
||||
this.packedLight = packedLight;
|
||||
this.arm = arm;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the arm being rendered}
|
||||
*/
|
||||
public HumanoidArm getArm() {
|
||||
return arm;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the pose stack used for rendering}
|
||||
*/
|
||||
public PoseStack getPoseStack() {
|
||||
return poseStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the source of rendering buffers}
|
||||
*/
|
||||
public MultiBufferSource getMultiBufferSource() {
|
||||
return multiBufferSource;
|
||||
}
|
||||
public RenderArmEvent {}
|
||||
|
||||
/**
|
||||
* {@return the amount of packed (sky and block) light for rendering}
|
||||
@@ -70,6 +45,6 @@ public final class RenderArmEvent extends MutableEvent implements Cancellable {
|
||||
* @see LightTexture
|
||||
*/
|
||||
public int getPackedLight() {
|
||||
return packedLight;
|
||||
return getPackedLight;
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,8 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -19,13 +18,21 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
/**
|
||||
* Fired before a block texture will be overlaid on the player's view.
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If this event is cancelled, then the overlay will not be rendered.</p>
|
||||
* <p>This event is fired only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
* @param getPlayer The player which the overlay will apply to
|
||||
* @param getPoseStack The pose stack used for rendering
|
||||
* @param getOverlayType The type of the overlay
|
||||
* @param getBlockState The block which the overlay is gotten from
|
||||
* @param getBlockPos The position of the block which the overlay is gotten from
|
||||
*/
|
||||
public final class RenderBlockScreenEffectEvent extends MutableEvent implements Cancellable {
|
||||
public record RenderBlockScreenEffectEvent(
|
||||
Player getPlayer,
|
||||
PoseStack getPoseStack,
|
||||
OverlayType getOverlayType,
|
||||
BlockState getBlockState,
|
||||
BlockPos getBlockPos
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<RenderBlockScreenEffectEvent> BUS = CancellableEventBus.create(RenderBlockScreenEffectEvent.class);
|
||||
|
||||
/**
|
||||
@@ -48,53 +55,6 @@ public final class RenderBlockScreenEffectEvent extends MutableEvent implements
|
||||
WATER
|
||||
}
|
||||
|
||||
private final Player player;
|
||||
private final PoseStack poseStack;
|
||||
private final OverlayType overlayType;
|
||||
private final BlockState blockState;
|
||||
private final BlockPos blockPos;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RenderBlockScreenEffectEvent(Player player, PoseStack poseStack, OverlayType type, BlockState block, BlockPos blockPos) {
|
||||
this.player = player;
|
||||
this.poseStack = poseStack;
|
||||
this.overlayType = type;
|
||||
this.blockState = block;
|
||||
this.blockPos = blockPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the player which the overlay will apply to}
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the pose stack used for rendering}
|
||||
*/
|
||||
public PoseStack getPoseStack() {
|
||||
return poseStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the type of the overlay}
|
||||
*/
|
||||
public OverlayType getOverlayType() {
|
||||
return overlayType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the block which the overlay is gotten from}
|
||||
*/
|
||||
public BlockState getBlockState() {
|
||||
return blockState;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the position of the block which the overlay is gotten from}
|
||||
*/
|
||||
public BlockPos getBlockPos() {
|
||||
return blockPos;
|
||||
}
|
||||
public RenderBlockScreenEffectEvent {}
|
||||
}
|
||||
@@ -10,9 +10,8 @@ import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -20,63 +19,36 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
/**
|
||||
* Fired before a hand is rendered in the first person view.
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If this event is cancelled, then the hand will not be rendered.</p>
|
||||
* <p>This event is {@linkplain Cancellable cancellable}. If this event is cancelled, then the hand will not be rendered.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
* <p>This event is fired only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*
|
||||
* @param getHand The hand being rendered
|
||||
* @param getPoseStack The pose stack used for rendering
|
||||
* @param getMultiBufferSource The source of rendering buffers
|
||||
* @param getPartialTick The partial tick
|
||||
* @param getInterpolatedPitch The interpolated pitch of the player entity
|
||||
* @param getSwingProgress The swing progress of the hand being rendered
|
||||
* @param getEquipProgress The progress of the equip animation, from {@code 0.0} to {@code 1.0}
|
||||
* @param getItemStack The item stack to be rendered
|
||||
*
|
||||
* @see RenderArmEvent
|
||||
*/
|
||||
public final class RenderHandEvent extends MutableEvent implements Cancellable {
|
||||
public record RenderHandEvent(
|
||||
InteractionHand getHand,
|
||||
PoseStack getPoseStack,
|
||||
MultiBufferSource getMultiBufferSource,
|
||||
int getPackedLight,
|
||||
float getPartialTick,
|
||||
float getInterpolatedPitch,
|
||||
float getSwingProgress,
|
||||
float getEquipProgress,
|
||||
ItemStack getItemStack
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<RenderHandEvent> BUS = CancellableEventBus.create(RenderHandEvent.class);
|
||||
|
||||
private final InteractionHand hand;
|
||||
private final PoseStack poseStack;
|
||||
private final MultiBufferSource multiBufferSource;
|
||||
private final int packedLight;
|
||||
private final float partialTick;
|
||||
private final float interpolatedPitch;
|
||||
private final float swingProgress;
|
||||
private final float equipProgress;
|
||||
private final ItemStack stack;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RenderHandEvent(InteractionHand hand, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight,
|
||||
float partialTick, float interpolatedPitch,
|
||||
float swingProgress, float equipProgress, ItemStack stack)
|
||||
{
|
||||
this.hand = hand;
|
||||
this.poseStack = poseStack;
|
||||
this.multiBufferSource = multiBufferSource;
|
||||
this.packedLight = packedLight;
|
||||
this.partialTick = partialTick;
|
||||
this.interpolatedPitch = interpolatedPitch;
|
||||
this.swingProgress = swingProgress;
|
||||
this.equipProgress = equipProgress;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the hand being rendered}
|
||||
*/
|
||||
public InteractionHand getHand() {
|
||||
return hand;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the pose stack used for rendering}
|
||||
*/
|
||||
public PoseStack getPoseStack() {
|
||||
return poseStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the source of rendering buffers}
|
||||
*/
|
||||
public MultiBufferSource getMultiBufferSource() {
|
||||
return multiBufferSource;
|
||||
}
|
||||
public RenderHandEvent {}
|
||||
|
||||
/**
|
||||
* {@return the amount of packed (sky and block) light for rendering}
|
||||
@@ -84,41 +56,6 @@ public final class RenderHandEvent extends MutableEvent implements Cancellable {
|
||||
* @see LightTexture
|
||||
*/
|
||||
public int getPackedLight() {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the partial tick}
|
||||
*/
|
||||
public float getPartialTick() {
|
||||
return partialTick;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the interpolated pitch of the player entity}
|
||||
*/
|
||||
public float getInterpolatedPitch() {
|
||||
return interpolatedPitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the swing progress of the hand being rendered}
|
||||
*/
|
||||
public float getSwingProgress() {
|
||||
return swingProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the progress of the equip animation, from {@code 0.0} to {@code 1.0}}
|
||||
*/
|
||||
public float getEquipProgress() {
|
||||
return equipProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the item stack to be rendered}
|
||||
*/
|
||||
public ItemStack getItemStack() {
|
||||
return stack;
|
||||
return getPackedLight;
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,8 @@ import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.ItemFrameRenderer;
|
||||
import net.minecraft.client.renderer.entity.state.ItemFrameRenderState;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -21,59 +20,28 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
* Fired before an item stack is rendered in an item frame.
|
||||
* This can be used to prevent normal rendering or add custom rendering.
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If the event is cancelled, then the item stack will not be rendered</p>
|
||||
* <p>This event is {@linkplain Cancellable cancellable}. If the event is cancelled, then the item stack will not be rendered</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
* <p>This event is fired only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*
|
||||
* @param getItemFrameState The item frame entity
|
||||
* @param getRenderer The renderer for the item frame entity
|
||||
* @param getPoseStack The pose stack used for rendering
|
||||
* @param getMultiBufferSource The source of rendering buffers
|
||||
*
|
||||
* @see ItemFrameRenderer
|
||||
*/
|
||||
public final class RenderItemInFrameEvent extends MutableEvent implements Cancellable {
|
||||
public record RenderItemInFrameEvent(
|
||||
ItemFrameRenderState getItemFrameState,
|
||||
ItemFrameRenderer<?> getRenderer,
|
||||
PoseStack getPoseStack,
|
||||
MultiBufferSource getMultiBufferSource,
|
||||
int getPackedLight
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<RenderItemInFrameEvent> BUS = CancellableEventBus.create(RenderItemInFrameEvent.class);
|
||||
|
||||
private final ItemFrameRenderState state;
|
||||
private final ItemFrameRenderer<?> renderer;
|
||||
private final PoseStack poseStack;
|
||||
private final MultiBufferSource multiBufferSource;
|
||||
private final int packedLight;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RenderItemInFrameEvent(ItemFrameRenderState state, ItemFrameRenderer<?> renderItemFrame, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight) {
|
||||
this.state = state;
|
||||
this.renderer = renderItemFrame;
|
||||
this.poseStack = poseStack;
|
||||
this.multiBufferSource = multiBufferSource;
|
||||
this.packedLight = packedLight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the item frame entity}
|
||||
*/
|
||||
public ItemFrameRenderState getItemFrameState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the renderer for the item frame entity}
|
||||
*/
|
||||
public ItemFrameRenderer<?> getRenderer() {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the pose stack used for rendering}
|
||||
*/
|
||||
public PoseStack getPoseStack() {
|
||||
return poseStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the source of rendering buffers}
|
||||
*/
|
||||
public MultiBufferSource getMultiBufferSource() {
|
||||
return multiBufferSource;
|
||||
}
|
||||
public RenderItemInFrameEvent {}
|
||||
|
||||
/**
|
||||
* {@return the amount of packed (sky and block) light for rendering}
|
||||
@@ -81,6 +49,6 @@ public final class RenderItemInFrameEvent extends MutableEvent implements Cancel
|
||||
* @see LightTexture
|
||||
*/
|
||||
public int getPackedLight() {
|
||||
return packedLight;
|
||||
return getPackedLight;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||
|
||||
private void drawMultiLineCenteredString(GuiGraphics guiGraphics, Font fr, Component str, int x, int y) {
|
||||
for (FormattedCharSequence s : fr.split(str, this.width)) {
|
||||
guiGraphics.drawString(fr, s, x - fr.width(s) / 2, y, 0xFFFFFF);
|
||||
guiGraphics.drawString(fr, s, x - fr.width(s) / 2, y, 0xFFFFFFFF);
|
||||
y += fr.lineHeight;
|
||||
}
|
||||
}
|
||||
@@ -134,9 +134,9 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||
int y = top + 2;
|
||||
for (var string : strings) {
|
||||
if (center)
|
||||
guiGraphics.drawString(font, string, left + (width / 2) - (font.width(string) / 2), y, 0xFFFFFF, false);
|
||||
guiGraphics.drawString(font, string, left + (width / 2) - (font.width(string) / 2), y, 0xFFFFFFFF, false);
|
||||
else
|
||||
guiGraphics.drawString(font, string, left + 5, y, 0xFFFFFF, false);
|
||||
guiGraphics.drawString(font, string, left + 5, y, 0xFFFFFFFF, false);
|
||||
y += font.lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ import net.minecraftforge.fml.loading.StringUtils;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
import net.minecraft.locale.Language;
|
||||
import net.minecraft.network.chat.ClickEvent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import org.slf4j.Logger;
|
||||
@@ -499,4 +500,12 @@ public class ModListScreen extends Screen {
|
||||
public void onClose() {
|
||||
this.minecraft.setScreen(this.parentScreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleClickEvent(Minecraft mc, ClickEvent event) {
|
||||
if (mc.player == null)
|
||||
defaultHandleClickEvent(event, mc, this);
|
||||
else
|
||||
defaultHandleGameClickEvent(event, mc, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.minecraftforge.client.gui.overlay;
|
||||
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
|
||||
public interface ForgeLayer {
|
||||
void render(GuiGraphics gg, DeltaTracker dt);
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.gui.overlay;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.FieldsAreNonnullByDefault;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.event.ForgeEventFactoryClient;
|
||||
import net.minecraftforge.client.event.AddGuiOverlayLayersEvent;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.*;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/**
|
||||
* As vanilla has switched to a layered drawing system for overlays, this system replaces ForgeGui and its associated headaches.
|
||||
* Vanilla will now have resource locations to represent its render layers which modders can order against.
|
||||
* This class is effectively a pseudo-registry for Layers. Add what you need during {@linkplain AddGuiOverlayLayersEvent}
|
||||
* Layers must be uniquely named per ForgeLayeredDraw, but may be duplicated across different instances.
|
||||
* Any change which would result in a duplicate will not be applied.
|
||||
* All methods which return a {@linkplain ForgeLayeredDraw} will return its caller's instance.
|
||||
* To select a specific instance, use {@linkplain ForgeLayeredDraw#locateStack(ResourceLocation)} before adding
|
||||
* or use the methods that include a stack identifier.
|
||||
*/
|
||||
@FieldsAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public final class ForgeLayeredDraw implements ForgeLayer {
|
||||
private final Map<ResourceLocation, ForgeLayer> namedLayers = new HashMap<>();
|
||||
private final Map<ResourceLocation, Map.Entry<ForgeLayeredDraw, BooleanSupplier>> subLayerStacks = new HashMap<>();
|
||||
private final List<ResourceLocation> order = new LinkedList<>();
|
||||
private final List<ForgeLayer> bakedLayers = new ArrayList<>();
|
||||
private final ResourceLocation name;
|
||||
|
||||
public static final ResourceLocation PRE_SLEEP_STACK = ResourceLocation.withDefaultNamespace("pre_sleep_phase");
|
||||
public static final ResourceLocation CAMERA_OVERLAY = ResourceLocation.withDefaultNamespace("camera_overlay");
|
||||
public static final ResourceLocation CROSSHAIR = ResourceLocation.withDefaultNamespace("crosshair");
|
||||
public static final ResourceLocation CHANGE_STRATUM = ResourceLocation.withDefaultNamespace("stratum_change");
|
||||
public static final ResourceLocation HOTBAR_AND_DECOS = ResourceLocation.withDefaultNamespace("hotbar");
|
||||
public static final ResourceLocation POTION_EFFECTS = ResourceLocation.withDefaultNamespace("potion_effects");
|
||||
public static final ResourceLocation BOSS_OVERLAY = ResourceLocation.withDefaultNamespace("boss_overlay");
|
||||
|
||||
public static final ResourceLocation POST_SLEEP_STACK = ResourceLocation.withDefaultNamespace("post_sleep_phase");
|
||||
public static final ResourceLocation DEMO_OVERLAY = ResourceLocation.withDefaultNamespace("demo");
|
||||
public static final ResourceLocation DEBUG_OVERLAY = ResourceLocation.withDefaultNamespace("debug");
|
||||
public static final ResourceLocation SCOREBOARD = ResourceLocation.withDefaultNamespace("scoreboard");
|
||||
public static final ResourceLocation HOTBAR_MESSAGE = ResourceLocation.withDefaultNamespace("hotbar_message");
|
||||
public static final ResourceLocation TITLE_OVERLAY = ResourceLocation.withDefaultNamespace("title");
|
||||
public static final ResourceLocation CHAT_OVERLAY = ResourceLocation.withDefaultNamespace("chat_overlay");
|
||||
public static final ResourceLocation TAB_LIST = ResourceLocation.withDefaultNamespace("tab_list");
|
||||
public static final ResourceLocation SUBTITLE_OVERLAY = ResourceLocation.withDefaultNamespace("subtitle");
|
||||
|
||||
public static final ResourceLocation VANILLA_ROOT = ResourceLocation.withDefaultNamespace("vanilla_root");
|
||||
public static final ResourceLocation SLEEP_OVERLAY = ResourceLocation.withDefaultNamespace("sleep_overlay");
|
||||
|
||||
private static final ForgeLayeredDraw instance = new ForgeLayeredDraw(VANILLA_ROOT);
|
||||
|
||||
/**
|
||||
* Creates an empty draw list. Add entries with {@linkplain ForgeLayeredDraw#add(ResourceLocation, ForgeLayer)}
|
||||
* @param name marker for which phase this is.
|
||||
*/
|
||||
public ForgeLayeredDraw(ResourceLocation name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a full draw stack with its provided condition.
|
||||
* Use {@linkplain ForgeLayeredDraw#putAbove} and {@linkplain ForgeLayeredDraw#putBelow} for fine location adjustment.
|
||||
* @param name RL of the name to identify this stack with.
|
||||
* @param layeredDraw the draw stack
|
||||
* @param supplier condition for this stack to render
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw add(ResourceLocation name, ForgeLayeredDraw layeredDraw, BooleanSupplier supplier) {
|
||||
if (isNameAvailable(name)) {
|
||||
subLayerStacks.put(name, Map.entry(layeredDraw, supplier));
|
||||
order.add(name);
|
||||
} else {
|
||||
nameTakenWarning(name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a layer to the layer list. This layer will be at the end of the list, which means
|
||||
* it will be rendered last (on top) of already added layers.
|
||||
* @param name RL for other mods to order against.
|
||||
* @param layer layer render code, see {@linkplain ForgeLayer} and example usages in {@linkplain Gui}
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw add(ResourceLocation targetStack, ResourceLocation name, ForgeLayer layer) {
|
||||
locateStack(targetStack).ifPresentOrElse((stack) -> stack.add(name, layer), () -> stackNotPresentWarning(targetStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, assumes the intended draw stack instance is the caller.
|
||||
* Use any of the non-deprecated add methods if you want a specific instance,
|
||||
* or call {@linkplain ForgeLayeredDraw#locateStack(ResourceLocation)} to get a reference to an instance.
|
||||
* @param name RL of layer to add
|
||||
* @param layer layer render code, see {@linkplain ForgeLayer} and example usages in {@linkplain Gui}
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw add(ResourceLocation name, ForgeLayer layer) {
|
||||
if (isNameAvailable(name)) {
|
||||
namedLayers.put(name, layer);
|
||||
order.add(name);
|
||||
} else {
|
||||
nameTakenWarning(name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to specify where your custom draw stack should go. Can also be used to re-order layers.
|
||||
* Both target and destination must be in the same draw stack.
|
||||
* @param expectedStack Which ForgeLayeredDraw the target is expected to be in. If you already have a reference to it, you can use {@linkplain ForgeLayeredDraw#move(ResourceLocation, ResourceLocation, LayerOffset)}
|
||||
* @param target layer name to move
|
||||
* @param destination layer name to order against
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw putAbove(ResourceLocation expectedStack, ResourceLocation target, ResourceLocation destination) {
|
||||
locateStack(expectedStack).ifPresentOrElse((stack) -> stack.move(target, destination, LayerOffset.ABOVE), () -> stackNotPresentWarning(expectedStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to specify where your custom draw stack should go. Can also be used to re-order layers.
|
||||
* Both target and destination must be in the same draw stack.
|
||||
* @param expectedStack Which ForgeLayeredDraw the target is expected to be in. If you already have a reference to it, you can use {@linkplain ForgeLayeredDraw#move(ResourceLocation, ResourceLocation, LayerOffset)}
|
||||
* @param target layer name to move
|
||||
* @param destination layer name to order against
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw putBelow(ResourceLocation expectedStack, ResourceLocation target, ResourceLocation destination) {
|
||||
locateStack(expectedStack).ifPresentOrElse((stack) -> stack.move(target, destination, LayerOffset.BELOW), () -> stackNotPresentWarning(expectedStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, assumes the intended draw stack instance is the caller.
|
||||
* Moves pre-existing names around within the order.
|
||||
* @param target Layer being moved.
|
||||
* @param destination Layer being ordered against
|
||||
* @param offset Self-explanatory
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw move(ResourceLocation target, ResourceLocation destination, LayerOffset offset) {
|
||||
if (!order.contains(target)) {
|
||||
layerNotPresentWarning(target);
|
||||
return this;
|
||||
}
|
||||
int loc = order.indexOf(destination);
|
||||
if (loc == -1) {
|
||||
layerNotPresentWarning(destination);
|
||||
return this;
|
||||
}
|
||||
order.remove(target);
|
||||
order.add(loc + (offset == LayerOffset.ABOVE ? 1 : 0), target);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an overlay layer to be rendered above the other provided layer.
|
||||
* To render "above" another layer means thisLayer will be rendered after otherLayer
|
||||
* If the current stack does not contain otherLayer, no changes will be made.
|
||||
* @param newLayer name of the layer to be added
|
||||
* @param otherLayer name of the layer being ordered against
|
||||
* @param layer layer render code, see {@linkplain ForgeLayer} and example usages in {@linkplain Gui}
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw addAbove(ResourceLocation expectedStack, ResourceLocation newLayer, ResourceLocation otherLayer, ForgeLayer layer) {
|
||||
locateStack(expectedStack).ifPresentOrElse((stack) -> {
|
||||
if (!stack.isNameAvailable(otherLayer)) {
|
||||
stack.add(newLayer, layer).move(newLayer, otherLayer, LayerOffset.ABOVE);
|
||||
} else {
|
||||
layerNotPresentWarning(otherLayer);
|
||||
}
|
||||
}, () -> stackNotPresentWarning(expectedStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, assumes intended draw stack is the caller
|
||||
*/
|
||||
public ForgeLayeredDraw addAbove(ResourceLocation newLayer, ResourceLocation otherLayer, ForgeLayer layer) {
|
||||
return addAbove(name, newLayer, otherLayer, layer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an overlay layer to be rendered below the other provided layer.
|
||||
* To render "below" another layer means thisLayer will be rendered before otherLayer
|
||||
* If the current stack does not contain otherLayer, no changes will be made.
|
||||
* @param newLayer name of the layer to be added
|
||||
* @param otherLayer name of the layer being ordered against
|
||||
* @param layer layer render code, see {@linkplain ForgeLayer} and example usages in {@linkplain Gui}
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw addBelow(ResourceLocation expectedStack, ResourceLocation newLayer, ResourceLocation otherLayer, ForgeLayer layer) {
|
||||
locateStack(expectedStack).ifPresentOrElse((stack) -> {
|
||||
if (!stack.isNameAvailable(otherLayer)) {
|
||||
stack.add(newLayer, layer).move(newLayer, otherLayer, LayerOffset.BELOW);
|
||||
} else {
|
||||
layerNotPresentWarning(otherLayer);
|
||||
}
|
||||
}, () -> stackNotPresentWarning(expectedStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, assumes intended draw stack is the caller
|
||||
*/
|
||||
public ForgeLayeredDraw addBelow(ResourceLocation newLayer, ResourceLocation otherLayer, ForgeLayer layer) {
|
||||
return addBelow(name, newLayer, otherLayer, layer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new layer that will only be rendered when the condition is met. The layer will be added
|
||||
* at the end of the list, which means it will render last (on top) of already added layers
|
||||
* @param name name of the layer to be added
|
||||
* @param layer render code of layer being added
|
||||
* @param condition supplier for the condition
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw addWithCondition(ResourceLocation targetStack, ResourceLocation name, ForgeLayer layer, BooleanSupplier condition) {
|
||||
locateStack(targetStack).ifPresentOrElse((stack) -> stack.addWithCondition(name, layer, condition), () -> stackNotPresentWarning(targetStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes the correct stack is the caller of this method, otherwise functions the same as other method.
|
||||
* @param name name of layer to be added
|
||||
* @param layer render code of layer being added
|
||||
* @param condition supplier for the condition
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw addWithCondition(ResourceLocation name, ForgeLayer layer, BooleanSupplier condition) {
|
||||
add(name, layer).addConditionTo(name, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a condition to a pre-existing layer in the specified stack, its render order is not changed.
|
||||
* If the target is not present, no changes are made.
|
||||
* @param targetStack name of the draw stack the target is expected to be in
|
||||
* @param targetLayer name of layer to add a condition to
|
||||
* @param condition supplier for the condition
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw addConditionTo(ResourceLocation targetStack, ResourceLocation targetLayer, BooleanSupplier condition) {
|
||||
locateStack(targetStack).ifPresentOrElse((stack) -> stack.addConditionTo(targetLayer, condition), () -> stackNotPresentWarning(targetStack));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes the correct stack is the caller of this method.
|
||||
* Use {@linkplain ForgeLayeredDraw#addConditionTo(ResourceLocation, ResourceLocation, BooleanSupplier)}
|
||||
* if you do not have a reference to the draw stack you want.
|
||||
* @param targetLayer name of layer to add condition to
|
||||
* @param condition supplier for the condition
|
||||
* @return this
|
||||
*/
|
||||
public ForgeLayeredDraw addConditionTo(ResourceLocation targetLayer, BooleanSupplier condition) {
|
||||
var result = namedLayers.computeIfPresent(targetLayer,
|
||||
(name, layer) -> (guiGraphics, deltaTracker) -> {
|
||||
if (condition.getAsBoolean()) {
|
||||
layer.render(guiGraphics, deltaTracker);
|
||||
}
|
||||
});
|
||||
if (result == null) {
|
||||
layerNotPresentWarning(targetLayer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate the layer order down to the inner render list after providing modders an opportunity to alter the list as they wish.
|
||||
* @apiNote Modders should <emph>NEVER</emph> be calling this method.
|
||||
* @return this
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public ForgeLayeredDraw resolveLayers() {
|
||||
if (!order.isEmpty()) {
|
||||
ForgeEventFactoryClient.onComputeLayerOrder(this);
|
||||
}
|
||||
resolveNested();
|
||||
order.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the layer order per stack, recursively as needed.
|
||||
* Parent layer stack {@linkplain ForgeLayeredDraw#VANILLA_ROOT} holds the results.
|
||||
*/
|
||||
private void resolveNested() {
|
||||
for (ResourceLocation layerName : order) {
|
||||
if (subLayerStacks.containsKey(layerName)) {
|
||||
var entry = subLayerStacks.get(layerName);
|
||||
entry.getKey().resolveNested();
|
||||
bakedLayers.add((gg, tr) -> {
|
||||
if (entry.getValue().getAsBoolean()) entry.getKey().render(gg,tr);
|
||||
});
|
||||
} else {
|
||||
bakedLayers.add(namedLayers.get(layerName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to locate a particular draw stack. Search starts at caller's instance. For global search call on VANILLA_ROOT
|
||||
* Entries which don't extend ForgeLayeredDraw may not have the proper fields to support internal list adjustment, so they are skipped.
|
||||
* @param targetStack Name of ForgeLayeredDraw to find
|
||||
* @return Filled Optional if target exists, empty otherwise.
|
||||
*/
|
||||
public Optional<ForgeLayeredDraw> locateStack(ResourceLocation targetStack) {
|
||||
if (!name.equals(targetStack)) {
|
||||
for (Map.Entry<ForgeLayeredDraw, BooleanSupplier> value : subLayerStacks.values()) {
|
||||
if (value.getKey() instanceof ForgeLayeredDraw searchable) {
|
||||
var res = searchable.locateStack(targetStack);
|
||||
if(res.isPresent()) return res;
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ForgeLayeredDraw getChild(ResourceLocation childName) {
|
||||
return locateStack(childName).orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ForgeLayer getLayer(ResourceLocation layerName) {
|
||||
return namedLayers.get(layerName);
|
||||
}
|
||||
|
||||
public ResourceLocation getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private void stackNotPresentWarning(ResourceLocation stackName) {
|
||||
LogUtils.getLogger().warn("Target stack {} was not present anywhere. Is your ResourceLocation correct?", stackName);
|
||||
}
|
||||
|
||||
private void layerNotPresentWarning(ResourceLocation layer) {
|
||||
LogUtils.getLogger().warn("Expected layer {} was not found in stack {}, no layer modifications have been made.", layer, name);
|
||||
}
|
||||
|
||||
private void nameTakenWarning(ResourceLocation layer) {
|
||||
LogUtils.getLogger().warn("Name {} was already present in {} and cannot be re-used.", layer, name);
|
||||
}
|
||||
|
||||
private boolean isNameAvailable(ResourceLocation name) {
|
||||
return !namedLayers.containsKey(name) && !subLayerStacks.containsKey(name);
|
||||
}
|
||||
|
||||
public enum LayerOffset {
|
||||
ABOVE,
|
||||
BELOW
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void beginRender(GuiGraphics gg, DeltaTracker dt) {
|
||||
instance.render(gg,dt);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void render(GuiGraphics gg, DeltaTracker dt) {
|
||||
for (ForgeLayer bakedLayer : bakedLayers) {
|
||||
bakedLayer.render(gg, dt);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void init(Gui gui, Minecraft minecraft) {
|
||||
var preSleepDraw = new ForgeLayeredDraw(PRE_SLEEP_STACK)
|
||||
.add(CAMERA_OVERLAY, gui::renderCameraOverlays)
|
||||
.add(CROSSHAIR, gui::renderCrosshair)
|
||||
.add(CHANGE_STRATUM, (gg, dt) -> gg.nextStratum())
|
||||
.add(HOTBAR_AND_DECOS, gui::renderHotbarAndDecorations)
|
||||
.add(POTION_EFFECTS, gui::renderEffects)
|
||||
.add(BOSS_OVERLAY, gui::renderBossOverlay);
|
||||
var postSleepDraw = new ForgeLayeredDraw(POST_SLEEP_STACK)
|
||||
.add(DEMO_OVERLAY, gui::renderDemoOverlay)
|
||||
.add(DEBUG_OVERLAY, gui::renderDebugOverlay)
|
||||
.add(SCOREBOARD, gui::renderScoreboardSidebar)
|
||||
.add(HOTBAR_MESSAGE, gui::renderOverlayMessage)
|
||||
.add(TITLE_OVERLAY, gui::renderTitle)
|
||||
.add(CHAT_OVERLAY, gui::renderChat)
|
||||
.add(TAB_LIST, gui::renderTabList)
|
||||
.add(SUBTITLE_OVERLAY, gui::renderSubtitleOverlay);
|
||||
instance
|
||||
.add(PRE_SLEEP_STACK, preSleepDraw, () -> !minecraft.options.hideGui)
|
||||
.add(SLEEP_OVERLAY, gui::renderSleepOverlay)
|
||||
.add(POST_SLEEP_STACK, postSleepDraw, () -> !minecraft.options.hideGui);
|
||||
instance.resolveLayers();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -22,8 +21,6 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
@@ -19,7 +19,6 @@ import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.event.level.ChunkEvent;
|
||||
import net.minecraftforge.event.network.ConnectionStartEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent;
|
||||
import net.minecraftforge.event.TickEvent.ServerTickEvent;
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.listener.Priority;
|
||||
import net.minecraftforge.eventbus.api.listener.SubscribeEvent;
|
||||
@@ -59,16 +58,6 @@ public final class ForgeInternalHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
static void onServerTick(ServerTickEvent.Pre event) {
|
||||
WorldWorkerManager.tick(true);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
static void onServerTick(ServerTickEvent.Post event) {
|
||||
WorldWorkerManager.tick(false);
|
||||
}
|
||||
|
||||
// @SubscribeEvent
|
||||
// static void checkSettings(ClientTickEvent event) {
|
||||
// if (event.phase == Phase.END)
|
||||
|
||||
@@ -20,23 +20,25 @@ import net.minecraft.world.entity.npc.VillagerTrades.ItemListing;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraftforge.event.village.VillagerTradesEvent;
|
||||
import net.minecraftforge.event.village.WandererTradesEvent;
|
||||
import net.minecraftforge.common.util.Lazy;
|
||||
import net.minecraftforge.event.server.ServerAboutToStartEvent;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
public class VillagerTradingManager {
|
||||
private static final Map<ResourceKey<VillagerProfession>, Int2ObjectMap<ItemListing[]>> VANILLA_TRADES = new HashMap<>();
|
||||
private static final List<Pair<ItemListing[], Integer>> WANDERER_TRADES = new ArrayList<>();
|
||||
private static final Lazy<Map<ResourceKey<VillagerProfession>, Int2ObjectMap<ItemListing[]>>> VANILLA_TRADES = Lazy.of(VillagerTradingManager::copyVanillaTrades);
|
||||
private static final Lazy<List<Pair<ItemListing[], Integer>>> WANDERER_TRADES = Lazy.of(() -> new ArrayList<Pair<ItemListing[], Integer>>(VillagerTrades.WANDERING_TRADER_TRADES));
|
||||
|
||||
static {
|
||||
private static Map<ResourceKey<VillagerProfession>, Int2ObjectMap<ItemListing[]>> copyVanillaTrades() {
|
||||
var ret = new HashMap<ResourceKey<VillagerProfession>, Int2ObjectMap<ItemListing[]>>();
|
||||
VillagerTrades.TRADES.forEach((key, value) -> {
|
||||
Int2ObjectMap<ItemListing[]> copy = new Int2ObjectOpenHashMap<>();
|
||||
for (var ent : value.int2ObjectEntrySet()) {
|
||||
copy.put(ent.getIntKey(), Arrays.copyOf(ent.getValue(), ent.getValue().length));
|
||||
}
|
||||
VANILLA_TRADES.put(key, copy);
|
||||
ret.put(key, copy);
|
||||
});
|
||||
WANDERER_TRADES.addAll(VillagerTrades.WANDERING_TRADER_TRADES);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void loadTrades(ServerAboutToStartEvent e) {
|
||||
@@ -46,7 +48,9 @@ public class VillagerTradingManager {
|
||||
|
||||
/** Posts the WandererTradesEvent. */
|
||||
private static void postWandererEvent() {
|
||||
var event = WandererTradesEvent.BUS.fire(new WandererTradesEvent(WANDERER_TRADES));
|
||||
if (!WandererTradesEvent.BUS.hasListeners())
|
||||
return;
|
||||
var event = WandererTradesEvent.BUS.fire(new WandererTradesEvent(WANDERER_TRADES.get()));
|
||||
VillagerTrades.WANDERING_TRADER_TRADES.clear();
|
||||
for (var pool : event.getPools())
|
||||
VillagerTrades.WANDERING_TRADER_TRADES.add(Pair.of(pool.getEntries().toArray(ItemListing[]::new), pool.getRolls()));
|
||||
@@ -54,10 +58,13 @@ public class VillagerTradingManager {
|
||||
|
||||
/** Posts a VillagerTradesEvent for each registered profession. */
|
||||
private static void postVillagerEvents() {
|
||||
if (!VillagerTradesEvent.BUS.hasListeners())
|
||||
return;
|
||||
// TODO [VillagerType][1.21.5] Villager Professions are stored as keys in vanilla now? Re-evaluate this.
|
||||
var vanilla = VANILLA_TRADES.get();
|
||||
for (VillagerProfession value : ForgeRegistries.VILLAGER_PROFESSIONS) {
|
||||
var prof = ForgeRegistries.VILLAGER_PROFESSIONS.getResourceKey(value).orElseThrow();
|
||||
Int2ObjectMap<ItemListing[]> trades = VANILLA_TRADES.getOrDefault(prof, new Int2ObjectOpenHashMap<>());
|
||||
Int2ObjectMap<ItemListing[]> trades = vanilla.getOrDefault(prof, new Int2ObjectOpenHashMap<>());
|
||||
Int2ObjectMap<List<ItemListing>> mutableTrades = new Int2ObjectOpenHashMap<>();
|
||||
for (int i = 1; i < 6; i++)
|
||||
mutableTrades.put(i, NonNullList.create());
|
||||
|
||||
@@ -5,73 +5,82 @@
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.listener.EventListener;
|
||||
|
||||
public class WorldWorkerManager
|
||||
{
|
||||
private static final List<IWorker> workers = new ArrayList<>();
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class WorldWorkerManager {
|
||||
private static final ArrayList<IWorker> workers = new ArrayList<>();
|
||||
private static long startTime = -1;
|
||||
private static int index = 0;
|
||||
private static EventListener tickStartListener;
|
||||
private static EventListener tickEndListener;
|
||||
|
||||
public static void tick(boolean start)
|
||||
{
|
||||
if (start)
|
||||
{
|
||||
startTime = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
private static void startTick() {
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private static void endTick() {
|
||||
index = 0;
|
||||
IWorker task = getNext();
|
||||
if (task == null)
|
||||
if (task == null) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
long time = 50 - (System.currentTimeMillis() - startTime);
|
||||
if (time < 10)
|
||||
time = 10; //If ticks are lagging, give us at least 10ms to do something.
|
||||
time += System.currentTimeMillis();
|
||||
|
||||
while (System.currentTimeMillis() < time && task != null)
|
||||
{
|
||||
while (System.currentTimeMillis() < time && task != null) {
|
||||
boolean again = task.doWork();
|
||||
|
||||
if (!task.hasWork())
|
||||
{
|
||||
if (!task.hasWork()) {
|
||||
remove(task);
|
||||
task = getNext();
|
||||
}
|
||||
else if (!again)
|
||||
{
|
||||
} else if (!again) {
|
||||
task = getNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void addWorker(IWorker worker)
|
||||
{
|
||||
workers.add(worker);
|
||||
@Deprecated(forRemoval = true, since = "1.21.8")
|
||||
public static void tick(boolean start) {
|
||||
if (start) startTick();
|
||||
else endTick();
|
||||
}
|
||||
|
||||
private static synchronized IWorker getNext()
|
||||
{
|
||||
public static synchronized void addWorker(IWorker worker) {
|
||||
workers.add(worker);
|
||||
if (tickStartListener == null) {
|
||||
tickStartListener = TickEvent.ServerTickEvent.Pre.BUS.addListener(event -> startTick());
|
||||
tickEndListener = TickEvent.ServerTickEvent.Post.BUS.addListener(event -> endTick());
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized IWorker getNext() {
|
||||
return workers.size() > index ? workers.get(index++) : null;
|
||||
}
|
||||
|
||||
private static synchronized void remove(IWorker worker)
|
||||
{
|
||||
private static synchronized void remove(IWorker worker) {
|
||||
workers.remove(worker);
|
||||
index--;
|
||||
}
|
||||
|
||||
//Internal only, used to clear everything when the server shuts down.
|
||||
public static synchronized void clear()
|
||||
{
|
||||
public static synchronized void clear() {
|
||||
workers.clear();
|
||||
if (tickStartListener != null) {
|
||||
TickEvent.ServerTickEvent.Pre.BUS.removeListener(tickStartListener);
|
||||
TickEvent.ServerTickEvent.Post.BUS.removeListener(tickEndListener);
|
||||
tickStartListener = null;
|
||||
tickEndListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface IWorker
|
||||
{
|
||||
public interface IWorker {
|
||||
boolean hasWork();
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
|
||||
@@ -30,69 +30,27 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
* This event (and items stacking on others in general) is fired on both {@linkplain LogicalSide sides}, but only on {@linkplain LogicalSide#CLIENT the client} in the creative menu.
|
||||
* Practically, that means that listeners of this event should require the player to be in survival mode if using capabilities that are not synced.
|
||||
* <p>
|
||||
* This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* This event is {@linkplain Cancellable cancellable}.
|
||||
* If the event is cancelled, the container's logic halts, the carried item and the slot will not be swapped, and handling is assumed to have been done by the mod.
|
||||
* This also means that the two vanilla checks described above will not be called.
|
||||
*
|
||||
* @param getCarriedItem The stack being carried by the mouse, which may be empty
|
||||
* @param getStackedOnItem The stack currently in the slot being clicked on, which may be empty
|
||||
* @param getSlot The slot being clicked on
|
||||
* @param getClickAction The click action being used. By default, {@linkplain ClickAction#PRIMARY} corresponds to left-click, and {@linkplain ClickAction#SECONDARY} is right-click.
|
||||
* @param getPlayer The player doing the item swap attempt
|
||||
* @param getCarriedSlotAccess A fake slot allowing the listener to see and change what item is being carried
|
||||
*/
|
||||
public final class ItemStackedOnOtherEvent extends MutableEvent implements Cancellable {
|
||||
public record ItemStackedOnOtherEvent(
|
||||
ItemStack getCarriedItem,
|
||||
ItemStack getStackedOnItem,
|
||||
Slot getSlot,
|
||||
ClickAction getClickAction,
|
||||
Player getPlayer,
|
||||
SlotAccess getCarriedSlotAccess
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<ItemStackedOnOtherEvent> BUS = CancellableEventBus.create(ItemStackedOnOtherEvent.class);
|
||||
|
||||
private final ItemStack carriedItem;
|
||||
private final ItemStack stackedOnItem;
|
||||
private final Slot slot;
|
||||
private final ClickAction action;
|
||||
private final Player player;
|
||||
private final SlotAccess carriedSlotAccess;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ItemStackedOnOtherEvent(ItemStack carriedItem, ItemStack stackedOnItem, Slot slot, ClickAction action, Player player, SlotAccess carriedSlotAccess) {
|
||||
this.carriedItem = carriedItem;
|
||||
this.stackedOnItem = stackedOnItem;
|
||||
this.slot = slot;
|
||||
this.action = action;
|
||||
this.player = player;
|
||||
this.carriedSlotAccess = carriedSlotAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the stack being carried by the mouse} This may be empty!
|
||||
*/
|
||||
public ItemStack getCarriedItem() {
|
||||
return carriedItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the stack currently in the slot being clicked on} This may be empty!
|
||||
*/
|
||||
public ItemStack getStackedOnItem() {
|
||||
return stackedOnItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the slot being clicked on}
|
||||
*/
|
||||
public Slot getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the click action being used} By default {@linkplain ClickAction#PRIMARY} corresponds to left-click, and {@linkplain ClickAction#SECONDARY} is right-click.
|
||||
*/
|
||||
public ClickAction getClickAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the player doing the item swap attempt}
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a fake slot allowing the listener to see and change what item is being carried}
|
||||
*/
|
||||
public SlotAccess getCarriedSlotAccess() {
|
||||
return carriedSlotAccess;
|
||||
}
|
||||
public ItemStackedOnOtherEvent {}
|
||||
}
|
||||
@@ -8,8 +8,9 @@ package net.minecraftforge.event;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -17,41 +18,19 @@ import java.util.List;
|
||||
* Fires when a player joins the server or when the reload command is ran,
|
||||
* before tags and crafting recipes are sent to the client. Send datapack data
|
||||
* to clients when this event fires.
|
||||
*
|
||||
* @param getPlayerList The server's player list to get a view of all players.
|
||||
* @param getPlayer The player to sync datapacks to. Null when syncing for all players, such as when the reload command runs.
|
||||
*/
|
||||
public final class OnDatapackSyncEvent extends MutableEvent {
|
||||
@NullMarked
|
||||
public record OnDatapackSyncEvent(PlayerList getPlayerList, @Nullable ServerPlayer getPlayer) implements RecordEvent {
|
||||
public static final EventBus<OnDatapackSyncEvent> BUS = EventBus.create(OnDatapackSyncEvent.class);
|
||||
|
||||
private final PlayerList playerList;
|
||||
|
||||
@Nullable
|
||||
private final ServerPlayer player;
|
||||
|
||||
public OnDatapackSyncEvent(PlayerList playerList, @Nullable ServerPlayer player) {
|
||||
this.playerList = playerList;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The server's player list to get a view of all players.
|
||||
*/
|
||||
public PlayerList getPlayerList() {
|
||||
return this.playerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The player to sync datapacks to. Null when syncing for all players,
|
||||
* such as when the reload command runs.
|
||||
*/
|
||||
@Nullable
|
||||
public ServerPlayer getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A list of players that should receive data during this event, which is the specified player (if not null)
|
||||
* or all players otherwise.
|
||||
*/
|
||||
public List<ServerPlayer> getPlayers() {
|
||||
return this.player == null ? this.playerList.getPlayers() : List.of(this.player);
|
||||
return getPlayer == null ? getPlayerList.getPlayers() : List.of(this.getPlayer);
|
||||
}
|
||||
}
|
||||
@@ -8,50 +8,24 @@ package net.minecraftforge.event;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.server.ReloadableServerResources;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
|
||||
/**
|
||||
* Commands are rebuilt whenever {@link ReloadableServerResources} is recreated.
|
||||
* You can use this event to register your commands whenever the {@link Commands} class in constructed.
|
||||
*
|
||||
* The event is fired on the {@link MinecraftForge#EVENT_BUS}
|
||||
* @param getDispatcher The command dispatcher for registering commands to be executed on the client
|
||||
* @param getCommandSelection The environment the command is being registered for
|
||||
* @param getBuildContext The context to build the commands for
|
||||
*/
|
||||
public final class RegisterCommandsEvent extends MutableEvent {
|
||||
public record RegisterCommandsEvent(
|
||||
CommandDispatcher<CommandSourceStack> getDispatcher,
|
||||
Commands.CommandSelection getCommandSelection,
|
||||
CommandBuildContext getBuildContext
|
||||
) implements RecordEvent {
|
||||
public static final EventBus<RegisterCommandsEvent> BUS = EventBus.create(RegisterCommandsEvent.class);
|
||||
|
||||
private final CommandDispatcher<CommandSourceStack> dispatcher;
|
||||
private final Commands.CommandSelection environment;
|
||||
private final CommandBuildContext context;
|
||||
|
||||
public RegisterCommandsEvent(CommandDispatcher<CommandSourceStack> dispatcher, Commands.CommandSelection environment, CommandBuildContext context) {
|
||||
this.dispatcher = dispatcher;
|
||||
this.environment = environment;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the command dispatcher for registering commands to be executed on the client}
|
||||
*/
|
||||
public CommandDispatcher<CommandSourceStack> getDispatcher() {
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the environment the command is being registered for}
|
||||
*/
|
||||
public Commands.CommandSelection getCommandSelection() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the context to build the commands for}
|
||||
*/
|
||||
public CommandBuildContext getBuildContext() {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,8 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -20,58 +19,26 @@ import org.jetbrains.annotations.Nullable;
|
||||
* <br>
|
||||
* This allows for listening to Vanilla's events in a more structured and global way that is not tied to needing a block entity listener. <br>
|
||||
* <br>
|
||||
* This event is fired on the {@link MinecraftForge#EVENT_BUS}. <br>
|
||||
* <br>
|
||||
* Cancel this event to prevent Vanilla from posting the {@link GameEvent} to all nearby {@link net.minecraft.world.level.gameevent.GameEventListener GameEventListeners}.
|
||||
*
|
||||
* @param getLevel The level the Vanilla {@link GameEvent} occurred in
|
||||
* @param getVanillaEvent The Vanilla event
|
||||
* @param getEventPosition The position the event took place at
|
||||
* @param getContext The context of the Vanilla event
|
||||
**/
|
||||
public final class VanillaGameEvent extends MutableEvent implements Cancellable {
|
||||
public record VanillaGameEvent(
|
||||
Level getLevel,
|
||||
GameEvent getVanillaEvent,
|
||||
Vec3 getEventPosition,
|
||||
GameEvent.Context getContext
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<VanillaGameEvent> BUS = CancellableEventBus.create(VanillaGameEvent.class);
|
||||
|
||||
private final Level level;
|
||||
private final GameEvent vanillaEvent;
|
||||
private final Vec3 position;
|
||||
private final GameEvent.Context context;
|
||||
|
||||
public VanillaGameEvent(Level level, GameEvent vanillaEvent, Vec3 position, GameEvent.Context context) {
|
||||
this.level = level;
|
||||
this.vanillaEvent = vanillaEvent;
|
||||
this.position = position;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The level the Vanilla {@link GameEvent} occurred.
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The entity that was the source or "cause" of the {@link GameEvent}.
|
||||
*/
|
||||
@Nullable
|
||||
public Entity getCause() {
|
||||
return context.sourceEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Vanilla event.
|
||||
*/
|
||||
public GameEvent getVanillaEvent() {
|
||||
return vanillaEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The position the event took place at.
|
||||
*/
|
||||
public Vec3 getEventPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the context of the vanilla event
|
||||
*/
|
||||
public GameEvent.Context getContext() {
|
||||
return context;
|
||||
return getContext.sourceEntity();
|
||||
}
|
||||
}
|
||||
+10
-22
@@ -11,40 +11,28 @@ import java.util.Set;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
|
||||
/**
|
||||
* Fired when the channel registration (see minecraft custom channel documentation) changes.
|
||||
* <br>
|
||||
* It seems plausible that this will fire multiple times for the same state, depending on what the server is doing.
|
||||
* It just directly dispatches upon receipt.
|
||||
*
|
||||
* @param getType The type of change, either {@link Type#REGISTER} or {@link Type#UNREGISTER}
|
||||
*/
|
||||
public final class ChannelRegistrationChangeEvent extends MutableEvent {
|
||||
public record ChannelRegistrationChangeEvent(
|
||||
Connection getSource,
|
||||
Type getType,
|
||||
Set<ResourceLocation> getChannels
|
||||
) implements RecordEvent {
|
||||
public static final EventBus<ChannelRegistrationChangeEvent> BUS = EventBus.create(ChannelRegistrationChangeEvent.class);
|
||||
|
||||
public enum Type {
|
||||
REGISTER, UNREGISTER
|
||||
}
|
||||
|
||||
private final Connection source;
|
||||
private final Type changeType;
|
||||
private final Set<ResourceLocation> channels;
|
||||
|
||||
public ChannelRegistrationChangeEvent(Connection source, Type changeType, Set<ResourceLocation> channels) {
|
||||
this.source = source;
|
||||
this.changeType = changeType;
|
||||
this.channels = Collections.unmodifiableSet(channels);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return changeType;
|
||||
}
|
||||
|
||||
public Connection getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Set<ResourceLocation> getChannels() {
|
||||
return channels;
|
||||
public ChannelRegistrationChangeEvent {
|
||||
getChannels = Collections.unmodifiableSet(getChannels);
|
||||
}
|
||||
}
|
||||
@@ -10,43 +10,20 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.entity.ai.village.VillageSiege;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
|
||||
/**
|
||||
* VillageSiegeEvent is fired just before a zombie siege finds a successful location in
|
||||
* {@code VillageSiege#tryToSetupSiege(ServerLevel)}, to give mods the chance to stop the siege.<br>
|
||||
* <br>
|
||||
* Canceling this event stops the siege.<br>
|
||||
* Cancelling this event stops the siege.<br>
|
||||
*/
|
||||
public final class VillageSiegeEvent extends MutableEvent implements Cancellable {
|
||||
public record VillageSiegeEvent(
|
||||
VillageSiege getSiege,
|
||||
Level getLevel,
|
||||
Player getPlayer,
|
||||
Vec3 getAttemptedSpawnPos
|
||||
) implements Cancellable, RecordEvent {
|
||||
public static final CancellableEventBus<VillageSiegeEvent> BUS = CancellableEventBus.create(VillageSiegeEvent.class);
|
||||
|
||||
private final VillageSiege siege;
|
||||
private final Level level;
|
||||
private final Player player;
|
||||
private final Vec3 attemptedSpawnPos;
|
||||
|
||||
public VillageSiegeEvent(VillageSiege siege, Level level, Player player, Vec3 attemptedSpawnPos) {
|
||||
this.siege = siege;
|
||||
this.level = level;
|
||||
this.player = player;
|
||||
this.attemptedSpawnPos = attemptedSpawnPos;
|
||||
}
|
||||
|
||||
public VillageSiege getSiege() {
|
||||
return siege;
|
||||
}
|
||||
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Vec3 getAttemptedSpawnPos() {
|
||||
return attemptedSpawnPos;
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,12 @@ public class WandererTradesEvent extends MutableEvent implements InheritableEven
|
||||
private final List<ItemListing> entries;
|
||||
|
||||
public Pool(Pair<ItemListing[], Integer> data) {
|
||||
this.rolls = data.getRight();
|
||||
this.entries = new ArrayList<>(Arrays.asList(data.getLeft()));
|
||||
this(Arrays.asList(data.getLeft()), data.getRight());
|
||||
}
|
||||
|
||||
public Pool(List<ItemListing> entries, int rolls) {
|
||||
this.rolls = rolls;
|
||||
this.entries = new ArrayList<>(entries);
|
||||
}
|
||||
|
||||
public int getRolls() {
|
||||
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.fml.event.lifecycle;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.BusGroup;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModLoadingStage;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
@@ -15,7 +16,7 @@ import net.minecraftforge.fml.event.IModBusEvent;
|
||||
* Supplied as a param to your mod's constructor to get access
|
||||
* to the mod EventBus and various mod-specific objects.
|
||||
*/
|
||||
public final class FMLConstructModEvent extends ParallelDispatchEvent {
|
||||
public final class FMLConstructModEvent extends ParallelDispatchEvent implements SelfDestructing {
|
||||
public static EventBus<FMLConstructModEvent> getBus(BusGroup modBusGroup) {
|
||||
return IModBusEvent.getBus(modBusGroup, FMLConstructModEvent.class);
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.gametest;
|
||||
|
||||
import net.minecraft.server.Main;
|
||||
|
||||
public class GameTestMain {
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("forge.enableGameTest", "true");
|
||||
System.setProperty("forge.gameTestServer", "true");
|
||||
Main.main(args);
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,12 @@ package net.minecraftforge.registries;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -55,7 +55,7 @@ public final class IdMappingEvent extends MutableEvent {
|
||||
this.isFrozen = isFrozen;
|
||||
this.remaps = Maps.newHashMap();
|
||||
remaps.forEach((name, rm) -> {
|
||||
List<ModRemapping> tmp = Lists.newArrayList();
|
||||
List<ModRemapping> tmp = new ArrayList<>();
|
||||
rm.forEach((key, value) -> tmp.add(new ModRemapping(name, key, value.currId, value.newId)));
|
||||
tmp.sort(Comparator.comparingInt(o -> o.newId));
|
||||
this.remaps.put(name, ImmutableList.copyOf(tmp));
|
||||
|
||||
@@ -344,6 +344,9 @@ public net.minecraft.client.data.models.ModelProvider$ItemInfoCollector
|
||||
public net.minecraft.client.data.models.ModelProvider$ItemInfoCollector <init>()V # constructor
|
||||
public net.minecraft.client.data.models.ModelProvider$SimpleModelCollector
|
||||
public net.minecraft.client.data.models.ModelProvider$SimpleModelCollector <init>()V # constructor
|
||||
public net.minecraft.client.gui.Gui *() # render methods
|
||||
public net.minecraft.client.gui.GuiGraphics$ScissorStack
|
||||
public net.minecraft.client.gui.GuiGraphics$ScissorStack <init>()V # constructor
|
||||
protected net.minecraft.client.gui.components.AbstractButton f_290895_ # SPRITES
|
||||
protected net.minecraft.client.gui.components.AbstractSelectionList$Entry f_93521_ # list
|
||||
protected net.minecraft.client.gui.components.AbstractSliderButton m_293290_()Lnet/minecraft/resources/ResourceLocation; # getHandleSprite
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:client_command/test_command",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:client_command_test/client_command_test",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "${mod_id} resources",
|
||||
"pack_format": 63
|
||||
"pack_format": 64
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:modify_overlay_test/add_condition",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:modify_overlay_test/full_stack_condition",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:modify_overlay_test/not_present_in_stack",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:modify_overlay_test/ordered_layers",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:pip_test/was_registered",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:render_frame_layer_test/frame_passes_run",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Forge tests resource pack",
|
||||
"pack_format": 63
|
||||
"pack_format": 64
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ 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 final class ExampleMod {
|
||||
// Define mod id in a common place for everything to reference
|
||||
public static final String MODID = "examplemod";
|
||||
// Directly reference a slf4j logger
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.gametest.framework.GameTestHelper;
|
||||
import net.minecraftforge.client.event.RegisterClientCommandsEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.gametest.GameTest;
|
||||
import net.minecraftforge.gametest.GameTestNamespace;
|
||||
import net.minecraftforge.test.BaseTestMod;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
|
||||
@GameTestNamespace("forge")
|
||||
@Mod(ClientCommandTest.MODID)
|
||||
public class ClientCommandTest extends BaseTestMod {
|
||||
public static final String MODID = "client_command";
|
||||
private static final String COMMAND = "testClientCommand";
|
||||
private static int LAST_COMMAND = -1;
|
||||
|
||||
public ClientCommandTest(FMLJavaModLoadingContext context) {
|
||||
super(context, false, false);
|
||||
RegisterClientCommandsEvent.BUS.addListener(this::addCommand);
|
||||
}
|
||||
|
||||
private void addCommand(RegisterClientCommandsEvent event) {
|
||||
event.getDispatcher()
|
||||
.register(Commands.literal(COMMAND)
|
||||
.then(Commands.argument("id", IntegerArgumentType.integer())
|
||||
.executes(ctx -> LAST_COMMAND = IntegerArgumentType.getInteger(ctx, "id"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void testCommand(GameTestHelper helper) throws IllegalAccessException {
|
||||
int random = new Random().nextInt();
|
||||
Minecraft.getInstance().getConnection().sendUnattendedCommand(COMMAND + ' ' + random, null);
|
||||
helper.assertTrue(LAST_COMMAND == random, "Client command did not execute");
|
||||
helper.succeed();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.client;
|
||||
|
||||
import net.minecraft.gametest.framework.GameTestHelper;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.event.AddGuiOverlayLayersEvent;
|
||||
import net.minecraftforge.client.gui.overlay.ForgeLayer;
|
||||
import net.minecraftforge.client.gui.overlay.ForgeLayeredDraw;
|
||||
import net.minecraftforge.common.extensions.IForgeGameTestHelper;
|
||||
import net.minecraftforge.eventbus.api.listener.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.gametest.GameTest;
|
||||
import net.minecraftforge.gametest.GameTestNamespace;
|
||||
import net.minecraftforge.test.BaseTestMod;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import static net.minecraftforge.client.gui.overlay.ForgeLayeredDraw.*;
|
||||
|
||||
@GameTestNamespace("forge")
|
||||
@Mod(ModifyOverlayTest.MODID)
|
||||
public class ModifyOverlayTest extends BaseTestMod {
|
||||
public static final String MODID = "modify_overlay_test";
|
||||
|
||||
private static final ResourceLocation myStackName = name("my_stack_name");
|
||||
private static final ForgeLayeredDraw myLayerStack = new ForgeLayeredDraw(myStackName);
|
||||
|
||||
private static final ForgeLayer notAddedLayer = (gg, tr) -> {};
|
||||
private static final ForgeLayer layerA = (gg,tr) -> {};
|
||||
private static final ResourceLocation layerAName = name("layer_a");
|
||||
private static final ForgeLayer layerB = (gg,tr) -> {};
|
||||
private static final ResourceLocation layerBName = name("layer_b");
|
||||
private static final ForgeLayer layerC = (gg,tr) -> {};
|
||||
private static final ResourceLocation layerCName = name("layer_c");
|
||||
|
||||
|
||||
private static final IForgeGameTestHelper.BoolFlag detectConditionFlag = new IForgeGameTestHelper.BoolFlag("det_cond_flag");
|
||||
private static final IForgeGameTestHelper.BoolFlag detectConditionStackFlag = new IForgeGameTestHelper.BoolFlag("det_cond_stack_flag");
|
||||
private static final IForgeGameTestHelper.BoolFlag enableConditionFlag = new IForgeGameTestHelper.BoolFlag("en_cond_flag");
|
||||
private static final IForgeGameTestHelper.BoolFlag enableConditionStackFlag = new IForgeGameTestHelper.BoolFlag("en_cond_stack_flag");
|
||||
|
||||
private static ForgeLayeredDraw drawStack;
|
||||
|
||||
public ModifyOverlayTest(FMLJavaModLoadingContext context) {
|
||||
super(context, false, false);
|
||||
AddGuiOverlayLayersEvent.getBus(context.getModBusGroup()).addListener(this::overlayTestListener);
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void not_present_in_stack(GameTestHelper helper) {
|
||||
// Test that we can't order against non-existent layers.
|
||||
List<ForgeLayer> internalLayersList = null;
|
||||
try {
|
||||
internalLayersList = getInternalLayersList(drawStack);
|
||||
} catch (Exception e) {
|
||||
helper.fail("Threw a " + e.getMessage() + " when trying to get the inner layer list.");
|
||||
}
|
||||
helper.assertFalse(internalLayersList.contains(notAddedLayer), "Found our layer when we shouldn't have. Not good!");
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void add_condition(GameTestHelper helper) {
|
||||
// Test that we can add conditions to pre-existing layers.
|
||||
helper.assertFalse(detectConditionFlag.getBool(), "Conditional rendering ran when it shouldn't have.");
|
||||
enableConditionFlag.set(true);
|
||||
helper.runAfterDelay(5, () -> {
|
||||
boolean result = detectConditionFlag.getBool();// Just in case of weird race conditions.
|
||||
enableConditionFlag.set(false);
|
||||
helper.assertTrue(result, "");
|
||||
helper.succeed();
|
||||
});
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void ordered_layers(GameTestHelper helper) {
|
||||
// Test that layers are in the correct order.
|
||||
List<ForgeLayer> internalLayersList = null;
|
||||
Map<ResourceLocation, ForgeLayer> check = null;
|
||||
try {
|
||||
Class<?> cls = drawStack.getClass();
|
||||
var field = cls.getDeclaredField("subLayerStacks");
|
||||
var field1 = cls.getDeclaredField("namedLayers");
|
||||
field.setAccessible(true);
|
||||
field1.setAccessible(true);
|
||||
Map<ResourceLocation, Map.Entry<ForgeLayeredDraw, BooleanSupplier>> VROOT = ((Map<ResourceLocation, Map.Entry<ForgeLayeredDraw, BooleanSupplier>>) field.get(drawStack));
|
||||
var PSS = ((ForgeLayeredDraw) VROOT.get(PRE_SLEEP_STACK).getKey());
|
||||
check = ((Map<ResourceLocation, ForgeLayer>) field1.get(PSS));
|
||||
internalLayersList = getInternalLayersList(PSS);
|
||||
} catch (Exception e) {
|
||||
helper.fail("Threw a " + e.getMessage() + " when trying to get the inner layer list.");
|
||||
}
|
||||
int locationOfPotionEffects = internalLayersList.indexOf(check.get(POTION_EFFECTS));
|
||||
int locationOfLayerA = internalLayersList.indexOf(check.get(layerAName));
|
||||
int locationOfLayerB = internalLayersList.indexOf(check.get(layerBName));
|
||||
int locationOfLayerC = internalLayersList.indexOf(check.get(layerCName));
|
||||
helper.assertTrue(locationOfPotionEffects == locationOfLayerA - 1, "Layer offset from vanilla -> A was incorrect");
|
||||
helper.assertTrue(locationOfLayerB == locationOfLayerA + 1, "Layer offset from A -> B was incorrect");
|
||||
helper.assertTrue(locationOfLayerC == locationOfLayerB + 1, "Layer offset from B -> C was incorrect");
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void full_stack_condition(GameTestHelper helper) {
|
||||
// Test conditional rendering & whether a full stack can be added in the first place.
|
||||
helper.assertFalse(detectConditionStackFlag.getBool(), "Conditional rendering ran when it shouldn't have.");
|
||||
enableConditionStackFlag.set(true);
|
||||
helper.runAfterDelay(5, () -> {
|
||||
boolean result = detectConditionStackFlag.getBool();// Just in case of weird race conditions.
|
||||
enableConditionStackFlag.set(false);
|
||||
helper.assertTrue(result, "");
|
||||
helper.succeed();
|
||||
});
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
private void overlayTestListener(AddGuiOverlayLayersEvent event) {
|
||||
drawStack = event.getLayeredDraw();
|
||||
var layeredDraw = event.getLayeredDraw();
|
||||
layeredDraw.addAbove(VANILLA_ROOT, name("i_won_t_exist"), name("non_existent_target_layer"), notAddedLayer);
|
||||
var pEffects = layeredDraw.locateStack(PRE_SLEEP_STACK).get();
|
||||
// Test if layers may be ordered against other layers.
|
||||
// Layers have to be present to be ordered against, of course, but we tested for that already above.
|
||||
pEffects.addAbove(layerBName, POTION_EFFECTS, layerB);
|
||||
pEffects.addAbove(layerCName, layerBName, layerC);
|
||||
layeredDraw.addBelow(PRE_SLEEP_STACK, layerAName, layerBName, layerA);
|
||||
layeredDraw.addConditionTo(PRE_SLEEP_STACK, BOSS_OVERLAY, () -> {
|
||||
if (enableConditionFlag.getBool()) {
|
||||
detectConditionFlag.set(true);
|
||||
return true;
|
||||
} else {
|
||||
detectConditionFlag.set(false);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
myLayerStack.add(name("my_inner_layer_name"), (gg, tr) -> {
|
||||
detectConditionStackFlag.set(true);
|
||||
});
|
||||
// Demonstrates that entire stacks can have conditions attached
|
||||
event.getLayeredDraw()
|
||||
.add(myStackName, myLayerStack, () -> {
|
||||
if (enableConditionStackFlag.getBool()) {
|
||||
return true;
|
||||
} else {
|
||||
detectConditionStackFlag.set(false);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static ResourceLocation name(String name) {
|
||||
return ResourceLocation.fromNamespaceAndPath(MODID, name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<ForgeLayer> getInternalLayersList(ForgeLayeredDraw stack) throws ClassCastException, NoSuchFieldException, IllegalAccessException {
|
||||
Class<?> cls = stack.getClass();
|
||||
var layersField = cls.getDeclaredField("bakedLayers");
|
||||
layersField.setAccessible(true);
|
||||
return (List<ForgeLayer>) layersField.get(stack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.navigation.ScreenPosition;
|
||||
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
||||
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
||||
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.gametest.framework.GameTestHelper;
|
||||
import net.minecraftforge.client.event.RegisterPictureInPictureRendererEvent;
|
||||
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.gametest.GameTest;
|
||||
import net.minecraftforge.gametest.GameTestNamespace;
|
||||
import net.minecraftforge.test.BaseTestMod;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Map;
|
||||
|
||||
@GameTestNamespace("forge")
|
||||
@Mod(PictureInPictureTest.MODID)
|
||||
public class PictureInPictureTest extends BaseTestMod {
|
||||
public static final String MODID = "pip_test";
|
||||
private static int RENDER_FRAMES = 0;
|
||||
|
||||
public PictureInPictureTest(FMLJavaModLoadingContext context) {
|
||||
super(context, false, false);
|
||||
RegisterPictureInPictureRendererEvent.BUS.addListener(this::registerTestPip);
|
||||
ScreenEvent.BackgroundRendered.BUS.addListener(this::onScreenBackground);
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void was_registered(GameTestHelper helper) throws IllegalAccessException, NoSuchFieldException {
|
||||
// Get the GameRenderer instance
|
||||
var gameRenderer = Minecraft.getInstance().gameRenderer;
|
||||
|
||||
// Get the guiRenderer field from GameRenderer class
|
||||
var guiRendererField = gameRenderer.getClass().getDeclaredField("guiRenderer");
|
||||
guiRendererField.setAccessible(true);
|
||||
|
||||
// Get the guiRenderer instance
|
||||
var guiRenderer = guiRendererField.get(gameRenderer);
|
||||
|
||||
// Get the pictureInPictureRenderers field from GuiRenderer class
|
||||
var pictureInPictureRenderersField = guiRenderer.getClass().getDeclaredField("pictureInPictureRenderers");
|
||||
pictureInPictureRenderersField.setAccessible(true);
|
||||
|
||||
// Get the pictureInPictureRenderers map
|
||||
Map<?,?> pictureInPictureRenderers = (Map<?, ?>) pictureInPictureRenderersField.get(guiRenderer);
|
||||
|
||||
helper.assertTrue(pictureInPictureRenderers != null, "PictureInPictureRenderer map was null");
|
||||
helper.assertTrue(pictureInPictureRenderers.containsKey(TestPipRendererState.class), "PictureInPictureRenderer was not registered");
|
||||
helper.succeed();
|
||||
// This is just a example feedback, doesn't matter too much so just show it when the test is run.
|
||||
RENDER_FRAMES = 100;
|
||||
}
|
||||
|
||||
// this will draw a blue box outline in red in the top left corner of a screen.
|
||||
private void onScreenBackground(ScreenEvent.BackgroundRendered event) {
|
||||
if (RENDER_FRAMES <= 0)
|
||||
return;
|
||||
RENDER_FRAMES--;
|
||||
var window = Minecraft.getInstance().getWindow();
|
||||
event.getGuiGraphics().getRenderState().submitPicturesInPictureState(new TestPipRendererState(
|
||||
event.getGuiGraphics(),
|
||||
10,
|
||||
10,
|
||||
20,
|
||||
20,
|
||||
new ScreenRectangle(new ScreenPosition(0, 0), window.getGuiScaledWidth(), window.getGuiScaledHeight())));
|
||||
}
|
||||
|
||||
private void registerTestPip(RegisterPictureInPictureRendererEvent event) {
|
||||
event.register(new TestPipRenderer(event.getBufferSource()));
|
||||
}
|
||||
|
||||
static class TestPipRenderer extends PictureInPictureRenderer<TestPipRendererState> {
|
||||
protected TestPipRenderer(MultiBufferSource.BufferSource bufferSource) {
|
||||
super(bufferSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<TestPipRendererState> getRenderStateClass() {
|
||||
return TestPipRendererState.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderToTexture(TestPipRendererState state, PoseStack poseStack) {
|
||||
var graphics = state.graphics();
|
||||
int red = Color.red.getRGB();
|
||||
int x1 = state.x0 - 1;
|
||||
int y1 = state.y0 - 1;
|
||||
int x2 = x1 + state.x1() + 2;
|
||||
int y2 = y1 + state.y1() + 2;
|
||||
|
||||
graphics.fill(x1 + 2, y1+ 2, x2, y2, Color.BLUE.getRGB());
|
||||
graphics.fill(x1, y1, x2, y1 + 2, red);
|
||||
graphics.fill(x1, y2, x2, y2 + 2, red);
|
||||
graphics.fill(x1, y1, x1 + 2, y2, red);
|
||||
graphics.fill(x2, y1, x2 + 2, y2 + 2, red);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTextureLabel() {
|
||||
return "test_pip_renderer";
|
||||
}
|
||||
}
|
||||
|
||||
record TestPipRendererState(GuiGraphics graphics, int x0, int y0, int x1, int y1, ScreenRectangle scissorArea, ScreenRectangle bounds) implements PictureInPictureRenderState {
|
||||
public TestPipRendererState(GuiGraphics graphics, int x0, int y0, int x1, int y1, ScreenRectangle scissorArea) {
|
||||
this(graphics, x0, y0, x1, y1, scissorArea, PictureInPictureRenderState.getBounds(x0, y0, x1, y1, scissorArea));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float scale() {
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
package net.minecraftforge.debug.client;
|
||||
|
||||
import net.minecraft.client.renderer.LevelTargetBundle;
|
||||
import net.minecraftforge.client.FramePassManager;
|
||||
import net.minecraftforge.client.event.AddFramePassEvent;
|
||||
import net.minecraftforge.common.extensions.IForgeGameTestHelper;
|
||||
import net.minecraftforge.eventbus.api.listener.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.gametest.GameTest;
|
||||
import net.minecraftforge.gametest.GameTestNamespace;
|
||||
import net.minecraftforge.test.BaseTestMod;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.ShapeRenderer;
|
||||
import net.minecraft.gametest.framework.GameTestHelper;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.framegraph.FramePass;
|
||||
|
||||
|
||||
@GameTestNamespace("forge")
|
||||
@Mod(RenderFrameLayerTest.MODID)
|
||||
public class RenderFrameLayerTest extends BaseTestMod {
|
||||
public static final String MODID = "render_frame_layer_test";
|
||||
private static final IForgeGameTestHelper.BoolFlag passOne = new IForgeGameTestHelper.BoolFlag("pass_one_flag");
|
||||
private static final IForgeGameTestHelper.BoolFlag passTwo = new IForgeGameTestHelper.BoolFlag("pass_two_flag");
|
||||
public RenderFrameLayerTest(FMLJavaModLoadingContext context) {
|
||||
super(context, false, false);
|
||||
AddFramePassEvent.BUS.addListener(RenderFrameLayerTest::renderTest);
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void frame_passes_run(GameTestHelper helper) {
|
||||
passOne.set(false); passTwo.set(false); // pass#executes will reset to true if they run
|
||||
helper.runAfterDelay(4, () -> {
|
||||
helper.assertTrue(passOne.getBool(), "Pass One was not executed");
|
||||
helper.assertTrue(passTwo.getBool(), "Pass Two was not executed");
|
||||
helper.succeed();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is working, two white line box cubes will be rendered at ground level in a superflat world around (0,0)
|
||||
*/
|
||||
public static void renderTest(AddFramePassEvent event) {
|
||||
var mainCamera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
FramePassManager.PassDefinition def = new FramePassManager.PassDefinition() {
|
||||
@Override
|
||||
public void targets(LevelTargetBundle bundle, FramePass pass) {
|
||||
bundle.main = pass.readsAndWrites(bundle.main);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executes() {
|
||||
PoseStack ps = new PoseStack();
|
||||
passOne.set(true);
|
||||
ps.translate(mainCamera.getPosition().multiply(-1,-1,-1));
|
||||
ps.pushPose();
|
||||
var buffSource = Minecraft.getInstance().renderBuffers().bufferSource();
|
||||
var vc = buffSource.getBuffer(RenderType.lines());
|
||||
|
||||
ShapeRenderer.renderLineBox(ps, vc, 0, -60, 0, 10, -50, 10, 1f, 1f, 1f, 1f);
|
||||
buffSource.endBatch();
|
||||
ps.popPose();
|
||||
}
|
||||
};
|
||||
event.addPass(rl(MODID), def);
|
||||
FramePassManager.PassDefinition def2 = new FramePassManager.PassDefinition() {
|
||||
@Override
|
||||
public void targets(LevelTargetBundle bundle, FramePass pass) {
|
||||
bundle.main = pass.readsAndWrites(bundle.main);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executes() {
|
||||
PoseStack ps = new PoseStack();
|
||||
passTwo.set(true);
|
||||
ps.translate(mainCamera.getPosition().multiply(-1,-1,-1));
|
||||
ps.pushPose();
|
||||
var buffSource = Minecraft.getInstance().renderBuffers().bufferSource();
|
||||
var vc = buffSource.getBuffer(RenderType.lines());
|
||||
|
||||
ShapeRenderer.renderLineBox(ps, vc, 1, -61, 1, 9, -49, 9, 1f, 1f, 1f, 1f);
|
||||
buffSource.endBatch();
|
||||
ps.popPose();
|
||||
}
|
||||
};
|
||||
event.addPass(rl(MODID+"_two"), def2);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
clientSideOnly=true
|
||||
@@ -1 +0,0 @@
|
||||
clientSideOnly=true
|
||||
@@ -1 +0,0 @@
|
||||
clientSideOnly=true
|
||||
File renamed without changes.
@@ -1 +0,0 @@
|
||||
clientSideOnly=true
|
||||
Reference in new issue
Block a user