Completed Packet Handling Code
Finished implementing all the packet handling code. It could be improved in the future to compress the initial packet sent to clients. With this, the code is complete enough to run! Commands have not been fixed yet but that will come in the future.
This commit is contained in:
@@ -3,13 +3,12 @@ package StevenDimDoors.mod_pocketDim;
|
|||||||
public class PacketConstants
|
public class PacketConstants
|
||||||
{
|
{
|
||||||
private PacketConstants() { }
|
private PacketConstants() { }
|
||||||
|
|
||||||
|
public static final String CHANNEL_NAME = "DimDoorsPackets";
|
||||||
|
|
||||||
public static final byte CLIENT_JOIN_PACKET_ID = 1;
|
public static final byte CLIENT_JOIN_PACKET_ID = 1;
|
||||||
public static final byte CREATE_DIM_PACKET_ID = 2;
|
public static final byte CREATE_DIM_PACKET_ID = 2;
|
||||||
public static final byte UPDATE_DIM_PACKET_ID = 3;
|
public static final byte DELETE_DIM_PACKET_ID = 3;
|
||||||
public static final byte DELETE_DIM_PACKET_ID = 4;
|
public static final byte CREATE_LINK_PACKET_ID = 4;
|
||||||
public static final byte CREATE_LINK_PACKET_ID = 5;
|
public static final byte DELETE_LINK_PACKET_ID = 5;
|
||||||
public static final byte UPDATE_LINK_PACKET_ID = 6;
|
|
||||||
public static final byte DELETE_LINK_PACKET_ID = 7;
|
|
||||||
public static final String CHANNEL_NAME = "DimDoorsPackets";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public abstract class DimLink
|
|||||||
|
|
||||||
protected DimLink(Point4D source, int linkType)
|
protected DimLink(Point4D source, int linkType)
|
||||||
{
|
{
|
||||||
if (linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX && linkType != LinkTypes.UNKNOWN)
|
if (linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX && linkType != LinkTypes.CLIENT_SIDE)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("The specified link type is invalid.");
|
throw new IllegalArgumentException("The specified link type is invalid.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public class LinkTypes
|
|||||||
public static final int ENUM_MIN = 0;
|
public static final int ENUM_MIN = 0;
|
||||||
public static final int ENUM_MAX = 8;
|
public static final int ENUM_MAX = 8;
|
||||||
|
|
||||||
public static final int UNKNOWN = -1337;
|
public static final int CLIENT_SIDE = -1337;
|
||||||
|
|
||||||
public static final int NORMAL = 0;
|
public static final int NORMAL = 0;
|
||||||
public static final int LIMBO = 1;
|
public static final int LIMBO = 1;
|
||||||
|
|||||||
@@ -167,6 +167,11 @@ public abstract class NewDimData
|
|||||||
protected NewDimData(int id, NewDimData root)
|
protected NewDimData(int id, NewDimData root)
|
||||||
{
|
{
|
||||||
// This constructor is meant for client-side code only
|
// This constructor is meant for client-side code only
|
||||||
|
if (root == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("root cannot be null.");
|
||||||
|
}
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.linkMapping = new TreeMap<Point4D, InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
this.linkMapping = new TreeMap<Point4D, InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
||||||
this.linkList = new ArrayList<InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
this.linkList = new ArrayList<InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
||||||
@@ -180,15 +185,7 @@ public abstract class NewDimData
|
|||||||
this.dungeon = null;
|
this.dungeon = null;
|
||||||
this.linkWatcher = null;
|
this.linkWatcher = null;
|
||||||
this.depth = 0;
|
this.depth = 0;
|
||||||
if (root != null)
|
this.root = root;
|
||||||
{
|
|
||||||
this.root = root;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.root = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import StevenDimDoors.mod_pocketDim.helpers.DeleteFolder;
|
|||||||
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.ClientDimData;
|
import StevenDimDoors.mod_pocketDim.watcher.ClientDimData;
|
||||||
|
import StevenDimDoors.mod_pocketDim.watcher.IUpdateSource;
|
||||||
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
||||||
import StevenDimDoors.mod_pocketDim.watcher.UpdateWatcherProxy;
|
import StevenDimDoors.mod_pocketDim.watcher.UpdateWatcherProxy;
|
||||||
|
|
||||||
@@ -44,14 +45,54 @@ public class PocketManager
|
|||||||
// This constructor is meant for client-side code only
|
// This constructor is meant for client-side code only
|
||||||
super(id, root);
|
super(id, root);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public InnerDimData(int id)
|
|
||||||
|
private static class ClientLinkWatcher implements IUpdateWatcher<Point4D>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onCreated(Point4D source)
|
||||||
{
|
{
|
||||||
// This constructor is meant for client-side code only
|
NewDimData dimension = getDimensionData(source.getDimension());
|
||||||
super(id, null);
|
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.CLIENT_SIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleted(Point4D source)
|
||||||
|
{
|
||||||
|
NewDimData dimension = getDimensionData(source.getDimension());
|
||||||
|
dimension.deleteLink(source.getX(), source.getY(), source.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ClientDimWatcher implements IUpdateWatcher<ClientDimData>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onCreated(ClientDimData data)
|
||||||
|
{
|
||||||
|
registerClientDimension(data.ID, data.RootID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleted(ClientDimData data)
|
||||||
|
{
|
||||||
|
deletePocket(getDimensionData(data.ID), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DimRegistrationCallback implements IDimRegistrationCallback
|
||||||
|
{
|
||||||
|
// We use this class to provide Compactor with the ability to send us dim data without
|
||||||
|
// having to instantiate a bunch of data containers and without exposing an "unsafe"
|
||||||
|
// creation method for anyone to call. Integrity protection for the win! It's like
|
||||||
|
// exposing a private constructor ONLY to a very specific trusted class.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NewDimData registerDimension(int dimensionID, int rootID)
|
||||||
|
{
|
||||||
|
return registerClientDimension(dimensionID, rootID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -301,6 +342,30 @@ public class PocketManager
|
|||||||
dimensionData.put(dimensionID, dimension);
|
dimensionData.put(dimensionID, dimension);
|
||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static NewDimData registerClientDimension(int dimensionID, int rootID)
|
||||||
|
{
|
||||||
|
// No need to raise events here since this code should only run on the client side
|
||||||
|
// getDimensionData() always handles root dimensions properly, even if the weren't defined before
|
||||||
|
|
||||||
|
InnerDimData root = (InnerDimData) getDimensionData(rootID);
|
||||||
|
InnerDimData dimension;
|
||||||
|
|
||||||
|
if (rootID != dimensionID)
|
||||||
|
{
|
||||||
|
dimension = dimensionData.get(dimensionID);
|
||||||
|
if (dimension == null)
|
||||||
|
{
|
||||||
|
dimension = new InnerDimData(dimensionID, root);
|
||||||
|
dimensionData.put(dimension.id(), dimension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dimension = root;
|
||||||
|
}
|
||||||
|
return dimension;
|
||||||
|
}
|
||||||
|
|
||||||
public static NewDimData getDimensionData(World world)
|
public static NewDimData getDimensionData(World world)
|
||||||
{
|
{
|
||||||
@@ -323,6 +388,11 @@ public class PocketManager
|
|||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Iterable<? extends NewDimData> getDimensions()
|
||||||
|
{
|
||||||
|
return dimensionData.values();
|
||||||
|
}
|
||||||
|
|
||||||
public static void unload()
|
public static void unload()
|
||||||
{
|
{
|
||||||
save();
|
save();
|
||||||
@@ -376,6 +446,11 @@ public class PocketManager
|
|||||||
{
|
{
|
||||||
return linkWatcher.unregisterReceiver(watcher);
|
return linkWatcher.unregisterReceiver(watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getWatchers(IUpdateSource updateSource)
|
||||||
|
{
|
||||||
|
updateSource.registerWatchers(new ClientDimWatcher(), new ClientLinkWatcher());
|
||||||
|
}
|
||||||
|
|
||||||
public static void writePacket(DataOutputStream output) throws IOException
|
public static void writePacket(DataOutputStream output) throws IOException
|
||||||
{
|
{
|
||||||
@@ -398,8 +473,8 @@ public class PocketManager
|
|||||||
|
|
||||||
// Set up fields
|
// Set up fields
|
||||||
dimensionData = new HashMap<Integer, InnerDimData>();
|
dimensionData = new HashMap<Integer, InnerDimData>();
|
||||||
dimWatcher = new UpdateWatcherProxy<ClientDimData>();
|
dimWatcher = null; // Clients shouldn't need to watch dims
|
||||||
linkWatcher = new UpdateWatcherProxy<Point4D>();
|
linkWatcher = null; // Clients shouldn't need to watch links
|
||||||
|
|
||||||
// Load compacted client-side dimension data
|
// Load compacted client-side dimension data
|
||||||
Compactor.readDimensions(input, new DimRegistrationCallback());
|
Compactor.readDimensions(input, new DimRegistrationCallback());
|
||||||
@@ -411,42 +486,4 @@ public class PocketManager
|
|||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DimRegistrationCallback implements IDimRegistrationCallback
|
|
||||||
{
|
|
||||||
// We use this class to provide Compactor with the ability to send us dim data without
|
|
||||||
// having to instantiate a bunch of data containers and without exposing an "unsafe"
|
|
||||||
// creation method for anyone to call. Integrity protection for the win! It's like
|
|
||||||
// exposing a private constructor ONLY to a very specific trusted class.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NewDimData registerDimension(int dimensionID, int rootID)
|
|
||||||
{
|
|
||||||
// No need to raise events here since this code should only run on the client side
|
|
||||||
// We assume that the root dimension has already been registered to avoid dependency issues
|
|
||||||
|
|
||||||
InnerDimData root = dimensionData.get(rootID);
|
|
||||||
InnerDimData dimension;
|
|
||||||
|
|
||||||
if (rootID != dimensionID)
|
|
||||||
{
|
|
||||||
dimension = dimensionData.get(dimensionID);
|
|
||||||
if (dimension == null)
|
|
||||||
{
|
|
||||||
dimension = new InnerDimData(dimensionID, root);
|
|
||||||
dimensionData.put(dimension.id(), dimension);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (root == null)
|
|
||||||
{
|
|
||||||
root = new InnerDimData(rootID);
|
|
||||||
dimensionData.put(root.id(), root);
|
|
||||||
}
|
|
||||||
dimension = root;
|
|
||||||
}
|
|
||||||
return dimension;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class Compactor
|
|||||||
for (int h = 0; h < linkCount; h++)
|
for (int h = 0; h < linkCount; h++)
|
||||||
{
|
{
|
||||||
Point4D source = Point4D.read(input);
|
Point4D source = Point4D.read(input);
|
||||||
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.UNKNOWN);
|
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.CLIENT_SIDE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class mod_pocketDim
|
|||||||
//MonolithSpawner should be initialized before any provider instances are created
|
//MonolithSpawner should be initialized before any provider instances are created
|
||||||
//Register the other regular tick receivers as well
|
//Register the other regular tick receivers as well
|
||||||
spawner = new MonolithSpawner(commonTickHandler, properties);
|
spawner = new MonolithSpawner(commonTickHandler, properties);
|
||||||
new RiftRegenerator(commonTickHandler, properties); //No need to store the reference
|
new RiftRegenerator(commonTickHandler); //No need to store the reference
|
||||||
LimboDecay decay = new LimboDecay(commonTickHandler, properties);
|
LimboDecay decay = new LimboDecay(commonTickHandler, properties);
|
||||||
|
|
||||||
transientDoor = (new TransientDoor(properties.TransientDoorID, Material.iron)).setHardness(1.0F) .setUnlocalizedName("transientDoor");
|
transientDoor = (new TransientDoor(properties.TransientDoorID, Material.iron)).setHardness(1.0F) .setUnlocalizedName("transientDoor");
|
||||||
|
|||||||
@@ -7,22 +7,16 @@ import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
|||||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
|
||||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||||
import cpw.mods.fml.common.FMLCommonHandler;
|
|
||||||
import cpw.mods.fml.relauncher.Side;
|
|
||||||
|
|
||||||
public class RiftRegenerator implements IRegularTickReceiver {
|
public class RiftRegenerator implements IRegularTickReceiver {
|
||||||
|
|
||||||
private static final int RIFT_REGENERATION_INTERVAL = 200; //Regenerate random rifts every 200 ticks
|
private static final int RIFT_REGENERATION_INTERVAL = 200; //Regenerate random rifts every 200 ticks
|
||||||
private static final int RIFTS_REGENERATED_PER_DIMENSION = 5;
|
private static final int RIFTS_REGENERATED_PER_DIMENSION = 5;
|
||||||
|
|
||||||
private DDProperties properties;
|
public RiftRegenerator(IRegularTickSender sender)
|
||||||
|
|
||||||
public RiftRegenerator(IRegularTickSender sender, DDProperties properties)
|
|
||||||
{
|
{
|
||||||
sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false);
|
sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false);
|
||||||
this.properties = properties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
8
StevenDimDoors/mod_pocketDim/watcher/IUpdateSource.java
Normal file
8
StevenDimDoors/mod_pocketDim/watcher/IUpdateSource.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.watcher;
|
||||||
|
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||||
|
|
||||||
|
public interface IUpdateSource
|
||||||
|
{
|
||||||
|
public void registerWatchers(IUpdateWatcher<ClientDimData> dimWatcher, IUpdateWatcher<Point4D> linkWatcher);
|
||||||
|
}
|
||||||
@@ -1,15 +1,70 @@
|
|||||||
package StevenDimDoors.mod_pocketDimClient;
|
package StevenDimDoors.mod_pocketDimClient;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
|
||||||
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.PacketConstants;
|
||||||
|
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.watcher.ClientDimData;
|
||||||
|
import StevenDimDoors.mod_pocketDim.watcher.IUpdateSource;
|
||||||
|
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
||||||
import cpw.mods.fml.common.network.IPacketHandler;
|
import cpw.mods.fml.common.network.IPacketHandler;
|
||||||
import cpw.mods.fml.common.network.Player;
|
import cpw.mods.fml.common.network.Player;
|
||||||
|
|
||||||
public class ClientPacketHandler implements IPacketHandler
|
public class ClientPacketHandler implements IPacketHandler, IUpdateSource
|
||||||
{
|
{
|
||||||
|
private IUpdateWatcher<Point4D> linkWatcher;
|
||||||
|
private IUpdateWatcher<ClientDimData> dimWatcher;
|
||||||
|
|
||||||
|
public ClientPacketHandler()
|
||||||
|
{
|
||||||
|
PocketManager.getWatchers(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerWatchers(IUpdateWatcher<ClientDimData> dimWatcher, IUpdateWatcher<Point4D> linkWatcher)
|
||||||
|
{
|
||||||
|
this.dimWatcher = dimWatcher;
|
||||||
|
this.linkWatcher = linkWatcher;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player)
|
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player)
|
||||||
{
|
{
|
||||||
|
// TODO: Is this even necessary? I'm not convinced we can receive packets from other channels anyway!
|
||||||
|
if (!packet.channel.equals(PacketConstants.CHANNEL_NAME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DataInputStream input = new DataInputStream(new ByteArrayInputStream(packet.data));
|
||||||
|
byte packetID = input.readByte();
|
||||||
|
switch (packetID)
|
||||||
|
{
|
||||||
|
case PacketConstants.CLIENT_JOIN_PACKET_ID:
|
||||||
|
PocketManager.readPacket(input);
|
||||||
|
break;
|
||||||
|
case PacketConstants.CREATE_DIM_PACKET_ID:
|
||||||
|
dimWatcher.onCreated( ClientDimData.read(input) );
|
||||||
|
break;
|
||||||
|
case PacketConstants.CREATE_LINK_PACKET_ID:
|
||||||
|
linkWatcher.onCreated( Point4D.read(input) );
|
||||||
|
break;
|
||||||
|
case PacketConstants.DELETE_DIM_PACKET_ID:
|
||||||
|
dimWatcher.onDeleted( ClientDimData.read(input) );
|
||||||
|
break;
|
||||||
|
case PacketConstants.DELETE_LINK_PACKET_ID:
|
||||||
|
linkWatcher.onDeleted( Point4D.read(input) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.err.println("An exception occurred while processing a data packet:");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user