diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/MessageType.java b/projects/common/src/main/java/dan200/computercraft/shared/network/MessageType.java new file mode 100644 index 000000000..b0d436f2a --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/MessageType.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.network; + +/** + * A type of message to send over the network. + *

+ * Much like recipe or argument serialisers, each type of {@link NetworkMessage} should have a unique type associated + * with it. This holds platform-specific information about how the packet should be sent over the network. + * + * @param The type of message to send + * @see NetworkMessages + * @see NetworkMessage#type() + */ +public interface MessageType> { +} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java index 235b1fc1f..6ccfb95e8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java @@ -17,6 +17,13 @@ * @see ServerNetworkContext */ public interface NetworkMessage { + /** + * Get the type of this message. + * + * @return The type of this message. + */ + MessageType type(); + /** * Write this packet to a buffer. *

@@ -24,7 +31,7 @@ public interface NetworkMessage { * * @param buf The buffer to write data to. */ - void toBytes(FriendlyByteBuf buf); + void write(FriendlyByteBuf buf); /** * Handle this {@link NetworkMessage}. diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessages.java b/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessages.java index 6a1c5748f..bf4c1927c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessages.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/NetworkMessages.java @@ -4,48 +4,84 @@ package dan200.computercraft.shared.network; +import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.shared.network.client.*; import dan200.computercraft.shared.network.server.*; import dan200.computercraft.shared.platform.PlatformHelper; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; -import java.util.function.Function; +import java.util.*; /** - * Registry for all packets provided by CC: Tweaked. + * List of all {@link MessageType}s provided by CC: Tweaked. * * @see PlatformHelper The platform helper is used to send packets. */ public final class NetworkMessages { + private static final IntSet seenIds = new IntOpenHashSet(); + private static final Set seenChannel = new HashSet<>(); + private static final List>> serverMessages = new ArrayList<>(); + private static final List>> clientMessages = new ArrayList<>(); + + public static final MessageType COMPUTER_ACTION = registerServerbound(0, "computer_action", ComputerActionServerMessage.class, ComputerActionServerMessage::new); + public static final MessageType QUEUE_EVENT = registerServerbound(1, "queue_event", QueueEventServerMessage.class, QueueEventServerMessage::new); + public static final MessageType KEY_EVENT = registerServerbound(2, "key_event", KeyEventServerMessage.class, KeyEventServerMessage::new); + public static final MessageType MOUSE_EVENT = registerServerbound(3, "mouse_event", MouseEventServerMessage.class, MouseEventServerMessage::new); + public static final MessageType UPLOAD_FILE = registerServerbound(4, "upload_file", UploadFileMessage.class, UploadFileMessage::new); + + public static final MessageType CHAT_TABLE = registerClientbound(10, "chat_table", ChatTableClientMessage.class, ChatTableClientMessage::new); + public static final MessageType POCKET_COMPUTER_DATA = registerClientbound(11, "pocket_computer_data", PocketComputerDataMessage.class, PocketComputerDataMessage::new); + public static final MessageType POCKET_COMPUTER_DELETED = registerClientbound(12, "pocket_computer_deleted", PocketComputerDeletedClientMessage.class, PocketComputerDeletedClientMessage::new); + public static final MessageType COMPUTER_TERMINAL = registerClientbound(13, "computer_terminal", ComputerTerminalClientMessage.class, ComputerTerminalClientMessage::new); + public static final MessageType PLAY_RECORD = registerClientbound(14, "play_record", PlayRecordClientMessage.class, PlayRecordClientMessage::new); + public static final MessageType MONITOR_CLIENT = registerClientbound(15, "monitor_client", MonitorClientMessage.class, MonitorClientMessage::new); + public static final MessageType SPEAKER_AUDIO = registerClientbound(16, "speaker_audio", SpeakerAudioClientMessage.class, SpeakerAudioClientMessage::new); + public static final MessageType SPEAKER_MOVE = registerClientbound(17, "speaker_move", SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new); + public static final MessageType SPEAKER_PLAY = registerClientbound(18, "speaker_play", SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new); + public static final MessageType SPEAKER_STOP = registerClientbound(19, "speaker_stop", SpeakerStopClientMessage.class, SpeakerStopClientMessage::new); + public static final MessageType UPLOAD_RESULT = registerClientbound(20, "upload_result", UploadResultMessage.class, UploadResultMessage::new); + public static final MessageType UPGRADES_LOADED = registerClientbound(21, "upgrades_loaded", UpgradesLoadedMessage.class, UpgradesLoadedMessage::new); + private NetworkMessages() { } - public interface PacketRegistry { - > void registerClientbound(int id, Class type, Function decoder); - - > void registerServerbound(int id, Class type, Function decoder); + private static > MessageType register( + List>> messages, + int id, String channel, Class klass, FriendlyByteBuf.Reader reader + ) { + if (!seenIds.add(id)) throw new IllegalArgumentException("Duplicate id " + id); + if (!seenChannel.add(channel)) throw new IllegalArgumentException("Duplicate channel " + channel); + var type = PlatformHelper.get().createMessageType(id, new ResourceLocation(ComputerCraftAPI.MOD_ID, channel), klass, reader); + messages.add(type); + return type; } - public static void register(PacketRegistry registry) { - // Server messages - registry.registerServerbound(0, ComputerActionServerMessage.class, ComputerActionServerMessage::new); - registry.registerServerbound(1, QueueEventServerMessage.class, QueueEventServerMessage::new); - registry.registerServerbound(2, KeyEventServerMessage.class, KeyEventServerMessage::new); - registry.registerServerbound(3, MouseEventServerMessage.class, MouseEventServerMessage::new); - registry.registerServerbound(4, UploadFileMessage.class, UploadFileMessage::new); + private static > MessageType registerServerbound(int id, String channel, Class klass, FriendlyByteBuf.Reader reader) { + return register(serverMessages, id, channel, klass, reader); + } - // Client messages - registry.registerClientbound(10, ChatTableClientMessage.class, ChatTableClientMessage::new); - registry.registerClientbound(11, PocketComputerDataMessage.class, PocketComputerDataMessage::new); - registry.registerClientbound(12, PocketComputerDeletedClientMessage.class, PocketComputerDeletedClientMessage::new); - registry.registerClientbound(13, ComputerTerminalClientMessage.class, ComputerTerminalClientMessage::new); - registry.registerClientbound(14, PlayRecordClientMessage.class, PlayRecordClientMessage::new); - registry.registerClientbound(15, MonitorClientMessage.class, MonitorClientMessage::new); - registry.registerClientbound(16, SpeakerAudioClientMessage.class, SpeakerAudioClientMessage::new); - registry.registerClientbound(17, SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new); - registry.registerClientbound(18, SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new); - registry.registerClientbound(19, SpeakerStopClientMessage.class, SpeakerStopClientMessage::new); - registry.registerClientbound(20, UploadResultMessage.class, UploadResultMessage::new); - registry.registerClientbound(21, UpgradesLoadedMessage.class, UpgradesLoadedMessage::new); + private static > MessageType registerClientbound(int id, String channel, Class klass, FriendlyByteBuf.Reader reader) { + return register(clientMessages, id, channel, klass, reader); + } + + /** + * Get all serverbound message types. + * + * @return An unmodifiable sequence of all serverbound message types. + */ + public static Collection>> getServerbound() { + return Collections.unmodifiableCollection(serverMessages); + } + + /** + * Get all clientbound message types. + * + * @return An unmodifiable sequence of all clientbound message types. + */ + public static Collection>> getClientbound() { + return Collections.unmodifiableCollection(clientMessages); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java index 73f7e48c2..d5ed9caca 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java @@ -5,7 +5,9 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.command.text.TableBuilder; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -43,7 +45,7 @@ public ChatTableClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeUtf(table.getId(), MAX_LEN); buf.writeVarInt(table.getColumns()); buf.writeBoolean(table.getHeaders() != null); @@ -63,4 +65,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleChatTable(table); } + + @Override + public MessageType type() { + return NetworkMessages.CHAT_TABLE; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java index 99656d4bb..e47bbf25c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java @@ -5,7 +5,9 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.computer.terminal.TerminalState; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -25,7 +27,7 @@ public ComputerTerminalClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeVarInt(containerId); terminal.write(buf); } @@ -34,4 +36,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleComputerTerminal(containerId, terminal); } + + @Override + public MessageType type() { + return NetworkMessages.COMPUTER_TERMINAL; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java index 5b1ee9680..efe0476c8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java @@ -5,7 +5,9 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.computer.terminal.TerminalState; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -25,7 +27,7 @@ public MonitorClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeBlockPos(pos); state.write(buf); } @@ -34,4 +36,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleMonitorData(pos, state); } + + @Override + public MessageType type() { + return NetworkMessages.MONITOR_CLIENT; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java index 7257e1ab0..c5580ae48 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java @@ -4,7 +4,9 @@ package dan200.computercraft.shared.network.client; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -43,7 +45,7 @@ public PlayRecordClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeBlockPos(pos); buf.writeNullable(soundEvent, (b, e) -> e.writeToNetwork(b)); buf.writeNullable(name, FriendlyByteBuf::writeUtf); @@ -53,4 +55,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handlePlayRecord(pos, soundEvent, name); } + + @Override + public MessageType type() { + return NetworkMessages.PLAY_RECORD; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDataMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDataMessage.java index 32a7483e9..2d032a800 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDataMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDataMessage.java @@ -7,7 +7,9 @@ import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.terminal.NetworkedTerminal; import dan200.computercraft.shared.computer.terminal.TerminalState; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.pocket.core.PocketServerComputer; import net.minecraft.network.FriendlyByteBuf; @@ -35,7 +37,7 @@ public PocketComputerDataMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeVarInt(instanceId); buf.writeEnum(state); buf.writeVarInt(lightState); @@ -46,4 +48,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handlePocketComputerData(instanceId, state, lightState, terminal); } + + @Override + public MessageType type() { + return NetworkMessages.POCKET_COMPUTER_DATA; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDeletedClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDeletedClientMessage.java index 7a89bd4a3..6ce365c69 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDeletedClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/PocketComputerDeletedClientMessage.java @@ -4,7 +4,9 @@ package dan200.computercraft.shared.network.client; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; @@ -20,7 +22,7 @@ public PocketComputerDeletedClientMessage(FriendlyByteBuf buffer) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeVarInt(instanceId); } @@ -28,4 +30,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handlePocketComputerDeleted(instanceId); } + + @Override + public MessageType type() { + return NetworkMessages.POCKET_COMPUTER_DELETED; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerAudioClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerAudioClientMessage.java index 9b085b541..c98f4366a 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerAudioClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerAudioClientMessage.java @@ -4,7 +4,9 @@ package dan200.computercraft.shared.network.client; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity; import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; import net.minecraft.network.FriendlyByteBuf; @@ -47,7 +49,7 @@ public SpeakerAudioClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeUUID(source); pos.write(buf); buf.writeFloat(volume); @@ -58,4 +60,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleSpeakerAudio(source, pos, volume); } + + @Override + public MessageType type() { + return NetworkMessages.SPEAKER_AUDIO; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerMoveClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerMoveClientMessage.java index bf9456316..fd7704321 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerMoveClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerMoveClientMessage.java @@ -4,7 +4,9 @@ package dan200.computercraft.shared.network.client; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity; import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; import net.minecraft.network.FriendlyByteBuf; @@ -33,7 +35,7 @@ public SpeakerMoveClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeUUID(source); pos.write(buf); } @@ -42,4 +44,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleSpeakerMove(source, pos); } + + @Override + public MessageType type() { + return NetworkMessages.SPEAKER_MOVE; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerPlayClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerPlayClientMessage.java index d45cf2a82..68eb1e63a 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerPlayClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerPlayClientMessage.java @@ -4,7 +4,9 @@ package dan200.computercraft.shared.network.client; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity; import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; import net.minecraft.network.FriendlyByteBuf; @@ -43,7 +45,7 @@ public SpeakerPlayClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeUUID(source); pos.write(buf); buf.writeResourceLocation(sound); @@ -55,4 +57,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleSpeakerPlay(source, pos, sound, volume, pitch); } + + @Override + public MessageType type() { + return NetworkMessages.SPEAKER_PLAY; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerStopClientMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerStopClientMessage.java index 7cbe7ace5..ac90d59c3 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerStopClientMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/SpeakerStopClientMessage.java @@ -4,7 +4,9 @@ package dan200.computercraft.shared.network.client; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity; import net.minecraft.network.FriendlyByteBuf; @@ -29,7 +31,7 @@ public SpeakerStopClientMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeUUID(source); } @@ -37,4 +39,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleSpeakerStop(source); } + + @Override + public MessageType type() { + return NetworkMessages.SPEAKER_STOP; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/UpgradesLoadedMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/UpgradesLoadedMessage.java index 61371e256..98f9e2ff7 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/UpgradesLoadedMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/UpgradesLoadedMessage.java @@ -13,7 +13,9 @@ import dan200.computercraft.impl.PocketUpgrades; import dan200.computercraft.impl.TurtleUpgrades; import dan200.computercraft.impl.UpgradeManager; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.platform.PlatformHelper; import net.minecraft.core.Registry; import net.minecraft.network.FriendlyByteBuf; @@ -27,7 +29,7 @@ /** * Syncs turtle and pocket upgrades to the client. */ -public class UpgradesLoadedMessage implements NetworkMessage { +public final class UpgradesLoadedMessage implements NetworkMessage { private final Map, ITurtleUpgrade>> turtleUpgrades; private final Map, IPocketUpgrade>> pocketUpgrades; @@ -65,7 +67,7 @@ private , T extends UpgradeBase> Map type() { + return NetworkMessages.UPGRADES_LOADED; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/client/UploadResultMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/client/UploadResultMessage.java index a3a94e1a8..ec2b8e192 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/client/UploadResultMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/client/UploadResultMessage.java @@ -6,7 +6,9 @@ import dan200.computercraft.core.util.Nullability; import dan200.computercraft.shared.computer.upload.UploadResult; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -43,7 +45,7 @@ public UploadResultMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeVarInt(containerId); buf.writeEnum(result); if (result == UploadResult.ERROR) buf.writeComponent(Nullability.assertNonNull(errorMessage)); @@ -53,4 +55,9 @@ public void toBytes(FriendlyByteBuf buf) { public void handle(ClientNetworkContext context) { context.handleUploadResult(containerId, result, errorMessage); } + + @Override + public MessageType type() { + return NetworkMessages.UPLOAD_RESULT; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java index c4e3afc20..e4811f8e3 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java @@ -5,6 +5,8 @@ package dan200.computercraft.shared.network.server; import dan200.computercraft.shared.computer.menu.ComputerMenu; +import dan200.computercraft.shared.network.MessageType; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -23,8 +25,8 @@ public ComputerActionServerMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { - super.toBytes(buf); + public void write(FriendlyByteBuf buf) { + super.write(buf); buf.writeEnum(action); } @@ -37,6 +39,11 @@ protected void handle(ServerNetworkContext context, ComputerMenu container) { } } + @Override + public MessageType type() { + return NetworkMessages.COMPUTER_ACTION; + } + public enum Action { TURN_ON, SHUTDOWN, diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java index f905e547b..c7bfe2d10 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java @@ -28,7 +28,7 @@ public ComputerServerMessage(FriendlyByteBuf buffer) { @Override @OverridingMethodsMustInvokeSuper - public void toBytes(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf) { buf.writeVarInt(containerId); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java index 8b6326e28..addcddc27 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java @@ -5,6 +5,8 @@ package dan200.computercraft.shared.network.server; import dan200.computercraft.shared.computer.menu.ComputerMenu; +import dan200.computercraft.shared.network.MessageType; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -30,8 +32,8 @@ public KeyEventServerMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { - super.toBytes(buf); + public void write(FriendlyByteBuf buf) { + super.write(buf); buf.writeByte(type); buf.writeVarInt(key); } @@ -45,4 +47,9 @@ protected void handle(ServerNetworkContext context, ComputerMenu container) { input.keyDown(key, type == TYPE_REPEAT); } } + + @Override + public MessageType type() { + return NetworkMessages.KEY_EVENT; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java index 82ef129fe..d76f2e6e2 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java @@ -5,6 +5,8 @@ package dan200.computercraft.shared.network.server; import dan200.computercraft.shared.computer.menu.ComputerMenu; +import dan200.computercraft.shared.network.MessageType; +import dan200.computercraft.shared.network.NetworkMessages; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -37,8 +39,8 @@ public MouseEventServerMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { - super.toBytes(buf); + public void write(FriendlyByteBuf buf) { + super.write(buf); buf.writeByte(type); buf.writeVarInt(arg); buf.writeVarInt(x); @@ -55,4 +57,9 @@ protected void handle(ServerNetworkContext context, ComputerMenu container) { case TYPE_SCROLL -> input.mouseScroll(arg, x, y); } } + + @Override + public MessageType type() { + return NetworkMessages.MOUSE_EVENT; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java index 56b8baff7..057718ef9 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java @@ -7,6 +7,8 @@ import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.menu.ComputerMenu; import dan200.computercraft.shared.computer.menu.ServerInputHandler; +import dan200.computercraft.shared.network.MessageType; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.util.NBTUtil; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -37,8 +39,8 @@ public QueueEventServerMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { - super.toBytes(buf); + public void write(FriendlyByteBuf buf) { + super.write(buf); buf.writeUtf(event); buf.writeNbt(args == null ? null : NBTUtil.encodeObjects(args)); } @@ -47,4 +49,9 @@ public void toBytes(FriendlyByteBuf buf) { protected void handle(ServerNetworkContext context, ComputerMenu container) { container.getInput().queueEvent(event, args); } + + @Override + public MessageType type() { + return NetworkMessages.QUEUE_EVENT; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java index 384a0093c..d96ec0a81 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java @@ -9,6 +9,8 @@ import dan200.computercraft.shared.computer.upload.FileSlice; import dan200.computercraft.shared.computer.upload.FileUpload; import dan200.computercraft.shared.config.Config; +import dan200.computercraft.shared.network.MessageType; +import dan200.computercraft.shared.network.NetworkMessages; import io.netty.handler.codec.DecoderException; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -91,8 +93,8 @@ public UploadFileMessage(FriendlyByteBuf buf) { } @Override - public void toBytes(FriendlyByteBuf buf) { - super.toBytes(buf); + public void write(FriendlyByteBuf buf) { + super.write(buf); buf.writeUUID(uuid); buf.writeByte(flag); @@ -166,4 +168,9 @@ protected void handle(ServerNetworkContext context, ComputerMenu container) { input.continueUpload(uuid, slices); if ((flag & FLAG_LAST) != 0) input.finishUpload(player, uuid); } + + @Override + public MessageType type() { + return NetworkMessages.UPLOAD_FILE; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java b/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java index 7df773f10..f38645759 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java @@ -10,6 +10,7 @@ import dan200.computercraft.api.network.wired.WiredElement; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.config.ConfigFile; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.network.container.ContainerData; @@ -164,6 +165,18 @@ static PlatformHelper get() { */ void openMenu(Player player, MenuProvider owner, ContainerData menu); + /** + * Create a new {@link MessageType}. + * + * @param id The descriminator for this message type. + * @param channel The channel name for this message type. + * @param klass The type of this message. + * @param reader The function which reads the packet from a buffer. Should be the inverse to {@link NetworkMessage#write(FriendlyByteBuf)}. + * @param The type of this message. + * @return The new {@link MessageType} instance. + */ + > MessageType createMessageType(int id, ResourceLocation channel, Class klass, FriendlyByteBuf.Reader reader); + /** * Send a message to a specific player. * diff --git a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java index fdb154833..240c16a57 100644 --- a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java +++ b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java @@ -13,6 +13,7 @@ import dan200.computercraft.impl.AbstractComputerCraftAPI; import dan200.computercraft.impl.ComputerCraftAPIService; import dan200.computercraft.shared.config.ConfigFile; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.network.container.ContainerData; @@ -168,6 +169,13 @@ public void openMenu(Player player, MenuProvider owner, ContainerData menu) { throw new UnsupportedOperationException("Cannot open menu inside tests"); } + @Override + public > MessageType createMessageType(int id, ResourceLocation channel, Class klass, FriendlyByteBuf.Reader reader) { + record TypeImpl>(Function reader) implements MessageType { + } + return new TypeImpl<>(reader); + } + @Override public ComponentAccess createPeripheralAccess(Consumer invalidate) { throw new UnsupportedOperationException("Cannot interact with the world inside tests"); diff --git a/projects/common/src/test/java/dan200/computercraft/shared/network/client/PlayRecordClientMessageTest.java b/projects/common/src/test/java/dan200/computercraft/shared/network/client/PlayRecordClientMessageTest.java index 368f47037..746adf57a 100644 --- a/projects/common/src/test/java/dan200/computercraft/shared/network/client/PlayRecordClientMessageTest.java +++ b/projects/common/src/test/java/dan200/computercraft/shared/network/client/PlayRecordClientMessageTest.java @@ -29,7 +29,7 @@ class PlayRecordClientMessageTest { @Property public void testRoundTrip(@ForAll("message") PlayRecordClientMessage message) { var buffer = new FriendlyByteBuf(Unpooled.directBuffer()); - message.toBytes(buffer); + message.write(buffer); var converted = new PlayRecordClientMessage(buffer); assertEquals(buffer.readableBytes(), 0, "Whole packet was read"); diff --git a/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java b/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java index 0322f34be..f6a2a2b5b 100644 --- a/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java +++ b/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java @@ -63,7 +63,7 @@ private static List send(List uploads) { private static List roundtripPackets(List packets) { return packets.stream().map(packet -> { var buffer = new FriendlyByteBuf(Unpooled.directBuffer()); - packet.toBytes(buffer); + packet.write(buffer); // We include things like file size in the packet, but not in the count, so grant a slightly larger threshold. assertThat("Packet is too large", buffer.writerIndex(), lessThanOrEqualTo(MAX_PACKET_SIZE + 128)); if ((packet.flag & FLAG_LAST) == 0) { diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java index e42deaa55..d882323cb 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -8,10 +8,11 @@ import dan200.computercraft.client.model.CustomModelLoader; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.config.ConfigSpec; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.peripheral.modem.wired.CableBlock; import dan200.computercraft.shared.platform.FabricConfigFile; -import dan200.computercraft.shared.platform.NetworkHandler; +import dan200.computercraft.shared.platform.FabricMessageType; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; @@ -30,10 +31,11 @@ public class ComputerCraftClient { public static void init() { - ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.ID, (client, handler, buf, responseSender) -> { - var packet = NetworkHandler.decodeClient(buf); - if (packet != null) client.execute(() -> packet.handle(ClientNetworkContext.get())); - }); + for (var type : NetworkMessages.getClientbound()) { + ClientPlayNetworking.registerGlobalReceiver( + FabricMessageType.toFabricType(type), (packet, player, responseSender) -> packet.payload().handle(ClientNetworkContext.get()) + ); + } ClientRegistry.register(); ClientRegistry.registerItemColours(ColorProviderRegistry.ITEM::register); diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java b/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java index f71256f72..ba3af63fa 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java @@ -10,9 +10,9 @@ import dan200.computercraft.client.render.ModelRenderer; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.server.ServerNetworkContext; -import dan200.computercraft.shared.platform.NetworkHandler; +import dan200.computercraft.shared.platform.FabricMessageType; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.entity.ItemRenderer; @@ -29,7 +29,7 @@ public class ClientPlatformHelperImpl implements ClientPlatformHelper { @Override public void sendToServer(NetworkMessage message) { - Minecraft.getInstance().player.connection.send(NetworkHandler.encodeServer(message)); + ClientPlayNetworking.send(FabricMessageType.toFabricPacket(message)); } @Override diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java index d187a1c0e..fc2d06125 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java @@ -13,6 +13,7 @@ import dan200.computercraft.shared.config.Config; import dan200.computercraft.shared.config.ConfigSpec; import dan200.computercraft.shared.details.FluidDetails; +import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.network.client.UpgradesLoadedMessage; import dan200.computercraft.shared.peripheral.commandblock.CommandBlockPeripheral; import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods; @@ -20,7 +21,7 @@ import dan200.computercraft.shared.peripheral.modem.wired.WiredModemFullBlockEntity; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemBlockEntity; import dan200.computercraft.shared.platform.FabricConfigFile; -import dan200.computercraft.shared.platform.NetworkHandler; +import dan200.computercraft.shared.platform.FabricMessageType; import dan200.computercraft.shared.platform.PlatformHelper; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -28,6 +29,7 @@ import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.loot.v2.LootTableEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.minecraft.resources.ResourceLocation; @@ -45,7 +47,12 @@ public class ComputerCraft { private static final LevelResource SERVERCONFIG = new LevelResource("serverconfig"); public static void init() { - NetworkHandler.init(); + for (var type : NetworkMessages.getServerbound()) { + ServerPlayNetworking.registerGlobalReceiver( + FabricMessageType.toFabricType(type), (packet, player, sender) -> packet.payload().handle(() -> player) + ); + } + ModRegistry.register(); ModRegistry.registerMainThread(); diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricMessageType.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricMessageType.java new file mode 100644 index 000000000..d10832cca --- /dev/null +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricMessageType.java @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.platform; + +import dan200.computercraft.shared.network.MessageType; +import dan200.computercraft.shared.network.NetworkMessage; +import net.fabricmc.fabric.api.networking.v1.FabricPacket; +import net.fabricmc.fabric.api.networking.v1.PacketType; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Function; + +/** + * An implementation of {@link MessageType} for Fabric. + *

+ * This provides conversions between the {@link FabricPacket}/{@link PacketType} and {@link NetworkMessage}/{@link MessageType} + * interfaces, allowing us to interop between the two. + * + * @param type The underlying {@link PacketType} + * @param The type of the message. + */ +public record FabricMessageType>( + PacketType> type +) implements MessageType { + public FabricMessageType(ResourceLocation id, Function reader) { + this(PacketType.create(id, b -> new PacketWrapper<>(reader.apply(b)))); + } + + public static > PacketType> toFabricType(MessageType type) { + return ((FabricMessageType) type).type(); + } + + public static FabricPacket toFabricPacket(NetworkMessage message) { + return new PacketWrapper<>(message); + } + + public record PacketWrapper>(T payload) implements FabricPacket { + @Override + public void write(FriendlyByteBuf buf) { + payload().write(buf); + } + + @Override + public PacketType getType() { + return FabricMessageType.toFabricType(payload().type()); + } + } +} diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java deleted file mode 100644 index afcd9f02a..000000000 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.shared.platform; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.shared.network.NetworkMessage; -import dan200.computercraft.shared.network.NetworkMessages; -import dan200.computercraft.shared.network.client.ClientNetworkContext; -import dan200.computercraft.shared.network.server.ServerNetworkContext; -import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.util.function.Function; - -public final class NetworkHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(NetworkHandler.class); - - public static final ResourceLocation ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "main"); - - private static final Int2ObjectMap>> clientPackets = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap>> serverPackets = new Int2ObjectOpenHashMap<>(); - private static final Object2IntMap>> packetIds = new Object2IntOpenHashMap<>(); - - public static void init() { - ServerPlayNetworking.registerGlobalReceiver(ID, (server, player, handler, buf, responseSender) -> { - var packet = decodeServer(buf); - if (packet != null) server.execute(() -> packet.handle(handler::getPlayer)); - }); - - NetworkMessages.register(new NetworkMessages.PacketRegistry() { - @Override - public > void registerClientbound(int id, Class type, Function decoder) { - clientPackets.put(id, decoder); - packetIds.put(type, id); - } - - @Override - public > void registerServerbound(int id, Class type, Function decoder) { - serverPackets.put(id, decoder); - packetIds.put(type, id); - } - }); - } - - private static FriendlyByteBuf encode(NetworkMessage message) { - var buf = new FriendlyByteBuf(Unpooled.buffer()); - buf.writeByte(packetIds.getInt(message.getClass())); - message.toBytes(buf); - return buf; - } - - public static ClientboundCustomPayloadPacket encodeClient(NetworkMessage message) { - return new ClientboundCustomPayloadPacket(ID, encode(message)); - } - - public static ServerboundCustomPayloadPacket encodeServer(NetworkMessage message) { - return new ServerboundCustomPayloadPacket(ID, encode(message)); - } - - @Nullable - private static NetworkMessage decode(Int2ObjectMap>> packets, FriendlyByteBuf buffer) { - int type = buffer.readByte(); - var reader = packets.get(type); - if (reader == null) { - LOGGER.debug("Unknown packet {}", type); - return null; - } - - return reader.apply(buffer); - } - - @Nullable - public static NetworkMessage decodeServer(FriendlyByteBuf buffer) { - return decode(serverPackets, buffer); - } - - @Nullable - public static NetworkMessage decodeClient(FriendlyByteBuf buffer) { - return decode(clientPackets, buffer); - } -} diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java index 9c56aa054..c94d39246 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java @@ -17,6 +17,7 @@ import dan200.computercraft.impl.Peripherals; import dan200.computercraft.mixin.ArgumentTypeInfosAccessor; import dan200.computercraft.shared.config.ConfigFile; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.network.container.ContainerData; @@ -27,6 +28,8 @@ import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache; import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; import net.fabricmc.fabric.api.registry.FuelRegistry; import net.fabricmc.fabric.api.resource.conditions.v1.DefaultResourceConditions; @@ -44,6 +47,8 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -170,31 +175,42 @@ public void openMenu(Player player, MenuProvider owner, ContainerData menu) { player.openMenu(new WrappedMenuProvider(owner, menu)); } + @Override + public > MessageType createMessageType(int id, ResourceLocation channel, Class klass, FriendlyByteBuf.Reader reader) { + return new FabricMessageType<>(channel, reader); + } + + private Packet encodeClientbound(NetworkMessage message) { + var buf = PacketByteBufs.create(); + message.write(buf); + return ServerPlayNetworking.createS2CPacket(FabricMessageType.toFabricType(message.type()).getId(), buf); + } + @Override public void sendToPlayer(NetworkMessage message, ServerPlayer player) { - player.connection.send(NetworkHandler.encodeClient(message)); + player.connection.send(encodeClientbound(message)); } @Override public void sendToPlayers(NetworkMessage message, Collection players) { if (players.isEmpty()) return; - var packet = NetworkHandler.encodeClient(message); + var packet = encodeClientbound(message); for (var player : players) player.connection.send(packet); } @Override public void sendToAllPlayers(NetworkMessage message, MinecraftServer server) { - server.getPlayerList().broadcastAll(NetworkHandler.encodeClient(message)); + server.getPlayerList().broadcastAll(encodeClientbound(message)); } @Override public void sendToAllAround(NetworkMessage message, ServerLevel level, Vec3 pos, float distance) { - level.getServer().getPlayerList().broadcast(null, pos.x, pos.y, pos.z, distance, level.dimension(), NetworkHandler.encodeClient(message)); + level.getServer().getPlayerList().broadcast(null, pos.x, pos.y, pos.z, distance, level.dimension(), encodeClientbound(message)); } @Override public void sendToAllTracking(NetworkMessage message, LevelChunk chunk) { - var packet = NetworkHandler.encodeClient(message); + var packet = encodeClientbound(message); for (var player : ((ServerChunkCache) chunk.getLevel().getChunkSource()).chunkMap.getPlayers(chunk.getPos(), false)) { player.connection.send(packet); } diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java b/projects/forge/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java index d621a2de0..c96e19a5e 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/platform/NetworkHandler.java @@ -5,12 +5,11 @@ package dan200.computercraft.shared.platform; import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.network.server.ServerNetworkContext; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; @@ -47,20 +46,15 @@ private NetworkHandler() { } public static void setup() { - IntSet usedIds = new IntOpenHashSet(); - NetworkMessages.register(new NetworkMessages.PacketRegistry() { - @Override - public > void registerClientbound(int id, Class type, Function decoder) { - if (!usedIds.add(id)) throw new IllegalArgumentException("Already have a packet with id " + id); - registerMainThread(id, NetworkDirection.PLAY_TO_CLIENT, type, decoder, x -> ClientNetworkContext.get()); - } + for (var type : NetworkMessages.getServerbound()) { + var forgeType = (MessageTypeImpl>) type; + registerMainThread(forgeType, NetworkDirection.PLAY_TO_SERVER, c -> () -> assertNonNull(c.getSender())); + } - @Override - public > void registerServerbound(int id, Class type, Function decoder) { - if (!usedIds.add(id)) throw new IllegalArgumentException("Already have a packet with id " + id); - registerMainThread(id, NetworkDirection.PLAY_TO_SERVER, type, decoder, c -> () -> assertNonNull(c.getSender())); - } - }); + for (var type : NetworkMessages.getClientbound()) { + var forgeType = (MessageTypeImpl>) type; + registerMainThread(forgeType, NetworkDirection.PLAY_TO_CLIENT, x -> ClientNetworkContext.get()); + } } static void sendToPlayer(NetworkMessage packet, ServerPlayer player) { @@ -96,19 +90,16 @@ public static void sendToServer(NetworkMessage packet) { * * @param The type of the packet to send. * @param The context this packet is evaluated under. - * @param type The class of the type of packet to send. - * @param id The identifier for this packet type. + * @param type The message type to register. * @param direction A network direction which will be asserted before any processing of this message occurs - * @param decoder The factory for this type of packet. * @param handler Gets or constructs the handler for this packet. */ static > void registerMainThread( - int id, NetworkDirection direction, Class type, Function decoder, - Function handler + MessageTypeImpl type, NetworkDirection direction, Function handler ) { - network.messageBuilder(type, id, direction) - .encoder(NetworkMessage::toBytes) - .decoder(decoder) + network.messageBuilder(type.klass(), type.id(), direction) + .encoder(NetworkMessage::write) + .decoder(type.reader()) .consumerMainThread((packet, contextSup) -> { try { packet.handle(handler.apply(contextSup.get())); @@ -119,4 +110,9 @@ static > void registerMainThread( }) .add(); } + + public record MessageTypeImpl>( + int id, Class klass, Function reader + ) implements MessageType { + } } diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java b/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java index 5d2152b7b..d8ec6098d 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java @@ -15,6 +15,7 @@ import dan200.computercraft.impl.Peripherals; import dan200.computercraft.shared.Capabilities; import dan200.computercraft.shared.config.ConfigFile; +import dan200.computercraft.shared.network.MessageType; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.network.container.ContainerData; @@ -157,6 +158,11 @@ public void openMenu(Player player, MenuProvider owner, ContainerData menu) { NetworkHooks.openScreen((ServerPlayer) player, owner, menu::toBytes); } + @Override + public > MessageType createMessageType(int id, ResourceLocation channel, Class klass, FriendlyByteBuf.Reader reader) { + return new NetworkHandler.MessageTypeImpl<>(id, klass, reader); + } + @Override public void sendToPlayer(NetworkMessage message, ServerPlayer player) { NetworkHandler.sendToPlayer(message, player);