Compare commits

..
14 Commits
Author SHA1 Message Date
LexManos 837c259668 1.21.8 - Intel Graphic Fixes 2025-07-17 11:09:42 -07:00
LexManos 2e48910b4c Fix crash when clicking links in modlist without being in-world. 2025-07-16 10:21:55 -07:00
LexManos 70dd556db6 Use vanilla's entrypoint for GameTest servers 2025-07-01 23:56:59 -07:00
LexManos e44a558f37 Fix Forge error screen not rendering text correctly. Closes #10569 2025-07-01 23:41:08 -07:00
LexManos 1e154cbe3e Minecraft 1.21.7 - Lava Chickens! 2025-06-30 11:06:39 -07:00
Paint_NinjaandLexManos d5c5df1b64 Bump ASM and EventBus
Improves support for Java 25 and better stability of the compile-time EventBus checks, respectively.

Co-Authored-By: LexManos <[email protected]>
2025-06-25 20:54:00 +01:00
Joseph T. McQuigg 5e75de5eb7 Add WanderTradesEvent#Pool Constructor with List<ItemListing> and int directly (#10566) 2025-06-23 17:06:32 -07:00
Mysticdrew ddb1e52e99 Fix client commands not working when using clickable commands. 2025-06-20 14:39:16 -07:00
Mysticdrew 9e55363e2c Add Event for Picture in Picture renderers registration. 2025-06-20 14:21:27 -07:00
Paint_Ninja 219abfed22 Make more events records 2025-06-20 18:22:53 +01:00
Paint_Ninja 6915753b5a Fix posting cancellable child events with non-cancellable inheritable parents
Also made more events SelfDestructing to save a tad more memory
2025-06-20 10:16:26 +01:00
LexManos 1527738ddc Fix wrong order in filter vanilla commands patch. Fixes #10563 2025-06-19 00:49:08 -07:00
LexManos 18c806f1d0 Fix not being able to break blocks in survival. Closes #10561 2025-06-18 12:28:19 -07:00
Paint_Ninja 47f7c68ed5 Fix bug with strict bulk registration
See EventBus#89 for more details
2025-06-18 18:10:33 +01:00
73 changed files with 598 additions and 620 deletions

No files matched your search

+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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',
@@ -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
View File
@@ -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
@@ -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 -1
View File
@@ -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,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_));
@@ -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/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)) {
@@ -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_) {
@@ -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_));
+3 -3
View File
@@ -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.10')
library('eventbus-validator', 'net.minecraftforge:eventbus-validator:7.0-beta.10')
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')
+1 -1
View File
@@ -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);
@@ -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);
}
}
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
}
@@ -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;
@@ -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();
}
}
@@ -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,8 @@ 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.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
@@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:client_command/test_command",
"max_ticks": 100,
"structure": "forge:empty3x3x3"
}
@@ -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 -1
View File
@@ -1,6 +1,6 @@
{
"pack": {
"description": "${mod_id} resources",
"pack_format": 63
"pack_format": 64
}
}
@@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:pip_test/was_registered",
"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,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;
}
}
}
@@ -1 +0,0 @@
clientSideOnly=true
@@ -1 +0,0 @@
clientSideOnly=true
@@ -1 +0,0 @@
clientSideOnly=true
@@ -1 +0,0 @@
clientSideOnly=true
@@ -1 +0,0 @@
clientSideOnly=true
@@ -1 +0,0 @@
clientSideOnly=true