implemented RPC slicing and fixed handling, close #1477

This commit is contained in:
SpaceToad 2014-03-08 18:51:55 +01:00
parent aaecf6126a
commit 854dab6c32
3 changed files with 119 additions and 48 deletions

View file

@ -83,32 +83,7 @@ public class PacketHandler extends BuildCraftChannelHandler {
}
case PacketIds.RPC_TILE: {
PacketRPCTile rpc = new PacketRPCTile();
rpc.sender = player;
int dimId = data.readShort();
World world = null;
if (!rpc.sender.worldObj.isRemote) {
// if this is a server, then get the world
world = DimensionManager.getProvider(dimId).worldObj;
} else if (rpc.sender.worldObj.provider.dimensionId == dimId) {
// if the player is on this world, then synchronize things
world = rpc.sender.worldObj;
}
if (world != null) {
int x = data.readInt();
int y = data.readInt();
int z = data.readInt();
TileEntity tile = world.getTileEntity(x, y, z);
rpc.setTile (tile);
rpc.readData(data);
}
((PacketRPCTile) packet).call(player);
break;
}

View file

@ -1,26 +1,38 @@
package buildcraft.core.network;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import org.apache.commons.lang3.ArrayUtils;
public class PacketRPCTile extends BuildCraftPacket {
public static int GLOBAL_ID = new Random(new Date().getTime()).nextInt();
public static HashMap <Integer, ByteBuf> bufferedPackets = new HashMap <Integer, ByteBuf> ();
public TileEntity tile;
byte [] contents;
int id;
boolean moreDataToCome = false;
public EntityPlayer sender;
int dimId;
int x, y, z;
public PacketRPCTile () {
id = GLOBAL_ID++;
}
public PacketRPCTile (byte [] bytes) {
public PacketRPCTile (TileEntity tile, byte [] bytes) {
this.tile = tile;
contents = bytes;
}
@ -35,15 +47,101 @@ public class PacketRPCTile extends BuildCraftPacket {
@Override
public void readData(ByteBuf data) {
dimId = data.readShort();
x = data.readInt();
y = data.readInt();
z = data.readInt();
id = data.readInt ();
moreDataToCome = data.readBoolean();
contents = new byte [data.readableBytes()];
data.readBytes(contents);
}
public void call (EntityPlayer sender) {
World world = null;
if (!sender.worldObj.isRemote) {
// if this is a server, then get the world
world = DimensionManager.getProvider(dimId).worldObj;
} else if (sender.worldObj.provider.dimensionId == dimId) {
// if the player is on this world, then synchronize things
world = sender.worldObj;
}
TileEntity tile = world.getTileEntity(x, y, z);
setTile (tile);
RPCMessageInfo info = new RPCMessageInfo();
info.sender = sender;
RPCHandler.receiveRPC(tile, info, data);
ByteBuf previousData = bufferedPackets.get(id);
bufferedPackets.remove(id);
ByteBuf completeData;
if (previousData != null) {
completeData = previousData.writeBytes(contents);
} else {
completeData = Unpooled.buffer();
completeData.writeBytes(contents);
}
if (!moreDataToCome) {
RPCHandler.receiveRPC(tile, info, completeData);
} else {
bufferedPackets.put(id, completeData);
}
}
@Override
public void writeData(ByteBuf data) {
// In order to save space on message, we assuming dimensions ids
// small. Maybe worth using a varint instead
data.writeShort(tile.getWorldObj().provider.dimensionId);
data.writeInt(tile.xCoord);
data.writeInt(tile.yCoord);
data.writeInt(tile.zCoord);
data.writeInt(id);
data.writeBoolean(moreDataToCome);
data.writeBytes(contents);
}
public ArrayList <PacketRPCTile> breakIntoSmallerPackets (int maxSize) {
ArrayList<PacketRPCTile> messages = new ArrayList<PacketRPCTile>();
if (contents.length < maxSize) {
messages.add(this);
return messages;
}
int start = 0;
while (true) {
byte [] subContents = ArrayUtils.subarray(contents, start, start + maxSize);
PacketRPCTile subPacket = new PacketRPCTile();
subPacket.id = id;
subPacket.contents = subContents;
subPacket.tile = tile;
messages.add(subPacket);
start += maxSize;
if (start >= contents.length) {
subPacket.moreDataToCome = false;
break;
} else {
subPacket.moreDataToCome = true;
}
}
return messages;
}
}

View file

@ -6,6 +6,7 @@ import io.netty.buffer.Unpooled;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
@ -57,14 +58,14 @@ public class RPCHandler {
LinkedList <Method> rpcMethods = new LinkedList<Method>();
for (int i = 0; i < sortedMethods.length; ++i) {
if (sortedMethods [i].getAnnotation (RPC.class) != null) {
methodsMap.put(sortedMethods [i].getName(), rpcMethods.size());
rpcMethods.add(sortedMethods [i]);
for (Method sortedMethod : sortedMethods) {
if (sortedMethod.getAnnotation (RPC.class) != null) {
methodsMap.put(sortedMethod.getName(), rpcMethods.size());
rpcMethods.add(sortedMethod);
MethodMapping mapping = new MethodMapping();
mapping.method = sortedMethods [i];
mapping.parameters = sortedMethods [i].getParameterTypes();
mapping.method = sortedMethod;
mapping.parameters = sortedMethod.getParameterTypes();
mapping.mappings = new ClassSerializer [mapping.parameters.length];
for (int j = 0; j < mapping.parameters.length; ++j) {
@ -96,7 +97,11 @@ public class RPCHandler {
PacketRPCTile packet = handlers.get (tile.getClass().getName()).createRCPPacket(tile, method, actuals);
if (packet != null) {
BuildCraftCore.instance.sendToServer(packet);
ArrayList<PacketRPCTile> packets = packet.breakIntoSmallerPackets(30 * 1024);
for (PacketRPCTile p : packets) {
BuildCraftCore.instance.sendToServer(p);
}
}
}
@ -216,13 +221,6 @@ public class RPCHandler {
ByteBuf data = Unpooled.buffer();
try {
// In order to save space on message, we assuming dimensions ids
// small. Maybe worth using a varint instead
data.writeShort(tile.getWorldObj().provider.dimensionId);
data.writeInt(tile.xCoord);
data.writeInt(tile.yCoord);
data.writeInt(tile.zCoord);
writeParameters(method, data, actuals);
} catch (IOException e) {
e.printStackTrace();
@ -235,7 +233,7 @@ public class RPCHandler {
byte [] bytes = new byte [data.readableBytes()];
data.readBytes(bytes);
return new PacketRPCTile(bytes);
return new PacketRPCTile(tile, bytes);
}
private void writeParameters(String method, ByteBuf data, Object... actuals)