Complete Large Packet Sending

This commit is contained in:
Kam committed 2025-01-29 15:04:19 -05:00
1 parent 36c8b70eb4
commit f573259fd1
11 files changed
+219 -152

No files matched your search

@@ -1,38 +1,43 @@
package kamkeel.npcs.network;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
import org.lwjgl.Sys;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
public abstract class LargeAbstractPacket extends AbstractPacket {
private static final int CHUNK_SIZE = 10000;
private static final Map<UUID, ByteBuf> packetChunks = new HashMap<>();
private static final Map<UUID, Integer> receivedChunks = new HashMap<>();
private static final Map<UUID, PacketStorage> packetChunks = new ConcurrentHashMap<>();
private static final int CHUNK_SIZE = 5000;
@Override
public void sendData(ByteBuf out) throws IOException {
ByteBuf data = Unpooled.buffer();
writeData(data);
int totalSize = data.readableBytes();
UUID packetId = UUID.randomUUID(); // Unique ID for this packet
int totalChunks = (int) Math.ceil((double) totalSize / CHUNK_SIZE);
byte[] data = getData();
int totalSize = data.length;
UUID packetId = UUID.randomUUID();
for (int i = 0; i < totalSize; i += CHUNK_SIZE) {
int chunkSize = Math.min(CHUNK_SIZE, totalSize - i);
ByteBuf chunk = data.readBytes(chunkSize);
System.out.println("Sending data with packetId: " + packetId + ", totalSize: " + totalSize);
// Break the data into chunks of CHUNK_SIZE bytes each
for (int offset = 0; offset < totalSize; offset += CHUNK_SIZE) {
int chunkSize = Math.min(CHUNK_SIZE, totalSize - offset);
// Write a header for each chunk
out.writeLong(packetId.getMostSignificantBits());
out.writeLong(packetId.getLeastSignificantBits());
out.writeInt(totalSize);
out.writeInt(i);
out.writeInt(totalChunks);
out.writeBytes(chunk);
out.writeInt(offset);
out.writeInt((totalSize + CHUNK_SIZE - 1) / CHUNK_SIZE); // totalChunks
// Write the chunk bytes
out.writeBytes(data, offset, chunkSize);
System.out.println("Sent chunk with offset: " + offset + ", size: " + chunkSize);
}
}
@@ -41,51 +46,70 @@ public abstract class LargeAbstractPacket extends AbstractPacket {
long mostSigBits = in.readLong();
long leastSigBits = in.readLong();
UUID packetId = new UUID(mostSigBits, leastSigBits);
int totalSize = in.readInt();
int offset = in.readInt();
int totalChunks = in.readInt();
ByteBuf chunk = in.readBytes(in.readableBytes());
int totalChunks = in.readInt(); // Currently unused aside from potential debugging/verification
int chunkSize = Math.min(CHUNK_SIZE, totalSize - offset);
ByteBuf data = packetChunks.computeIfAbsent(packetId, k -> Unpooled.buffer(totalSize));
data.setBytes(offset, chunk);
// Basic validation to ensure the chunk won't overwrite out of bounds
if (chunkSize <= 0 || offset < 0 || (offset + chunkSize) > totalSize) {
throw new IndexOutOfBoundsException("Invalid chunk size/offset: chunkSize="
+ chunkSize + ", offset=" + offset + ", totalSize=" + totalSize);
}
int receivedChunkCount = receivedChunks.compute(packetId, (k, v) -> (v == null) ? 1 : v + 1);
// Read the exact chunk data
ByteBuf chunk = in.readBytes(chunkSize);
if (receivedChunkCount == totalChunks) {
System.out.println("Receiving data: packetId=" + packetId
+ ", totalSize=" + totalSize
+ ", offset=" + offset
+ ", chunkSize=" + chunkSize);
// Store the received chunk in a PacketStorage
PacketStorage storage = packetChunks.computeIfAbsent(packetId,
k -> new PacketStorage(Unpooled.buffer(totalSize), 0, totalSize));
// Write this chunk into the buffer at the correct offset
storage.data.setBytes(offset, chunk);
storage.receivedSoFar += chunkSize;
// If we've received all bytes, finalize
if (storage.receivedSoFar >= totalSize) {
// Remove from the map to clean up
packetChunks.remove(packetId);
receivedChunks.remove(packetId);
handleData(data, player);
// We now have the complete data in storage.data
// Copy (or slice) the exact bytes, then handle them
ByteBuf completeData = storage.data.copy(0, totalSize);
System.out.println("Received complete data for packetId: " + packetId);
// Clean up and handle
storage.data.release();
handleCompleteData(completeData, player);
completeData.release();
}
chunk.release();
}
public final List<FMLProxyPacket> generatePacketChunks() {
List<FMLProxyPacket> chunks = new ArrayList<>();
ByteBuf data = Unpooled.buffer();
try {
writeData(data);
int totalSize = data.readableBytes();
UUID packetId = UUID.randomUUID();
int totalChunks = (int) Math.ceil((double) totalSize / CHUNK_SIZE);
protected abstract byte[] getData() throws IOException;
for (int i = 0; i < totalSize; i += CHUNK_SIZE) {
int chunkSize = Math.min(CHUNK_SIZE, totalSize - i);
ByteBuf chunk = data.readBytes(chunkSize);
ByteBuf out = Unpooled.buffer();
out.writeLong(packetId.getMostSignificantBits());
out.writeLong(packetId.getLeastSignificantBits());
out.writeInt(totalSize);
out.writeInt(i);
out.writeInt(totalChunks);
out.writeBytes(chunk);
chunks.add(new FMLProxyPacket(out, getChannel().getChannelName()));
}
} catch (IOException e) {
e.printStackTrace();
protected abstract void handleCompleteData(ByteBuf data, EntityPlayer player) throws IOException;
/**
* Simple storage class to keep track of partial data and how many bytes we've received so far.
*/
private static class PacketStorage {
final ByteBuf data;
int receivedSoFar;
final int totalSize;
PacketStorage(ByteBuf data, int receivedSoFar, int totalSize) {
this.data = data;
this.receivedSoFar = receivedSoFar;
this.totalSize = totalSize;
}
return chunks;
}
public abstract void writeData(ByteBuf out) throws IOException;
public abstract void handleData(ByteBuf data, EntityPlayer player) throws IOException;
}
@@ -15,7 +15,6 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import noppes.npcs.CustomNpcs;
import java.io.IOException;
import java.util.*;
import java.util.function.Consumer;
@@ -43,6 +42,9 @@ public final class PacketHandler {
LARGE_PACKET.registerPacket(new LargeScrollGroupPacket());
LARGE_PACKET.registerPacket(new LargeScrollDataPacket());
LARGE_PACKET.registerPacket(new LargeScrollListPacket());
// Log channel registration
System.out.println("PacketHandler initialized and channels registered.");
}
public void registerChannels() {
@@ -51,105 +53,110 @@ public final class PacketHandler {
eventChannel = NetworkRegistry.INSTANCE.newEventDrivenChannel(channel.getChannelName());
eventChannel.register(this);
channels.put(channel.getChannelType(), eventChannel);
System.out.println("Registered channel: " + channel.getChannelName());
}
}
public PacketChannel getPacketChannel(EnumPacketType type){
PacketChannel packetChannel;
switch (type){
case DATA:
packetChannel = DATA_PACKET;
break;
case INFO:
packetChannel = INFO_PACKET;
break;
case LARGE:
packetChannel = LARGE_PACKET;
break;
default:
packetChannel = CLIENT_PACKET;
break;
}
return packetChannel;
return packetChannels.stream()
.filter(channel -> channel.getChannelType() == type)
.findFirst()
.orElse(null);
}
public FMLEventChannel getEventChannel(AbstractPacket abstractPacket){
return channels.get(getPacketChannel(abstractPacket.getChannel().getChannelType()));
PacketChannel packetChannel = getPacketChannel(abstractPacket.getChannel().getChannelType());
if (packetChannel == null) {
return null;
}
return channels.get(packetChannel.getChannelType());
}
@SubscribeEvent
public void onServerPacket(FMLNetworkEvent.ServerCustomPacketEvent event) {
try {
handlePacket(event.packet, ((NetHandlerPlayServer) event.handler).playerEntity);
} catch (Exception e) {
e.printStackTrace();
}
handlePacket(event.packet, ((NetHandlerPlayServer) event.handler).playerEntity);
}
@SubscribeEvent
public void onClientPacket(FMLNetworkEvent.ClientCustomPacketEvent event) {
try {
handlePacket(event.packet, CustomNpcs.proxy.getPlayer());
} catch (Exception e) {
e.printStackTrace();
}
handlePacket(event.packet, CustomNpcs.proxy.getPlayer());
}
private void handlePacket(FMLProxyPacket packet, EntityPlayer player) {
ByteBuf buf = packet.payload();
try {
int channelTypeOrdinal = buf.readInt();
int packetTypeOrdinal = buf.readInt();
EnumPacketType channelType = EnumPacketType.values()[channelTypeOrdinal];
PacketChannel packetChannel = getPacketChannel(channelType);
AbstractPacket abstractPacket = packetChannel.packets.get(packetTypeOrdinal);
if (abstractPacket != null) {
try {
abstractPacket.receiveData(buf, player);
} catch (IOException e) {
e.printStackTrace();
}
EnumPacketType packetType = EnumPacketType.values()[packetTypeOrdinal];
PacketChannel packetChannel = getPacketChannel(packetType);
if (packetChannel == null) {
System.err.println("Error: Packet channel is null for packet type: " + packetType);
return;
}
int packetId = buf.readInt();
AbstractPacket abstractPacket = packetChannel.packets.get(packetId);
if (abstractPacket == null) {
System.err.println("Error: Abstract packet is null for packet ID: " + packetId);
return;
}
abstractPacket.receiveData(buf, player);
} catch (IndexOutOfBoundsException e) {
System.err.println("Error: IndexOutOfBoundsException in handlePacket: " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
System.err.println("Error: Exception in handlePacket: " + e.getMessage());
e.printStackTrace();
}
}
public void sendPacket(AbstractPacket packet, Consumer<FMLProxyPacket> sendFunction) {
try {
if (packet instanceof LargeAbstractPacket) {
List<FMLProxyPacket> chunks = ((LargeAbstractPacket) packet).generatePacketChunks();
for (FMLProxyPacket chunk : chunks) {
sendFunction.accept(chunk);
}
} else {
FMLProxyPacket proxyPacket = packet.generatePacket();
sendFunction.accept(proxyPacket);
}
} catch (Exception e) {
e.printStackTrace();
FMLProxyPacket proxyPacket = packet.generatePacket();
if (proxyPacket != null) {
sendFunction.accept(proxyPacket);
}
}
public void sendToPlayer(AbstractPacket packet, EntityPlayerMP player) {
sendPacket(packet, proxyPacket -> getEventChannel(packet).sendTo(proxyPacket, player));
FMLEventChannel eventChannel = getEventChannel(packet);
if (eventChannel == null) {
System.err.println("Error: Event channel is null for packet: " + packet.getClass().getName());
return;
}
sendPacket(packet, proxyPacket -> eventChannel.sendTo(proxyPacket, player));
}
public void sendToServer(AbstractPacket packet) {
sendPacket(packet, proxyPacket -> getEventChannel(packet).sendToServer(proxyPacket));
FMLEventChannel eventChannel = getEventChannel(packet);
if (eventChannel == null) {
System.err.println("Error: Event channel is null for packet: " + packet.getClass().getName());
return;
}
sendPacket(packet, eventChannel::sendToServer);
}
public void sendToAll(AbstractPacket packet) {
sendPacket(packet, proxyPacket -> getEventChannel(packet).sendToAll(proxyPacket));
FMLEventChannel eventChannel = getEventChannel(packet);
if (eventChannel == null) {
System.err.println("Error: Event channel is null for packet: " + packet.getClass().getName());
return;
}
sendPacket(packet, eventChannel::sendToAll);
}
public void sendToAllAround(AbstractPacket packet, NetworkRegistry.TargetPoint point) {
sendPacket(packet, proxyPacket -> getEventChannel(packet).sendToAllAround(proxyPacket, point));
FMLEventChannel eventChannel = getEventChannel(packet);
if (eventChannel == null) {
System.err.println("Error: Event channel is null for packet: " + packet.getClass().getName());
return;
}
sendPacket(packet, proxyPacket -> eventChannel.sendToAllAround(proxyPacket, point));
}
public void sendToDimension(AbstractPacket packet, int dimensionId) {
sendPacket(packet, proxyPacket -> getEventChannel(packet).sendToDimension(proxyPacket, dimensionId));
FMLEventChannel eventChannel = getEventChannel(packet);
if (eventChannel == null) {
System.err.println("Error: Event channel is null for packet: " + packet.getClass().getName());
return;
}
sendPacket(packet, proxyPacket -> eventChannel.sendToDimension(proxyPacket, dimensionId));
}
}
@@ -6,6 +6,7 @@ import kamkeel.npcs.network.PacketChannel;
import kamkeel.npcs.network.PacketHandler;
import kamkeel.npcs.network.enums.EnumClientPacket;
import net.minecraft.entity.player.EntityPlayer;
import noppes.npcs.Server;
import noppes.npcs.client.ClientEventHandler;
import java.io.IOException;
@@ -42,11 +42,12 @@ public final class MessagePacket extends AbstractPacket {
if(CustomNpcs.side() != Side.CLIENT)
return;
String description = StatCollector.translateToLocal(Server.readString(in));
String message = Server.readString(in);
Achievement achievement = new Achievement(message, description);
GuiAchievement guiAchievement = Minecraft.getMinecraft().guiAchievement;
guiAchievement.func_146256_a(achievement);
ObfuscationReflectionHelper.setPrivateValue(GuiAchievement.class, guiAchievement, achievement.getDescription(), 4);
// TODO: Fix Message Packet
// String description = StatCollector.translateToLocal(Server.readString(in));
// String message = Server.readString(in);
// Achievement achievement = new Achievement(message, description);
// GuiAchievement guiAchievement = Minecraft.getMinecraft().guiAchievement;
// guiAchievement.func_146256_a(achievement);
// ObfuscationReflectionHelper.setPrivateValue(GuiAchievement.class, guiAchievement, achievement.getDescription(), 4);
}
}
@@ -8,6 +8,7 @@ import kamkeel.npcs.network.enums.EnumClientPacket;
import net.minecraft.entity.player.EntityPlayer;
import noppes.npcs.CustomNpcs;
import noppes.npcs.constants.EnumGuiType;
import noppes.npcs.entity.EntityNPCInterface;
import java.io.IOException;
@@ -33,6 +34,6 @@ public final class TeleporterPacket extends AbstractPacket {
@Override
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
CustomNpcs.proxy.openGui(null, EnumGuiType.NpcDimensions);
CustomNpcs.proxy.openGui((EntityNPCInterface)null,EnumGuiType.NpcDimensions);
}
}
@@ -1,6 +1,7 @@
package kamkeel.npcs.network.packets.large;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import kamkeel.npcs.network.LargeAbstractPacket;
import kamkeel.npcs.network.PacketChannel;
import kamkeel.npcs.network.PacketHandler;
@@ -10,6 +11,7 @@ import net.minecraft.entity.player.EntityPlayer;
import noppes.npcs.client.NoppesUtil;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public final class LargeScrollDataPacket extends LargeAbstractPacket {
@@ -34,16 +36,27 @@ public final class LargeScrollDataPacket extends LargeAbstractPacket {
}
@Override
public void writeData(ByteBuf out) throws IOException {
out.writeInt(data.size());
protected byte[] getData() throws IOException {
ByteBuf buffer = Unpooled.buffer();
buffer.writeInt(data.size());
for (Map.Entry<String, Integer> entry : data.entrySet()) {
ByteBufUtils.writeString(out, entry.getKey());
out.writeInt(entry.getValue());
buffer.writeInt(entry.getValue());
ByteBufUtils.writeString(buffer, entry.getKey());
}
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
System.out.println("getData: Written data to buffer: " + buffer.toString());
return bytes;
}
@Override
public void handleData(ByteBuf data, EntityPlayer player) throws IOException {
protected void handleCompleteData(ByteBuf data, EntityPlayer player) throws IOException {
if (data == null || data.readableBytes() <= 0) {
System.err.println("LargeScrollDataPacket: ByteBuf is empty or already read.");
return;
}
data.readerIndex(0);
System.out.println("handleCompleteData: Reading data from buffer: " + data.toString());
NoppesUtil.setScrollData(data);
}
}
@@ -1,6 +1,7 @@
package kamkeel.npcs.network.packets.large;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import kamkeel.npcs.network.LargeAbstractPacket;
import kamkeel.npcs.network.PacketChannel;
import kamkeel.npcs.network.PacketHandler;
@@ -34,16 +35,20 @@ public final class LargeScrollGroupPacket extends LargeAbstractPacket {
}
@Override
public void writeData(ByteBuf out) throws IOException {
out.writeInt(data.size());
protected byte[] getData() throws IOException {
ByteBuf buffer = Unpooled.buffer();
buffer.writeInt(data.size());
for (Map.Entry<String, Integer> entry : data.entrySet()) {
ByteBufUtils.writeString(out, entry.getKey());
out.writeInt(entry.getValue());
ByteBufUtils.writeString(buffer, entry.getKey());
buffer.writeInt(entry.getValue());
}
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
return bytes;
}
@Override
public void handleData(ByteBuf data, EntityPlayer player) throws IOException {
NoppesUtil.setScrollGroup(data);
protected void handleCompleteData(ByteBuf data, EntityPlayer player) throws IOException {
NoppesUtil.setScrollData(data);
}
}
@@ -1,7 +1,7 @@
// src/main/java/kamkeel/network/packets/large/LargeScrollListPacket.java
package kamkeel.npcs.network.packets.large;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import kamkeel.npcs.network.LargeAbstractPacket;
import kamkeel.npcs.network.PacketChannel;
import kamkeel.npcs.network.PacketHandler;
@@ -35,15 +35,19 @@ public final class LargeScrollListPacket extends LargeAbstractPacket {
}
@Override
public void writeData(ByteBuf out) throws IOException {
out.writeInt(data.size());
protected byte[] getData() throws IOException {
ByteBuf buffer = Unpooled.buffer();
buffer.writeInt(data.size());
for (String entry : data) {
ByteBufUtils.writeString(out, entry);
ByteBufUtils.writeString(buffer, entry);
}
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
return bytes;
}
@Override
public void handleData(ByteBuf data, EntityPlayer player) throws IOException {
protected void handleCompleteData(ByteBuf data, EntityPlayer player) throws IOException {
NoppesUtil.setScrollList(data);
}
}
@@ -16,6 +16,7 @@ import kamkeel.npcs.command.profile.CommandProfile;
import kamkeel.npcs.controllers.ProfileController;
import kamkeel.npcs.controllers.data.CNPCData;
import kamkeel.npcs.developer.Developer;
import kamkeel.npcs.network.PacketHandler;
import net.minecraft.block.Block;
import net.minecraft.block.BlockIce;
import net.minecraft.block.BlockLeavesBase;
@@ -249,6 +250,13 @@ public class CustomNpcs {
ServerTagMapController.Instance = new ServerTagMapController();
}
//Loading items in the about to start event was corrupting items with a damage value
@EventHandler
public void postInit(FMLPostInitializationEvent event) {
PacketHandler.Instance = new PacketHandler();
}
@EventHandler
public void stopped(FMLServerStoppedEvent event){
ServerCloneController.Instance = null;
+14 -12
View File
@@ -49,6 +49,8 @@ import java.text.DecimalFormat;
import java.util.*;
import java.util.zip.GZIPOutputStream;
import static kamkeel.npcs.network.KamUtilServer.sendScrollData;
public class NoppesUtilServer {
private static HashMap<String,Quest> editingQuests = new HashMap<String,Quest>();
@@ -505,7 +507,7 @@ public class NoppesUtilServer {
}
}
NoppesUtilServer.sendScrollData(player, map);
sendScrollData(player, map);
}
public static void removePlayerData(ByteBuf buffer, EntityPlayerMP player) throws IOException {
@@ -593,17 +595,17 @@ public class NoppesUtilServer {
}
sendScrollData(player, map);
}
public static void sendScrollData(EntityPlayerMP player, Map<String,Integer> map){
Map<String, Integer> send = new HashMap<String, Integer>();
for(String key : map.keySet()){
send.put(key, map.get(key));
if(send.size() == 100){
Server.sendData(player, EnumPacketClient.SCROLL_DATA_PART, send);
send = new HashMap<String, Integer>();
}
}
Server.sendData(player, EnumPacketClient.SCROLL_DATA, send);
}
// public static void sendScrollData(EntityPlayerMP player, Map<String,Integer> map){
// Map<String, Integer> send = new HashMap<String, Integer>();
// for(String key : map.keySet()){
// send.put(key, map.get(key));
// if(send.size() == 100){
// Server.sendData(player, EnumPacketClient.SCROLL_DATA_PART, send);
// send = new HashMap<String, Integer>();
// }
// }
// Server.sendData(player, EnumPacketClient.SCROLL_DATA, send);
// }
public static void sendScrollGroup(EntityPlayerMP player, Map<String,Integer> map){
Map<String, Integer> send = new HashMap<String, Integer>();
@@ -6,6 +6,7 @@ import cpw.mods.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent;
import cpw.mods.fml.relauncher.Side;
import foxz.utils.Market;
import io.netty.buffer.ByteBuf;
import kamkeel.npcs.network.KamUtilServer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.passive.EntityVillager;
@@ -102,7 +103,7 @@ public class PacketHandlerServer{
WorldProvider provider = DimensionManager.createProviderFor(id);
map.put(provider.getDimensionName(), id);
}
NoppesUtilServer.sendScrollData(player, map);
KamUtilServer.sendScrollData(player, map);
} else if(type == EnumPacketServer.TagsGet){
NoppesUtilServer.sendTagDataAll(player);
} else if (type == EnumPacketServer.NpcTagsGet) {
@@ -584,7 +585,7 @@ public class PacketHandlerServer{
Server.sendData(player, EnumPacketClient.GUI_DATA, compound);
}
else if(type == EnumPacketServer.DialogCategoriesGet){
NoppesUtilServer.sendScrollData(player, DialogController.Instance.getScroll());
KamUtilServer.sendScrollData(player, DialogController.Instance.getScroll());
}
else if(type == EnumPacketServer.DialogsGetFromDialog){
Dialog dialog = DialogController.Instance.dialogs.get(buffer.readInt());
@@ -797,7 +798,7 @@ public class PacketHandlerServer{
NoppesUtilServer.setRecipeGui(player,recipe);
}
else if(type == EnumPacketServer.NaturalSpawnGetAll){
NoppesUtilServer.sendScrollData(player, SpawnController.Instance.getScroll());
KamUtilServer.sendScrollData(player, SpawnController.Instance.getScroll());
}
else if(type == EnumPacketServer.NaturalSpawnGet){
SpawnData spawn = SpawnController.Instance.getSpawnData(buffer.readInt());
@@ -810,21 +811,21 @@ public class PacketHandlerServer{
data.readNBT(Server.readNBT(buffer));
SpawnController.Instance.saveSpawnData(data);
NoppesUtilServer.sendScrollData(player, SpawnController.Instance.getScroll());
KamUtilServer.sendScrollData(player, SpawnController.Instance.getScroll());
}
else if(type == EnumPacketServer.NaturalSpawnRemove){
SpawnController.Instance.removeSpawnData(buffer.readInt());
NoppesUtilServer.sendScrollData(player, SpawnController.Instance.getScroll());
KamUtilServer.sendScrollData(player, SpawnController.Instance.getScroll());
}
else if(type == EnumPacketServer.DialogCategorySave){
DialogCategory category = new DialogCategory();
category.readNBT(Server.readNBT(buffer));
DialogController.Instance.saveCategory(category);
NoppesUtilServer.sendScrollData(player, DialogController.Instance.getScroll());
KamUtilServer.sendScrollData(player, DialogController.Instance.getScroll());
}
else if(type == EnumPacketServer.DialogCategoryRemove){
DialogController.Instance.removeCategory(buffer.readInt());
NoppesUtilServer.sendScrollData(player, DialogController.Instance.getScroll());
KamUtilServer.sendScrollData(player, DialogController.Instance.getScroll());
}
else if(type == EnumPacketServer.DialogCategoryGet){
DialogCategory category = DialogController.Instance.categories.get(buffer.readInt());