diff --git a/src/main/java/ru/bclib/api/dataexchange/BaseDataHandler.java b/src/main/java/ru/bclib/api/dataexchange/BaseDataHandler.java new file mode 100644 index 00000000..eedeba27 --- /dev/null +++ b/src/main/java/ru/bclib/api/dataexchange/BaseDataHandler.java @@ -0,0 +1,98 @@ +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.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; + +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +public abstract class BaseDataHandler { + private final boolean originatesOnServer; + @NotNull + private final ResourceLocation identifier; + + protected BaseDataHandler(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) + abstract void receiveFromServer(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender); + + private ServerPlayer lastMessageSender; + + void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender) { + lastMessageSender = player; + } + + final protected boolean reply(BaseDataHandler message, MinecraftServer server) { + if (lastMessageSender == null) return false; + message.sendToClient(server, lastMessageSender); + return true; + } + + abstract void sendToClient(MinecraftServer server); + + abstract void sendToClient(MinecraftServer server, ServerPlayer player); + + @Environment(EnvType.CLIENT) + abstract void sendToServer(Minecraft client); + + + @Override + public String toString() { + return "BasDataHandler{" + "originatesOnServer=" + originatesOnServer + ", identifier=" + identifier + '}'; + } + + /** + * Write a String to a buffer (Convenience Method) + * + * @param buf The buffer to write to + * @param s The String you want to write + */ + public static void writeString(FriendlyByteBuf buf, String s) { + buf.writeByteArray(s.getBytes(StandardCharsets.UTF_8)); + } + + /** + * Read a string from a buffer (Convenience Method) + * + * @param buf Thea buffer to read from + * @return The received String + */ + public static String readString(FriendlyByteBuf buf) { + byte[] data = buf.readByteArray(); + return new String(data, StandardCharsets.UTF_8); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BaseDataHandler)) return false; + BaseDataHandler that = (BaseDataHandler) o; + return originatesOnServer == that.originatesOnServer && identifier.equals(that.identifier); + } + + @Override + public int hashCode() { + return Objects.hash(originatesOnServer, identifier); + } +} + diff --git a/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java b/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java index 3ed6fa1f..6e192b91 100644 --- a/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java +++ b/src/main/java/ru/bclib/api/dataexchange/ConnectorClientside.java @@ -42,7 +42,7 @@ public class ConnectorClientside extends Connector { public void onPlayReady(ClientPacketListener handler, PacketSender sender, Minecraft client){ for(DataHandlerDescriptor desc : getDescriptors()){ if (desc.sendOnJoin){ - DataHandler h = desc.JOIN_INSTANCE.get(); + BaseDataHandler h = desc.JOIN_INSTANCE.get(); if (!h.getOriginatesOnServer()) { h.sendToServer(client); } @@ -57,11 +57,11 @@ public class ConnectorClientside extends Connector { } void receiveFromServer(DataHandlerDescriptor desc, Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender){ - DataHandler h = desc.INSTANCE.get(); + BaseDataHandler h = desc.INSTANCE.get(); h.receiveFromServer(client, handler, buf, responseSender); } - public void sendToServer(DataHandler h){ + public void sendToServer(BaseDataHandler h){ if (client==null){ throw new RuntimeException("[internal error] Client not initialized yet!"); } diff --git a/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java b/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java index 0a42a147..f8debc99 100644 --- a/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java +++ b/src/main/java/ru/bclib/api/dataexchange/ConnectorServerside.java @@ -39,7 +39,7 @@ public class ConnectorServerside extends Connector { public void onPlayReady(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server){ for(DataHandlerDescriptor desc : getDescriptors()){ if (desc.sendOnJoin){ - DataHandler h = desc.JOIN_INSTANCE.get(); + BaseDataHandler h = desc.JOIN_INSTANCE.get(); if (h.getOriginatesOnServer()) { h.sendToClient(server, handler.player); } @@ -54,11 +54,11 @@ public class ConnectorServerside extends Connector { } void receiveFromClient(DataHandlerDescriptor desc, MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender){ - DataHandler h = desc.INSTANCE.get(); + BaseDataHandler h = desc.INSTANCE.get(); h.receiveFromClient(server, player, handler, buf, responseSender); } - public void sendToClient(DataHandler h){ + public void sendToClient(BaseDataHandler h){ if (server==null){ throw new RuntimeException("[internal error] Server not initialized yet!"); } diff --git a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java index 0af4a224..d49cf23b 100644 --- a/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java +++ b/src/main/java/ru/bclib/api/dataexchange/DataExchangeAPI.java @@ -42,6 +42,15 @@ public class DataExchangeAPI extends DataExchange { if (!MODS.contains(modID)) MODS.add(modID); } + /** + * Register a mod dependency to participate in the DataExchange. + * + * @param modID - {@link String} modID. + */ + public static void registerModDependency(String modID) { + registerMod(modID); + } + /** * Returns the IDs of all registered Mods. * @@ -79,12 +88,12 @@ public class DataExchangeAPI extends DataExchange { * 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
+ * The method {@link DataHandler#serializeData(FriendlyByteBuf, boolean)} 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) {
+ public static void send(BaseDataHandler h) {
if (h.getOriginatesOnServer()) {
DataExchangeAPI.getInstance().server.sendToClient(h);
}
diff --git a/src/main/java/ru/bclib/api/dataexchange/DataHandler.java b/src/main/java/ru/bclib/api/dataexchange/DataHandler.java
index a552716b..1d489bac 100644
--- a/src/main/java/ru/bclib/api/dataexchange/DataHandler.java
+++ b/src/main/java/ru/bclib/api/dataexchange/DataHandler.java
@@ -14,136 +14,230 @@ 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;
+import ru.bclib.BCLib;
-import java.nio.charset.StandardCharsets;
-
-public abstract class DataHandler {
-
- public abstract static class WithoutPayload extends DataHandler{
+public abstract class DataHandler extends BaseDataHandler {
+ public abstract static class WithoutPayload extends DataHandler {
protected WithoutPayload(ResourceLocation identifier, boolean originatesOnServer) {
super(identifier, originatesOnServer);
}
@Override
- protected boolean prepareData(boolean isClient){ return true; }
+ protected boolean prepareData(boolean isClient) { return true; }
@Override
protected void serializeData(FriendlyByteBuf buf, boolean isClient) {
}
@Override
- protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean isClient){
+ protected void deserializeIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean isClient) {
}
}
- private final boolean originatesOnServer;
- @NotNull
- private final ResourceLocation identifier;
-
- protected DataHandler(ResourceLocation identifier, boolean originatesOnServer){
- this.originatesOnServer = originatesOnServer;
- this.identifier = identifier;
+ protected DataHandler(ResourceLocation identifier, boolean originatesOnServer) {
+ super(identifier, originatesOnServer);
}
- final public boolean getOriginatesOnServer(){
- return originatesOnServer;
- }
+ protected boolean prepareData(boolean isClient) { return true; }
+
+ abstract protected void serializeData(FriendlyByteBuf buf, boolean isClient);
+
+ abstract protected void deserializeIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean isClient);
+
+ abstract protected void runOnGameThread(Minecraft client, MinecraftServer server, boolean isClient);
- final public ResourceLocation getIdentifier(){
- return identifier;
- }
@Environment(EnvType.CLIENT)
- void receiveFromServer(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender){
- deserializeFromIncomingData(buf, responseSender, true);
+ @Override
+ void receiveFromServer(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender) {
+ deserializeIncomingData(buf, responseSender, true);
client.execute(() -> runOnGameThread(client, null, true));
}
- private ServerPlayer lastMessageSender;
- void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender){
- lastMessageSender = player;
- deserializeFromIncomingData(buf, responseSender, false);
+ @Override
+ void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender) {
+ super.receiveFromClient(server, player, handler, buf, responseSender);
+
+ deserializeIncomingData(buf, responseSender, false);
server.execute(() -> runOnGameThread(null, server, false));
}
-
- protected boolean prepareData(boolean isClient){ return true; }
- abstract protected void serializeData(FriendlyByteBuf buf, boolean isClient) ;
- abstract protected void deserializeFromIncomingData(FriendlyByteBuf buf, PacketSender responseSender, boolean isClient);
- abstract protected void runOnGameThread(Minecraft client, MinecraftServer server, boolean isClient);
-
- final protected boolean reply(DataHandler message, MinecraftServer server){
- if (lastMessageSender==null) return false;
- message.sendToClient(server, lastMessageSender);
- return true;
- }
- void sendToClient(MinecraftServer server){
+ @Override
+ void sendToClient(MinecraftServer server) {
if (prepareData(false)) {
FriendlyByteBuf buf = PacketByteBufs.create();
serializeData(buf, false);
for (ServerPlayer player : PlayerLookup.all(server)) {
- ServerPlayNetworking.send(player, this.identifier, buf);
+ ServerPlayNetworking.send(player, getIdentifier(), buf);
}
}
}
- void sendToClient(MinecraftServer server, ServerPlayer player){
+ @Override
+ void sendToClient(MinecraftServer server, ServerPlayer player) {
if (prepareData(false)) {
FriendlyByteBuf buf = PacketByteBufs.create();
serializeData(buf, false);
- ServerPlayNetworking.send(player, this.identifier, buf);
+ ServerPlayNetworking.send(player, getIdentifier(), buf);
}
}
@Environment(EnvType.CLIENT)
- void sendToServer(Minecraft client){
+ @Override
+ void sendToServer(Minecraft client) {
if (prepareData(true)) {
FriendlyByteBuf buf = PacketByteBufs.create();
serializeData(buf, true);
- ClientPlayNetworking.send(identifier, buf);
+ ClientPlayNetworking.send(getIdentifier(), 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;
+ /**
+ * A Message that always originates on the Client
+ */
+ public abstract static class FromClient extends BaseDataHandler {
+ public abstract static class WithoutPayload extends FromClient {
+ protected WithoutPayload(ResourceLocation identifier) {
+ super(identifier);
+ }
+
+ @Override
+ protected boolean prepareDataOnClient() { return true; }
+
+ @Override
+ protected void serializeDataOnClient(FriendlyByteBuf buf) {
+ }
+
+ @Override
+ protected void deserializeIncomingDataOnServer(FriendlyByteBuf buf, PacketSender responseSender) {
+ }
+ }
- return hash;
- }
-
- @Override
- public String toString() {
- return "DataHandler{" + "originatesOnServer=" + originatesOnServer + ", identifier=" + identifier + '}';
+ protected FromClient(ResourceLocation identifier) {
+ super(identifier, false);
+ }
+
+ @Environment(EnvType.CLIENT)
+ protected boolean prepareDataOnClient() { return true; }
+
+ @Environment(EnvType.CLIENT)
+ abstract protected void serializeDataOnClient(FriendlyByteBuf buf);
+
+ abstract protected void deserializeIncomingDataOnServer(FriendlyByteBuf buf, PacketSender responseSender);
+
+ abstract protected void runOnServerGameThread(MinecraftServer server);
+
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ void receiveFromServer(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender) {
+ BCLib.LOGGER.error("[Internal Error] The message '" + getIdentifier() + "' must originate from the client!");
+ }
+
+ @Override
+ void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender) {
+ super.receiveFromClient(server, player, handler, buf, responseSender);
+
+ deserializeIncomingDataOnServer(buf, responseSender);
+ server.execute(() -> runOnServerGameThread(server));
+ }
+
+ @Override
+ void sendToClient(MinecraftServer server) {
+ BCLib.LOGGER.error("[Internal Error] The message '" + getIdentifier() + "' must originate from the client!");
+ }
+
+ @Override
+ void sendToClient(MinecraftServer server, ServerPlayer player) {
+ BCLib.LOGGER.error("[Internal Error] The message '" + getIdentifier() + "' must originate from the client!");
+ }
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ void sendToServer(Minecraft client) {
+ if (prepareDataOnClient()) {
+ FriendlyByteBuf buf = PacketByteBufs.create();
+ serializeDataOnClient(buf);
+ ClientPlayNetworking.send(getIdentifier(), buf);
+ }
+ }
}
/**
- * Write a String to a buffer (Convenience Method)
- * @param buf The buffer to write to
- * @param s The String you want to write
+ * A Message that always originates on the Server
*/
- public static void writeString(FriendlyByteBuf buf, String s){
- buf.writeByteArray(s.getBytes(StandardCharsets.UTF_8));
- }
-
- /**
- * Read a string from a buffer (Convenience Method)
- * @param buf Thea buffer to read from
- * @return The received String
- */
- public static String readString(FriendlyByteBuf buf){
- byte[] data = buf.readByteArray();
- return new String(data, StandardCharsets.UTF_8);
+ public abstract static class FromServer extends BaseDataHandler {
+ public abstract static class WithoutPayload extends FromServer {
+ protected WithoutPayload(ResourceLocation identifier) {
+ super(identifier);
+ }
+
+ @Override
+ protected boolean prepareDataOnServer() { return true; }
+
+ @Override
+ protected void serializeDataOnServer(FriendlyByteBuf buf) {
+ }
+
+ @Override
+ protected void deserializeIncomingDataOnClient(FriendlyByteBuf buf, PacketSender responseSender) {
+ }
+ }
+
+ protected FromServer(ResourceLocation identifier) {
+ super(identifier, true);
+ }
+
+ protected boolean prepareDataOnServer() { return true; }
+
+ abstract protected void serializeDataOnServer(FriendlyByteBuf buf);
+
+ @Environment(EnvType.CLIENT)
+ abstract protected void deserializeIncomingDataOnClient(FriendlyByteBuf buf, PacketSender responseSender);
+
+ @Environment(EnvType.CLIENT)
+ abstract protected void runOnClientGameThread(Minecraft client);
+
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ final void receiveFromServer(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender) {
+ deserializeIncomingDataOnClient(buf, responseSender);
+ client.execute(() -> runOnClientGameThread(client));
+ }
+
+ @Override
+ final void receiveFromClient(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender) {
+ super.receiveFromClient(server, player, handler, buf, responseSender);
+ BCLib.LOGGER.error("[Internal Error] The message '" + getIdentifier() + "' must originate from the server!");
+ }
+
+ @Override
+ final void sendToClient(MinecraftServer server) {
+ if (prepareDataOnServer()) {
+ FriendlyByteBuf buf = PacketByteBufs.create();
+ serializeDataOnServer(buf);
+
+ for (ServerPlayer player : PlayerLookup.all(server)) {
+ ServerPlayNetworking.send(player, getIdentifier(), buf);
+ }
+ }
+ }
+
+ @Override
+ final void sendToClient(MinecraftServer server, ServerPlayer player) {
+ if (prepareDataOnServer()) {
+ FriendlyByteBuf buf = PacketByteBufs.create();
+ serializeDataOnServer(buf);
+ ServerPlayNetworking.send(player, getIdentifier(), buf);
+ }
+ }
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ final void sendToServer(Minecraft client) {
+ BCLib.LOGGER.error("[Internal Error] The message '" + getIdentifier() + "' must originate from the server!");
+ }
}
}
diff --git a/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java b/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java
index 99017fe4..ec85d6cf 100644
--- a/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java
+++ b/src/main/java/ru/bclib/api/dataexchange/DataHandlerDescriptor.java
@@ -5,14 +5,14 @@ import net.minecraft.resources.ResourceLocation;
import java.util.function.Supplier;
public class DataHandlerDescriptor {
- public DataHandlerDescriptor(ResourceLocation identifier, Supplier
* For Details refer to {@link HelloServer}
*/
-public class HelloClient extends DataHandler {
+public class HelloClient extends DataHandler.FromServer {
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_client"), HelloClient::new, false, false);
public HelloClient() {
- super(DESCRIPTOR.IDENTIFIER, true);
+ super(DESCRIPTOR.IDENTIFIER);
}
static String getBCLibVersion() {
@@ -48,7 +46,7 @@ public class HelloClient extends DataHandler {
}
@Override
- protected boolean prepareData(boolean isClient) {
+ protected boolean prepareDataOnServer() {
if (!Config.isAllowingAutoSync()) {
BCLib.LOGGER.info("Auto-Sync was disabled on the server.");
return false;
@@ -59,7 +57,7 @@ public class HelloClient extends DataHandler {
}
@Override
- protected void serializeData(FriendlyByteBuf buf, boolean isClient) {
+ protected void serializeDataOnServer(FriendlyByteBuf buf) {
final String vbclib = getBCLibVersion();
BCLib.LOGGER.info("Sending Hello to Client. (server=" + vbclib + ")");
final List