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
This commit is contained in:
Jab125
2024-04-30 01:31:05 +10:00
committed by GitHub
parent 3f0bf226c4
commit 02c89ba625
12 changed files with 129 additions and 42 deletions

View File

@@ -26,8 +26,6 @@ import dev.architectury.networking.transformers.PacketTransformer;
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 class NetworkAggregator {
public interface Adaptor {
<T extends CustomPacketPayload> void registerC2S(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkManager.NetworkReceiver<T> receiver);
@Environment(EnvType.CLIENT)
<T extends CustomPacketPayload> void registerS2C(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkManager.NetworkReceiver<T> receiver);
<T extends CustomPacketPayload> Packet<?> toC2SPacket(T payload);
@Environment(EnvType.CLIENT)
<T extends CustomPacketPayload> Packet<?> toS2CPacket(T payload);
<T extends CustomPacketPayload> void registerS2CType(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec);

View File

@@ -63,10 +63,23 @@ public class NetworkManagerImpl {
public <T extends CustomPacketPayload> void registerS2C(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkReceiver<T> 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<T extends CustomPacketPayload> implements ClientPlayNetworking.PlayPayloadHandler<T> {
private final NetworkReceiver<T> receiver;
ClientPlayPayloadHandler(NetworkReceiver<T> 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

View File

@@ -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=

View File

@@ -26,6 +26,6 @@ import java.util.function.Supplier;
public class ArchitecturyLiquidBlock extends LiquidBlock {
public ArchitecturyLiquidBlock(Supplier<? extends FlowingFluid> fluid, Properties properties) {
super(fluid, properties);
super(fluid.get(), properties);
}
}

View File

@@ -36,7 +36,7 @@ public class ArchitecturyBucketItem extends BucketItem {
private static final Logger LOGGER = LogManager.getLogger(ArchitecturyBucketItem.class);
public ArchitecturyBucketItem(Supplier<? extends Fluid> fluid, Properties properties) {
super(fluid, properties);
super(fluid.get(), properties);
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.<RegisterCapabilitiesEvent>addListener(event -> {
if (BuiltInRegistries.ITEM.containsValue(this)) {

View File

@@ -28,6 +28,6 @@ import java.util.function.Supplier;
public class ArchitecturyMobBucketItem extends MobBucketItem {
public ArchitecturyMobBucketItem(Supplier<? extends EntityType<?>> entity, Supplier<? extends Fluid> fluid, Supplier<? extends SoundEvent> sound, Properties properties) {
super(entity, fluid, sound, properties);
super(entity.get(), fluid.get(), sound.get(), properties);
}
}

View File

@@ -39,7 +39,7 @@ import net.neoforged.bus.api.EventPriority;
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 class EventHandlerImplClient {
}
@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)

View File

@@ -35,16 +35,14 @@ import net.minecraft.world.level.LevelAccessor;
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 @@ import net.neoforged.neoforge.server.ServerLifecycleHooks;
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 class EventHandlerImplCommon {
}
@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)

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -10,6 +10,7 @@
"MixinMinecraft"
],
"mixins": [
"neoforge.LiquidBlockAccessor",
"neoforge.MixinChunkSerializer",
"MixinFallingBlockEntity",
"MixinItemExtension",

View File

@@ -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<ServerToClientTestPayload> SERVER_TO_CLIENT_TEST_PAYLOAD = new CustomPacketPayload.Type<>(new ResourceLocation(TestMod.MOD_ID, "s2c_test_payload"));
CustomPacketPayload.Type<BigDataPayload> 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 interface TestModNet {
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 interface TestModNet {
return TestModNet.BIG_DATA_PAYLOAD;
}
}
record ServerToClientTestPayload(long num) implements CustomPacketPayload {
@Override
public Type<? extends CustomPacketPayload> type() {
return TestModNet.SERVER_TO_CLIENT_TEST_PAYLOAD;
}
}
}