diff --git a/StevenDimDoors/mod_pocketDim/PacketConstants.java b/StevenDimDoors/mod_pocketDim/PacketConstants.java index 67d4e60..847a5b0 100644 --- a/StevenDimDoors/mod_pocketDim/PacketConstants.java +++ b/StevenDimDoors/mod_pocketDim/PacketConstants.java @@ -3,13 +3,12 @@ package StevenDimDoors.mod_pocketDim; public class PacketConstants { private PacketConstants() { } + + public static final String CHANNEL_NAME = "DimDoorsPackets"; public static final byte CLIENT_JOIN_PACKET_ID = 1; 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 = 4; - public static final byte CREATE_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"; + public static final byte DELETE_DIM_PACKET_ID = 3; + public static final byte CREATE_LINK_PACKET_ID = 4; + public static final byte DELETE_LINK_PACKET_ID = 5; } diff --git a/StevenDimDoors/mod_pocketDim/core/DimLink.java b/StevenDimDoors/mod_pocketDim/core/DimLink.java index af8c7aa..cdf25a6 100644 --- a/StevenDimDoors/mod_pocketDim/core/DimLink.java +++ b/StevenDimDoors/mod_pocketDim/core/DimLink.java @@ -23,7 +23,7 @@ public abstract class DimLink 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."); } diff --git a/StevenDimDoors/mod_pocketDim/core/LinkTypes.java b/StevenDimDoors/mod_pocketDim/core/LinkTypes.java index f5fe139..5e64aff 100644 --- a/StevenDimDoors/mod_pocketDim/core/LinkTypes.java +++ b/StevenDimDoors/mod_pocketDim/core/LinkTypes.java @@ -7,7 +7,7 @@ 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 CLIENT_SIDE = -1337; public static final int NORMAL = 0; public static final int LIMBO = 1; diff --git a/StevenDimDoors/mod_pocketDim/core/NewDimData.java b/StevenDimDoors/mod_pocketDim/core/NewDimData.java index de313b9..0be6468 100644 --- a/StevenDimDoors/mod_pocketDim/core/NewDimData.java +++ b/StevenDimDoors/mod_pocketDim/core/NewDimData.java @@ -167,6 +167,11 @@ public abstract class NewDimData protected NewDimData(int id, NewDimData root) { // This constructor is meant for client-side code only + if (root == null) + { + throw new IllegalArgumentException("root cannot be null."); + } + 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 @@ -180,15 +185,7 @@ public abstract class NewDimData this.dungeon = null; this.linkWatcher = null; this.depth = 0; - if (root != null) - { - this.root = root; - } - else - { - this.root = this; - } - + this.root = root; } public DimLink findNearestRift(World world, int range, int x, int y, int z) diff --git a/StevenDimDoors/mod_pocketDim/core/PocketManager.java b/StevenDimDoors/mod_pocketDim/core/PocketManager.java index fc1f854..d590930 100644 --- a/StevenDimDoors/mod_pocketDim/core/PocketManager.java +++ b/StevenDimDoors/mod_pocketDim/core/PocketManager.java @@ -17,6 +17,7 @@ import StevenDimDoors.mod_pocketDim.helpers.DeleteFolder; import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift; 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 StevenDimDoors.mod_pocketDim.watcher.UpdateWatcherProxy; @@ -44,14 +45,54 @@ public class PocketManager // This constructor is meant for client-side code only super(id, root); } - - public InnerDimData(int id) + } + + private static class ClientLinkWatcher implements IUpdateWatcher + { + @Override + public void onCreated(Point4D source) { - // This constructor is meant for client-side code only - super(id, null); + NewDimData dimension = getDimensionData(source.getDimension()); + 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 + { + @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 volatile boolean isLoading = false; @@ -301,6 +342,30 @@ public class PocketManager dimensionData.put(dimensionID, 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) { @@ -323,6 +388,11 @@ public class PocketManager return dimension; } + public static Iterable getDimensions() + { + return dimensionData.values(); + } + public static void unload() { save(); @@ -376,6 +446,11 @@ public class PocketManager { return linkWatcher.unregisterReceiver(watcher); } + + public static void getWatchers(IUpdateSource updateSource) + { + updateSource.registerWatchers(new ClientDimWatcher(), new ClientLinkWatcher()); + } public static void writePacket(DataOutputStream output) throws IOException { @@ -398,8 +473,8 @@ public class PocketManager // Set up fields dimensionData = new HashMap(); - dimWatcher = new UpdateWatcherProxy(); - linkWatcher = new UpdateWatcherProxy(); + dimWatcher = null; // Clients shouldn't need to watch dims + linkWatcher = null; // Clients shouldn't need to watch links // Load compacted client-side dimension data Compactor.readDimensions(input, new DimRegistrationCallback()); @@ -411,42 +486,4 @@ public class PocketManager 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 index 6d5f5d5..e13d902 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/Compactor.java +++ b/StevenDimDoors/mod_pocketDim/helpers/Compactor.java @@ -76,7 +76,7 @@ public class Compactor for (int h = 0; h < linkCount; h++) { 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); } } } diff --git a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java index cde2099..c7cd467 100644 --- a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java +++ b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java @@ -164,7 +164,7 @@ public class mod_pocketDim //MonolithSpawner should be initialized before any provider instances are created //Register the other regular tick receivers as well 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); transientDoor = (new TransientDoor(properties.TransientDoorID, Material.iron)).setHardness(1.0F) .setUnlocalizedName("transientDoor"); diff --git a/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java b/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java index 4c82dc1..114fa35 100644 --- a/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java +++ b/StevenDimDoors/mod_pocketDim/ticking/RiftRegenerator.java @@ -7,22 +7,16 @@ import StevenDimDoors.mod_pocketDim.mod_pocketDim; import StevenDimDoors.mod_pocketDim.core.DimLink; import StevenDimDoors.mod_pocketDim.core.NewDimData; import StevenDimDoors.mod_pocketDim.core.PocketManager; -import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift; import StevenDimDoors.mod_pocketDim.util.Point4D; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.Side; public class RiftRegenerator implements IRegularTickReceiver { private static final int RIFT_REGENERATION_INTERVAL = 200; //Regenerate random rifts every 200 ticks private static final int RIFTS_REGENERATED_PER_DIMENSION = 5; - private DDProperties properties; - - public RiftRegenerator(IRegularTickSender sender, DDProperties properties) + public RiftRegenerator(IRegularTickSender sender) { sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false); - this.properties = properties; } @Override diff --git a/StevenDimDoors/mod_pocketDim/watcher/IUpdateSource.java b/StevenDimDoors/mod_pocketDim/watcher/IUpdateSource.java new file mode 100644 index 0000000..98e260e --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/watcher/IUpdateSource.java @@ -0,0 +1,8 @@ +package StevenDimDoors.mod_pocketDim.watcher; + +import StevenDimDoors.mod_pocketDim.util.Point4D; + +public interface IUpdateSource +{ + public void registerWatchers(IUpdateWatcher dimWatcher, IUpdateWatcher linkWatcher); +} diff --git a/StevenDimDoors/mod_pocketDimClient/ClientPacketHandler.java b/StevenDimDoors/mod_pocketDimClient/ClientPacketHandler.java index 9100b78..a98f115 100644 --- a/StevenDimDoors/mod_pocketDimClient/ClientPacketHandler.java +++ b/StevenDimDoors/mod_pocketDimClient/ClientPacketHandler.java @@ -1,15 +1,70 @@ package StevenDimDoors.mod_pocketDimClient; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; + import net.minecraft.network.INetworkManager; 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.Player; -public class ClientPacketHandler implements IPacketHandler +public class ClientPacketHandler implements IPacketHandler, IUpdateSource { + private IUpdateWatcher linkWatcher; + private IUpdateWatcher dimWatcher; + + public ClientPacketHandler() + { + PocketManager.getWatchers(this); + } + + @Override + public void registerWatchers(IUpdateWatcher dimWatcher, IUpdateWatcher linkWatcher) + { + this.dimWatcher = dimWatcher; + this.linkWatcher = linkWatcher; + } + @Override 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(); + } } }