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: {
|
case PacketIds.RPC_TILE: {
|
||||||
PacketRPCTile rpc = new PacketRPCTile();
|
((PacketRPCTile) packet).call(player);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,38 @@
|
||||||
package buildcraft.core.network;
|
package buildcraft.core.network;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.util.ArrayList;
|
||||||
import java.io.DataOutputStream;
|
import java.util.Date;
|
||||||
import java.io.IOException;
|
import java.util.HashMap;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
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 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;
|
public TileEntity tile;
|
||||||
|
|
||||||
byte [] contents;
|
byte [] contents;
|
||||||
|
int id;
|
||||||
|
boolean moreDataToCome = false;
|
||||||
|
|
||||||
public EntityPlayer sender;
|
int dimId;
|
||||||
|
int x, y, z;
|
||||||
|
|
||||||
public PacketRPCTile () {
|
public PacketRPCTile () {
|
||||||
|
id = GLOBAL_ID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PacketRPCTile (byte [] bytes) {
|
public PacketRPCTile (TileEntity tile, byte [] bytes) {
|
||||||
|
this.tile = tile;
|
||||||
contents = bytes;
|
contents = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,15 +47,101 @@ public class PacketRPCTile extends BuildCraftPacket {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readData(ByteBuf data) {
|
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();
|
RPCMessageInfo info = new RPCMessageInfo();
|
||||||
info.sender = sender;
|
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
|
@Override
|
||||||
public void writeData(ByteBuf data) {
|
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);
|
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.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -57,14 +58,14 @@ public class RPCHandler {
|
||||||
|
|
||||||
LinkedList <Method> rpcMethods = new LinkedList<Method>();
|
LinkedList <Method> rpcMethods = new LinkedList<Method>();
|
||||||
|
|
||||||
for (int i = 0; i < sortedMethods.length; ++i) {
|
for (Method sortedMethod : sortedMethods) {
|
||||||
if (sortedMethods [i].getAnnotation (RPC.class) != null) {
|
if (sortedMethod.getAnnotation (RPC.class) != null) {
|
||||||
methodsMap.put(sortedMethods [i].getName(), rpcMethods.size());
|
methodsMap.put(sortedMethod.getName(), rpcMethods.size());
|
||||||
rpcMethods.add(sortedMethods [i]);
|
rpcMethods.add(sortedMethod);
|
||||||
|
|
||||||
MethodMapping mapping = new MethodMapping();
|
MethodMapping mapping = new MethodMapping();
|
||||||
mapping.method = sortedMethods [i];
|
mapping.method = sortedMethod;
|
||||||
mapping.parameters = sortedMethods [i].getParameterTypes();
|
mapping.parameters = sortedMethod.getParameterTypes();
|
||||||
mapping.mappings = new ClassSerializer [mapping.parameters.length];
|
mapping.mappings = new ClassSerializer [mapping.parameters.length];
|
||||||
|
|
||||||
for (int j = 0; j < mapping.parameters.length; ++j) {
|
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);
|
PacketRPCTile packet = handlers.get (tile.getClass().getName()).createRCPPacket(tile, method, actuals);
|
||||||
|
|
||||||
if (packet != null) {
|
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();
|
ByteBuf data = Unpooled.buffer();
|
||||||
|
|
||||||
try {
|
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);
|
writeParameters(method, data, actuals);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -235,7 +233,7 @@ public class RPCHandler {
|
||||||
byte [] bytes = new byte [data.readableBytes()];
|
byte [] bytes = new byte [data.readableBytes()];
|
||||||
data.readBytes(bytes);
|
data.readBytes(bytes);
|
||||||
|
|
||||||
return new PacketRPCTile(bytes);
|
return new PacketRPCTile(tile, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeParameters(String method, ByteBuf data, Object... actuals)
|
private void writeParameters(String method, ByteBuf data, Object... actuals)
|
||||||
|
|
Loading…
Reference in a new issue