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;
import com.owlmaddie.chat.ChatDataManager;
import com.owlmaddie.network.ClientPackets;
import com.owlmaddie.ui.BubbleRenderer;
import com.owlmaddie.ui.ClickHandler;
import com.owlmaddie.ui.PlayerMessageManager;
......@@ -23,7 +24,9 @@ public class ClientInit implements ClientModInitializer {
PlayerMessageManager.tickUpdate();
});
// Register events
ClickHandler.register();
ClientPackets.register();
// Register an event callback to render text bubbles
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;
import com.owlmaddie.chat.ChatDataManager;
import com.owlmaddie.network.ModPackets;
import com.owlmaddie.network.ClientPackets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
......@@ -72,7 +72,7 @@ public class ChatScreen extends Screen {
private void sendChatMessage() {
// Send message to server
String message = textField.getText();
ModPackets.sendChat(screenEntity, message);
ClientPackets.sendChat(screenEntity, message);
close();
}
......
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.network.ModPackets;
import com.owlmaddie.network.ClientPackets;
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.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.Camera;
......@@ -21,9 +16,6 @@ import net.minecraft.world.World;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
......@@ -37,7 +29,6 @@ import java.util.stream.Stream;
public class ClickHandler {
public static final Logger LOGGER = LoggerFactory.getLogger("creaturechat");
private static boolean wasClicked = false;
static HashMap<Integer, byte[]> receivedChunks = new HashMap<>();
public static void register() {
ClientTickEvents.END_CLIENT_TICK.register(client -> {
......@@ -52,78 +43,6 @@ public class ClickHandler {
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) {
......@@ -187,26 +106,26 @@ public class ClickHandler {
if (chatData.status == ChatDataManager.ChatStatus.NONE) {
// Start conversation
ModPackets.sendGenerateGreeting(closestEntity);
ClientPackets.sendGenerateGreeting(closestEntity);
} else if (chatData.status == ChatDataManager.ChatStatus.DISPLAY) {
if (hitRegion.equals("RIGHT") && !chatData.isEndOfMessage()) {
// 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) {
// 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()) {
// End of chat (open player chat screen)
ModPackets.sendStartChat(closestEntity);
ClientPackets.sendStartChat(closestEntity);
client.setScreen(new ChatScreen(closestEntity));
} else if (hitRegion.equals("TOP")) {
// Hide chat
ModPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.HIDDEN);
ClientPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.HIDDEN);
}
} else if (chatData.status == ChatDataManager.ChatStatus.HIDDEN) {
// Show chat
ModPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.DISPLAY);
ClientPackets.setChatStatus(closestEntity, ChatDataManager.ChatStatus.DISPLAY);
}
}
......
......@@ -2,7 +2,6 @@ package com.owlmaddie.chat;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.owlmaddie.ModInit;
import com.owlmaddie.controls.SpeedControls;
import com.owlmaddie.goals.*;
import com.owlmaddie.items.RarityItemCollector;
......@@ -10,6 +9,7 @@ import com.owlmaddie.json.QuestJson;
import com.owlmaddie.message.Behavior;
import com.owlmaddie.message.MessageParser;
import com.owlmaddie.message.ParsedMessage;
import com.owlmaddie.network.ServerPackets;
import com.owlmaddie.utils.LivingEntityInterface;
import com.owlmaddie.utils.ServerEntityFinder;
import net.minecraft.entity.mob.MobEntity;
......@@ -303,7 +303,7 @@ public class ChatDataManager {
}
// Broadcast to all players
ModInit.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this);
});
}
......@@ -329,7 +329,7 @@ public class ChatDataManager {
this.playerId = playerId;
// Broadcast to all players
ModInit.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this);
}
// Get wrapped lines
......@@ -349,14 +349,14 @@ public class ChatDataManager {
currentLineNumber = Math.min(Math.max(lineNumber, 0), totalLines);
// Broadcast to all players
ModInit.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this);
}
public void setStatus(ChatStatus new_status) {
status = new_status;
// Broadcast to all players
ModInit.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this);
}
}
......
package com.owlmaddie.chat;
import com.google.gson.Gson;
import com.owlmaddie.ModInit;
import com.owlmaddie.commands.ConfigurationHandler;
import com.owlmaddie.json.ChatGPTResponse;
import com.owlmaddie.network.ServerPackets;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
......@@ -99,7 +99,7 @@ public class ChatGPTRequest {
public static CompletableFuture<String> fetchMessageFromChatGPT(String systemPrompt, Map<String, String> context, List<ChatDataManager.ChatMessage> messageHistory, Boolean jsonMode) {
// 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
String apiUrl = config.getUrl();
......@@ -113,7 +113,7 @@ public class ChatGPTRequest {
try {
String systemMessage = "";
if (systemPrompt != null && !systemPrompt.isEmpty()) {
systemMessage = loadPromptFromResource(ModInit.serverInstance.getResourceManager(), "prompts/" + systemPrompt);
systemMessage = loadPromptFromResource(ServerPackets.serverInstance.getResourceManager(), "prompts/" + systemPrompt);
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