Commit f67f7ad0 by Jonathan Thomas

Large refactor of clientPackets and serverPackets, to gather all network code…

Large refactor of clientPackets and serverPackets, to gather all network code into a more sane place.
parent 339c5bb7
Pipeline #12007 passed with stage
in 22 seconds
package com.owlmaddie; package com.owlmaddie;
import com.owlmaddie.chat.ChatDataManager; import com.owlmaddie.chat.ChatDataManager;
import com.owlmaddie.network.ClientPackets;
import com.owlmaddie.ui.BubbleRenderer; import com.owlmaddie.ui.BubbleRenderer;
import com.owlmaddie.ui.ClickHandler; import com.owlmaddie.ui.ClickHandler;
import com.owlmaddie.ui.PlayerMessageManager; import com.owlmaddie.ui.PlayerMessageManager;
...@@ -23,7 +24,9 @@ public class ClientInit implements ClientModInitializer { ...@@ -23,7 +24,9 @@ public class ClientInit implements ClientModInitializer {
PlayerMessageManager.tickUpdate(); PlayerMessageManager.tickUpdate();
}); });
// Register events
ClickHandler.register(); ClickHandler.register();
ClientPackets.register();
// Register an event callback to render text bubbles // Register an event callback to render text bubbles
WorldRenderEvents.LAST.register((context) -> { WorldRenderEvents.LAST.register((context) -> {
......
package com.owlmaddie.network;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.owlmaddie.chat.ChatDataManager;
import com.owlmaddie.ui.PlayerMessageManager;
import com.owlmaddie.utils.ClientEntityFinder;
import com.owlmaddie.utils.Decompression;
import io.netty.buffer.Unpooled;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.network.PacketByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.UUID;
/**
* The {@code ClientPackets} class provides methods to send packets to/from the server for generating greetings,
* updating message details, and sending user messages.
*/
public class ClientPackets {
public static final Logger LOGGER = LoggerFactory.getLogger("creaturechat");
static HashMap<Integer, byte[]> receivedChunks = new HashMap<>();
public static void sendGenerateGreeting(Entity entity) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
// Send C2S packet
ClientPlayNetworking.send(ServerPackets.PACKET_C2S_GREETING, buf);
}
public static void sendUpdateLineNumber(Entity entity, Integer lineNumber) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
buf.writeInt(lineNumber);
// Send C2S packet
ClientPlayNetworking.send(ServerPackets.PACKET_C2S_READ_NEXT, buf);
}
public static void sendStartChat(Entity entity) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
// Send C2S packet
ClientPlayNetworking.send(ServerPackets.PACKET_C2S_START_CHAT, buf);
}
public static void setChatStatus(Entity entity, ChatDataManager.ChatStatus new_status) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
buf.writeString(new_status.toString());
// Send C2S packet
ClientPlayNetworking.send(ServerPackets.PACKET_C2S_SET_STATUS, buf);
}
public static void sendChat(Entity entity, String message) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
buf.writeString(message);
// Send C2S packet
ClientPlayNetworking.send(ServerPackets.PACKET_C2S_SEND_CHAT, buf);
}
public static void register() {
// Client-side packet handler, message sync
ClientPlayNetworking.registerGlobalReceiver(ServerPackets.PACKET_S2C_MESSAGE, (client, handler, buffer, responseSender) -> {
// Read the data from the server packet
UUID entityId = UUID.fromString(buffer.readString());
String playerId = buffer.readString();
String message = buffer.readString(32767);
int line = buffer.readInt();
String status_name = buffer.readString(32767);
String sender_name = buffer.readString(32767);
int friendship = buffer.readInt();
// Update the chat data manager on the client-side
client.execute(() -> { // Make sure to run on the client thread
MobEntity entity = ClientEntityFinder.getEntityByUUID(client.world, entityId);
if (entity != null) {
ChatDataManager chatDataManager = ChatDataManager.getClientInstance();
ChatDataManager.EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString());
chatData.playerId = playerId;
if (!message.isEmpty()) {
chatData.currentMessage = message;
}
chatData.currentLineNumber = line;
chatData.status = ChatDataManager.ChatStatus.valueOf(status_name);
chatData.sender = ChatDataManager.ChatSender.valueOf(sender_name);
chatData.friendship = friendship;
if (chatData.sender == ChatDataManager.ChatSender.USER && !playerId.isEmpty()) {
// Add player message to queue for rendering
PlayerMessageManager.addMessage(UUID.fromString(chatData.playerId), chatData.currentMessage, ChatDataManager.TICKS_TO_DISPLAY_USER_MESSAGE);
}
}
});
});
// Client-side player login: get all chat data
ClientPlayNetworking.registerGlobalReceiver(ServerPackets.PACKET_S2C_LOGIN, (client, handler, buffer, responseSender) -> {
int sequenceNumber = buffer.readInt(); // Sequence number of the current packet
int totalPackets = buffer.readInt(); // Total number of packets for this data
byte[] chunk = buffer.readByteArray(); // Read the byte array chunk from the current packet
client.execute(() -> { // Make sure to run on the client thread
// Store the received chunk
receivedChunks.put(sequenceNumber, chunk);
// Check if all chunks have been received
if (receivedChunks.size() == totalPackets) {
LOGGER.info("Reassemble chunks on client and decompress lite JSON data string");
// Combine all byte array chunks
ByteArrayOutputStream combined = new ByteArrayOutputStream();
for (int i = 0; i < totalPackets; i++) {
combined.write(receivedChunks.get(i), 0, receivedChunks.get(i).length);
}
// Decompress the combined byte array to get the original JSON string
String chatDataJSON = Decompression.decompressString(combined.toByteArray());
if (chatDataJSON == null) {
LOGGER.info("Error decompressing lite JSON string from bytes");
return;
}
// Parse JSON and update client chat data
Gson GSON = new Gson();
Type type = new TypeToken<HashMap<String, ChatDataManager.EntityChatData>>(){}.getType();
ChatDataManager.getClientInstance().entityChatDataMap = GSON.fromJson(chatDataJSON, type);
// Clear receivedChunks for future use
receivedChunks.clear();
}
});
});
}
}
package com.owlmaddie.network;
import com.owlmaddie.ModInit;
import com.owlmaddie.chat.ChatDataManager;
import io.netty.buffer.Unpooled;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.entity.Entity;
import net.minecraft.network.PacketByteBuf;
/**
* The {@code ModPackets} class provides methods to send packets to the server for generating greetings,
* updating message details, and sending user messages.
*/
public class ModPackets {
public static void sendGenerateGreeting(Entity entity) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
// Send C2S packet
ClientPlayNetworking.send(ModInit.PACKET_C2S_GREETING, buf);
}
public static void sendUpdateLineNumber(Entity entity, Integer lineNumber) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
buf.writeInt(lineNumber);
// Send C2S packet
ClientPlayNetworking.send(ModInit.PACKET_C2S_READ_NEXT, buf);
}
public static void sendStartChat(Entity entity) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
// Send C2S packet
ClientPlayNetworking.send(ModInit.PACKET_C2S_START_CHAT, buf);
}
public static void setChatStatus(Entity entity, ChatDataManager.ChatStatus new_status) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
buf.writeString(new_status.toString());
// Send C2S packet
ClientPlayNetworking.send(ModInit.PACKET_C2S_SET_STATUS, buf);
}
public static void sendChat(Entity entity, String message) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(entity.getUuidAsString());
buf.writeString(message);
// Send C2S packet
ClientPlayNetworking.send(ModInit.PACKET_C2S_SEND_CHAT, buf);
}
}
package com.owlmaddie.ui; package com.owlmaddie.ui;
import com.owlmaddie.chat.ChatDataManager; import com.owlmaddie.chat.ChatDataManager;
import com.owlmaddie.network.ModPackets; import com.owlmaddie.network.ClientPackets;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
...@@ -72,7 +72,7 @@ public class ChatScreen extends Screen { ...@@ -72,7 +72,7 @@ public class ChatScreen extends Screen {
private void sendChatMessage() { private void sendChatMessage() {
// Send message to server // Send message to server
String message = textField.getText(); String message = textField.getText();
ModPackets.sendChat(screenEntity, message); ClientPackets.sendChat(screenEntity, message);
close(); close();
} }
......
package com.owlmaddie.ui; package com.owlmaddie.ui;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.owlmaddie.ModInit;
import com.owlmaddie.chat.ChatDataManager; import com.owlmaddie.chat.ChatDataManager;
import com.owlmaddie.network.ModPackets; import com.owlmaddie.network.ClientPackets;
import com.owlmaddie.utils.ClientEntityFinder; import com.owlmaddie.utils.ClientEntityFinder;
import com.owlmaddie.utils.Decompression;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.Camera; import net.minecraft.client.render.Camera;
...@@ -21,9 +16,6 @@ import net.minecraft.world.World; ...@@ -21,9 +16,6 @@ import net.minecraft.world.World;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
...@@ -37,7 +29,6 @@ import java.util.stream.Stream; ...@@ -37,7 +29,6 @@ import java.util.stream.Stream;
public class ClickHandler { public class ClickHandler {
public static final Logger LOGGER = LoggerFactory.getLogger("creaturechat"); public static final Logger LOGGER = LoggerFactory.getLogger("creaturechat");
private static boolean wasClicked = false; private static boolean wasClicked = false;
static HashMap<Integer, byte[]> receivedChunks = new HashMap<>();
public static void register() { public static void register() {
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
...@@ -52,78 +43,6 @@ public class ClickHandler { ...@@ -52,78 +43,6 @@ public class ClickHandler {
wasClicked = false; wasClicked = false;
} }
}); });
// Client-side packet handler, message sync
ClientPlayNetworking.registerGlobalReceiver(ModInit.PACKET_S2C_MESSAGE, (client, handler, buffer, responseSender) -> {
// Read the data from the server packet
UUID entityId = UUID.fromString(buffer.readString());
String playerId = buffer.readString();
String message = buffer.readString(32767);
int line = buffer.readInt();
String status_name = buffer.readString(32767);
String sender_name = buffer.readString(32767);
int friendship = buffer.readInt();
// Update the chat data manager on the client-side
client.execute(() -> { // Make sure to run on the client thread
MobEntity entity = ClientEntityFinder.getEntityByUUID(client.world, entityId);
if (entity != null) {
ChatDataManager chatDataManager = ChatDataManager.getClientInstance();
ChatDataManager.EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString());
chatData.playerId = playerId;
if (!message.isEmpty()) {
chatData.currentMessage = message;
}
chatData.currentLineNumber = line;
chatData.status = ChatDataManager.ChatStatus.valueOf(status_name);
chatData.sender = ChatDataManager.ChatSender.valueOf(sender_name);
chatData.friendship = friendship;
if (chatData.sender == ChatDataManager.ChatSender.USER && !playerId.isEmpty()) {
// Add player message to queue for rendering
PlayerMessageManager.addMessage(UUID.fromString(chatData.playerId), chatData.currentMessage, ChatDataManager.TICKS_TO_DISPLAY_USER_MESSAGE);
}
}
});
});
// Client-side player login: get all chat data
ClientPlayNetworking.registerGlobalReceiver(ModInit.PACKET_S2C_LOGIN, (client, handler, buffer, responseSender) -> {
int sequenceNumber = buffer.readInt(); // Sequence number of the current packet
int totalPackets = buffer.readInt(); // Total number of packets for this data
byte[] chunk = buffer.readByteArray(); // Read the byte array chunk from the current packet
client.execute(() -> { // Make sure to run on the client thread
// Store the received chunk
receivedChunks.put(sequenceNumber, chunk);
// Check if all chunks have been received
if (receivedChunks.size() == totalPackets) {
LOGGER.info("Reassemble chunks on client and decompress lite JSON data string");
// Combine all byte array chunks
ByteArrayOutputStream combined = new ByteArrayOutputStream();
for (int i = 0; i < totalPackets; i++) {
combined.write(receivedChunks.get(i), 0, receivedChunks.get(i).length);
}
// Decompress the combined byte array to get the original JSON string
String chatDataJSON = Decompression.decompressString(combined.toByteArray());
if (chatDataJSON == null) {
LOGGER.info("Error decompressing lite JSON string from bytes");
return;
}
// Parse JSON and update client chat data
Gson GSON = new Gson();
Type type = new TypeToken<HashMap<String, ChatDataManager.EntityChatData>>(){}.getType();
ChatDataManager.getClientInstance().entityChatDataMap = GSON.fromJson(chatDataJSON, type);
// Clear receivedChunks for future use
receivedChunks.clear();
}
});
});
} }
public static void handleUseKeyClick(MinecraftClient client) { public static void handleUseKeyClick(MinecraftClient client) {
...@@ -187,26 +106,26 @@ public class ClickHandler { ...@@ -187,26 +106,26 @@ public class ClickHandler {
if (chatData.status == ChatDataManager.ChatStatus.NONE) { if (chatData.status == ChatDataManager.ChatStatus.NONE) {
// Start conversation // Start conversation
ModPackets.sendGenerateGreeting(closestEntity); ClientPackets.sendGenerateGreeting(closestEntity);
} else if (chatData.status == ChatDataManager.ChatStatus.DISPLAY) { } else if (chatData.status == ChatDataManager.ChatStatus.DISPLAY) {
if (hitRegion.equals("RIGHT") && !chatData.isEndOfMessage()) { if (hitRegion.equals("RIGHT") && !chatData.isEndOfMessage()) {
// Update lines read > next lines // Update lines read > next lines
ModPackets.sendUpdateLineNumber(closestEntity, chatData.currentLineNumber + ChatDataManager.DISPLAY_NUM_LINES); ClientPackets.sendUpdateLineNumber(closestEntity, chatData.currentLineNumber + ChatDataManager.DISPLAY_NUM_LINES);
} else if (hitRegion.equals("LEFT") && chatData.currentLineNumber > 0) { } else if (hitRegion.equals("LEFT") && chatData.currentLineNumber > 0) {
// Update lines read < previous lines // Update lines read < previous lines
ModPackets.sendUpdateLineNumber(closestEntity, chatData.currentLineNumber - ChatDataManager.DISPLAY_NUM_LINES); ClientPackets.sendUpdateLineNumber(closestEntity, chatData.currentLineNumber - ChatDataManager.DISPLAY_NUM_LINES);
} else if (hitRegion.equals("RIGHT") && chatData.isEndOfMessage()) { } else if (hitRegion.equals("RIGHT") && chatData.isEndOfMessage()) {
// End of chat (open player chat screen) // End of chat (open player chat screen)
ModPackets.sendStartChat(closestEntity); ClientPackets.sendStartChat(closestEntity);
client.setScreen(new ChatScreen(closestEntity)); client.setScreen(new ChatScreen(closestEntity));
} else if (hitRegion.equals("TOP")) { } else if (hitRegion.equals("TOP")) {
// Hide chat // Hide chat
ModPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.HIDDEN); ClientPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.HIDDEN);
} }
} else if (chatData.status == ChatDataManager.ChatStatus.HIDDEN) { } else if (chatData.status == ChatDataManager.ChatStatus.HIDDEN) {
// Show chat // Show chat
ModPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.DISPLAY); ClientPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.DISPLAY);
} }
} }
......
...@@ -2,7 +2,6 @@ package com.owlmaddie.chat; ...@@ -2,7 +2,6 @@ package com.owlmaddie.chat;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.owlmaddie.ModInit;
import com.owlmaddie.controls.SpeedControls; import com.owlmaddie.controls.SpeedControls;
import com.owlmaddie.goals.*; import com.owlmaddie.goals.*;
import com.owlmaddie.items.RarityItemCollector; import com.owlmaddie.items.RarityItemCollector;
...@@ -10,6 +9,7 @@ import com.owlmaddie.json.QuestJson; ...@@ -10,6 +9,7 @@ import com.owlmaddie.json.QuestJson;
import com.owlmaddie.message.Behavior; import com.owlmaddie.message.Behavior;
import com.owlmaddie.message.MessageParser; import com.owlmaddie.message.MessageParser;
import com.owlmaddie.message.ParsedMessage; import com.owlmaddie.message.ParsedMessage;
import com.owlmaddie.network.ServerPackets;
import com.owlmaddie.utils.LivingEntityInterface; import com.owlmaddie.utils.LivingEntityInterface;
import com.owlmaddie.utils.ServerEntityFinder; import com.owlmaddie.utils.ServerEntityFinder;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
...@@ -303,7 +303,7 @@ public class ChatDataManager { ...@@ -303,7 +303,7 @@ public class ChatDataManager {
} }
// Broadcast to all players // Broadcast to all players
ModInit.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this);
}); });
} }
...@@ -329,7 +329,7 @@ public class ChatDataManager { ...@@ -329,7 +329,7 @@ public class ChatDataManager {
this.playerId = playerId; this.playerId = playerId;
// Broadcast to all players // Broadcast to all players
ModInit.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this);
} }
// Get wrapped lines // Get wrapped lines
...@@ -349,14 +349,14 @@ public class ChatDataManager { ...@@ -349,14 +349,14 @@ public class ChatDataManager {
currentLineNumber = Math.min(Math.max(lineNumber, 0), totalLines); currentLineNumber = Math.min(Math.max(lineNumber, 0), totalLines);
// Broadcast to all players // Broadcast to all players
ModInit.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this);
} }
public void setStatus(ChatStatus new_status) { public void setStatus(ChatStatus new_status) {
status = new_status; status = new_status;
// Broadcast to all players // Broadcast to all players
ModInit.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this);
} }
} }
......
package com.owlmaddie.chat; package com.owlmaddie.chat;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.owlmaddie.ModInit;
import com.owlmaddie.commands.ConfigurationHandler; import com.owlmaddie.commands.ConfigurationHandler;
import com.owlmaddie.json.ChatGPTResponse; import com.owlmaddie.json.ChatGPTResponse;
import com.owlmaddie.network.ServerPackets;
import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -99,7 +99,7 @@ public class ChatGPTRequest { ...@@ -99,7 +99,7 @@ public class ChatGPTRequest {
public static CompletableFuture<String> fetchMessageFromChatGPT(String systemPrompt, Map<String, String> context, List<ChatDataManager.ChatMessage> messageHistory, Boolean jsonMode) { public static CompletableFuture<String> fetchMessageFromChatGPT(String systemPrompt, Map<String, String> context, List<ChatDataManager.ChatMessage> messageHistory, Boolean jsonMode) {
// Get config (api key, url, settings) // Get config (api key, url, settings)
ConfigurationHandler.Config config = new ConfigurationHandler(ModInit.serverInstance).loadConfig(); ConfigurationHandler.Config config = new ConfigurationHandler(ServerPackets.serverInstance).loadConfig();
// Init API & LLM details // Init API & LLM details
String apiUrl = config.getUrl(); String apiUrl = config.getUrl();
...@@ -113,7 +113,7 @@ public class ChatGPTRequest { ...@@ -113,7 +113,7 @@ public class ChatGPTRequest {
try { try {
String systemMessage = ""; String systemMessage = "";
if (systemPrompt != null && !systemPrompt.isEmpty()) { if (systemPrompt != null && !systemPrompt.isEmpty()) {
systemMessage = loadPromptFromResource(ModInit.serverInstance.getResourceManager(), "prompts/" + systemPrompt); systemMessage = loadPromptFromResource(ServerPackets.serverInstance.getResourceManager(), "prompts/" + systemPrompt);
systemMessage = replacePlaceholders(systemMessage, context); systemMessage = replacePlaceholders(systemMessage, context);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment