Files
CustomNPC-Plus/src/main/java/kamkeel/npcs/network/LargeAbstractPacket.java
T

132 lines
4.6 KiB
Java
Raw Normal View History

2025-01-29 13:20:04 -05:00
package kamkeel.npcs.network;
2025-01-29 15:04:19 -05:00
2025-01-29 18:25:34 -05:00
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
2025-01-28 18:14:18 -05:00
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
2025-01-29 15:04:19 -05:00
import org.lwjgl.Sys;
2025-01-28 18:14:18 -05:00
import java.io.IOException;
2025-01-29 18:25:34 -05:00
import java.util.ArrayList;
import java.util.List;
2025-01-28 18:14:18 -05:00
import java.util.Map;
2025-01-28 18:25:30 -05:00
import java.util.UUID;
2025-01-29 15:04:19 -05:00
import java.util.concurrent.ConcurrentHashMap;
2025-01-28 18:14:18 -05:00
public abstract class LargeAbstractPacket extends AbstractPacket {
2025-01-29 15:04:19 -05:00
private static final Map<UUID, PacketStorage> packetChunks = new ConcurrentHashMap<>();
2025-01-29 18:25:34 -05:00
private static final int CHUNK_SIZE = 10000;
2025-01-28 18:14:18 -05:00
2025-01-29 18:25:34 -05:00
/**
* Create multiple FMLProxyPacket objects, each containing up to CHUNK_SIZE bytes.
*/
2025-01-28 18:14:18 -05:00
@Override
2025-01-29 18:25:34 -05:00
public List<FMLProxyPacket> generatePackets() {
List<FMLProxyPacket> packets = new ArrayList<>();
PacketChannel packetChannel = getChannel();
byte[] fullData;
try {
fullData = getData();
} catch (IOException e) {
e.printStackTrace();
return packets;
}
int totalSize = fullData.length;
2025-01-29 15:04:19 -05:00
UUID packetId = UUID.randomUUID();
2025-01-29 18:25:34 -05:00
// Break data into CHUNK_SIZE chunks
2025-01-29 15:04:19 -05:00
for (int offset = 0; offset < totalSize; offset += CHUNK_SIZE) {
int chunkSize = Math.min(CHUNK_SIZE, totalSize - offset);
2025-01-29 18:25:34 -05:00
ByteBuf chunkBuf = Unpooled.buffer();
chunkBuf.writeInt(packetChannel.getChannelType().ordinal());
chunkBuf.writeInt(getType().ordinal());
2025-01-29 15:04:19 -05:00
2025-01-29 18:25:34 -05:00
chunkBuf.writeLong(packetId.getMostSignificantBits());
chunkBuf.writeLong(packetId.getLeastSignificantBits());
chunkBuf.writeInt(totalSize);
chunkBuf.writeInt(offset);
chunkBuf.writeInt((totalSize + CHUNK_SIZE - 1) / CHUNK_SIZE);
2025-01-29 15:04:19 -05:00
2025-01-29 18:25:34 -05:00
chunkBuf.writeBytes(fullData, offset, chunkSize);
FMLProxyPacket proxyPacket = new FMLProxyPacket(chunkBuf, packetChannel.getChannelName());
packets.add(proxyPacket);
2025-01-28 18:14:18 -05:00
}
2025-01-29 18:25:34 -05:00
return packets;
2025-01-28 18:14:18 -05:00
}
@Override
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
2025-01-28 18:25:30 -05:00
long mostSigBits = in.readLong();
long leastSigBits = in.readLong();
UUID packetId = new UUID(mostSigBits, leastSigBits);
2025-01-29 15:04:19 -05:00
2025-01-28 18:14:18 -05:00
int totalSize = in.readInt();
int offset = in.readInt();
2025-01-29 15:04:19 -05:00
int totalChunks = in.readInt(); // Currently unused aside from potential debugging/verification
int chunkSize = Math.min(CHUNK_SIZE, totalSize - offset);
// 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);
}
// Read the exact chunk data
ByteBuf chunk = in.readBytes(chunkSize);
2025-01-28 18:14:18 -05:00
2025-01-29 15:04:19 -05:00
// Store the received chunk in a PacketStorage
PacketStorage storage = packetChunks.computeIfAbsent(packetId,
k -> new PacketStorage(Unpooled.buffer(totalSize), 0, totalSize));
2025-01-28 18:14:18 -05:00
2025-01-29 15:04:19 -05:00
// 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
2025-01-28 18:14:18 -05:00
packetChunks.remove(packetId);
2025-01-29 15:04:19 -05:00
// 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);
// Clean up and handle
storage.data.release();
handleCompleteData(completeData, player);
completeData.release();
2025-01-29 13:28:14 -05:00
}
2025-01-29 15:04:19 -05:00
chunk.release();
2025-01-29 13:28:14 -05:00
}
2025-01-29 15:04:19 -05:00
protected abstract byte[] getData() throws IOException;
protected abstract void handleCompleteData(ByteBuf data, EntityPlayer player) throws IOException;
2025-01-29 18:25:34 -05:00
@Override
public final FMLProxyPacket generatePacket() {return null;}
@Override
public void sendData(ByteBuf out) throws IOException {}
2025-01-29 15:04:19 -05:00
/**
* 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;
2025-01-28 18:25:30 -05:00
2025-01-29 15:04:19 -05:00
PacketStorage(ByteBuf data, int receivedSoFar, int totalSize) {
this.data = data;
this.receivedSoFar = receivedSoFar;
this.totalSize = totalSize;
}
}
2025-01-28 18:14:18 -05:00
}