implemented RPC slicing and fixed handling, close #1477
This commit is contained in:
parent
aaecf6126a
commit
854dab6c32
3 changed files with 119 additions and 48 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue