Overhauled Server-Side Packet Handling
Threw out the complicated architecture that I'd made for synchronizing server and client data perfectly. Instead, we now send just enough data to the client and the resulting code is simpler. Some of the client-side code is also done so all packet handling should be finished soon.
This commit is contained in:
parent
307d2258d1
commit
3568d223ff
17 changed files with 377 additions and 459 deletions
|
@ -11,7 +11,6 @@ import net.minecraft.network.packet.Packet1Login;
|
|||
import net.minecraft.network.packet.Packet250CustomPayload;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.messages.IDataMessage;
|
||||
import cpw.mods.fml.common.network.IConnectionHandler;
|
||||
import cpw.mods.fml.common.network.Player;
|
||||
|
||||
|
@ -41,12 +40,11 @@ public class ConnectionHandler implements IConnectionHandler
|
|||
//Send information about all the registered dimensions and links to the client
|
||||
try
|
||||
{
|
||||
IDataMessage message = PocketManager.getState();
|
||||
Packet250CustomPayload packet = new Packet250CustomPayload();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(buffer);
|
||||
writer.writeByte(PacketConstants.CLIENT_JOIN_PACKET_ID);
|
||||
message.writeToStream(writer);
|
||||
PocketManager.writePacket(writer);
|
||||
writer.close();
|
||||
packet.channel = PacketConstants.CHANNEL_NAME;
|
||||
packet.data = buffer.toByteArray();
|
||||
|
|
|
@ -7,8 +7,9 @@ import java.io.IOException;
|
|||
import net.minecraft.network.INetworkManager;
|
||||
import net.minecraft.network.packet.Packet250CustomPayload;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.messages.IDataMessage;
|
||||
import StevenDimDoors.mod_pocketDim.messages.IUpdateWatcher;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientDimData;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
||||
import cpw.mods.fml.common.network.IPacketHandler;
|
||||
import cpw.mods.fml.common.network.PacketDispatcher;
|
||||
import cpw.mods.fml.common.network.Player;
|
||||
|
@ -22,54 +23,39 @@ public class ServerPacketHandler implements IPacketHandler
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player)
|
||||
{
|
||||
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { }
|
||||
|
||||
}
|
||||
|
||||
private class DimWatcher implements IUpdateWatcher
|
||||
private static class DimWatcher implements IUpdateWatcher<ClientDimData>
|
||||
{
|
||||
@Override
|
||||
public void onCreated(IDataMessage message)
|
||||
public void onCreated(ClientDimData message)
|
||||
{
|
||||
sendMessageToAllPlayers(PacketConstants.CREATE_DIM_PACKET_ID, message);
|
||||
sendDimPacket(PacketConstants.CREATE_DIM_PACKET_ID, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdated(IDataMessage message)
|
||||
public void onDeleted(ClientDimData message)
|
||||
{
|
||||
sendMessageToAllPlayers(PacketConstants.UPDATE_DIM_PACKET_ID, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(IDataMessage message)
|
||||
{
|
||||
sendMessageToAllPlayers(PacketConstants.DELETE_DIM_PACKET_ID, message);
|
||||
sendDimPacket(PacketConstants.DELETE_DIM_PACKET_ID, message);
|
||||
}
|
||||
}
|
||||
|
||||
private class LinkWatcher implements IUpdateWatcher
|
||||
private static class LinkWatcher implements IUpdateWatcher<Point4D>
|
||||
{
|
||||
@Override
|
||||
public void onCreated(IDataMessage message)
|
||||
public void onCreated(Point4D message)
|
||||
{
|
||||
sendMessageToAllPlayers(PacketConstants.CREATE_LINK_PACKET_ID, message);
|
||||
sendLinkPacket(PacketConstants.CREATE_LINK_PACKET_ID, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdated(IDataMessage message)
|
||||
public void onDeleted(Point4D message)
|
||||
{
|
||||
sendMessageToAllPlayers(PacketConstants.UPDATE_LINK_PACKET_ID, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(IDataMessage message)
|
||||
{
|
||||
sendMessageToAllPlayers(PacketConstants.DELETE_LINK_PACKET_ID, message);
|
||||
sendLinkPacket(PacketConstants.DELETE_LINK_PACKET_ID, message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendMessageToAllPlayers(byte id, IDataMessage message)
|
||||
private static void sendDimPacket(byte id, ClientDimData data)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -77,7 +63,29 @@ public class ServerPacketHandler implements IPacketHandler
|
|||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(buffer);
|
||||
writer.writeByte(id);
|
||||
message.writeToStream(writer);
|
||||
data.write(writer);
|
||||
writer.close();
|
||||
packet.channel = PacketConstants.CHANNEL_NAME;
|
||||
packet.data = buffer.toByteArray();
|
||||
packet.length = packet.data.length;
|
||||
PacketDispatcher.sendPacketToAllPlayers(packet);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
//This shouldn't happen...
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendLinkPacket(byte id, Point4D data)
|
||||
{
|
||||
try
|
||||
{
|
||||
Packet250CustomPayload packet = new Packet250CustomPayload();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(buffer);
|
||||
writer.writeByte(id);
|
||||
Point4D.write(data, writer);
|
||||
writer.close();
|
||||
packet.channel = PacketConstants.CHANNEL_NAME;
|
||||
packet.data = buffer.toByteArray();
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public abstract class DimLink
|
||||
{
|
||||
private static final int EXPECTED_CHILDREN = 2;
|
||||
|
||||
protected Point4D source;
|
||||
protected DimLink parent;
|
||||
protected LinkTail tail;
|
||||
protected ArrayList<DimLink> children;
|
||||
protected List<DimLink> children;
|
||||
|
||||
protected DimLink(Point4D source, DimLink parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.source = source;
|
||||
this.tail = parent.tail;
|
||||
this.children = new ArrayList<DimLink>(EXPECTED_CHILDREN);
|
||||
this.children = new LinkedList<DimLink>();
|
||||
parent.children.add(this);
|
||||
}
|
||||
|
||||
protected DimLink(Point4D source, int linkType)
|
||||
{
|
||||
if (linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX)
|
||||
if (linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX && linkType != LinkTypes.UNKNOWN)
|
||||
{
|
||||
throw new IllegalArgumentException("The specified link type is invalid.");
|
||||
}
|
||||
|
@ -32,7 +31,7 @@ public abstract class DimLink
|
|||
this.parent = null;
|
||||
this.source = source;
|
||||
this.tail = new LinkTail(linkType, null);
|
||||
this.children = new ArrayList<DimLink>(EXPECTED_CHILDREN);
|
||||
this.children = new LinkedList<DimLink>();
|
||||
}
|
||||
|
||||
public Point4D source()
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
public interface IDimRegistrationCallback
|
||||
{
|
||||
public NewDimData registerDimension(int dimensionID, int rootID);
|
||||
}
|
|
@ -7,6 +7,8 @@ public class LinkTypes
|
|||
public static final int ENUM_MIN = 0;
|
||||
public static final int ENUM_MAX = 8;
|
||||
|
||||
public static final int UNKNOWN = -1337;
|
||||
|
||||
public static final int NORMAL = 0;
|
||||
public static final int LIMBO = 1;
|
||||
public static final int POCKET = 2;
|
||||
|
|
|
@ -10,10 +10,8 @@ import net.minecraft.world.World;
|
|||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
|
||||
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.watcher.IUpdateWatcher;
|
||||
|
||||
public abstract class NewDimData
|
||||
{
|
||||
|
@ -106,19 +104,8 @@ public abstract class NewDimData
|
|||
parent = null;
|
||||
tail = new LinkTail(linkType, null);
|
||||
}
|
||||
|
||||
public IDataMessage toMessage()
|
||||
{
|
||||
return linkMessageBuilder.createMessage(this);
|
||||
}
|
||||
|
||||
public IDataMessage toKey()
|
||||
{
|
||||
return linkMessageBuilder.createKey(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static LinkMessageBuilder linkMessageBuilder = new LinkMessageBuilder();
|
||||
private static Random random = new Random();
|
||||
|
||||
private final int id;
|
||||
|
@ -134,13 +121,12 @@ public abstract class NewDimData
|
|||
private Point4D origin;
|
||||
private int orientation;
|
||||
private DungeonData dungeon;
|
||||
private final IUpdateWatcher dimWatcher;
|
||||
private final IUpdateWatcher linkWatcher;
|
||||
private final IUpdateWatcher<Point4D> linkWatcher;
|
||||
|
||||
protected NewDimData(int id, NewDimData parent, boolean isPocket, boolean isDungeon,
|
||||
IUpdateWatcher dimWatcher, IUpdateWatcher linkWatcher)
|
||||
IUpdateWatcher<Point4D> linkWatcher)
|
||||
{
|
||||
//The isPocket flag is redundant. It's meant as an integrity safeguard.
|
||||
// The isPocket flag is redundant. It's meant as an integrity safeguard.
|
||||
if (isPocket == (parent != null))
|
||||
{
|
||||
throw new NullPointerException("Dimensions can be pocket dimensions if and only if they have a parent dimension.");
|
||||
|
@ -161,7 +147,6 @@ public abstract class NewDimData
|
|||
this.orientation = 0;
|
||||
this.origin = null;
|
||||
this.dungeon = null;
|
||||
this.dimWatcher = dimWatcher;
|
||||
this.linkWatcher = linkWatcher;
|
||||
|
||||
//Register with parent
|
||||
|
@ -179,8 +164,32 @@ public abstract class NewDimData
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract IDataMessage toMessage();
|
||||
protected abstract IDataMessage toKey();
|
||||
protected NewDimData(int id, NewDimData root)
|
||||
{
|
||||
// This constructor is meant for client-side code only
|
||||
this.id = id;
|
||||
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.children = new ArrayList<NewDimData>();
|
||||
this.parent = null;
|
||||
this.packDepth = 0;
|
||||
this.isDungeon = false;
|
||||
this.isFilled = false;
|
||||
this.orientation = 0;
|
||||
this.origin = null;
|
||||
this.dungeon = null;
|
||||
this.linkWatcher = null;
|
||||
this.depth = 0;
|
||||
if (root != null)
|
||||
{
|
||||
this.root = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.root = this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DimLink findNearestRift(World world, int range, int x, int y, int z)
|
||||
{
|
||||
|
@ -251,7 +260,7 @@ public abstract class NewDimData
|
|||
link.overwrite(linkType);
|
||||
}
|
||||
//Link created!
|
||||
linkWatcher.onCreated(link.toMessage());
|
||||
linkWatcher.onCreated(link.source);
|
||||
return link;
|
||||
}
|
||||
|
||||
|
@ -278,14 +287,14 @@ public abstract class NewDimData
|
|||
linkList.add(link);
|
||||
|
||||
//Link created!
|
||||
linkWatcher.onCreated(link.toMessage());
|
||||
linkWatcher.onCreated(link.source);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link.overwrite(parent))
|
||||
{
|
||||
//Link created!
|
||||
linkWatcher.onCreated(link.toMessage());
|
||||
linkWatcher.onCreated(link.source);
|
||||
}
|
||||
}
|
||||
return link;
|
||||
|
@ -302,7 +311,7 @@ public abstract class NewDimData
|
|||
{
|
||||
linkList.remove(target);
|
||||
//Raise deletion event
|
||||
linkWatcher.onDeleted(target.toKey());
|
||||
linkWatcher.onDeleted(target.source);
|
||||
target.clear();
|
||||
}
|
||||
return (target != null);
|
||||
|
@ -316,7 +325,7 @@ public abstract class NewDimData
|
|||
{
|
||||
linkList.remove(target);
|
||||
//Raise deletion event
|
||||
linkWatcher.onDeleted(target.toKey());
|
||||
linkWatcher.onDeleted(target.source);
|
||||
target.clear();
|
||||
}
|
||||
return (target != null);
|
||||
|
@ -345,7 +354,7 @@ public abstract class NewDimData
|
|||
|
||||
public boolean isPocketDimension()
|
||||
{
|
||||
return (parent != null);
|
||||
return (root != this);
|
||||
}
|
||||
|
||||
public boolean isDungeon()
|
||||
|
@ -361,8 +370,6 @@ public abstract class NewDimData
|
|||
public void setFilled(boolean isFilled)
|
||||
{
|
||||
this.isFilled = isFilled;
|
||||
//Raise the dim update event
|
||||
dimWatcher.onUpdated(this.toMessage());
|
||||
}
|
||||
|
||||
public int id()
|
||||
|
@ -412,7 +419,7 @@ public abstract class NewDimData
|
|||
|
||||
public int linkCount()
|
||||
{
|
||||
return linkMapping.size();
|
||||
return linkList.size();
|
||||
}
|
||||
|
||||
public Iterable<NewDimData> children()
|
||||
|
@ -420,6 +427,11 @@ public abstract class NewDimData
|
|||
return children;
|
||||
}
|
||||
|
||||
public Iterable<? extends DimLink> links()
|
||||
{
|
||||
return linkList;
|
||||
}
|
||||
|
||||
public void initializeDungeon(int originX, int originY, int originZ, int orientation, DimLink incoming, DungeonData dungeon)
|
||||
{
|
||||
if (!isDungeon)
|
||||
|
@ -436,8 +448,6 @@ public abstract class NewDimData
|
|||
this.orientation = orientation;
|
||||
this.dungeon = dungeon;
|
||||
this.packDepth = calculatePackDepth(parent, dungeon);
|
||||
//Raise the dim update event
|
||||
dimWatcher.onUpdated(this.toMessage());
|
||||
}
|
||||
|
||||
private static int calculatePackDepth(NewDimData parent, DungeonData current)
|
||||
|
@ -486,16 +496,12 @@ public abstract class NewDimData
|
|||
setDestination(incoming, originX, originY, originZ);
|
||||
this.origin = incoming.destination();
|
||||
this.orientation = orientation;
|
||||
//Raise the dim update event
|
||||
dimWatcher.onUpdated(this.toMessage());
|
||||
}
|
||||
|
||||
public void setDestination(DimLink incoming, int x, int y, int z)
|
||||
{
|
||||
InnerDimLink link = (InnerDimLink) incoming;
|
||||
link.setDestination(x, y, z, this);
|
||||
//Raise update event
|
||||
linkWatcher.onUpdated(link.toMessage());
|
||||
}
|
||||
|
||||
public DimLink getRandomLink()
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
@ -13,13 +12,13 @@ import net.minecraft.tileentity.TileEntity;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.Compactor;
|
||||
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.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientDimData;
|
||||
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
|
||||
|
@ -29,41 +28,40 @@ public class PocketManager
|
|||
{
|
||||
private static class InnerDimData extends NewDimData
|
||||
{
|
||||
//This inner class allows us to instantiate NewDimData indirectly without exposing
|
||||
//a public constructor from NewDimData. It's meant to stop us from constructing instances
|
||||
//of NewDimData without using PocketManager's functions. In turn, that enforces that any
|
||||
//link destinations must be real dimensions controlled by PocketManager.
|
||||
// This class allows us to instantiate NewDimData indirectly without exposing
|
||||
// a public constructor from NewDimData. It's meant to stop us from constructing
|
||||
// instances of NewDimData going through PocketManager. In turn, that enforces
|
||||
// that any link destinations must be real dimensions controlled by PocketManager.
|
||||
|
||||
public InnerDimData(int id, NewDimData parent, boolean isPocket, boolean isDungeon,
|
||||
IUpdateWatcher dimWatcher, IUpdateWatcher linkWatcher)
|
||||
public InnerDimData(int id, InnerDimData parent, boolean isPocket, boolean isDungeon,
|
||||
IUpdateWatcher<Point4D> linkWatcher)
|
||||
{
|
||||
super(id, parent, isPocket, isDungeon, dimWatcher, linkWatcher);
|
||||
super(id, parent, isPocket, isDungeon, linkWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IDataMessage toMessage()
|
||||
public InnerDimData(int id, InnerDimData root)
|
||||
{
|
||||
return dimMessageBuilder.createMessage(this);
|
||||
// This constructor is meant for client-side code only
|
||||
super(id, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IDataMessage toKey()
|
||||
public InnerDimData(int id)
|
||||
{
|
||||
return dimMessageBuilder.createKey(this);
|
||||
// This constructor is meant for client-side code only
|
||||
super(id, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static DimMessageBuilder dimMessageBuilder = new DimMessageBuilder();
|
||||
private static int OVERWORLD_DIMENSION_ID = 0;
|
||||
|
||||
private static volatile boolean isLoading = false;
|
||||
private static volatile boolean isLoaded = false;
|
||||
private static volatile boolean isSaving = false;
|
||||
private static UpdateWatcherProxy linkWatcher = null;
|
||||
private static UpdateWatcherProxy dimWatcher = null;
|
||||
private static UpdateWatcherProxy<Point4D> linkWatcher = null;
|
||||
private static UpdateWatcherProxy<ClientDimData> dimWatcher = null;
|
||||
|
||||
//HashMap that maps all the dimension IDs registered with DimDoors to their DD data.
|
||||
private static HashMap<Integer, NewDimData> dimensionData = new HashMap<Integer, NewDimData>();
|
||||
private static HashMap<Integer, InnerDimData> dimensionData = null;
|
||||
|
||||
public static boolean isLoaded()
|
||||
{
|
||||
|
@ -87,16 +85,17 @@ public class PocketManager
|
|||
|
||||
isLoading = true;
|
||||
|
||||
//Set up watcher proxies
|
||||
dimWatcher = new UpdateWatcherProxy();
|
||||
linkWatcher = new UpdateWatcherProxy();
|
||||
|
||||
loadInternal();
|
||||
//Set up fields
|
||||
dimensionData = new HashMap<Integer, InnerDimData>();
|
||||
dimWatcher = new UpdateWatcherProxy<ClientDimData>();
|
||||
linkWatcher = new UpdateWatcherProxy<Point4D>();
|
||||
|
||||
//Register Limbo
|
||||
DDProperties properties = DDProperties.instance();
|
||||
registerDimension(properties.LimboDimensionID, null, false, false);
|
||||
|
||||
loadInternal();
|
||||
|
||||
//Register pocket dimensions
|
||||
registerPockets(properties);
|
||||
|
||||
|
@ -134,7 +133,7 @@ public class PocketManager
|
|||
DeleteFolder.deleteFolder(save);
|
||||
}
|
||||
//Raise the dim deleted event
|
||||
dimWatcher.onDeleted(dimension.toKey());
|
||||
dimWatcher.onDeleted(new ClientDimData(dimension));
|
||||
//dimension.implode()??? -- more like delete, but yeah
|
||||
return true;
|
||||
}
|
||||
|
@ -184,9 +183,7 @@ public class PocketManager
|
|||
|
||||
/**
|
||||
* loads the dim data from the saved hashMap. Also handles compatibility with old saves, see OldSaveHandler
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void loadInternal()
|
||||
{
|
||||
// SenseiKiwi: This is a temporary function for testing purposes.
|
||||
|
@ -196,10 +193,9 @@ public class PocketManager
|
|||
DimensionManager.getCurrentSaveRootDirectory() != null)
|
||||
{
|
||||
System.out.println("Loading Dimensional Doors save data...");
|
||||
File saveFile = new File(DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.dat");
|
||||
//Missing code for converting the binary data in the file into an IOpaqueMessage
|
||||
IDataMessage saveData;
|
||||
setState(saveData);
|
||||
/*File saveFile = new File(DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.dat");
|
||||
|
||||
setState(saveData);*/
|
||||
System.out.println("Loaded successfully!");
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +224,7 @@ public class PocketManager
|
|||
try
|
||||
{
|
||||
System.out.println("Writing Dimensional Doors save data...");
|
||||
String tempPath = DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.tmp";
|
||||
/*String tempPath = DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.tmp";
|
||||
String savePath = DimensionManager.getCurrentSaveRootDirectory() + "/dimdoors.dat";
|
||||
File tempFile = new File(tempPath);
|
||||
File saveFile = new File(savePath);
|
||||
|
@ -236,17 +232,17 @@ public class PocketManager
|
|||
getState().writeToStream(writer);
|
||||
writer.close();
|
||||
saveFile.delete();
|
||||
tempFile.renameTo(saveFile);
|
||||
tempFile.renameTo(saveFile);*/
|
||||
System.out.println("Saved successfully!");
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
/*catch (FileNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
finally
|
||||
{
|
||||
isSaving = false;
|
||||
|
@ -291,17 +287,17 @@ public class PocketManager
|
|||
DDProperties properties = DDProperties.instance();
|
||||
int dimensionID = DimensionManager.getNextFreeDimId();
|
||||
DimensionManager.registerDimension(dimensionID, properties.PocketProviderID);
|
||||
return registerDimension(dimensionID, parent, true, isDungeon);
|
||||
return registerDimension(dimensionID, (InnerDimData) parent, true, isDungeon);
|
||||
}
|
||||
|
||||
private static NewDimData registerDimension(int dimensionID, NewDimData parent, boolean isPocket, boolean isDungeon)
|
||||
private static NewDimData registerDimension(int dimensionID, InnerDimData parent, boolean isPocket, boolean isDungeon)
|
||||
{
|
||||
if (dimensionData.containsKey(dimensionID))
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot register a dimension with ID = " + dimensionID + " because it has already been registered.");
|
||||
}
|
||||
|
||||
NewDimData dimension = new InnerDimData(dimensionID, parent, isPocket, isDungeon, dimWatcher, linkWatcher);
|
||||
InnerDimData dimension = new InnerDimData(dimensionID, parent, isPocket, isDungeon, linkWatcher);
|
||||
dimensionData.put(dimensionID, dimension);
|
||||
return dimension;
|
||||
}
|
||||
|
@ -330,14 +326,18 @@ public class PocketManager
|
|||
public static void unload()
|
||||
{
|
||||
save();
|
||||
dimWatcher = null;
|
||||
linkWatcher = null;
|
||||
dimensionData = null;
|
||||
unregisterPockets();
|
||||
dimensionData.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* This isn't needed right now and it's causing me problems due to the iterator's generic type -_-
|
||||
public static Iterable<NewDimData> getDimensions()
|
||||
{
|
||||
return dimensionData.values();
|
||||
}
|
||||
}*/
|
||||
|
||||
public static DimLink getLink(int x, int y, int z, World world)
|
||||
{
|
||||
|
@ -357,37 +357,96 @@ public class PocketManager
|
|||
}
|
||||
}
|
||||
|
||||
public static void registerDimWatcher(IUpdateWatcher watcher)
|
||||
public static void registerDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
||||
{
|
||||
dimWatcher.registerReceiver(watcher);
|
||||
}
|
||||
|
||||
public static boolean unregisterDimWatcher(IUpdateWatcher watcher)
|
||||
public static boolean unregisterDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
||||
{
|
||||
return dimWatcher.unregisterReceiver(watcher);
|
||||
}
|
||||
|
||||
public static void registerLinkWatcher(IUpdateWatcher watcher)
|
||||
public static void registerLinkWatcher(IUpdateWatcher<Point4D> watcher)
|
||||
{
|
||||
linkWatcher.registerReceiver(watcher);
|
||||
}
|
||||
|
||||
public static boolean unregisterLinkWatcher(IUpdateWatcher watcher)
|
||||
public static boolean unregisterLinkWatcher(IUpdateWatcher<Point4D> watcher)
|
||||
{
|
||||
return linkWatcher.unregisterReceiver(watcher);
|
||||
}
|
||||
|
||||
public static IDataMessage getState()
|
||||
public static void writePacket(DataOutputStream output) throws IOException
|
||||
{
|
||||
|
||||
// Write a very compact description of our dimensions and links to be sent to a client
|
||||
Compactor.write(dimensionData.values(), output);
|
||||
}
|
||||
|
||||
public static void setState(IDataMessage state)
|
||||
public static void readPacket(DataInputStream input) throws IOException
|
||||
{
|
||||
if (isLoaded)
|
||||
{
|
||||
throw new IllegalStateException("Pocket dimensions have already been loaded!");
|
||||
}
|
||||
if (isLoading)
|
||||
{
|
||||
throw new IllegalStateException("Pocket dimensions are already loading!");
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
// Set up fields
|
||||
dimensionData = new HashMap<Integer, InnerDimData>();
|
||||
dimWatcher = new UpdateWatcherProxy<ClientDimData>();
|
||||
linkWatcher = new UpdateWatcherProxy<Point4D>();
|
||||
|
||||
// Load compacted client-side dimension data
|
||||
Compactor.readDimensions(input, new DimRegistrationCallback());
|
||||
|
||||
// Register pocket dimensions
|
||||
DDProperties properties = DDProperties.instance();
|
||||
registerPockets(properties);
|
||||
|
||||
isLoaded = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
83
StevenDimDoors/mod_pocketDim/helpers/Compactor.java
Normal file
83
StevenDimDoors/mod_pocketDim/helpers/Compactor.java
Normal file
|
@ -0,0 +1,83 @@
|
|||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.IDimRegistrationCallback;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class Compactor
|
||||
{
|
||||
|
||||
private static class DimComparator implements Comparator<NewDimData>
|
||||
{
|
||||
@Override
|
||||
public int compare(NewDimData a, NewDimData b)
|
||||
{
|
||||
return a.id() - b.id();
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Collection<? extends NewDimData> values, DataOutputStream output) throws IOException
|
||||
{
|
||||
// SenseiKiwi: Just encode the data straight up for now. I'll implement fancier compression later.
|
||||
output.writeInt(values.size());
|
||||
for (NewDimData dimension : values)
|
||||
{
|
||||
output.writeInt(dimension.id());
|
||||
output.writeInt(dimension.root().id());
|
||||
output.writeInt(dimension.linkCount());
|
||||
for (DimLink link : dimension.links())
|
||||
{
|
||||
Point4D.write(link.source(), output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note to self: the root ID can be "compressed" by grouping
|
||||
// dimensions by their root ID and then only sending it once
|
||||
|
||||
/*
|
||||
// To compress the dimension IDs, we'll sort them by ID
|
||||
// and write the _difference_ between their ID numbers.
|
||||
NewDimData[] dimensions = new NewDimData[values.size()];
|
||||
dimensions = values.toArray(dimensions);
|
||||
Arrays.sort(dimensions, new DimComparator());
|
||||
*/
|
||||
}
|
||||
|
||||
public static void readDimensions(DataInputStream input, IDimRegistrationCallback callback) throws IOException
|
||||
{
|
||||
// Read in the dimensions one by one. Make sure we register root dimensions before
|
||||
// attempting to register the dimensions under them.
|
||||
|
||||
HashSet<Integer> rootIDs = new HashSet<Integer>();
|
||||
|
||||
int dimCount = input.readInt();
|
||||
for (int k = 0; k < dimCount; k++)
|
||||
{
|
||||
int id = input.readInt();
|
||||
int rootID = input.readInt();
|
||||
|
||||
if (rootIDs.add(rootID))
|
||||
{
|
||||
callback.registerDimension(rootID, rootID);
|
||||
}
|
||||
// Don't check if (id != rootID) - we want to retrieve the reference anyway
|
||||
NewDimData dimension = callback.registerDimension(id, rootID);
|
||||
int linkCount = input.readInt();
|
||||
for (int h = 0; h < linkCount; h++)
|
||||
{
|
||||
Point4D source = Point4D.read(input);
|
||||
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package StevenDimDoors.mod_pocketDim.messages;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface IDataMessage
|
||||
{
|
||||
public void writeToStream(DataOutputStream stream) throws IOException;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package StevenDimDoors.mod_pocketDim.messages;
|
||||
|
||||
public interface IUpdateWatcher
|
||||
{
|
||||
public void onCreated(IDataMessage message);
|
||||
public void onUpdated(IDataMessage message);
|
||||
public void onDeleted(IDataMessage message);
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package StevenDimDoors.mod_pocketDim.messages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UpdateWatcherProxy implements IUpdateWatcher
|
||||
{
|
||||
private List<IUpdateWatcher> watchers;
|
||||
|
||||
public UpdateWatcherProxy()
|
||||
{
|
||||
watchers = new ArrayList<IUpdateWatcher>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreated(IDataMessage message)
|
||||
{
|
||||
for (IUpdateWatcher receiver : watchers)
|
||||
{
|
||||
receiver.onCreated(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdated(IDataMessage message)
|
||||
{
|
||||
for (IUpdateWatcher receiver : watchers)
|
||||
{
|
||||
receiver.onUpdated(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(IDataMessage message)
|
||||
{
|
||||
for (IUpdateWatcher receiver : watchers)
|
||||
{
|
||||
receiver.onDeleted(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerReceiver(IUpdateWatcher receiver)
|
||||
{
|
||||
watchers.add(receiver);
|
||||
}
|
||||
|
||||
public boolean unregisterReceiver(IUpdateWatcher receiver)
|
||||
{
|
||||
return watchers.remove(receiver);
|
||||
}
|
||||
}
|
37
StevenDimDoors/mod_pocketDim/watcher/ClientDimData.java
Normal file
37
StevenDimDoors/mod_pocketDim/watcher/ClientDimData.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package StevenDimDoors.mod_pocketDim.watcher;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
|
||||
public class ClientDimData
|
||||
{
|
||||
//We'll use public fields since this is just a data container and it's immutable
|
||||
public final int ID;
|
||||
public final int RootID;
|
||||
|
||||
public ClientDimData(int id, int rootID)
|
||||
{
|
||||
ID = id;
|
||||
RootID = rootID;
|
||||
}
|
||||
|
||||
public ClientDimData(NewDimData dimension)
|
||||
{
|
||||
ID = dimension.id();
|
||||
RootID = dimension.root().id();
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException
|
||||
{
|
||||
output.writeInt(ID);
|
||||
output.writeInt(RootID);
|
||||
}
|
||||
|
||||
public static ClientDimData read(DataInputStream input) throws IOException
|
||||
{
|
||||
return new ClientDimData(input.readInt(), input.readInt());
|
||||
}
|
||||
}
|
7
StevenDimDoors/mod_pocketDim/watcher/IUpdateWatcher.java
Normal file
7
StevenDimDoors/mod_pocketDim/watcher/IUpdateWatcher.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package StevenDimDoors.mod_pocketDim.watcher;
|
||||
|
||||
public interface IUpdateWatcher<T>
|
||||
{
|
||||
public void onCreated(T message);
|
||||
public void onDeleted(T message);
|
||||
}
|
42
StevenDimDoors/mod_pocketDim/watcher/UpdateWatcherProxy.java
Normal file
42
StevenDimDoors/mod_pocketDim/watcher/UpdateWatcherProxy.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
package StevenDimDoors.mod_pocketDim.watcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UpdateWatcherProxy<T> implements IUpdateWatcher<T>
|
||||
{
|
||||
private List<IUpdateWatcher<T>> watchers;
|
||||
|
||||
public UpdateWatcherProxy()
|
||||
{
|
||||
watchers = new ArrayList<IUpdateWatcher<T>>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreated(T message)
|
||||
{
|
||||
for (IUpdateWatcher<T> receiver : watchers)
|
||||
{
|
||||
receiver.onCreated(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(T message)
|
||||
{
|
||||
for (IUpdateWatcher<T> receiver : watchers)
|
||||
{
|
||||
receiver.onDeleted(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerReceiver(IUpdateWatcher<T> receiver)
|
||||
{
|
||||
watchers.add(receiver);
|
||||
}
|
||||
|
||||
public boolean unregisterReceiver(IUpdateWatcher<T> receiver)
|
||||
{
|
||||
return watchers.remove(receiver);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue