From 02c89ba625546fc72623cc8629f5c056827530d2 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 30 Apr 2024 01:31:05 +1000 Subject: [PATCH] Fix breakage in NeoForge 20.5.14, fix crash when registering packets on Fabric, fix players getting kicked when a S2C packet is sent to them. (#499) * Fix #497 * Fix #496 * Fix #498 * Add test for #498 * Update architectury.mixins.json --- .../architectury/impl/NetworkAggregator.java | 4 -- .../networking/fabric/NetworkManagerImpl.java | 17 ++++++- gradle.properties | 2 +- .../imitator/ArchitecturyLiquidBlock.java | 2 +- .../imitator/ArchitecturyBucketItem.java | 2 +- .../imitator/ArchitecturyMobBucketItem.java | 2 +- .../event/forge/EventHandlerImplClient.java | 14 +++--- .../event/forge/EventHandlerImplCommon.java | 49 ++++++++++--------- .../fluid/forge/LiquidBlockHooksImpl.java | 3 +- .../forge/neoforge/LiquidBlockAccessor.java | 31 ++++++++++++ .../main/resources/architectury.mixins.json | 1 + .../test/networking/TestModNet.java | 44 +++++++++++++++-- 12 files changed, 129 insertions(+), 42 deletions(-) create mode 100644 neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/LiquidBlockAccessor.java diff --git a/common/src/main/java/dev/architectury/impl/NetworkAggregator.java b/common/src/main/java/dev/architectury/impl/NetworkAggregator.java index 2d3e67edb..e9d9bf65a 100644 --- a/common/src/main/java/dev/architectury/impl/NetworkAggregator.java +++ b/common/src/main/java/dev/architectury/impl/NetworkAggregator.java @@ -26,8 +26,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.minecraft.core.RegistryAccess; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; @@ -190,12 +188,10 @@ public static void registerS2CType(CustomPacketP public interface Adaptor { void registerC2S(CustomPacketPayload.Type type, StreamCodec codec, NetworkManager.NetworkReceiver receiver); - @Environment(EnvType.CLIENT) void registerS2C(CustomPacketPayload.Type type, StreamCodec codec, NetworkManager.NetworkReceiver receiver); Packet toC2SPacket(T payload); - @Environment(EnvType.CLIENT) Packet toS2CPacket(T payload); void registerS2CType(CustomPacketPayload.Type type, StreamCodec codec); diff --git a/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java b/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java index f872095a6..12ec6dbe0 100644 --- a/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java +++ b/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java @@ -63,10 +63,23 @@ public void registerC2S(CustomPacketPayload.Type public void registerS2C(CustomPacketPayload.Type type, StreamCodec codec, NetworkReceiver receiver) { LOGGER.info("Registering S2C receiver with id {}", type.id()); PayloadTypeRegistry.playS2C().register(type, codec); - ClientPlayNetworking.registerGlobalReceiver(type, (payload, fabricContext) -> { + ClientPlayNetworking.registerGlobalReceiver(type, new ClientPlayPayloadHandler<>(receiver)); + } + + // Lambda methods aren't included in @EnvType, so this inelegant solution is used instead. + @Environment(EnvType.CLIENT) + class ClientPlayPayloadHandler implements ClientPlayNetworking.PlayPayloadHandler { + private final NetworkReceiver receiver; + + ClientPlayPayloadHandler(NetworkReceiver receiver) { + this.receiver = receiver; + } + + @Override + public void receive(T payload, ClientPlayNetworking.Context fabricContext) { var context = context(fabricContext.player(), fabricContext.client(), true); receiver.receive(payload, context); - }); + } } @Override diff --git a/gradle.properties b/gradle.properties index 9680aa644..75202266a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ fabric_api_version=0.97.6+1.20.5 mod_menu_version=10.0.0-beta.1 forge_version=50.0.0 -neoforge_version=20.5.0-beta +neoforge_version=20.5.20-beta # Set to empty if not snapshots neoforge_pr= diff --git a/neoforge/src/main/java/dev/architectury/core/block/forge/imitator/ArchitecturyLiquidBlock.java b/neoforge/src/main/java/dev/architectury/core/block/forge/imitator/ArchitecturyLiquidBlock.java index 45daccce7..c5871d8f4 100644 --- a/neoforge/src/main/java/dev/architectury/core/block/forge/imitator/ArchitecturyLiquidBlock.java +++ b/neoforge/src/main/java/dev/architectury/core/block/forge/imitator/ArchitecturyLiquidBlock.java @@ -26,6 +26,6 @@ public class ArchitecturyLiquidBlock extends LiquidBlock { public ArchitecturyLiquidBlock(Supplier fluid, Properties properties) { - super(fluid, properties); + super(fluid.get(), properties); } } \ No newline at end of file diff --git a/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyBucketItem.java b/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyBucketItem.java index 353204870..db8ae5f66 100644 --- a/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyBucketItem.java +++ b/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyBucketItem.java @@ -36,7 +36,7 @@ public class ArchitecturyBucketItem extends BucketItem { private static final Logger LOGGER = LogManager.getLogger(ArchitecturyBucketItem.class); public ArchitecturyBucketItem(Supplier fluid, Properties properties) { - super(fluid, properties); + super(fluid.get(), properties); EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> { bus.addListener(event -> { if (BuiltInRegistries.ITEM.containsValue(this)) { diff --git a/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyMobBucketItem.java b/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyMobBucketItem.java index 3a484a2ab..5afc47b36 100644 --- a/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyMobBucketItem.java +++ b/neoforge/src/main/java/dev/architectury/core/item/forge/imitator/ArchitecturyMobBucketItem.java @@ -28,6 +28,6 @@ public class ArchitecturyMobBucketItem extends MobBucketItem { public ArchitecturyMobBucketItem(Supplier> entity, Supplier fluid, Supplier sound, Properties properties) { - super(entity, fluid, sound, properties); + super(entity.get(), fluid.get(), sound.get(), properties); } } diff --git a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java index 05f477703..febf20e9c 100644 --- a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java +++ b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java @@ -39,7 +39,7 @@ import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.*; -import net.neoforged.neoforge.event.TickEvent; +import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.level.LevelEvent; @@ -52,11 +52,13 @@ public static void event(ItemTooltipEvent event) { } @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(TickEvent.ClientTickEvent event) { - if (event.phase == TickEvent.Phase.START) - ClientTickEvent.CLIENT_PRE.invoker().tick(Minecraft.getInstance()); - else if (event.phase == TickEvent.Phase.END) - ClientTickEvent.CLIENT_POST.invoker().tick(Minecraft.getInstance()); + public static void event(ClientTickEvent.Pre event) { + dev.architectury.event.events.client.ClientTickEvent.CLIENT_PRE.invoker().tick(Minecraft.getInstance()); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void event(ClientTickEvent.Post event) { + dev.architectury.event.events.client.ClientTickEvent.CLIENT_POST.invoker().tick(Minecraft.getInstance()); } @SubscribeEvent(priority = EventPriority.HIGH) diff --git a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java index ff5fd3d5a..43af0fad1 100644 --- a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java +++ b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java @@ -35,16 +35,14 @@ import net.neoforged.bus.api.Event; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.LogicalSide; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.event.CommandEvent; import net.neoforged.neoforge.event.LootTableLoadEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.ServerChatEvent; -import net.neoforged.neoforge.event.TickEvent.LevelTickEvent; -import net.neoforged.neoforge.event.TickEvent.Phase; -import net.neoforged.neoforge.event.TickEvent.PlayerTickEvent; -import net.neoforged.neoforge.event.TickEvent.ServerTickEvent; +import net.neoforged.neoforge.event.tick.LevelTickEvent; +import net.neoforged.neoforge.event.tick.PlayerTickEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent; import net.neoforged.neoforge.event.entity.item.ItemTossEvent; import net.neoforged.neoforge.event.entity.living.AnimalTameEvent; @@ -65,20 +63,26 @@ public class EventHandlerImplCommon { @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerTickEvent event) { - if (event.phase == Phase.START) - TickEvent.SERVER_PRE.invoker().tick(ServerLifecycleHooks.getCurrentServer()); - else if (event.phase == Phase.END) - TickEvent.SERVER_POST.invoker().tick(ServerLifecycleHooks.getCurrentServer()); + public static void event(ServerTickEvent.Pre event) { + TickEvent.SERVER_PRE.invoker().tick(ServerLifecycleHooks.getCurrentServer()); } @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(LevelTickEvent event) { - if (event.side == LogicalSide.SERVER) { - if (event.phase == Phase.START) - TickEvent.SERVER_LEVEL_PRE.invoker().tick((ServerLevel) event.level); - else if (event.phase == Phase.END) - TickEvent.SERVER_LEVEL_POST.invoker().tick((ServerLevel) event.level); + public static void event(ServerTickEvent.Post event) { + TickEvent.SERVER_POST.invoker().tick(ServerLifecycleHooks.getCurrentServer()); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void event(LevelTickEvent.Pre event) { + if (!event.getLevel().isClientSide()) { + TickEvent.SERVER_LEVEL_PRE.invoker().tick((ServerLevel) event.getLevel()); + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void event(LevelTickEvent.Post event) { + if (!event.getLevel().isClientSide()) { + TickEvent.SERVER_LEVEL_POST.invoker().tick((ServerLevel) event.getLevel()); } } @@ -133,12 +137,13 @@ public static void event(CommandEvent event) { } @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(PlayerTickEvent event) { - if (event.phase == Phase.START) { - TickEvent.PLAYER_PRE.invoker().tick(event.player); - } else if (event.phase == Phase.END) { - TickEvent.PLAYER_POST.invoker().tick(event.player); - } + public static void event(PlayerTickEvent.Pre event) { + TickEvent.PLAYER_PRE.invoker().tick(event.getEntity()); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void event(PlayerTickEvent.Post event) { + TickEvent.PLAYER_POST.invoker().tick(event.getEntity()); } @SubscribeEvent(priority = EventPriority.HIGH) diff --git a/neoforge/src/main/java/dev/architectury/hooks/fluid/forge/LiquidBlockHooksImpl.java b/neoforge/src/main/java/dev/architectury/hooks/fluid/forge/LiquidBlockHooksImpl.java index f5f7bb639..e73bd9405 100644 --- a/neoforge/src/main/java/dev/architectury/hooks/fluid/forge/LiquidBlockHooksImpl.java +++ b/neoforge/src/main/java/dev/architectury/hooks/fluid/forge/LiquidBlockHooksImpl.java @@ -19,11 +19,12 @@ package dev.architectury.hooks.fluid.forge; +import dev.architectury.mixin.forge.neoforge.LiquidBlockAccessor; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.material.FlowingFluid; public class LiquidBlockHooksImpl { public static FlowingFluid getFluid(LiquidBlock block) { - return block.getFluid(); + return ((LiquidBlockAccessor) block).getFluid(); } } diff --git a/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/LiquidBlockAccessor.java b/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/LiquidBlockAccessor.java new file mode 100644 index 000000000..54dfc14a8 --- /dev/null +++ b/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/LiquidBlockAccessor.java @@ -0,0 +1,31 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.mixin.forge.neoforge; + +import net.minecraft.world.level.block.LiquidBlock; +import net.minecraft.world.level.material.FlowingFluid; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(LiquidBlock.class) +public interface LiquidBlockAccessor { + @Accessor("fluid") + FlowingFluid getFluid(); +} diff --git a/neoforge/src/main/resources/architectury.mixins.json b/neoforge/src/main/resources/architectury.mixins.json index c9577f146..66e0d7b02 100644 --- a/neoforge/src/main/resources/architectury.mixins.json +++ b/neoforge/src/main/resources/architectury.mixins.json @@ -10,6 +10,7 @@ "MixinMinecraft" ], "mixins": [ + "neoforge.LiquidBlockAccessor", "neoforge.MixinChunkSerializer", "MixinFallingBlockEntity", "MixinItemExtension", diff --git a/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java b/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java index d71a7dab9..58793fadb 100644 --- a/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java +++ b/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java @@ -20,19 +20,17 @@ package dev.architectury.test.networking; import dev.architectury.event.events.client.ClientPlayerEvent; +import dev.architectury.event.events.common.PlayerEvent; import dev.architectury.networking.NetworkManager; import dev.architectury.networking.simple.MessageType; import dev.architectury.networking.simple.SimpleNetworkManager; import dev.architectury.networking.transformers.SplitPacketTransformer; import dev.architectury.test.TestMod; import io.netty.buffer.Unpooled; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.ExtraCodecs; import org.apache.commons.lang3.StringUtils; import java.util.Collections; @@ -47,6 +45,8 @@ public interface TestModNet { // An example Server to Client message MessageType SYNC_DATA = NET.registerS2C("sync_data", SyncDataMessage::new); ResourceLocation BIG_DATA = new ResourceLocation(TestMod.MOD_ID, "big_data"); + ResourceLocation SERVER_TO_CLIENT_TEST = new ResourceLocation(TestMod.MOD_ID, "s2c_test"); + CustomPacketPayload.Type SERVER_TO_CLIENT_TEST_PAYLOAD = new CustomPacketPayload.Type<>(new ResourceLocation(TestMod.MOD_ID, "s2c_test_payload")); CustomPacketPayload.Type BIG_DATA_PAYLOAD = new CustomPacketPayload.Type<>(new ResourceLocation(TestMod.MOD_ID, "big_data_payload")); String BIG_STRING = StringUtils.repeat('a', 100000); @@ -82,6 +82,37 @@ public void encode(RegistryFriendlyByteBuf object, BigDataPayload payload) { throw new AssertionError(value.data()); } }); + + NetworkManager.registerReceiver(NetworkManager.Side.S2C, SERVER_TO_CLIENT_TEST, (buf, context) -> { + long num = buf.readLong(); + if (num == 0xA4C5E75EC7941L) { + TestMod.SINK.accept("S2C worked!, 0xA4C5E75EC7941L"); + } else { + throw new AssertionError(num); + } + }); + + NetworkManager.registerReceiver(NetworkManager.Side.S2C, SERVER_TO_CLIENT_TEST_PAYLOAD, new StreamCodec<>() { + @Override + public ServerToClientTestPayload decode(RegistryFriendlyByteBuf object) { + return new ServerToClientTestPayload(object.readLong()); + } + + @Override + public void encode(RegistryFriendlyByteBuf object, ServerToClientTestPayload payload) { + object.writeLong(payload.num); + } + }, (value, context) -> { + if (value.num() == 0xA4C5E75EC7941L) { + TestMod.SINK.accept("S2C worked!, 0xA4C5E75EC7941L"); + } else { + throw new AssertionError(value.num()); + } + }); + + PlayerEvent.PLAYER_JOIN.register(player -> { + NetworkManager.sendToPlayer(player, new ServerToClientTestPayload(0xA4C5E75EC7941L)); + }); } static void initializeClient() { @@ -101,4 +132,11 @@ public Type type() { return TestModNet.BIG_DATA_PAYLOAD; } } + + record ServerToClientTestPayload(long num) implements CustomPacketPayload { + @Override + public Type type() { + return TestModNet.SERVER_TO_CLIENT_TEST_PAYLOAD; + } + } } \ No newline at end of file