diff --git a/StevenDimDoors/mod_pocketDim/ConnectionHandler.java b/StevenDimDoors/mod_pocketDim/ConnectionHandler.java index 2abf8d3..07a0b77 100644 --- a/StevenDimDoors/mod_pocketDim/ConnectionHandler.java +++ b/StevenDimDoors/mod_pocketDim/ConnectionHandler.java @@ -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(); diff --git a/StevenDimDoors/mod_pocketDim/ServerPacketHandler.java b/StevenDimDoors/mod_pocketDim/ServerPacketHandler.java index d33c613..e8eb51a 100644 --- a/StevenDimDoors/mod_pocketDim/ServerPacketHandler.java +++ b/StevenDimDoors/mod_pocketDim/ServerPacketHandler.java @@ -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 { @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 { @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(); diff --git a/StevenDimDoors/mod_pocketDim/core/DimLink.java b/StevenDimDoors/mod_pocketDim/core/DimLink.java index a8c296b..af8c7aa 100644 --- a/StevenDimDoors/mod_pocketDim/core/DimLink.java +++ b/StevenDimDoors/mod_pocketDim/core/DimLink.java @@ -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 children; + protected List children; protected DimLink(Point4D source, DimLink parent) { this.parent = parent; this.source = source; this.tail = parent.tail; - this.children = new ArrayList(EXPECTED_CHILDREN); + this.children = new LinkedList(); 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(EXPECTED_CHILDREN); + this.children = new LinkedList(); } public Point4D source() diff --git a/StevenDimDoors/mod_pocketDim/core/IDimRegistrationCallback.java b/StevenDimDoors/mod_pocketDim/core/IDimRegistrationCallback.java new file mode 100644 index 0000000..04a0c38 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/core/IDimRegistrationCallback.java @@ -0,0 +1,6 @@ +package StevenDimDoors.mod_pocketDim.core; + +public interface IDimRegistrationCallback +{ + public NewDimData registerDimension(int dimensionID, int rootID); +} diff --git a/StevenDimDoors/mod_pocketDim/core/LinkTypes.java b/StevenDimDoors/mod_pocketDim/core/LinkTypes.java index b493e6c..f5fe139 100644 --- a/StevenDimDoors/mod_pocketDim/core/LinkTypes.java +++ b/StevenDimDoors/mod_pocketDim/core/LinkTypes.java @@ -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; diff --git a/StevenDimDoors/mod_pocketDim/core/NewDimData.java b/StevenDimDoors/mod_pocketDim/core/NewDimData.java index 7ff3160..de313b9 100644 --- a/StevenDimDoors/mod_pocketDim/core/NewDimData.java +++ b/StevenDimDoors/mod_pocketDim/core/NewDimData.java @@ -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 linkWatcher; protected NewDimData(int id, NewDimData parent, boolean isPocket, boolean isDungeon, - IUpdateWatcher dimWatcher, IUpdateWatcher linkWatcher) + IUpdateWatcher 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(); //Should be stored in oct tree -- temporary solution + this.linkList = new ArrayList(); //Should be stored in oct tree -- temporary solution + this.children = new ArrayList(); + 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 children() @@ -420,6 +427,11 @@ public abstract class NewDimData return children; } + public Iterable 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() diff --git a/StevenDimDoors/mod_pocketDim/core/PocketManager.java b/StevenDimDoors/mod_pocketDim/core/PocketManager.java index 91f90ca..fc1f854 100644 --- a/StevenDimDoors/mod_pocketDim/core/PocketManager.java +++ b/StevenDimDoors/mod_pocketDim/core/PocketManager.java @@ -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 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 linkWatcher = null; + private static UpdateWatcherProxy dimWatcher = null; //HashMap that maps all the dimension IDs registered with DimDoors to their DD data. - private static HashMap dimensionData = new HashMap(); + private static HashMap 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(); + dimWatcher = new UpdateWatcherProxy(); + linkWatcher = new UpdateWatcherProxy(); //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 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 watcher) { dimWatcher.registerReceiver(watcher); } - public static boolean unregisterDimWatcher(IUpdateWatcher watcher) + public static boolean unregisterDimWatcher(IUpdateWatcher watcher) { return dimWatcher.unregisterReceiver(watcher); } - public static void registerLinkWatcher(IUpdateWatcher watcher) + public static void registerLinkWatcher(IUpdateWatcher watcher) { linkWatcher.registerReceiver(watcher); } - public static boolean unregisterLinkWatcher(IUpdateWatcher watcher) + public static boolean unregisterLinkWatcher(IUpdateWatcher 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(); + dimWatcher = new UpdateWatcherProxy(); + linkWatcher = new UpdateWatcherProxy(); + + // 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; + } } } diff --git a/StevenDimDoors/mod_pocketDim/helpers/Compactor.java b/StevenDimDoors/mod_pocketDim/helpers/Compactor.java new file mode 100644 index 0000000..6d5f5d5 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/helpers/Compactor.java @@ -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 + { + @Override + public int compare(NewDimData a, NewDimData b) + { + return a.id() - b.id(); + } + } + + public static void write(Collection 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 rootIDs = new HashSet(); + + 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); + } + } + } +} diff --git a/StevenDimDoors/mod_pocketDim/messages/DimMessageBuilder.java b/StevenDimDoors/mod_pocketDim/messages/DimMessageBuilder.java deleted file mode 100644 index cb46451..0000000 --- a/StevenDimDoors/mod_pocketDim/messages/DimMessageBuilder.java +++ /dev/null @@ -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 -{ - 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); - } - } -} diff --git a/StevenDimDoors/mod_pocketDim/messages/IDataMessage.java b/StevenDimDoors/mod_pocketDim/messages/IDataMessage.java deleted file mode 100644 index 8ee841d..0000000 --- a/StevenDimDoors/mod_pocketDim/messages/IDataMessage.java +++ /dev/null @@ -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; -} diff --git a/StevenDimDoors/mod_pocketDim/messages/IMessageBuilder.java b/StevenDimDoors/mod_pocketDim/messages/IMessageBuilder.java deleted file mode 100644 index 297f8e5..0000000 --- a/StevenDimDoors/mod_pocketDim/messages/IMessageBuilder.java +++ /dev/null @@ -1,11 +0,0 @@ -package StevenDimDoors.mod_pocketDim.messages; - -import java.io.DataInputStream; -import java.io.IOException; - -public interface IMessageBuilder -{ - public IDataMessage createKey(T target); - public IDataMessage createMessage(T target); - public IDataMessage read(DataInputStream source) throws IOException; -} diff --git a/StevenDimDoors/mod_pocketDim/messages/IUpdateWatcher.java b/StevenDimDoors/mod_pocketDim/messages/IUpdateWatcher.java deleted file mode 100644 index 3bc24fd..0000000 --- a/StevenDimDoors/mod_pocketDim/messages/IUpdateWatcher.java +++ /dev/null @@ -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); -} diff --git a/StevenDimDoors/mod_pocketDim/messages/LinkMessageBuilder.java b/StevenDimDoors/mod_pocketDim/messages/LinkMessageBuilder.java deleted file mode 100644 index d9d21bc..0000000 --- a/StevenDimDoors/mod_pocketDim/messages/LinkMessageBuilder.java +++ /dev/null @@ -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 -{ - 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 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 builder = new ImmutableList.Builder(); - 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 builder = new ImmutableList.Builder(); - 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); - } - } -} diff --git a/StevenDimDoors/mod_pocketDim/messages/UpdateWatcherProxy.java b/StevenDimDoors/mod_pocketDim/messages/UpdateWatcherProxy.java deleted file mode 100644 index 1326151..0000000 --- a/StevenDimDoors/mod_pocketDim/messages/UpdateWatcherProxy.java +++ /dev/null @@ -1,51 +0,0 @@ -package StevenDimDoors.mod_pocketDim.messages; - -import java.util.ArrayList; -import java.util.List; - -public class UpdateWatcherProxy implements IUpdateWatcher -{ - private List watchers; - - public UpdateWatcherProxy() - { - watchers = new ArrayList(); - } - - @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); - } -} diff --git a/StevenDimDoors/mod_pocketDim/watcher/ClientDimData.java b/StevenDimDoors/mod_pocketDim/watcher/ClientDimData.java new file mode 100644 index 0000000..7614a10 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/watcher/ClientDimData.java @@ -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()); + } +} diff --git a/StevenDimDoors/mod_pocketDim/watcher/IUpdateWatcher.java b/StevenDimDoors/mod_pocketDim/watcher/IUpdateWatcher.java new file mode 100644 index 0000000..eb8f920 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/watcher/IUpdateWatcher.java @@ -0,0 +1,7 @@ +package StevenDimDoors.mod_pocketDim.watcher; + +public interface IUpdateWatcher +{ + public void onCreated(T message); + public void onDeleted(T message); +} diff --git a/StevenDimDoors/mod_pocketDim/watcher/UpdateWatcherProxy.java b/StevenDimDoors/mod_pocketDim/watcher/UpdateWatcherProxy.java new file mode 100644 index 0000000..e105476 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/watcher/UpdateWatcherProxy.java @@ -0,0 +1,42 @@ +package StevenDimDoors.mod_pocketDim.watcher; + +import java.util.ArrayList; +import java.util.List; + +public class UpdateWatcherProxy implements IUpdateWatcher +{ + private List> watchers; + + public UpdateWatcherProxy() + { + watchers = new ArrayList>(); + } + + @Override + public void onCreated(T message) + { + for (IUpdateWatcher receiver : watchers) + { + receiver.onCreated(message); + } + } + + @Override + public void onDeleted(T 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); + } +}