Progress on Rewriting Packet Handling

Continued building a system for transferring the complete internal
states of our dimensions from the server to the client. However, Steven
suggested that clients only need minimal data to operate properly, as
opposed to the server. My motivation for this more complicated system
was the concern that minimal information wouldn't be enough. I'm going
to commit my progress, then tear it down and write a much simpler
version.
This commit is contained in:
SenseiKiwi
2013-09-02 16:51:20 -04:00
parent 56ecb0cd9e
commit 307d2258d1
15 changed files with 348 additions and 64 deletions

View File

@@ -11,7 +11,7 @@ import net.minecraft.network.packet.Packet1Login;
import net.minecraft.network.packet.Packet250CustomPayload; import net.minecraft.network.packet.Packet250CustomPayload;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.core.PocketManager;
import StevenDimDoors.mod_pocketDim.watcher.IOpaqueMessage; import StevenDimDoors.mod_pocketDim.messages.IDataMessage;
import cpw.mods.fml.common.network.IConnectionHandler; import cpw.mods.fml.common.network.IConnectionHandler;
import cpw.mods.fml.common.network.Player; import cpw.mods.fml.common.network.Player;
@@ -41,7 +41,7 @@ public class ConnectionHandler implements IConnectionHandler
//Send information about all the registered dimensions and links to the client //Send information about all the registered dimensions and links to the client
try try
{ {
IOpaqueMessage message = PocketManager.getState(); IDataMessage message = PocketManager.getState();
Packet250CustomPayload packet = new Packet250CustomPayload(); Packet250CustomPayload packet = new Packet250CustomPayload();
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream writer = new DataOutputStream(buffer); DataOutputStream writer = new DataOutputStream(buffer);

View File

@@ -7,8 +7,8 @@ import java.io.IOException;
import net.minecraft.network.INetworkManager; import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet250CustomPayload; import net.minecraft.network.packet.Packet250CustomPayload;
import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.core.PocketManager;
import StevenDimDoors.mod_pocketDim.watcher.IOpaqueMessage; import StevenDimDoors.mod_pocketDim.messages.IDataMessage;
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher; import StevenDimDoors.mod_pocketDim.messages.IUpdateWatcher;
import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.common.network.PacketDispatcher; import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.common.network.Player; import cpw.mods.fml.common.network.Player;
@@ -30,19 +30,19 @@ public class ServerPacketHandler implements IPacketHandler
private class DimWatcher implements IUpdateWatcher private class DimWatcher implements IUpdateWatcher
{ {
@Override @Override
public void onCreated(IOpaqueMessage message) public void onCreated(IDataMessage message)
{ {
sendMessageToAllPlayers(PacketConstants.CREATE_DIM_PACKET_ID, message); sendMessageToAllPlayers(PacketConstants.CREATE_DIM_PACKET_ID, message);
} }
@Override @Override
public void onUpdated(IOpaqueMessage message) public void onUpdated(IDataMessage message)
{ {
sendMessageToAllPlayers(PacketConstants.UPDATE_DIM_PACKET_ID, message); sendMessageToAllPlayers(PacketConstants.UPDATE_DIM_PACKET_ID, message);
} }
@Override @Override
public void onDeleted(IOpaqueMessage message) public void onDeleted(IDataMessage message)
{ {
sendMessageToAllPlayers(PacketConstants.DELETE_DIM_PACKET_ID, message); sendMessageToAllPlayers(PacketConstants.DELETE_DIM_PACKET_ID, message);
} }
@@ -51,25 +51,25 @@ public class ServerPacketHandler implements IPacketHandler
private class LinkWatcher implements IUpdateWatcher private class LinkWatcher implements IUpdateWatcher
{ {
@Override @Override
public void onCreated(IOpaqueMessage message) public void onCreated(IDataMessage message)
{ {
sendMessageToAllPlayers(PacketConstants.CREATE_LINK_PACKET_ID, message); sendMessageToAllPlayers(PacketConstants.CREATE_LINK_PACKET_ID, message);
} }
@Override @Override
public void onUpdated(IOpaqueMessage message) public void onUpdated(IDataMessage message)
{ {
sendMessageToAllPlayers(PacketConstants.UPDATE_LINK_PACKET_ID, message); sendMessageToAllPlayers(PacketConstants.UPDATE_LINK_PACKET_ID, message);
} }
@Override @Override
public void onDeleted(IOpaqueMessage message) public void onDeleted(IDataMessage message)
{ {
sendMessageToAllPlayers(PacketConstants.DELETE_LINK_PACKET_ID, message); sendMessageToAllPlayers(PacketConstants.DELETE_LINK_PACKET_ID, message);
} }
} }
private static void sendMessageToAllPlayers(byte id, IOpaqueMessage message) private static void sendMessageToAllPlayers(byte id, IDataMessage message)
{ {
try try
{ {

View File

@@ -13,7 +13,7 @@ public abstract class DimLink
protected LinkTail tail; protected LinkTail tail;
protected ArrayList<DimLink> children; protected ArrayList<DimLink> children;
public DimLink(Point4D source, DimLink parent) protected DimLink(Point4D source, DimLink parent)
{ {
this.parent = parent; this.parent = parent;
this.source = source; this.source = source;
@@ -22,7 +22,7 @@ public abstract class DimLink
parent.children.add(this); parent.children.add(this);
} }
public DimLink(Point4D source, int linkType) protected DimLink(Point4D source, int linkType)
{ {
if (linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX) if (linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX)
{ {

View File

@@ -10,9 +10,10 @@ import net.minecraft.world.World;
import StevenDimDoors.mod_pocketDim.DDProperties; import StevenDimDoors.mod_pocketDim.DDProperties;
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData; import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack; import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
import StevenDimDoors.mod_pocketDim.messages.IDataMessage;
import StevenDimDoors.mod_pocketDim.messages.IUpdateWatcher;
import StevenDimDoors.mod_pocketDim.messages.LinkMessageBuilder;
import StevenDimDoors.mod_pocketDim.util.Point4D; import StevenDimDoors.mod_pocketDim.util.Point4D;
import StevenDimDoors.mod_pocketDim.watcher.IOpaqueMessage;
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
public abstract class NewDimData public abstract class NewDimData
{ {
@@ -106,17 +107,18 @@ public abstract class NewDimData
tail = new LinkTail(linkType, null); tail = new LinkTail(linkType, null);
} }
public IOpaqueMessage toMessage() public IDataMessage toMessage()
{ {
return null; return linkMessageBuilder.createMessage(this);
} }
public IOpaqueMessage toKey() public IDataMessage toKey()
{ {
return null; return linkMessageBuilder.createKey(this);
} }
} }
private static LinkMessageBuilder linkMessageBuilder = new LinkMessageBuilder();
private static Random random = new Random(); private static Random random = new Random();
private final int id; private final int id;
@@ -177,8 +179,8 @@ public abstract class NewDimData
} }
} }
protected abstract IOpaqueMessage toMessage(); protected abstract IDataMessage toMessage();
protected abstract IOpaqueMessage toKey(); protected abstract IDataMessage toKey();
public DimLink findNearestRift(World world, int range, int x, int y, int z) public DimLink findNearestRift(World world, int range, int x, int y, int z)
{ {

View File

@@ -14,11 +14,12 @@ import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.DimensionManager;
import StevenDimDoors.mod_pocketDim.DDProperties; import StevenDimDoors.mod_pocketDim.DDProperties;
import StevenDimDoors.mod_pocketDim.helpers.DeleteFolder; import StevenDimDoors.mod_pocketDim.helpers.DeleteFolder;
import StevenDimDoors.mod_pocketDim.messages.DimMessageBuilder;
import StevenDimDoors.mod_pocketDim.messages.IDataMessage;
import StevenDimDoors.mod_pocketDim.messages.IUpdateWatcher;
import StevenDimDoors.mod_pocketDim.messages.UpdateWatcherProxy;
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift; import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
import StevenDimDoors.mod_pocketDim.util.Point4D; import StevenDimDoors.mod_pocketDim.util.Point4D;
import StevenDimDoors.mod_pocketDim.watcher.IOpaqueMessage;
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
import StevenDimDoors.mod_pocketDim.watcher.UpdateWatcherProxy;
/** /**
* This class regulates all the operations involving the storage and manipulation of dimensions. It handles saving dim data, teleporting the player, and * This class regulates all the operations involving the storage and manipulation of dimensions. It handles saving dim data, teleporting the player, and
@@ -40,20 +41,19 @@ public class PocketManager
} }
@Override @Override
protected IOpaqueMessage toMessage() protected IDataMessage toMessage()
{ {
// TODO Auto-generated method stub return dimMessageBuilder.createMessage(this);
return null;
} }
@Override @Override
protected IOpaqueMessage toKey() protected IDataMessage toKey()
{ {
// TODO Auto-generated method stub return dimMessageBuilder.createKey(this);
return null;
} }
} }
private static DimMessageBuilder dimMessageBuilder = new DimMessageBuilder();
private static int OVERWORLD_DIMENSION_ID = 0; private static int OVERWORLD_DIMENSION_ID = 0;
private static volatile boolean isLoading = false; private static volatile boolean isLoading = false;
@@ -198,7 +198,7 @@ public class PocketManager
System.out.println("Loading Dimensional Doors save data..."); System.out.println("Loading Dimensional Doors save data...");
File saveFile = new File(DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.dat"); File saveFile = new File(DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.dat");
//Missing code for converting the binary data in the file into an IOpaqueMessage //Missing code for converting the binary data in the file into an IOpaqueMessage
IOpaqueMessage saveData; IDataMessage saveData;
setState(saveData); setState(saveData);
System.out.println("Loaded successfully!"); System.out.println("Loaded successfully!");
} }
@@ -377,12 +377,12 @@ public class PocketManager
return linkWatcher.unregisterReceiver(watcher); return linkWatcher.unregisterReceiver(watcher);
} }
public static IOpaqueMessage getState() public static IDataMessage getState()
{ {
} }
public static void setState(IOpaqueMessage state) public static void setState(IDataMessage state)
{ {
if (isLoaded) if (isLoaded)
{ {

View File

@@ -0,0 +1,116 @@
package StevenDimDoors.mod_pocketDim.messages;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import StevenDimDoors.mod_pocketDim.core.DimLink;
import StevenDimDoors.mod_pocketDim.core.NewDimData;
import StevenDimDoors.mod_pocketDim.core.NewDimData.InnerDimLink;
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
import StevenDimDoors.mod_pocketDim.util.Point4D;
import com.google.common.collect.ImmutableList;
public class DimMessageBuilder implements IMessageBuilder<NewDimData>
{
public static class DimMessage implements IDataMessage
{
//We'll use public fields here since this is a data container object and all the fields are immutable
//We will not transfer dungeon, link data, or any data on child dimensions
//As far as I can tell, the children will handle updating their parents anyway
public final int ID;
public final boolean IsDungeon;
public final boolean IsFilled;
public final int Depth;
public final int PackDepth;
public final Integer ParentID;
public final int RootID;
public final Point4D Origin;
public final int Orientation;
private DimMessage(NewDimData dimension)
{
ID = dimension.id();
IsDungeon = dimension.isDungeon();
IsFilled = dimension.isFilled();
Depth = dimension.depth();
PackDepth = dimension.packDepth();
ParentID = (dimension.parent() != null) ? dimension.parent().id() : null;
RootID = dimension.root().id();
Origin = dimension.origin();
Orientation = dimension.orientation();
}
private DimMessage(DataInputStream stream) throws IOException
{
ID = stream.readInt();
IsDungeon = stream.readBoolean();
IsFilled = stream.readBoolean();
Depth = stream.readInt();
PackDepth = stream.readInt();
ParentID = stream.
}
@Override
public void writeToStream(DataOutputStream stream) throws IOException
{
//Write a flag indicating that this is a full message and not a key
stream.writeBoolean(true);
}
}
public static class DimKeyMessage implements IDataMessage
{
//We'll use public fields here since this is a data container object and all the fields are immutable
public final int ID;
private DimKeyMessage(NewDimData dimension)
{
ID = dimension.id();
}
private DimKeyMessage(DataInputStream stream) throws IOException
{
ID = stream.readInt();
}
@Override
public void writeToStream(DataOutputStream stream) throws IOException
{
//Write a flag indicating that this is a key
stream.writeBoolean(false);
stream.writeInt(ID);
}
}
@Override
public IDataMessage createKey(NewDimData target)
{
return new DimKeyMessage(target);
}
@Override
public IDataMessage createMessage(NewDimData target)
{
return new DimMessage(target);
}
@Override
public IDataMessage read(DataInputStream source) throws IOException
{
//Check whether the message is a full message or just a key
if (source.readBoolean())
{
return new DimMessage(source);
}
else
{
return new DimKeyMessage(source);
}
}
}

View File

@@ -0,0 +1,9 @@
package StevenDimDoors.mod_pocketDim.messages;
import java.io.DataOutputStream;
import java.io.IOException;
public interface IDataMessage
{
public void writeToStream(DataOutputStream stream) throws IOException;
}

View File

@@ -0,0 +1,11 @@
package StevenDimDoors.mod_pocketDim.messages;
import java.io.DataInputStream;
import java.io.IOException;
public interface IMessageBuilder<T>
{
public IDataMessage createKey(T target);
public IDataMessage createMessage(T target);
public IDataMessage read(DataInputStream source) throws IOException;
}

View File

@@ -0,0 +1,8 @@
package StevenDimDoors.mod_pocketDim.messages;
public interface IUpdateWatcher
{
public void onCreated(IDataMessage message);
public void onUpdated(IDataMessage message);
public void onDeleted(IDataMessage message);
}

View File

@@ -0,0 +1,134 @@
package StevenDimDoors.mod_pocketDim.messages;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import StevenDimDoors.mod_pocketDim.core.DimLink;
import StevenDimDoors.mod_pocketDim.util.Point4D;
import com.google.common.collect.ImmutableList;
public class LinkMessageBuilder implements IMessageBuilder<DimLink>
{
public static class LinkMessage implements IDataMessage
{
//We'll use public fields here since this is a data container object and all the fields are immutable
public final Point4D Source;
public final Point4D Destination;
public final int LinkType;
public final Point4D Parent;
public final ImmutableList<Point4D> Children;
private LinkMessage(DimLink link)
{
// TODO: In the case that a child's parent has been removed but the rest of the group still exists,
// this group bond will be lost to this link on the client side. Currently, that's not a problem since
// destination data and groups don't matter to the client, but it's something to think about later.
Source = link.source();
Destination = link.destination();
LinkType = link.linkType();
Parent = link.parent().source();
ImmutableList.Builder<Point4D> builder = new ImmutableList.Builder<Point4D>();
for (DimLink child : link.children())
{
builder.add(child.source());
}
Children = builder.build();
}
private LinkMessage(DataInputStream stream) throws IOException
{
Source = Point4D.read(stream);
Parent = Point4D.read(stream);
if (Parent == null)
{
Destination = Point4D.read(stream);
LinkType = stream.readInt();
}
else
{
Destination = null;
LinkType = -1;
}
int childCount = stream.readInt();
ImmutableList.Builder<Point4D> builder = new ImmutableList.Builder<Point4D>();
for (int k = 0; k < childCount; k++)
{
builder.add(Point4D.read(stream));
}
Children = builder.build();
}
@Override
public void writeToStream(DataOutputStream stream) throws IOException
{
//Write a flag indicating that this is a full message and not a key
stream.writeBoolean(true);
Point4D.write(Source, stream);
Point4D.write(Parent, stream);
//A link only has its own destination information if it has no parent to provide it
if (Parent == null)
{
Point4D.write(Destination, stream);
stream.writeInt(LinkType);
}
stream.writeInt(Children.size());
for (Point4D child : Children)
{
Point4D.write(child, stream);
}
}
}
public static class LinkKeyMessage implements IDataMessage
{
//We'll use public fields here since this is a data container object and all the fields are immutable
public final Point4D Source;
private LinkKeyMessage(DimLink link)
{
Source = link.source();
}
private LinkKeyMessage(DataInputStream stream) throws IOException
{
Source = Point4D.read(stream);
}
@Override
public void writeToStream(DataOutputStream stream) throws IOException
{
//Write a flag indicating that this is a key
stream.writeBoolean(false);
Point4D.write(Source, stream);
}
}
@Override
public IDataMessage createKey(DimLink target)
{
return new LinkKeyMessage(target);
}
@Override
public IDataMessage createMessage(DimLink target)
{
return new LinkMessage(target);
}
@Override
public IDataMessage read(DataInputStream source) throws IOException
{
//Check whether the message is a full message or just a key
if (source.readBoolean())
{
return new LinkMessage(source);
}
else
{
return new LinkKeyMessage(source);
}
}
}

View File

@@ -1,4 +1,4 @@
package StevenDimDoors.mod_pocketDim.watcher; package StevenDimDoors.mod_pocketDim.messages;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -13,7 +13,7 @@ public class UpdateWatcherProxy implements IUpdateWatcher
} }
@Override @Override
public void onCreated(IOpaqueMessage message) public void onCreated(IDataMessage message)
{ {
for (IUpdateWatcher receiver : watchers) for (IUpdateWatcher receiver : watchers)
{ {
@@ -22,7 +22,7 @@ public class UpdateWatcherProxy implements IUpdateWatcher
} }
@Override @Override
public void onUpdated(IOpaqueMessage message) public void onUpdated(IDataMessage message)
{ {
for (IUpdateWatcher receiver : watchers) for (IUpdateWatcher receiver : watchers)
{ {
@@ -31,7 +31,7 @@ public class UpdateWatcherProxy implements IUpdateWatcher
} }
@Override @Override
public void onDeleted(IOpaqueMessage message) public void onDeleted(IDataMessage message)
{ {
for (IUpdateWatcher receiver : watchers) for (IUpdateWatcher receiver : watchers)
{ {

View File

@@ -1,5 +1,9 @@
package StevenDimDoors.mod_pocketDim.util; package StevenDimDoors.mod_pocketDim.util;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public final class Point4D implements Comparable<Point4D> public final class Point4D implements Comparable<Point4D>
{ {
@@ -155,4 +159,28 @@ public final class Point4D implements Comparable<Point4D>
{ {
return "(" + x + ", " + y + ", " + z + ", " + dimension + ")"; return "(" + x + ", " + y + ", " + z + ", " + dimension + ")";
} }
public static void write(Point4D point, DataOutputStream stream) throws IOException
{
stream.writeBoolean(point != null);
if (point != null)
{
stream.writeInt(point.x);
stream.writeInt(point.y);
stream.writeInt(point.z);
stream.writeInt(point.dimension);
}
}
public static Point4D read(DataInputStream stream) throws IOException
{
if (stream.readBoolean())
{
return new Point4D( stream.readInt(), stream.readInt(), stream.readInt(), stream.readInt() );
}
else
{
return null;
}
}
} }

View File

@@ -1,8 +0,0 @@
package StevenDimDoors.mod_pocketDim.watcher;
import java.io.DataOutputStream;
public interface IOpaqueMessage
{
void writeToStream(DataOutputStream stream);
}

View File

@@ -1,8 +0,0 @@
package StevenDimDoors.mod_pocketDim.watcher;
import com.google.common.io.ByteArrayDataInput;
public interface IOpaqueReader
{
IOpaqueMessage read(ByteArrayDataInput source);
}

View File

@@ -1,8 +0,0 @@
package StevenDimDoors.mod_pocketDim.watcher;
public interface IUpdateWatcher
{
public void onCreated(IOpaqueMessage message);
public void onUpdated(IOpaqueMessage message);
public void onDeleted(IOpaqueMessage message);
}