From 30b7c8043a3435a8a72740449ca3f78645015d78 Mon Sep 17 00:00:00 2001 From: Frank Bauer Date: Wed, 28 Jul 2021 23:28:42 +0200 Subject: [PATCH 1/4] First network test --- .../ru/bclib/api/dataexchange/Connector.java | 19 +++ .../api/dataexchange/ConnectorClientside.java | 59 ++++++++++ .../api/dataexchange/ConnectorServerside.java | 64 ++++++++++ .../api/dataexchange/DataExchangeAPI.java | 69 +++++++++++ .../bclib/api/dataexchange/DataHandler.java | 111 ++++++++++++++++++ .../dataexchange/DataHandlerDescriptor.java | 20 ++++ .../bclib/api/dataexchange/TestHandler.java | 33 ++++++ .../java/ru/bclib/client/BCLibClient.java | 4 + .../java/ru/bclib/server/BCLibServer.java | 3 + 9 files changed, 382 insertions(+) create mode 100644 src/main/java/ru/bclib/api/dataexchange/Connector.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/DataHandler.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/TestHandler.java diff --git a/src/main/java/ru/bclib/api/dataexchange/Connector.java b/src/main/java/ru/bclib/api/dataexchange/Connector.java new file mode 100644 index 00000000..683c845e --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/Connector.java @@ -0,0 +1,19 @@ +package ru.bclib.api.dataexchange; + +import java.util.HashSet; +import java.util.Set; + +abstract class Connector { + protected final DataExchangeAPI api; + protected final Set descriptors; + + Connector(DataExchangeAPI api) { + this.api = api; + descriptors = new HashSet<>(); + } + public abstract boolean onClient(); + + public void addDescriptor(DataHandlerDescriptor desc){ + this.descriptors.add(desc); + } +} diff --git a/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java b/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java new file mode 100644 index 00000000..aba569a7 --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java @@ -0,0 +1,59 @@ +package ru.bclib.api.dataexchange; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.FriendlyByteBuf; +import ru.bclib.BCLib; + +@Environment(EnvType.CLIENT) +class ConnectorClientside extends Connector { + private Minecraft client; + ConnectorClientside(DataExchangeAPI api) { + super(api); + this.client = null; + } + + + @Override + public boolean onClient() { + return true; + } + + protected void onPlayInit(ClientPacketListener handler, Minecraft client){ + if (this.client!=null && this.client != client){ + BCLib.LOGGER.warning("Client changed!"); + } + this.client = client; + for(DataHandlerDescriptor desc : descriptors){ + ClientPlayNetworking.registerReceiver(desc.identifier, (_client, _handler, _buf, _responseSender)->{ + receiveFromServer(desc, _client, _handler, _buf, _responseSender); + }); + } + } + + void onPlayReady(ClientPacketListener handler, PacketSender sender, Minecraft client){ + + } + + void onPlayDisconnect(ClientPacketListener handler, Minecraft client){ + for(DataHandlerDescriptor desc : descriptors) { + ClientPlayNetworking.unregisterReceiver(desc.identifier); + } + } + + void receiveFromServer(DataHandlerDescriptor desc, Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender){ + DataHandler h = desc.instancer.get(); + h.receiveFromServer(client, handler, buf, responseSender); + } + + void sendToServer(DataHandler h){ + if (client==null){ + throw new RuntimeException("[internal error] Client not initialized yet!"); + } + h.sendToServer(this.client); + } +} diff --git a/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java b/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java new file mode 100644 index 00000000..39ce6253 --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java @@ -0,0 +1,64 @@ +package ru.bclib.api.dataexchange; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import ru.bclib.BCLib; + +@Environment(EnvType.SERVER) +class ConnectorServerside extends Connector { + private MinecraftServer server; + ConnectorServerside(DataExchangeAPI api) { + super(api); + server = null; + } + + @Override + public boolean onClient() { + return false; + } + + protected void onPlayInit(ServerGamePacketListenerImpl handler, MinecraftServer server){ + if (this.server!=null && this.server != server){ + BCLib.LOGGER.warning("Server changed!"); + } + this.server = server; + for(DataHandlerDescriptor desc : descriptors){ + ServerPlayNetworking.registerReceiver(handler, desc.identifier, (_server, _player, _handler, _buf, _responseSender) -> { + receiveFromClient(desc, _server, _player, _handler, _buf, _responseSender); + }); + } + } + + void onPlayReady(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server){ + for(DataHandlerDescriptor desc : descriptors){ + if (desc.sendOnJoin){ + DataHandler h = desc.instancer.get(); + h.sendToClient(server, handler.player); + } + } + } + + void onPlayDisconnect(ServerGamePacketListenerImpl handler, MinecraftServer server){ + for(DataHandlerDescriptor desc : descriptors){ + ServerPlayNetworking.unregisterReceiver(handler, desc.identifier); + } + } + + void receiveFromClient(DataHandlerDescriptor desc, MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender){ + DataHandler h = desc.instancer.get(); + h.receiveFromClient(server, player, handler, buf, responseSender); + } + + void sendToClient(DataHandler h){ + if (server==null){ + throw new RuntimeException("[internal error] Server not initialized yet!"); + } + h.sendToClient(this.server); + } +} diff --git a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java new file mode 100644 index 00000000..1d88fa26 --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java @@ -0,0 +1,69 @@ +package ru.bclib.api.dataexchange; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; + +public class DataExchangeAPI { + private static DataExchangeAPI instance; + private final ConnectorServerside server; + private final ConnectorClientside client; + + public static DataExchangeAPI getInstance(){ + return instance; + } + + private static DataExchangeAPI getOrCreateInstance(boolean isClient){ + if (instance==null){ + instance = new DataExchangeAPI(isClient); + } + return instance; + } + + private DataExchangeAPI(boolean isClient){ + if (isClient){ + client = new ConnectorClientside(this); + server = null; + + ClientPlayConnectionEvents.INIT.register(client::onPlayInit); + ClientPlayConnectionEvents.JOIN.register(client::onPlayReady); + ClientPlayConnectionEvents.DISCONNECT.register(client::onPlayDisconnect); + } else { + client = null; + server = new ConnectorServerside(this); + + ServerPlayConnectionEvents.INIT.register(server::onPlayInit); + ServerPlayConnectionEvents.JOIN.register(server::onPlayReady); + ServerPlayConnectionEvents.DISCONNECT.register(server::onPlayDisconnect); + } + } + + + @Environment(EnvType.CLIENT) + public static void registerClientsideHandler(DataHandlerDescriptor desc){ + DataExchangeAPI api = DataExchangeAPI.getOrCreateInstance(true); + if (api.client == null){ + throw new RuntimeException("[Internal Error] DataExchangeAPI was already created as a Server"); + } + api.client.addDescriptor(desc); + } + + @Environment(EnvType.SERVER) + public static void registerServersideHandler(DataHandlerDescriptor desc){ + DataExchangeAPI api = DataExchangeAPI.getOrCreateInstance(false); + if (api.server == null){ + throw new RuntimeException("[Internal Error] DataExchangeAPI was already created as a Client"); + } + api.server.addDescriptor(desc); + } + + public static void send(DataHandler h){ + if (h.getOriginatesOnServer()){ + DataExchangeAPI.getInstance().server.sendToClient(h); + } else { + DataExchangeAPI.getInstance().client.sendToServer(h); + } + } + +} diff --git a/src/main/java/ru/bclib/api/dataexchange/DataHandler.java b/src/main/java/ru/bclib/api/dataexchange/DataHandler.java new file mode 100644 index 00000000..1200c15c --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/DataHandler.java @@ -0,0 +1,111 @@ +package ru.bclib.api.dataexchange; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.api.networking.v1.PlayerLookup; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import org.jetbrains.annotations.NotNull; + +public abstract class DataHandler { + private final boolean originatesOnServer; + @NotNull + private final ResourceLocation identifier; + + protected DataHandler(ResourceLocation identifier, boolean originatesOnServer){ + this.originatesOnServer = originatesOnServer; + this.identifier = identifier; + } + + final public boolean getOriginatesOnServer(){ + return originatesOnServer; + } + + final public ResourceLocation getIdentifier(){ + return identifier; + } + + @Environment(EnvType.CLIENT) + void receiveFromServer(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender){ + deserializeFromIncomingData(buf, responseSender, false); + client.execute(() -> runOnClient(client)); + } + + @Environment(EnvType.SERVER) + void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender){ + deserializeFromIncomingData(buf, responseSender, true); + server.execute(() -> runOnServer(server)); + } + + protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient){ + } + + @Environment(EnvType.CLIENT) + protected void runOnClient(Minecraft client){ + + } + + @Environment(EnvType.SERVER) + protected void runOnServer(MinecraftServer server){ + + } + + protected void serializeData(FriendlyByteBuf buf) { + + } + + @Environment(EnvType.SERVER) + void sendToClient(MinecraftServer server){ + FriendlyByteBuf buf = PacketByteBufs.create(); + serializeData(buf); + + for (ServerPlayer player : PlayerLookup.all(server)) { + ServerPlayNetworking.send(player, this.identifier, buf); + } + } + + @Environment(EnvType.SERVER) + void sendToClient(MinecraftServer server, ServerPlayer player){ + FriendlyByteBuf buf = PacketByteBufs.create(); + serializeData(buf); + ServerPlayNetworking.send(player, this.identifier, buf); + } + + @Environment(EnvType.CLIENT) + void sendToServer(Minecraft client){ + FriendlyByteBuf buf = PacketByteBufs.create(); + serializeData(buf); + ClientPlayNetworking.send(identifier, buf); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DataHandler that = (DataHandler) o; + return originatesOnServer == that.originatesOnServer && identifier.equals(that.identifier); + } + + @Override + public int hashCode() { + int hash = identifier.hashCode(); + if (originatesOnServer) hash |= 0x80000000; + else hash &=0x7FFFFFFF; + + return hash; + } + + @Override + public String toString() { + return "DataHandler{" + "originatesOnServer=" + originatesOnServer + ", identifier=" + identifier + '}'; + } +} diff --git a/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java b/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java new file mode 100644 index 00000000..9ca5077f --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java @@ -0,0 +1,20 @@ +package ru.bclib.api.dataexchange; + +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Supplier; + +public class DataHandlerDescriptor { + public DataHandlerDescriptor(ResourceLocation identifier, Supplier instancer){ + this(identifier, instancer, false); + } + public DataHandlerDescriptor(ResourceLocation identifier, Supplier instancer, boolean sendOnJoin){ + this.instancer = instancer; + this.identifier = identifier; + this.sendOnJoin = sendOnJoin; + } + + public final boolean sendOnJoin; + public final ResourceLocation identifier; + public final Supplier instancer; +} diff --git a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java new file mode 100644 index 00000000..b805a299 --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java @@ -0,0 +1,33 @@ +package ru.bclib.api.dataexchange; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import ru.bclib.BCLib; + +public class TestHandler extends DataHandler{ + public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "__test"), TestHandler::new, true); + + public TestHandler() { + super(DESCRIPTOR.identifier, true); + } + + @Override + protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) { + BCLib.LOGGER.info("PROCESSING INCOMING TEST-DATA fromClient="+fromClient); + } + + @Override + @Environment(EnvType.CLIENT) + protected void runOnClient(Minecraft client) { + BCLib.LOGGER.info("RUNNING INCOMING TEST-DATA ON CLIENT"); + } + + @Override + protected void serializeData(FriendlyByteBuf buf) { + BCLib.LOGGER.info("BUILDING OUTGOING TEST-DATA ON SERVER"); + } +} diff --git a/src/main/java/ru/bclib/client/BCLibClient.java b/src/main/java/ru/bclib/client/BCLibClient.java index 7b338cfa..27bd5f66 100644 --- a/src/main/java/ru/bclib/client/BCLibClient.java +++ b/src/main/java/ru/bclib/client/BCLibClient.java @@ -3,6 +3,8 @@ package ru.bclib.client; import net.fabricmc.api.ClientModInitializer; import ru.bclib.api.ModIntegrationAPI; import ru.bclib.api.PostInitAPI; +import ru.bclib.api.dataexchange.DataExchangeAPI; +import ru.bclib.api.dataexchange.TestHandler; import ru.bclib.registry.BaseBlockEntityRenders; public class BCLibClient implements ClientModInitializer { @@ -10,6 +12,8 @@ public class BCLibClient implements ClientModInitializer { public void onInitializeClient() { ModIntegrationAPI.registerAll(); BaseBlockEntityRenders.register(); + DataExchangeAPI.registerClientsideHandler(TestHandler.DESCRIPTOR); + PostInitAPI.postInit(true); } } diff --git a/src/main/java/ru/bclib/server/BCLibServer.java b/src/main/java/ru/bclib/server/BCLibServer.java index e1ba1107..9568a169 100644 --- a/src/main/java/ru/bclib/server/BCLibServer.java +++ b/src/main/java/ru/bclib/server/BCLibServer.java @@ -3,11 +3,14 @@ package ru.bclib.server; import net.fabricmc.api.DedicatedServerModInitializer; import ru.bclib.api.ModIntegrationAPI; import ru.bclib.api.PostInitAPI; +import ru.bclib.api.dataexchange.*; public class BCLibServer implements DedicatedServerModInitializer { @Override public void onInitializeServer() { ModIntegrationAPI.registerAll(); + DataExchangeAPI.registerServersideHandler(TestHandler.DESCRIPTOR); + PostInitAPI.postInit(false); } } From 7632c4e498e4b5af97ace04f396d08b4f4f3dc44 Mon Sep 17 00:00:00 2001 From: Frank Bauer Date: Wed, 28 Jul 2021 23:52:18 +0200 Subject: [PATCH 2/4] Send first test-message --- src/main/java/ru/bclib/api/dataexchange/TestHandler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java index b805a299..27fc621b 100644 --- a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java +++ b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java @@ -8,6 +8,8 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import ru.bclib.BCLib; +import java.nio.charset.StandardCharsets; + public class TestHandler extends DataHandler{ public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "__test"), TestHandler::new, true); @@ -17,7 +19,9 @@ public class TestHandler extends DataHandler{ @Override protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) { - BCLib.LOGGER.info("PROCESSING INCOMING TEST-DATA fromClient="+fromClient); + int length = buf.readInt(); + CharSequence text = buf.readCharSequence(length, StandardCharsets.UTF_8); + BCLib.LOGGER.info("PROCESSING INCOMING TEST-DATA fromClient="+fromClient+": "+text); } @Override @@ -28,6 +32,9 @@ public class TestHandler extends DataHandler{ @Override protected void serializeData(FriendlyByteBuf buf) { + CharSequence text = "Welcome from BCLib"; + buf.writeInt(text.length()); + buf.writeCharSequence(text, StandardCharsets.UTF_8); BCLib.LOGGER.info("BUILDING OUTGOING TEST-DATA ON SERVER"); } } From 2260d547dc2f928bee8fc52791e0848294ea2f7a Mon Sep 17 00:00:00 2001 From: Frank Bauer Date: Thu, 29 Jul 2021 10:01:02 +0200 Subject: [PATCH 3/4] changes to run on non dedicated servers as well --- src/main/java/ru/bclib/BCLib.java | 3 + .../ru/bclib/api/dataexchange/Connector.java | 7 +- .../api/dataexchange/ConnectorClientside.java | 19 +++-- .../api/dataexchange/ConnectorServerside.java | 21 +++-- .../api/dataexchange/DataExchangeAPI.java | 78 ++++++++++--------- .../bclib/api/dataexchange/DataHandler.java | 4 - .../dataexchange/DataHandlerDescriptor.java | 17 ++-- .../bclib/api/dataexchange/TestHandler.java | 2 +- .../java/ru/bclib/client/BCLibClient.java | 3 +- .../mixin/common/MinecraftServerMixin.java | 15 +++- .../java/ru/bclib/server/BCLibServer.java | 2 +- 11 files changed, 99 insertions(+), 72 deletions(-) diff --git a/src/main/java/ru/bclib/BCLib.java b/src/main/java/ru/bclib/BCLib.java index d3174cae..6eb2634c 100644 --- a/src/main/java/ru/bclib/BCLib.java +++ b/src/main/java/ru/bclib/BCLib.java @@ -6,6 +6,8 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.resources.ResourceLocation; import ru.bclib.api.TagAPI; import ru.bclib.api.WorldDataAPI; +import ru.bclib.api.dataexchange.DataExchangeAPI; +import ru.bclib.api.dataexchange.TestHandler; import ru.bclib.config.Configs; import ru.bclib.recipes.CraftingRecipes; import ru.bclib.registry.BaseBlockEntities; @@ -26,6 +28,7 @@ public class BCLib implements ModInitializer { CraftingRecipes.init(); WorldDataAPI.registerModCache(MOD_ID); Configs.save(); + DataExchangeAPI.registerDescriptor(TestHandler.DESCRIPTOR); } public static boolean isDevEnvironment() { diff --git a/src/main/java/ru/bclib/api/dataexchange/Connector.java b/src/main/java/ru/bclib/api/dataexchange/Connector.java index 683c845e..55a046a0 100644 --- a/src/main/java/ru/bclib/api/dataexchange/Connector.java +++ b/src/main/java/ru/bclib/api/dataexchange/Connector.java @@ -1,19 +1,16 @@ package ru.bclib.api.dataexchange; -import java.util.HashSet; import java.util.Set; abstract class Connector { protected final DataExchangeAPI api; - protected final Set descriptors; Connector(DataExchangeAPI api) { this.api = api; - descriptors = new HashSet<>(); } public abstract boolean onClient(); - public void addDescriptor(DataHandlerDescriptor desc){ - this.descriptors.add(desc); + protected Set getDescriptors(){ + return api.descriptors; } } diff --git a/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java b/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java index aba569a7..2e34765f 100644 --- a/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java +++ b/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java @@ -28,25 +28,32 @@ class ConnectorClientside extends Connector { BCLib.LOGGER.warning("Client changed!"); } this.client = client; - for(DataHandlerDescriptor desc : descriptors){ - ClientPlayNetworking.registerReceiver(desc.identifier, (_client, _handler, _buf, _responseSender)->{ + for(DataHandlerDescriptor desc : getDescriptors()){ + ClientPlayNetworking.registerReceiver(desc.IDENTIFIER, (_client, _handler, _buf, _responseSender)->{ receiveFromServer(desc, _client, _handler, _buf, _responseSender); }); } } void onPlayReady(ClientPacketListener handler, PacketSender sender, Minecraft client){ - + for(DataHandlerDescriptor desc : getDescriptors()){ + if (desc.sendOnJoin){ + DataHandler h = desc.JOIN_INSTANCE.get(); + if (!h.getOriginatesOnServer()) { + h.sendToServer(client); + } + } + } } void onPlayDisconnect(ClientPacketListener handler, Minecraft client){ - for(DataHandlerDescriptor desc : descriptors) { - ClientPlayNetworking.unregisterReceiver(desc.identifier); + for(DataHandlerDescriptor desc : getDescriptors()) { + ClientPlayNetworking.unregisterReceiver(desc.IDENTIFIER); } } void receiveFromServer(DataHandlerDescriptor desc, Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender){ - DataHandler h = desc.instancer.get(); + DataHandler h = desc.INSTANCE.get(); h.receiveFromServer(client, handler, buf, responseSender); } diff --git a/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java b/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java index 39ce6253..b5d7e920 100644 --- a/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java +++ b/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java @@ -1,7 +1,5 @@ package ru.bclib.api.dataexchange; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.network.FriendlyByteBuf; @@ -10,7 +8,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import ru.bclib.BCLib; -@Environment(EnvType.SERVER) class ConnectorServerside extends Connector { private MinecraftServer server; ConnectorServerside(DataExchangeAPI api) { @@ -28,30 +25,32 @@ class ConnectorServerside extends Connector { BCLib.LOGGER.warning("Server changed!"); } this.server = server; - for(DataHandlerDescriptor desc : descriptors){ - ServerPlayNetworking.registerReceiver(handler, desc.identifier, (_server, _player, _handler, _buf, _responseSender) -> { + for(DataHandlerDescriptor desc : getDescriptors()){ + ServerPlayNetworking.registerReceiver(handler, desc.IDENTIFIER, (_server, _player, _handler, _buf, _responseSender) -> { receiveFromClient(desc, _server, _player, _handler, _buf, _responseSender); }); } } void onPlayReady(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server){ - for(DataHandlerDescriptor desc : descriptors){ + for(DataHandlerDescriptor desc : getDescriptors()){ if (desc.sendOnJoin){ - DataHandler h = desc.instancer.get(); - h.sendToClient(server, handler.player); + DataHandler h = desc.JOIN_INSTANCE.get(); + if (h.getOriginatesOnServer()) { + h.sendToClient(server, handler.player); + } } } } void onPlayDisconnect(ServerGamePacketListenerImpl handler, MinecraftServer server){ - for(DataHandlerDescriptor desc : descriptors){ - ServerPlayNetworking.unregisterReceiver(handler, desc.identifier); + for(DataHandlerDescriptor desc : getDescriptors()){ + ServerPlayNetworking.unregisterReceiver(handler, desc.IDENTIFIER); } } void receiveFromClient(DataHandlerDescriptor desc, MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender){ - DataHandler h = desc.instancer.get(); + DataHandler h = desc.INSTANCE.get(); h.receiveFromClient(server, player, handler, buf, responseSender); } diff --git a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java index 1d88fa26..375103b0 100644 --- a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java +++ b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java @@ -5,57 +5,62 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import java.util.HashSet; +import java.util.Set; + public class DataExchangeAPI { private static DataExchangeAPI instance; - private final ConnectorServerside server; - private final ConnectorClientside client; + private ConnectorServerside server; + private ConnectorClientside client; + protected final Set descriptors; + + + private DataExchangeAPI(){ + descriptors = new HashSet<>(); + } public static DataExchangeAPI getInstance(){ - return instance; - } - - private static DataExchangeAPI getOrCreateInstance(boolean isClient){ if (instance==null){ - instance = new DataExchangeAPI(isClient); + instance = new DataExchangeAPI(); } return instance; } - private DataExchangeAPI(boolean isClient){ - if (isClient){ - client = new ConnectorClientside(this); - server = null; - - ClientPlayConnectionEvents.INIT.register(client::onPlayInit); - ClientPlayConnectionEvents.JOIN.register(client::onPlayReady); - ClientPlayConnectionEvents.DISCONNECT.register(client::onPlayDisconnect); - } else { - client = null; - server = new ConnectorServerside(this); - - ServerPlayConnectionEvents.INIT.register(server::onPlayInit); - ServerPlayConnectionEvents.JOIN.register(server::onPlayReady); - ServerPlayConnectionEvents.DISCONNECT.register(server::onPlayDisconnect); - } + @Environment(EnvType.CLIENT) + private void initClientside(){ + if (client!=null) return; + client = new ConnectorClientside(this); + + ClientPlayConnectionEvents.INIT.register(client::onPlayInit); + ClientPlayConnectionEvents.JOIN.register(client::onPlayReady); + ClientPlayConnectionEvents.DISCONNECT.register(client::onPlayDisconnect); + } + + private void initServerSide(){ + if (server!=null) return; + server = new ConnectorServerside(this); + + ServerPlayConnectionEvents.INIT.register(server::onPlayInit); + ServerPlayConnectionEvents.JOIN.register(server::onPlayReady); + ServerPlayConnectionEvents.DISCONNECT.register(server::onPlayDisconnect); + } + + public static void registerDescriptor(DataHandlerDescriptor desc){ + DataExchangeAPI api = DataExchangeAPI.getInstance(); + api.descriptors.add(desc); } @Environment(EnvType.CLIENT) - public static void registerClientsideHandler(DataHandlerDescriptor desc){ - DataExchangeAPI api = DataExchangeAPI.getOrCreateInstance(true); - if (api.client == null){ - throw new RuntimeException("[Internal Error] DataExchangeAPI was already created as a Server"); - } - api.client.addDescriptor(desc); + public static void prepareClientside(){ + DataExchangeAPI api = DataExchangeAPI.getInstance(); + api.initClientside(); + } - @Environment(EnvType.SERVER) - public static void registerServersideHandler(DataHandlerDescriptor desc){ - DataExchangeAPI api = DataExchangeAPI.getOrCreateInstance(false); - if (api.server == null){ - throw new RuntimeException("[Internal Error] DataExchangeAPI was already created as a Client"); - } - api.server.addDescriptor(desc); + public static void prepareServerside(){ + DataExchangeAPI api = DataExchangeAPI.getInstance(); + api.initServerSide(); } public static void send(DataHandler h){ @@ -66,4 +71,5 @@ public class DataExchangeAPI { } } + } diff --git a/src/main/java/ru/bclib/api/dataexchange/DataHandler.java b/src/main/java/ru/bclib/api/dataexchange/DataHandler.java index 1200c15c..ece8b021 100644 --- a/src/main/java/ru/bclib/api/dataexchange/DataHandler.java +++ b/src/main/java/ru/bclib/api/dataexchange/DataHandler.java @@ -40,7 +40,6 @@ public abstract class DataHandler { client.execute(() -> runOnClient(client)); } - @Environment(EnvType.SERVER) void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender){ deserializeFromIncomingData(buf, responseSender, true); server.execute(() -> runOnServer(server)); @@ -54,7 +53,6 @@ public abstract class DataHandler { } - @Environment(EnvType.SERVER) protected void runOnServer(MinecraftServer server){ } @@ -63,7 +61,6 @@ public abstract class DataHandler { } - @Environment(EnvType.SERVER) void sendToClient(MinecraftServer server){ FriendlyByteBuf buf = PacketByteBufs.create(); serializeData(buf); @@ -73,7 +70,6 @@ public abstract class DataHandler { } } - @Environment(EnvType.SERVER) void sendToClient(MinecraftServer server, ServerPlayer player){ FriendlyByteBuf buf = PacketByteBufs.create(); serializeData(buf); diff --git a/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java b/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java index 9ca5077f..585a3725 100644 --- a/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java +++ b/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java @@ -6,15 +6,22 @@ import java.util.function.Supplier; public class DataHandlerDescriptor { public DataHandlerDescriptor(ResourceLocation identifier, Supplier instancer){ - this(identifier, instancer, false); + this(identifier, instancer, instancer, false); } + public DataHandlerDescriptor(ResourceLocation identifier, Supplier instancer, boolean sendOnJoin){ - this.instancer = instancer; - this.identifier = identifier; + this(identifier, instancer, instancer, sendOnJoin); + } + public DataHandlerDescriptor(ResourceLocation identifier, Supplier receiv_instancer, Supplier join_instancer, boolean sendOnJoin){ + this.INSTANCE = receiv_instancer; + this.JOIN_INSTANCE = join_instancer; + this.IDENTIFIER = identifier; + this.sendOnJoin = sendOnJoin; } public final boolean sendOnJoin; - public final ResourceLocation identifier; - public final Supplier instancer; + public final ResourceLocation IDENTIFIER; + public final Supplier INSTANCE; + public final Supplier JOIN_INSTANCE; } diff --git a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java index 27fc621b..d55612ad 100644 --- a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java +++ b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java @@ -14,7 +14,7 @@ public class TestHandler extends DataHandler{ public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "__test"), TestHandler::new, true); public TestHandler() { - super(DESCRIPTOR.identifier, true); + super(DESCRIPTOR.IDENTIFIER, true); } @Override diff --git a/src/main/java/ru/bclib/client/BCLibClient.java b/src/main/java/ru/bclib/client/BCLibClient.java index 27bd5f66..ff803130 100644 --- a/src/main/java/ru/bclib/client/BCLibClient.java +++ b/src/main/java/ru/bclib/client/BCLibClient.java @@ -4,7 +4,6 @@ import net.fabricmc.api.ClientModInitializer; import ru.bclib.api.ModIntegrationAPI; import ru.bclib.api.PostInitAPI; import ru.bclib.api.dataexchange.DataExchangeAPI; -import ru.bclib.api.dataexchange.TestHandler; import ru.bclib.registry.BaseBlockEntityRenders; public class BCLibClient implements ClientModInitializer { @@ -12,7 +11,7 @@ public class BCLibClient implements ClientModInitializer { public void onInitializeClient() { ModIntegrationAPI.registerAll(); BaseBlockEntityRenders.register(); - DataExchangeAPI.registerClientsideHandler(TestHandler.DESCRIPTOR); + DataExchangeAPI.prepareClientside(); PostInitAPI.postInit(true); } diff --git a/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java b/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java index 0fea24a6..203da109 100644 --- a/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java +++ b/src/main/java/ru/bclib/mixin/common/MinecraftServerMixin.java @@ -1,12 +1,20 @@ package ru.bclib.mixin.common; +import com.mojang.authlib.GameProfileRepository; +import com.mojang.authlib.minecraft.MinecraftSessionService; +import com.mojang.datafixers.DataFixer; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.core.RegistryAccess.RegistryHolder; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerResources; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListenerFactory; +import net.minecraft.server.packs.repository.PackRepository; +import net.minecraft.server.players.GameProfileCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; import net.minecraft.world.level.storage.WorldData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -16,8 +24,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import ru.bclib.api.BiomeAPI; +import ru.bclib.api.dataexchange.DataExchangeAPI; import ru.bclib.recipes.BCLRecipeManager; +import java.net.Proxy; import java.util.Collection; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -34,7 +44,10 @@ public class MinecraftServerMixin { @Final @Shadow protected WorldData worldData; - + @Inject(method = "*", at = @At("TAIL")) + private void bclib_onServerInit(Thread thread, RegistryHolder registryHolder, LevelStorageAccess levelStorageAccess, WorldData worldData, PackRepository packRepository, Proxy proxy, DataFixer dataFixer, ServerResources serverResources, MinecraftSessionService minecraftSessionService, GameProfileRepository gameProfileRepository, GameProfileCache gameProfileCache, ChunkProgressListenerFactory chunkProgressListenerFactory, CallbackInfo ci){ + DataExchangeAPI.prepareServerside(); + } @Inject(method="convertFromRegionFormatIfNeeded", at = @At("HEAD")) private static void bclib_applyPatches(LevelStorageSource.LevelStorageAccess session, CallbackInfo ci){ diff --git a/src/main/java/ru/bclib/server/BCLibServer.java b/src/main/java/ru/bclib/server/BCLibServer.java index 9568a169..d4011c97 100644 --- a/src/main/java/ru/bclib/server/BCLibServer.java +++ b/src/main/java/ru/bclib/server/BCLibServer.java @@ -9,7 +9,7 @@ public class BCLibServer implements DedicatedServerModInitializer { @Override public void onInitializeServer() { ModIntegrationAPI.registerAll(); - DataExchangeAPI.registerServersideHandler(TestHandler.DESCRIPTOR); + DataExchangeAPI.prepareServerside(); PostInitAPI.postInit(false); } From b74f680191ef253dec1df0f9212d5e4b99402f3d Mon Sep 17 00:00:00 2001 From: Frank Bauer Date: Thu, 29 Jul 2021 10:57:58 +0200 Subject: [PATCH 4/4] Added HelloServer handler --- src/main/java/ru/bclib/BCLib.java | 4 +- .../api/dataexchange/DataExchangeAPI.java | 28 +++++++++- .../bclib/api/dataexchange/TestHandler.java | 40 ------------- .../api/dataexchange/handler/HelloServer.java | 56 +++++++++++++++++++ 4 files changed, 85 insertions(+), 43 deletions(-) delete mode 100644 src/main/java/ru/bclib/api/dataexchange/TestHandler.java create mode 100644 src/main/java/ru/bclib/api/dataexchange/handler/HelloServer.java diff --git a/src/main/java/ru/bclib/BCLib.java b/src/main/java/ru/bclib/BCLib.java index 6eb2634c..15f4b841 100644 --- a/src/main/java/ru/bclib/BCLib.java +++ b/src/main/java/ru/bclib/BCLib.java @@ -7,7 +7,7 @@ import net.minecraft.resources.ResourceLocation; import ru.bclib.api.TagAPI; import ru.bclib.api.WorldDataAPI; import ru.bclib.api.dataexchange.DataExchangeAPI; -import ru.bclib.api.dataexchange.TestHandler; +import ru.bclib.api.dataexchange.handler.HelloServer; import ru.bclib.config.Configs; import ru.bclib.recipes.CraftingRecipes; import ru.bclib.registry.BaseBlockEntities; @@ -28,7 +28,7 @@ public class BCLib implements ModInitializer { CraftingRecipes.init(); WorldDataAPI.registerModCache(MOD_ID); Configs.save(); - DataExchangeAPI.registerDescriptor(TestHandler.DESCRIPTOR); + DataExchangeAPI.registerDescriptor(HelloServer.DESCRIPTOR); } public static boolean isDevEnvironment() { diff --git a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java index 375103b0..3796160a 100644 --- a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java +++ b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java @@ -4,6 +4,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.minecraft.network.FriendlyByteBuf; import java.util.HashSet; import java.util.Set; @@ -19,7 +20,7 @@ public class DataExchangeAPI { descriptors = new HashSet<>(); } - public static DataExchangeAPI getInstance(){ + static DataExchangeAPI getInstance(){ if (instance==null){ instance = new DataExchangeAPI(); } @@ -45,12 +46,21 @@ public class DataExchangeAPI { ServerPlayConnectionEvents.DISCONNECT.register(server::onPlayDisconnect); } + /** + * Add a new Descriptor for a DataHandler. + * @param desc The Descriptor you want to add. + */ public static void registerDescriptor(DataHandlerDescriptor desc){ DataExchangeAPI api = DataExchangeAPI.getInstance(); api.descriptors.add(desc); } + /** + * Initializes all datastructures that need to exist in the client component. + *

+ * This is automatically called by BCLib. You can register {@link DataHandler}-Objects before this Method is called + */ @Environment(EnvType.CLIENT) public static void prepareClientside(){ DataExchangeAPI api = DataExchangeAPI.getInstance(); @@ -58,11 +68,27 @@ public class DataExchangeAPI { } + /** + * Initializes all datastructures that need to exist in the server component. + *

+ * This is automatically called by BCLib. You can register {@link DataHandler}-Objects before this Method is called + */ public static void prepareServerside(){ DataExchangeAPI api = DataExchangeAPI.getInstance(); api.initServerSide(); } + + /** + * Sends the Handler. + *

+ * Depending on what the result of {@link DataHandler#getOriginatesOnServer()}, the Data is sent from the server + * to the client (if {@code true}) or the other way around. + *

+ * The method {@link DataHandler#serializeData(FriendlyByteBuf)} is called just before the data is sent. You should + * use this method to add the Data you need to the communication. + * @param h The Data that you want to send + */ public static void send(DataHandler h){ if (h.getOriginatesOnServer()){ DataExchangeAPI.getInstance().server.sendToClient(h); diff --git a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java b/src/main/java/ru/bclib/api/dataexchange/TestHandler.java deleted file mode 100644 index d55612ad..00000000 --- a/src/main/java/ru/bclib/api/dataexchange/TestHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.bclib.api.dataexchange; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import ru.bclib.BCLib; - -import java.nio.charset.StandardCharsets; - -public class TestHandler extends DataHandler{ - public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "__test"), TestHandler::new, true); - - public TestHandler() { - super(DESCRIPTOR.IDENTIFIER, true); - } - - @Override - protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) { - int length = buf.readInt(); - CharSequence text = buf.readCharSequence(length, StandardCharsets.UTF_8); - BCLib.LOGGER.info("PROCESSING INCOMING TEST-DATA fromClient="+fromClient+": "+text); - } - - @Override - @Environment(EnvType.CLIENT) - protected void runOnClient(Minecraft client) { - BCLib.LOGGER.info("RUNNING INCOMING TEST-DATA ON CLIENT"); - } - - @Override - protected void serializeData(FriendlyByteBuf buf) { - CharSequence text = "Welcome from BCLib"; - buf.writeInt(text.length()); - buf.writeCharSequence(text, StandardCharsets.UTF_8); - BCLib.LOGGER.info("BUILDING OUTGOING TEST-DATA ON SERVER"); - } -} diff --git a/src/main/java/ru/bclib/api/dataexchange/handler/HelloServer.java b/src/main/java/ru/bclib/api/dataexchange/handler/HelloServer.java new file mode 100644 index 00000000..571de6d5 --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/handler/HelloServer.java @@ -0,0 +1,56 @@ +package ru.bclib.api.dataexchange.handler; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import ru.bclib.BCLib; +import ru.bclib.api.dataexchange.DataHandler; +import ru.bclib.api.dataexchange.DataHandlerDescriptor; +import ru.bclib.api.datafixer.DataFixerAPI; + +import java.util.Optional; + +public class HelloServer extends DataHandler { + public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_server"), HelloServer::new, true); + + public HelloServer() { + super(DESCRIPTOR.IDENTIFIER, false); + } + + public static String getModVersion(String modID){ + Optional optional = FabricLoader.getInstance().getModContainer(modID); + if (optional.isPresent()) { + ModContainer modContainer = optional.get(); + return modContainer.getMetadata().getVersion().toString(); + } + return "0.0.0"; + } + + protected static String getBCLibVersion(){ + return getModVersion(BCLib.MOD_ID); + } + + @Override + protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean fromClient) { + String bclibVersion = DataFixerAPI.getModVersion(buf.readInt()); + String localBclibVersion = getBCLibVersion(); + + BCLib.LOGGER.info("Hello Server received from BCLib. (server="+localBclibVersion+", client="+bclibVersion+")"); + } + + @Override + @Environment(EnvType.CLIENT) + protected void runOnClient(Minecraft client) { + + } + + @Override + protected void serializeData(FriendlyByteBuf buf) { + buf.writeInt(DataFixerAPI.getModVersion(getBCLibVersion())); + } +}