From 27cec3bcad30ce7887931e9f3e0e05c58b22e357 Mon Sep 17 00:00:00 2001 From: Runemoro <runemoro@users.noreply.github.com> Date: Wed, 17 Jan 2018 00:44:44 -0500 Subject: [PATCH] Destination system and registry rewrite - Major simplifincations to the TileEntityRift class and destination classes - Use a graph in the RiftRegistry for simpler tracking of rift sources and targets --- build.gradle | 1 + .../java/org/dimdev/ddutils/EntityUtils.java | 8 +- .../org/dimdev/ddutils/RotatedLocation.java | 2 +- .../java/org/dimdev/ddutils/TypeFilter.java | 17 + .../java/org/dimdev/ddutils/nbt/NBTUtils.java | 3 +- .../dimdev/dimdoors/ddutils/GraphUtils.java | 20 + .../dimdev/dimdoors/shared/CommonProxy.java | 3 +- .../dimdev/dimdoors/shared/EventHandler.java | 6 +- .../dimdoors/shared/VirtualLocation.java | 4 +- .../shared/blocks/BlockDimensionalDoor.java | 5 +- .../blocks/BlockDimensionalDoorGold.java | 16 +- .../blocks/BlockDimensionalDoorIron.java | 6 +- .../blocks/BlockDimensionalDoorPersonal.java | 5 +- .../blocks/BlockDimensionalTrapdoorWood.java | 2 +- .../dimdoors/shared/blocks/IRiftProvider.java | 3 - .../shared/commands/CommandDimTeleport.java | 4 +- .../shared/commands/CommandPocket.java | 4 +- .../shared/items/ItemDimensionalDoorGold.java | 1 - .../shared/items/ItemRiftSignature.java | 4 +- .../items/ItemStabilizedRiftSignature.java | 2 +- .../dimdoors/shared/pockets/Pocket.java | 130 +++--- .../shared/pockets/PocketGenerator.java | 4 +- .../shared/pockets/PocketRegistry.java | 14 +- .../shared/pockets/PocketTemplate.java | 10 +- .../{ => pockets}/SchematicHandler.java | 4 +- .../shared/rifts/RiftDestination.java | 44 +- .../dimdoors/shared/rifts/RiftRegistry.java | 292 ------------ .../dimdoors/shared/rifts/TileEntityRift.java | 306 ++++--------- .../shared/rifts/WeightedRiftDestination.java | 58 --- .../AvailableLinkDestination.java | 114 ++--- .../rifts/destinations/EscapeDestination.java | 11 +- .../rifts/destinations/GlobalDestination.java | 9 +- .../rifts/destinations/LimboDestination.java | 4 +- .../destinations/LinkingDestination.java | 60 +++ .../rifts/destinations/LocalDestination.java | 9 +- .../destinations/NewPublicDestination.java | 45 -- .../PocketEntranceDestination.java | 17 +- .../destinations/PocketExitDestination.java | 6 +- .../destinations/PrivateDestination.java | 47 +- .../PrivatePocketExitDestination.java | 58 +-- .../destinations/PublicPocketDestination.java | 33 ++ .../destinations/RelativeDestination.java | 9 +- .../LinkProperties.java} | 5 +- .../rifts/registry/PlayerRiftPointer.java | 13 + .../rifts/registry/PocketEntrancePointer.java | 12 + .../shared/rifts/registry/RegistryVertex.java | 26 ++ .../dimdoors/shared/rifts/registry/Rift.java | 57 +++ .../rifts/registry/RiftPlaceholder.java | 3 + .../shared/rifts/registry/RiftRegistry.java | 416 ++++++++++++++++++ .../tools/PocketSchematicGenerator.java | 17 +- .../world/limbodimension/BiomeLimbo.java | 1 - .../world/pocketdimension/BiomeBlank.java | 1 - 52 files changed, 1033 insertions(+), 918 deletions(-) create mode 100644 src/main/java/org/dimdev/ddutils/TypeFilter.java create mode 100644 src/main/java/org/dimdev/dimdoors/ddutils/GraphUtils.java rename src/main/java/org/dimdev/dimdoors/shared/{ => pockets}/SchematicHandler.java (99%) delete mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/RiftRegistry.java delete mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/WeightedRiftDestination.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LinkingDestination.java delete mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/NewPublicDestination.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PublicPocketDestination.java rename src/main/java/org/dimdev/dimdoors/shared/rifts/{AvailableLink.java => registry/LinkProperties.java} (86%) create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PlayerRiftPointer.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PocketEntrancePointer.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RegistryVertex.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/registry/Rift.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftPlaceholder.java create mode 100644 src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftRegistry.java diff --git a/build.gradle b/build.gradle index ab0042d7..cfa59951 100644 --- a/build.gradle +++ b/build.gradle @@ -64,6 +64,7 @@ configurations { dependencies { embed 'com.flowpowered:flow-math:1.0.3' + embed 'org.jgrapht:jgrapht-core:1.1.0' compile 'com.github.DimensionalDevelopment:AnnotatedNBT:-SNAPSHOT' } diff --git a/src/main/java/org/dimdev/ddutils/EntityUtils.java b/src/main/java/org/dimdev/ddutils/EntityUtils.java index c746578e..67192595 100644 --- a/src/main/java/org/dimdev/ddutils/EntityUtils.java +++ b/src/main/java/org/dimdev/ddutils/EntityUtils.java @@ -7,9 +7,11 @@ import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.*; +import java.util.UUID; + public final class EntityUtils { - public static String getEntityOwnerUUID(Entity entity) { // TODO: make this recursive + public static UUID getEntityOwnerUUID(Entity entity) { // TODO: make this recursive if (entity instanceof EntityThrowable) entity = ((EntityThrowable) entity).getThrower(); if (entity instanceof EntityArrow) entity = ((EntityArrow) entity).shootingEntity; if (entity instanceof EntityFireball) entity = ((EntityFireball) entity).shootingEntity; @@ -25,8 +27,8 @@ public final class EntityUtils { if (player != null) entity = player; } - if (entity instanceof IEntityOwnable && ((IEntityOwnable) entity).getOwnerId() != null) return ((IEntityOwnable) entity).getOwnerId().toString(); - if (entity instanceof EntityPlayer) return entity.getUniqueID().toString(); // ownable players shouldn't be a problem, but just in case we have a slave mod, check their owner's uuid first to send them to their owner's pocket :) + if (entity instanceof IEntityOwnable && ((IEntityOwnable) entity).getOwnerId() != null) return ((IEntityOwnable) entity).getOwnerId(); + if (entity instanceof EntityPlayer) return entity.getUniqueID(); // ownable players shouldn't be a problem, but just in case we have a slave mod, check their owner's uuid first to send them to their owner's pocket :) return null; } } diff --git a/src/main/java/org/dimdev/ddutils/RotatedLocation.java b/src/main/java/org/dimdev/ddutils/RotatedLocation.java index c2404b63..1b9b85e9 100644 --- a/src/main/java/org/dimdev/ddutils/RotatedLocation.java +++ b/src/main/java/org/dimdev/ddutils/RotatedLocation.java @@ -8,7 +8,7 @@ import org.dimdev.annotatednbt.Saved; import org.dimdev.annotatednbt.NBTSerializable; @ToString @AllArgsConstructor @NoArgsConstructor -@NBTSerializable public class RotatedLocation implements INBTStorable { +@NBTSerializable public class RotatedLocation implements INBTStorable { // TODO: extend Location @Getter @Saved /*private*/ Location location; @Getter @Saved /*private*/ float yaw; @Getter @Saved /*private*/ float pitch; diff --git a/src/main/java/org/dimdev/ddutils/TypeFilter.java b/src/main/java/org/dimdev/ddutils/TypeFilter.java new file mode 100644 index 00000000..7d9bc987 --- /dev/null +++ b/src/main/java/org/dimdev/ddutils/TypeFilter.java @@ -0,0 +1,17 @@ +package org.dimdev.ddutils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class TypeFilter { + public static <T extends U, U> List<T> filter(Collection<U> list, Class<T> filterClass) { + List<T> filtered = new ArrayList<>(); + for (U e : list) { + if (filterClass.isAssignableFrom(e.getClass())) { + filtered.add(filterClass.cast(e)); + } + } + return filtered; + } +} diff --git a/src/main/java/org/dimdev/ddutils/nbt/NBTUtils.java b/src/main/java/org/dimdev/ddutils/nbt/NBTUtils.java index 0403cd79..bda8c7cf 100644 --- a/src/main/java/org/dimdev/ddutils/nbt/NBTUtils.java +++ b/src/main/java/org/dimdev/ddutils/nbt/NBTUtils.java @@ -19,7 +19,7 @@ public final class NBTUtils { } } - public static void readFromNBT(Object obj, NBTTagCompound nbt) { + public static <T> T readFromNBT(T obj, NBTTagCompound nbt) { try { Class<?> callingClass = Class.forName(new Exception().getStackTrace()[1].getClassName()); Class<?> nbtWriter = Class.forName(callingClass.getPackage().getName() + "." + callingClass.getSimpleName() + "NBTWriter"); @@ -28,5 +28,6 @@ public final class NBTUtils { } catch (ClassNotFoundException|NoSuchMethodException|IllegalAccessException|InvocationTargetException e) { throw new RuntimeException(e); } + return obj; } } diff --git a/src/main/java/org/dimdev/dimdoors/ddutils/GraphUtils.java b/src/main/java/org/dimdev/dimdoors/ddutils/GraphUtils.java new file mode 100644 index 00000000..ff9e809f --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/ddutils/GraphUtils.java @@ -0,0 +1,20 @@ +package org.dimdev.dimdoors.ddutils; + +import org.jgrapht.Graph; + +public final class GraphUtils { + public static <V, E> void replaceVertex(Graph<V, E> graph, V vertex, V replace) { + graph.addVertex(replace); + for (E edge : graph.outgoingEdgesOf(vertex)) graph.addEdge(replace, graph.getEdgeTarget(edge), edge); + for (E edge : graph.incomingEdgesOf(vertex)) graph.addEdge(graph.getEdgeSource(edge), replace, edge); + graph.removeVertex(vertex); + } + + public static <V, E> V followPointer(Graph<V, E> graph, V pointer) { + if (pointer != null) { + E edge = graph.outgoingEdgesOf(pointer).stream().findFirst().orElse(null); + return graph.getEdgeTarget(edge); + } + return null; + } +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/CommonProxy.java b/src/main/java/org/dimdev/dimdoors/shared/CommonProxy.java index b65c7c2c..7b2b41b6 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/CommonProxy.java +++ b/src/main/java/org/dimdev/dimdoors/shared/CommonProxy.java @@ -7,6 +7,7 @@ import org.dimdev.dimdoors.DimDoors; import org.dimdev.dimdoors.shared.blocks.ModBlocks; import org.dimdev.dimdoors.shared.entities.EntityMonolith; import org.dimdev.dimdoors.shared.items.ModItems; +import org.dimdev.dimdoors.shared.pockets.SchematicHandler; import org.dimdev.dimdoors.shared.rifts.*; import org.dimdev.dimdoors.shared.rifts.destinations.*; import org.dimdev.dimdoors.shared.sound.ModSounds; @@ -44,7 +45,7 @@ public abstract class CommonProxy { RiftDestination.destinationRegistry.put("global", GlobalDestination.class); RiftDestination.destinationRegistry.put("limbo", LimboDestination.class); RiftDestination.destinationRegistry.put("local", LocalDestination.class); - RiftDestination.destinationRegistry.put("new_public", NewPublicDestination.class); + RiftDestination.destinationRegistry.put("public_pocket", PublicPocketDestination.class); RiftDestination.destinationRegistry.put("pocket_entrance", PocketEntranceDestination.class); RiftDestination.destinationRegistry.put("pocket_exit", PocketExitDestination.class); RiftDestination.destinationRegistry.put("private", PrivateDestination.class); diff --git a/src/main/java/org/dimdev/dimdoors/shared/EventHandler.java b/src/main/java/org/dimdev/dimdoors/shared/EventHandler.java index 0afd537d..eeb83a61 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/EventHandler.java +++ b/src/main/java/org/dimdev/dimdoors/shared/EventHandler.java @@ -10,7 +10,7 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; import org.dimdev.dimdoors.shared.pockets.PocketRegistry; -import org.dimdev.dimdoors.shared.rifts.RiftRegistry; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; import org.dimdev.dimdoors.shared.world.ModDimensions; public final class EventHandler { @@ -34,7 +34,7 @@ public final class EventHandler { if (!world.isRemote && !player.isDead && ModDimensions.isDimDoorsPocketDimension(world) - && !PocketRegistry.getForDim(dim).isPlayerAllowedToBeHere(player, player.getPosition())) { + && !PocketRegistry.instance(dim).isPlayerAllowedToBeHere(player, player.getPosition())) { // TODO: make the world circular } } @@ -44,7 +44,7 @@ public final class EventHandler { public static void onDimensionChange(PlayerEvent.PlayerChangedDimensionEvent event) { // TODO: PocketLib compatibility if (ModDimensions.isDimDoorsPocketDimension(event.fromDim) && !ModDimensions.isDimDoorsPocketDimension(event.toDim)) { - RiftRegistry.setOverworldRift(event.player.getCachedUniqueIdString(), null); + RiftRegistry.instance().setOverworldRift(event.player.getUniqueID(), null); } } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/VirtualLocation.java b/src/main/java/org/dimdev/dimdoors/shared/VirtualLocation.java index 18cfee90..b62be6c7 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/VirtualLocation.java +++ b/src/main/java/org/dimdev/dimdoors/shared/VirtualLocation.java @@ -25,11 +25,11 @@ import org.dimdev.dimdoors.shared.world.limbodimension.WorldProviderLimbo; public static VirtualLocation fromLocation(Location location) { VirtualLocation virtualLocation = null; if (ModDimensions.isDimDoorsPocketDimension(location.getDim())) { - Pocket pocket = PocketRegistry.getForDim(location.getDim()).getPocketAt(location.getPos()); + Pocket pocket = PocketRegistry.instance(location.getDim()).getPocketAt(location.getPos()); if (pocket != null) { virtualLocation = pocket.getVirtualLocation(); // TODO: pocket-relative coordinates } else { - virtualLocation = new VirtualLocation(0, 0, 0, 0); // TODO: door was placed in a pocket dim but outside of a pocket... + virtualLocation = null; // TODO: door was placed in a pocket dim but outside of a pocket... } } else if (location.getWorld().provider instanceof WorldProviderLimbo) { virtualLocation = new VirtualLocation(location.getDim(), location.getX(), location.getZ(), Config.getMaxDungeonDepth()); diff --git a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoor.java b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoor.java index 3bdaf81d..49725de2 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoor.java +++ b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoor.java @@ -15,7 +15,8 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import org.dimdev.dimdoors.shared.rifts.RiftRegistry; +import org.dimdev.ddutils.Location; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; import org.dimdev.dimdoors.shared.tileentities.TileEntityEntranceRift; import org.dimdev.dimdoors.shared.tileentities.TileEntityFloatingRift; @@ -130,7 +131,7 @@ public abstract class BlockDimensionalDoor extends BlockDoor implements IRiftPro TileEntityEntranceRift rift = getRift(world, pos, state); super.breakBlock(world, pos, state); if (world.isRemote) return; - if (rift.isPlaceRiftOnBreak() || rift.isRegistered() && RiftRegistry.getRiftInfo(rift.getLocation()).getSources().size() > 0 && !rift.isAlwaysDelete()) { + if (rift.isPlaceRiftOnBreak() || rift.isRegistered() && RiftRegistry.instance().getSources(new Location(rift.getWorld(), rift.getPos())).size() > 0 && !rift.isAlwaysDelete()) { world.setBlockState(rift.getPos(), ModBlocks.RIFT.getDefaultState()); TileEntityFloatingRift newRift = (TileEntityFloatingRift) world.getTileEntity(pos); newRift.copyFrom(rift); diff --git a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorGold.java b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorGold.java index a6c75577..1df15342 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorGold.java +++ b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorGold.java @@ -3,10 +3,8 @@ package org.dimdev.dimdoors.shared.blocks; import net.minecraft.block.state.IBlockState; import org.dimdev.dimdoors.DimDoors; import org.dimdev.dimdoors.shared.items.ModItems; -import org.dimdev.dimdoors.shared.rifts.AvailableLink; -import org.dimdev.dimdoors.shared.rifts.WeightedRiftDestination; +import org.dimdev.dimdoors.shared.rifts.registry.LinkProperties; import org.dimdev.dimdoors.shared.rifts.destinations.AvailableLinkDestination; -import org.dimdev.dimdoors.shared.rifts.destinations.NewPublicDestination; import org.dimdev.dimdoors.shared.tileentities.TileEntityEntranceRift; import net.minecraft.block.material.Material; import net.minecraft.item.Item; @@ -37,21 +35,19 @@ public class BlockDimensionalDoorGold extends BlockDimensionalDoor { @Override public void setupRift(TileEntityEntranceRift rift) { - AvailableLink link = AvailableLink.builder() + rift.setProperties(LinkProperties.builder() .groups(new HashSet<>(Arrays.asList(0, 1))) .linksRemaining(1) - .replaceDestination(UUID.randomUUID()).build(); - rift.addAvailableLink(link); - AvailableLinkDestination destination = AvailableLinkDestination.builder() + .replaceDestination(UUID.randomUUID()).build()); + rift.setDestination(AvailableLinkDestination.builder() .acceptedGroups(Collections.singleton(0)) .coordFactor(1) .negativeDepthFactor(10000) .positiveDepthFactor(80) .weightMaximum(100) - .linkId(link.id) .noLink(false) - .newRiftWeight(1).build(); - rift.addWeightedDestination(new WeightedRiftDestination(destination, 1, 0, null, link.replaceDestination)); + .noLinkBack(false) + .newRiftWeight(1).build()); } @Override diff --git a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorIron.java b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorIron.java index b8b027cd..547506ef 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorIron.java +++ b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorIron.java @@ -4,7 +4,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import org.dimdev.dimdoors.DimDoors; import org.dimdev.dimdoors.shared.items.ModItems; -import org.dimdev.dimdoors.shared.rifts.destinations.NewPublicDestination; +import org.dimdev.dimdoors.shared.rifts.destinations.PublicPocketDestination; import org.dimdev.dimdoors.shared.tileentities.TileEntityEntranceRift; import net.minecraft.block.material.Material; import net.minecraft.item.Item; @@ -36,8 +36,8 @@ public class BlockDimensionalDoorIron extends BlockDimensionalDoor { @Override public void setupRift(TileEntityEntranceRift rift) { - NewPublicDestination destination = NewPublicDestination.builder().build(); - rift.setSingleDestination(destination); + PublicPocketDestination destination = PublicPocketDestination.builder().build(); + rift.setDestination(destination); } @Override diff --git a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorPersonal.java b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorPersonal.java index c65bcc19..1022ae00 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorPersonal.java +++ b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalDoorPersonal.java @@ -37,11 +37,10 @@ public class BlockDimensionalDoorPersonal extends BlockDimensionalDoor { @Override public void setupRift(TileEntityEntranceRift rift) { if (rift.getWorld().provider instanceof WorldProviderPersonalPocket) { - rift.setSingleDestination(new PrivatePocketExitDestination()); // exit + rift.setDestination(new PrivatePocketExitDestination()); // exit } else { - rift.setSingleDestination(new PrivateDestination()); // entrances + rift.setDestination(new PrivateDestination()); // entrances } - rift.setChaosWeight(0); // TODO: generated schematic exits too } @Override diff --git a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalTrapdoorWood.java b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalTrapdoorWood.java index 5b1e5d42..d704b2ea 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalTrapdoorWood.java +++ b/src/main/java/org/dimdev/dimdoors/shared/blocks/BlockDimensionalTrapdoorWood.java @@ -32,7 +32,7 @@ public class BlockDimensionalTrapdoorWood extends BlockDimensionalTrapdoor { @Override public void setupRift(TileEntityEntranceRift rift) { - rift.setSingleDestination(new EscapeDestination()); + rift.setDestination(new EscapeDestination()); } @Override public boolean canBePlacedOnRift() { diff --git a/src/main/java/org/dimdev/dimdoors/shared/blocks/IRiftProvider.java b/src/main/java/org/dimdev/dimdoors/shared/blocks/IRiftProvider.java index cf596d58..21002db9 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/blocks/IRiftProvider.java +++ b/src/main/java/org/dimdev/dimdoors/shared/blocks/IRiftProvider.java @@ -25,9 +25,6 @@ public interface IRiftProvider<T extends TileEntityRift> extends ITileEntityProv if (world.isRemote) return; T rift = getRift(world, pos, state); - // Set the rift's virtual position - rift.setVirtualLocation(VirtualLocation.fromLocation(new Location(world, pos))); - // Configure the rift to its default functionality setupRift(rift); diff --git a/src/main/java/org/dimdev/dimdoors/shared/commands/CommandDimTeleport.java b/src/main/java/org/dimdev/dimdoors/shared/commands/CommandDimTeleport.java index d29bad84..66c7a4f7 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/commands/CommandDimTeleport.java +++ b/src/main/java/org/dimdev/dimdoors/shared/commands/CommandDimTeleport.java @@ -19,7 +19,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentString; import net.minecraftforge.common.DimensionManager; -public class CommandDimTeleport extends CommandBase { // TODO: localization +public class CommandDimTeleport extends CommandBase { // TODO: localization, CommandException private final List<String> aliases; @@ -47,7 +47,7 @@ public class CommandDimTeleport extends CommandBase { // TODO: localization @Override public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { - // Check correct number of arguments + // Check that the number of arguments is correct if (args.length < 4 || args.length > 6) { sender.sendMessage(new TextComponentString("[DimDoors] Usage: /" + getUsage(sender))); return; diff --git a/src/main/java/org/dimdev/dimdoors/shared/commands/CommandPocket.java b/src/main/java/org/dimdev/dimdoors/shared/commands/CommandPocket.java index 48d071a8..054d0ede 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/commands/CommandPocket.java +++ b/src/main/java/org/dimdev/dimdoors/shared/commands/CommandPocket.java @@ -1,8 +1,6 @@ package org.dimdev.dimdoors.shared.commands; -import net.minecraft.util.EnumFacing; import org.dimdev.dimdoors.DimDoors; -import org.dimdev.dimdoors.shared.*; import org.dimdev.dimdoors.shared.pockets.*; import org.dimdev.dimdoors.shared.rifts.TileEntityRift; import org.dimdev.ddutils.Location; @@ -48,7 +46,7 @@ public class CommandPocket extends CommandBase { @Override public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { // TODO: more pocket commands (replace pocket, get ID, teleport to pocket, etc.) - // Check correct number of arguments + // Check that the number of arguments is correct if (args.length < 2 || args.length > 3) { sender.sendMessage(new TextComponentString("[DimDoors] Usage: /" + getUsage(sender))); return; diff --git a/src/main/java/org/dimdev/dimdoors/shared/items/ItemDimensionalDoorGold.java b/src/main/java/org/dimdev/dimdoors/shared/items/ItemDimensionalDoorGold.java index 427928a7..297f3bb2 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/items/ItemDimensionalDoorGold.java +++ b/src/main/java/org/dimdev/dimdoors/shared/items/ItemDimensionalDoorGold.java @@ -7,7 +7,6 @@ import org.dimdev.dimdoors.shared.blocks.BlockDimensionalDoorGold; import org.dimdev.dimdoors.shared.blocks.ModBlocks; import org.dimdev.ddutils.I18nUtils; import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.ItemDoor; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; diff --git a/src/main/java/org/dimdev/dimdoors/shared/items/ItemRiftSignature.java b/src/main/java/org/dimdev/dimdoors/shared/items/ItemRiftSignature.java index 809b1b8a..d9e453e8 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/items/ItemRiftSignature.java +++ b/src/main/java/org/dimdev/dimdoors/shared/items/ItemRiftSignature.java @@ -65,7 +65,7 @@ public class ItemRiftSignature extends Item { World sourceWorld = target.getLocation().getWorld(); sourceWorld.setBlockState(target.getLocation().getPos(), ModBlocks.RIFT.getDefaultState()); TileEntityRift rift1 = (TileEntityRift) target.getLocation().getTileEntity(); - rift1.setSingleDestination(new GlobalDestination(new Location(world, pos))); + rift1.setDestination(new GlobalDestination(new Location(world, pos))); rift1.register(); rift1.setRotation(target.getYaw(), 0); } @@ -73,7 +73,7 @@ public class ItemRiftSignature extends Item { // Place a rift at the target point world.setBlockState(pos, ModBlocks.RIFT.getDefaultState()); TileEntityRift rift2 = (TileEntityRift) world.getTileEntity(pos); - rift2.setSingleDestination(new GlobalDestination(target.getLocation())); + rift2.setDestination(new GlobalDestination(target.getLocation())); rift2.setRotation(player.rotationYaw, 0); rift2.register(); diff --git a/src/main/java/org/dimdev/dimdoors/shared/items/ItemStabilizedRiftSignature.java b/src/main/java/org/dimdev/dimdoors/shared/items/ItemStabilizedRiftSignature.java index e5360a21..91b27b4e 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/items/ItemStabilizedRiftSignature.java +++ b/src/main/java/org/dimdev/dimdoors/shared/items/ItemStabilizedRiftSignature.java @@ -72,7 +72,7 @@ public class ItemStabilizedRiftSignature extends Item { // TODO: common supercla // Place a rift at the source point world.setBlockState(pos, ModBlocks.RIFT.getDefaultState()); TileEntityRift rift2 = (TileEntityRift) world.getTileEntity(pos); - rift2.setSingleDestination(new GlobalDestination(target.getLocation())); + rift2.setDestination(new GlobalDestination(target.getLocation())); rift2.setRotation(player.rotationYaw, 0); rift2.register(); diff --git a/src/main/java/org/dimdev/dimdoors/shared/pockets/Pocket.java b/src/main/java/org/dimdev/dimdoors/shared/pockets/Pocket.java index 410117fc..e92e8c77 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/pockets/Pocket.java +++ b/src/main/java/org/dimdev/dimdoors/shared/pockets/Pocket.java @@ -1,34 +1,37 @@ package org.dimdev.dimdoors.shared.pockets; -import org.dimdev.ddutils.nbt.INBTStorable; -import org.dimdev.ddutils.nbt.NBTUtils; -import org.dimdev.annotatednbt.Saved; -import org.dimdev.annotatednbt.NBTSerializable; -import org.dimdev.dimdoors.shared.VirtualLocation; -import org.dimdev.dimdoors.shared.rifts.*; -import org.dimdev.dimdoors.shared.rifts.destinations.PocketEntranceDestination; -import org.dimdev.dimdoors.shared.rifts.destinations.PocketExitDestination; -import org.dimdev.dimdoors.shared.tileentities.TileEntityEntranceRift; -import org.dimdev.ddutils.Location; - -import java.util.*; - -import org.dimdev.ddutils.math.MathUtils; import lombok.Getter; import lombok.Setter; -import net.minecraft.nbt.*; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; +import org.dimdev.annotatednbt.NBTSerializable; +import org.dimdev.annotatednbt.Saved; +import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.math.MathUtils; +import org.dimdev.ddutils.nbt.INBTStorable; +import org.dimdev.ddutils.nbt.NBTUtils; +import org.dimdev.dimdoors.shared.VirtualLocation; +import org.dimdev.dimdoors.shared.rifts.RiftDestination; +import org.dimdev.dimdoors.shared.rifts.TileEntityRift; +import org.dimdev.dimdoors.shared.rifts.destinations.PocketEntranceDestination; +import org.dimdev.dimdoors.shared.rifts.destinations.PocketExitDestination; +import org.dimdev.dimdoors.shared.rifts.registry.LinkProperties; +import org.dimdev.dimdoors.shared.tileentities.TileEntityEntranceRift; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; @NBTSerializable public class Pocket implements INBTStorable { // TODO: better visibilities - @Saved @Getter /*package-private*/ int id; - @Saved @Getter /*package-private*/ int x; // Grid x TODO: rename to gridX and gridY - @Saved @Getter /*package-private*/ int z; // Grid y - @Saved @Getter @Setter /*package-private*/ int size; // In chunks TODO: non chunk-based size, better bounds such as minX, minZ, maxX, maxZ, etc. - @Saved @Getter @Setter /*package-private*/ VirtualLocation virtualLocation; // The non-pocket dimension from which this dungeon was created - @Saved @Getter @Setter /*package-private*/ Location entrance; - @Saved @Getter /*package-private*/ List<Location> riftLocations; + @Saved @Getter protected int id; + @Saved @Getter protected int x; // Grid x TODO: rename to gridX and gridY, or just convert to non-grid dependant coordinates + @Saved @Getter protected int z; // Grid y + @Saved @Getter @Setter protected int size; // In chunks TODO: non chunk-based size, better bounds such as minX, minZ, maxX, maxZ, etc. + @Saved @Getter @Setter protected VirtualLocation virtualLocation; + @Saved @Getter @Setter protected Location entrance; // TODO: move this to the rift registry (pocketlib) + @Saved @Getter protected List<Location> riftLocations; // TODO: convert to a list of all tile entities (for chests, and to make it independant of pocketlib) @Getter int dim; // Not saved @@ -44,11 +47,12 @@ import net.minecraft.util.math.BlockPos; // TODO: make these static? @Override public void readFromNBT(NBTTagCompound nbt) { NBTUtils.readFromNBT(this, nbt); } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { return NBTUtils.writeToNBT(this, nbt); } boolean isInBounds(BlockPos pos) { // pocket bounds - int gridSize = PocketRegistry.getForDim(dim).getGridSize(); + int gridSize = PocketRegistry.instance(dim).getGridSize(); int minX = x * gridSize; int minZ = z * gridSize; int maxX = minX + (size + 1) * 16; @@ -72,89 +76,57 @@ import net.minecraft.util.math.BlockPos; public void setup() { // Always call after creating a pocket except when building the pocket List<TileEntityRift> rifts = getRifts(); - HashMap<Integer, Float> entranceIndexWeights = new HashMap<>(); + HashMap<TileEntityRift, Float> entranceIndexWeights = new HashMap<>(); - int index = 0; for (TileEntityRift rift : rifts) { // Find an entrance - for (WeightedRiftDestination weightedPocketEntranceDest : rift.getDestinations()) { - if (weightedPocketEntranceDest.getDestination() instanceof PocketEntranceDestination) { - entranceIndexWeights.put(index, weightedPocketEntranceDest.getWeight()); - rift.markDirty(); - index++; - } + if (rift.getDestination() instanceof PocketEntranceDestination) { + entranceIndexWeights.put(rift, ((PocketEntranceDestination) rift.getDestination()).getWeight()); + rift.markDirty(); } } + if (entranceIndexWeights.size() == 0) return; - int selectedEntranceIndex = MathUtils.weightedRandom(entranceIndexWeights); + TileEntityRift selectedEntrance = MathUtils.weightedRandom(entranceIndexWeights); // Replace entrances with appropriate destinations - index = 0; for (TileEntityRift rift : rifts) { - ListIterator<WeightedRiftDestination> destIterator = rift.getDestinations().listIterator(); - while (destIterator.hasNext()) { - WeightedRiftDestination wdest = destIterator.next(); - RiftDestination dest = wdest.getDestination(); - if (dest instanceof PocketEntranceDestination) { - destIterator.remove(); - if (index == selectedEntranceIndex) { - entrance = new Location(rift.getWorld(), rift.getPos()); - PocketRegistry.getForDim(dim).markDirty(); - List<WeightedRiftDestination> ifDestinations = ((PocketEntranceDestination) dest).getIfDestinations(); - for (WeightedRiftDestination ifDestination : ifDestinations) { - destIterator.add(new WeightedRiftDestination(ifDestination.getDestination(), ifDestination.getWeight() / wdest.getWeight(), ifDestination.getGroup())); - destIterator.previous(); // An entrance destination shouldn't be in an if/otherwise destination, but just in case, pass over it too - } - } else { - List<WeightedRiftDestination> otherwiseDestinations = ((PocketEntranceDestination) dest).getOtherwiseDestinations(); - for (WeightedRiftDestination otherwiseDestination : otherwiseDestinations) { - destIterator.add(new WeightedRiftDestination(otherwiseDestination.getDestination(), otherwiseDestination.getWeight() / wdest.getWeight(), otherwiseDestination.getGroup())); - destIterator.previous(); // An entrance destination shouldn't be in an if/otherwise destination, but just in case, pass over it too - } - } - index++; + RiftDestination dest = rift.getDestination(); + if (dest instanceof PocketEntranceDestination) { + if (rift == selectedEntrance) { + entrance = new Location(rift.getWorld(), rift.getPos()); + PocketRegistry.instance(dim).markDirty(); + rift.setDestination(((PocketEntranceDestination) dest).getIfDestination()); + } else { + rift.setDestination(((PocketEntranceDestination) dest).getOtherwiseDestination()); } } } - // set virtual locations and register rifts + // register the rifts for (TileEntityRift rift : rifts) { - rift.setVirtualLocation(virtualLocation); rift.register(); } } - public void linkPocketTo(RiftDestination linkTo, RiftDestination oldDest, AvailableLink availableLink) { + public void linkPocketTo(RiftDestination linkTo, LinkProperties linkProperties) { List<TileEntityRift> rifts = getRifts(); // Link pocket exits back for (TileEntityRift rift : rifts) { - ListIterator<WeightedRiftDestination> destIterator = rift.getDestinations().listIterator(); - while (destIterator.hasNext()) { - WeightedRiftDestination wdest = destIterator.next(); - RiftDestination dest = wdest.getDestination(); - if (dest instanceof PocketExitDestination) { - destIterator.remove(); - if (rift.isRegistered()) dest.unregister(rift); - if (availableLink != null) rift.addAvailableLink(availableLink.toBuilder().build()); - if (linkTo != null) destIterator.add(new WeightedRiftDestination(linkTo, wdest.getWeight(), wdest.getGroup(), oldDest)); - if (rift.isRegistered()) linkTo.register(rift); - if (rift instanceof TileEntityEntranceRift && !rift.isAlwaysDelete()) { - ((TileEntityEntranceRift) rift).setPlaceRiftOnBreak(true); // We modified the door's state - } - rift.markDirty(); + RiftDestination dest = rift.getDestination(); + if (dest instanceof PocketExitDestination) { + if (linkProperties != null) rift.setProperties(linkProperties); + rift.setDestination(linkTo); + if (rift instanceof TileEntityEntranceRift && !rift.isAlwaysDelete()) { + ((TileEntityEntranceRift) rift).setPlaceRiftOnBreak(true); // We modified the door's state } + rift.markDirty(); } } } - public void unlinkPocket() { - // TODO - } - public BlockPos getOrigin() { - int gridSize = PocketRegistry.getForDim(dim).getGridSize(); + int gridSize = PocketRegistry.instance(dim).getGridSize(); return new BlockPos(x * gridSize * 16, 0, z * gridSize * 16); // TODO: configurable yBase? } - - // TODO: method to erase a pocket } diff --git a/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketGenerator.java b/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketGenerator.java index b4b20981..2364a869 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketGenerator.java +++ b/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketGenerator.java @@ -11,9 +11,9 @@ public final class PocketGenerator { public static Pocket generatePocketFromTemplate(int dim, PocketTemplate pocketTemplate, VirtualLocation virtualLocation) { DimDoors.log.info("Generating pocket from template " + pocketTemplate.getName() + " at virtual location " + virtualLocation); - PocketRegistry registry = PocketRegistry.getForDim(dim); + PocketRegistry registry = PocketRegistry.instance(dim); Pocket pocket = registry.newPocket(); - pocketTemplate.place(pocket, 0); // TODO: config option for yBase + pocketTemplate.place(pocket); pocket.setVirtualLocation(virtualLocation); return pocket; } diff --git a/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketRegistry.java b/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketRegistry.java index d40de5bd..62261cdc 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketRegistry.java +++ b/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketRegistry.java @@ -13,6 +13,7 @@ import org.dimdev.dimdoors.shared.world.ModDimensions; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import lombok.Getter; import net.minecraft.entity.player.EntityPlayerMP; @@ -21,7 +22,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.storage.MapStorage; import net.minecraft.world.storage.WorldSavedData; -@NBTSerializable public class PocketRegistry extends WorldSavedData { // TODO: unregister pocket entrances, private pocket entrances/exits +@NBTSerializable public class +PocketRegistry extends WorldSavedData { // TODO: unregister pocket entrances, private pocket entrances/exits private static final String DATA_NAME = DimDoors.MODID + "_pockets"; @Getter private static final int DATA_VERSION = 0; // IMPORTANT: Update this and upgradeRegistry when making changes. @@ -30,7 +32,7 @@ import net.minecraft.world.storage.WorldSavedData; @Saved @Getter /*package-private*/ int maxPocketSize; @Saved @Getter /*package-private*/ int privatePocketSize; @Saved @Getter /*package-private*/ int publicPocketSize; - @Saved /*package-private*/ BiMap<String, Integer> privatePocketMap; // Player UUID -> Pocket ID, in pocket dim only + @Saved /*package-private*/ BiMap<UUID, Integer> privatePocketMap; // Player UUID -> Pocket ID, in pocket dim only TODO: move this out of pocketlib @Saved @Getter /*package-private*/ Map<Integer, Pocket> pockets; // TODO: remove getter? @Saved @Getter /*package-private*/ int nextID; @@ -44,7 +46,7 @@ import net.minecraft.world.storage.WorldSavedData; super(s); } - public static PocketRegistry getForDim(int dim) { + public static PocketRegistry instance(int dim) { if (!ModDimensions.isDimDoorsPocketDimension(dim)) throw new UnsupportedOperationException("PocketRegistry is only available for pocket dimensions!"); MapStorage storage = WorldUtils.getWorld(dim).getPerWorldStorage(); @@ -155,17 +157,17 @@ import net.minecraft.world.storage.WorldSavedData; } // TODO: these should be per-map rather than per-world - public int getPrivatePocketID(String playerUUID) { + public int getPrivatePocketID(UUID playerUUID) { Integer id = privatePocketMap.get(playerUUID); if (id == null) return -1; return id; } - public String getPrivatePocketOwner(int id) { + public UUID getPrivatePocketOwner(int id) { return privatePocketMap.inverse().get(id); } - public void setPrivatePocketID(String playerUUID, int id) { + public void setPrivatePocketID(UUID playerUUID, int id) { privatePocketMap.put(playerUUID, id); markDirty(); } diff --git a/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketTemplate.java b/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketTemplate.java index 7e4d2937..a51d243a 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketTemplate.java +++ b/src/main/java/org/dimdev/dimdoors/shared/pockets/PocketTemplate.java @@ -17,7 +17,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldServer; /** - * * @author Robijnvogel */ @AllArgsConstructor @RequiredArgsConstructor// TODO: use @Builder? @@ -33,22 +32,23 @@ public class PocketTemplate { public float getWeight(int depth) { if (depth < 0) return 100; // TODO: get rid of this later - if (maxDepth - minDepth + 1 != weights.length) throw new IllegalStateException("This PocetTemplate wasn't set up correctly!"); + if (maxDepth - minDepth + 1 != weights.length) throw new IllegalStateException("This PocketTemplate wasn't set up correctly!"); if (depth < minDepth) return 0; if (depth > maxDepth) return weights[weights.length - 1]; return weights[depth - minDepth]; } - public void place(Pocket pocket, int yBase) { + public void place(Pocket pocket) { pocket.setSize(size); - int gridSize = PocketRegistry.getForDim(pocket.dim).getGridSize(); + int gridSize = PocketRegistry.instance(pocket.dim).getGridSize(); int dim = pocket.dim; int xBase = pocket.getX() * gridSize * 16; + int yBase = 0; int zBase = pocket.getZ() * gridSize * 16; DimDoors.log.info("Placing new pocket using schematic " + schematic.schematicName + " at x = " + xBase + ", z = " + zBase); WorldServer world = WorldUtils.getWorld(dim); - Schematic.place(schematic, world, xBase, yBase, zBase); + Schematic.place(schematic, world, xBase, 0, zBase); // Set pocket riftLocations pocket.riftLocations = new ArrayList<>(); diff --git a/src/main/java/org/dimdev/dimdoors/shared/SchematicHandler.java b/src/main/java/org/dimdev/dimdoors/shared/pockets/SchematicHandler.java similarity index 99% rename from src/main/java/org/dimdev/dimdoors/shared/SchematicHandler.java rename to src/main/java/org/dimdev/dimdoors/shared/pockets/SchematicHandler.java index c991f89f..f3c01c56 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/SchematicHandler.java +++ b/src/main/java/org/dimdev/dimdoors/shared/pockets/SchematicHandler.java @@ -1,6 +1,6 @@ -package org.dimdev.dimdoors.shared; +package org.dimdev.dimdoors.shared.pockets; -import org.dimdev.dimdoors.shared.pockets.PocketTemplate; +import org.dimdev.dimdoors.shared.Config; import org.dimdev.ddutils.math.MathUtils; import org.dimdev.ddutils.schem.Schematic; import com.google.gson.JsonArray; diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftDestination.java index 627ced93..c4b69b2a 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftDestination.java @@ -3,23 +3,23 @@ package org.dimdev.dimdoors.shared.rifts; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.RGBA; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.ddutils.nbt.INBTStorable; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; import lombok.*; // Don't change import order! (Gradle bug): https://stackoverflow.com/questions/26557133/ +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; import java.lang.reflect.InvocationTargetException; +import java.util.Set; -@Getter @EqualsAndHashCode @ToString +@EqualsAndHashCode @ToString public abstract class RiftDestination implements INBTStorable { - /*private*/ public static final BiMap<String, Class<? extends RiftDestination>> destinationRegistry = HashBiMap.create(); // TODO: move to RiftDestinationRegistry - //private String type; - protected WeightedRiftDestination weightedDestination; + public static final BiMap<String, Class<? extends RiftDestination>> destinationRegistry = HashBiMap.create(); // TODO: move to RiftDestinationRegistry - public RiftDestination() { - //type = destinationRegistry.inverse().get(getClass()); - } + public RiftDestination() {} public static RiftDestination readDestinationNBT(NBTTagCompound nbt) { String type = nbt.getString("type"); @@ -28,7 +28,6 @@ public abstract class RiftDestination implements INBTStorable { try { RiftDestination destination = destinationClass.getConstructor().newInstance(); destination.readFromNBT(nbt); - //destination.type = type; return destination; } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException("The class registered for type " + type + " must have a public no-args constructor.", e); @@ -38,7 +37,7 @@ public abstract class RiftDestination implements INBTStorable { } @Override - public void readFromNBT(NBTTagCompound nbt) { } + public void readFromNBT(NBTTagCompound nbt) {} @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @@ -48,19 +47,30 @@ public abstract class RiftDestination implements INBTStorable { return nbt; } - public Location getReferencedRift(Location rift) { // TODO: change to getReferencedRifts + public abstract boolean teleport(RotatedLocation rift, Entity entity); + + public Location getFixedTarget(Location location) { return null; } - public void register(TileEntityRift rift) { - Location loc = getReferencedRift(rift.getLocation()); - if (loc != null) RiftRegistry.addLink(rift.getLocation(), loc); + public void register(Location location) { + RiftRegistry.instance().addLink(location, getFixedTarget(location)); } - public void unregister(TileEntityRift rift) { - Location loc = getReferencedRift(rift.getLocation()); - if (loc != null) RiftRegistry.removeLink(rift.getLocation(), loc); + public void unregister(Location location) { + RiftRegistry.instance().removeLink(location, getFixedTarget(location)); } - public abstract boolean teleport(TileEntityRift rift, Entity entity); + public boolean keepAfterTargetGone(Location location) { + return true; + } + + public RGBA getColor(Location location) { + Location target = getFixedTarget(location); + if (target != null && RiftRegistry.instance().isRiftAt(target)) { + Set<Location> otherRiftTargets = RiftRegistry.instance().getTargets(target); + if (otherRiftTargets.size() == 1 && otherRiftTargets.contains(location)) return new RGBA(0, 1, 0, 1); + } + return new RGBA(1, 0, 0, 1); + } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftRegistry.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftRegistry.java deleted file mode 100644 index 172e483c..00000000 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/RiftRegistry.java +++ /dev/null @@ -1,292 +0,0 @@ -package org.dimdev.dimdoors.shared.rifts; - -import com.google.common.collect.ConcurrentHashMultiset; -import com.google.common.collect.Multiset; -import lombok.*; -import lombok.experimental.Wither; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; -import net.minecraft.world.storage.MapStorage; -import net.minecraft.world.storage.WorldSavedData; -import net.minecraftforge.common.DimensionManager; -import org.dimdev.ddutils.Location; -import org.dimdev.ddutils.WorldUtils; -import org.dimdev.ddutils.nbt.INBTStorable; -import org.dimdev.ddutils.nbt.NBTUtils; -import org.dimdev.annotatednbt.Saved; -import org.dimdev.annotatednbt.NBTSerializable; -import org.dimdev.dimdoors.DimDoors; -import org.dimdev.dimdoors.shared.VirtualLocation; -import org.dimdev.dimdoors.shared.world.ModDimensions; - -import java.util.*; - -@NBTSerializable public class RiftRegistry extends WorldSavedData { - - private static final String DATA_NAME = DimDoors.MODID + "_rifts"; - @Getter private static final int DATA_VERSION = 0; // IMPORTANT: Update this and upgradeRegistry when making changes. - - @Saved @Getter protected /*final*/ Map<Location, RiftInfo> rifts = new HashMap<>(); // TODO: convert to a static directed graph, but store links per-world - - @Saved @Getter protected /*final*/ Map<String, Location> privatePocketEntrances = new HashMap<>(); // Player UUID -> last rift used to exit pocket TODO: split into PrivatePocketRiftRegistry subclass - @Saved @Getter protected /*final*/ Map<String, List<Location>> privatePocketEntranceLists = new HashMap<>(); // Player UUID -> private pocket entrances TODO: split into PrivatePocketRiftRegistry subclass - @Saved @Getter protected /*final*/ Map<String, Location> privatePocketExits = new HashMap<>(); // Player UUID -> last rift used to enter pocket - @Saved @Getter protected /*final*/ Map<String, Location> overworldRifts = new HashMap<>(); - - @Getter private int dim; - private World world; - - @AllArgsConstructor @EqualsAndHashCode @Builder(toBuilder = true) - @NBTSerializable public static class RiftInfo implements INBTStorable { - // IntelliJ warnings are wrong, Builder needs these initializers! - @Saved @Getter public VirtualLocation virtualLocation; - @Saved @Getter @Wither public Location location; - @Saved @Getter public boolean isEntrance; - @Builder.Default @Getter public Set<AvailableLink> availableLinks = new HashSet<>(); - @Builder.Default @Getter public Multiset<Location> sources = ConcurrentHashMultiset.create(); - @Builder.Default @Getter public Multiset<Location> destinations = ConcurrentHashMultiset.create(); - - public RiftInfo() { - availableLinks = new HashSet<>(); - sources = ConcurrentHashMultiset.create(); - destinations = ConcurrentHashMultiset.create(); - } - - @Override public void readFromNBT(NBTTagCompound nbt) { NBTUtils.readFromNBT(this, nbt); } - @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { return NBTUtils.writeToNBT(this, nbt); } - } - - public RiftRegistry() { - super(DATA_NAME); - } - - public RiftRegistry(String s) { - super(s); - } - - public static RiftRegistry getForDim(int dim) { - MapStorage storage = WorldUtils.getWorld(dim).getPerWorldStorage(); - RiftRegistry instance = (RiftRegistry) storage.getOrLoadData(RiftRegistry.class, DATA_NAME); - - if (instance == null) { - instance = new RiftRegistry(); - instance.initNewRegistry(); - storage.setData(DATA_NAME, instance); - } - - instance.world = WorldUtils.getWorld(dim); - instance.dim = dim; - return instance; - } - - public void initNewRegistry() { - // Nothing to do - } - - @Override - public void readFromNBT(NBTTagCompound nbt) { - Integer version = nbt.getInteger("version"); - if (version == null || version != DATA_VERSION) { - if (upgradeRegistry(nbt, version == null ? -1 : version)) { - markDirty(); - } else { - DimDoors.log.warn("Failed to upgrade the pocket registry, you'll have to recreate your world!"); - throw new RuntimeException("Couldn't upgrade registry"); // TODO: better exceptions - } - } - - NBTUtils.readFromNBT(this, nbt); - } - - private static boolean upgradeRegistry(@SuppressWarnings("unused") NBTTagCompound nbt, int oldVersion) { - if (oldVersion > DATA_VERSION) throw new RuntimeException("Upgrade the mod!"); // TODO: better exceptions - switch (oldVersion) { - case -1: // No version tag - return false; - case 0: - // Upgrade to 1 or return false - case 1: - // Upgrade to 2 or return false - case 2: - // Upgrade to 3 or return false - // ... - } - return true; - } - - @Override - public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt.setInteger("version", DATA_VERSION); - return NBTUtils.writeToNBT(this, nbt); - } - - public static RiftInfo getRiftInfo(Location rift) { - return getRegistry(rift).rifts.get(rift); - } - - public static void addRift(Location rift) { - DimDoors.log.info("Rift added at " + rift); - RiftRegistry registry = getRegistry(rift); - registry.rifts.computeIfAbsent(rift, k -> new RiftInfo()); - registry.markDirty(); - } - - public static void removeRift(Location rift) { - DimDoors.log.info("Rift removed at " + rift); - RiftRegistry registry = getRegistry(rift); - RiftInfo oldRift = registry.rifts.remove(rift); - if (oldRift == null) return; - List<TileEntityRift> updateQueue = new ArrayList<>(); - for (Location source : oldRift.sources) { - RiftRegistry sourceRegistry = getRegistry(source); - sourceRegistry.rifts.get(source).destinations.remove(rift); - sourceRegistry.markDirty(); - TileEntityRift riftEntity = (TileEntityRift) sourceRegistry.world.getTileEntity(source.getPos()); - riftEntity.destinationGone(rift); - updateQueue.add(riftEntity); - } - for (Location destination : oldRift.destinations) { - RiftRegistry destinationRegistry = getRegistry(destination); - destinationRegistry.rifts.get(destination).sources.remove(rift); - destinationRegistry.markDirty(); - TileEntityRift riftEntity = (TileEntityRift) destinationRegistry.world.getTileEntity(destination.getPos()); - updateQueue.add(riftEntity); - //riftEntity.allSourcesGone(); // TODO - } - for (TileEntityRift riftEntity : updateQueue) { - //riftEntity.updateColor(); - riftEntity.markDirty(); - } - getForDim(ModDimensions.getPrivateDim()).privatePocketEntrances.entrySet().removeIf(e -> e.getValue().equals(rift)); - getForDim(0).overworldRifts.entrySet().removeIf(e -> e.getValue().equals(rift)); - registry.markDirty(); - } - - public static void addLink(Location from, Location to) { - DimDoors.log.info("Link added " + from + " -> " + to); - RiftRegistry registryFrom = getRegistry(from); - RiftRegistry registryTo = getRegistry(to); - RiftInfo riftInfoFrom = registryFrom.rifts.computeIfAbsent(from, k -> new RiftInfo()); - RiftInfo riftInfoTo = registryTo.rifts.computeIfAbsent(to, k -> new RiftInfo()); - riftInfoFrom.destinations.add(to); - registryFrom.markDirty(); - riftInfoTo.sources.add(from); - registryTo.markDirty(); - if (to.getTileEntity() instanceof TileEntityRift) ((TileEntityRift) to.getTileEntity()).updateColor(); - if (from.getTileEntity() instanceof TileEntityRift) ((TileEntityRift) from.getTileEntity()).updateColor(); - } - - public static void removeLink(Location from, Location to) { - DimDoors.log.info("Link removed " + from + " -> " + to); - RiftRegistry registryFrom = getRegistry(from); - RiftRegistry registryTo = getRegistry(to); - registryFrom.rifts.get(from).destinations.remove(to); - registryTo.rifts.get(to).sources.remove(from); - registryFrom.markDirty(); - registryTo.markDirty(); - if (to.getTileEntity() instanceof TileEntityRift) ((TileEntityRift) to.getTileEntity()).updateColor(); - if (from.getTileEntity() instanceof TileEntityRift) ((TileEntityRift) from.getTileEntity()).updateColor(); - } - - public static void addAvailableLink(Location rift, AvailableLink link) { // TODO cache rifts with availableLinks - DimDoors.log.info("AvailableLink added at " + rift); - RiftRegistry registry = getRegistry(rift); - registry.rifts.get(rift).availableLinks.add(link); - registry.markDirty(); - } - - public static void removeAvailableLink(Location rift, AvailableLink link) { - DimDoors.log.info("AvailableLink removed at " + rift); - RiftRegistry registry = getRegistry(rift); - registry.rifts.get(rift).availableLinks.remove(link); - registry.markDirty(); - } - - public static void clearAvailableLinks(Location rift) { - DimDoors.log.info("AvailableLink cleared at " + rift); - RiftRegistry registry = getRegistry(rift); - registry.rifts.get(rift).availableLinks.clear(); - registry.markDirty(); - } - - /* - public static void removeAvailableLinkByID(Location rift, int id) { - DimDoors.log.info("AvailableLink with id " + id + " removed at " + rift); - RiftRegistry registry = getRegistry(rift); - for (AvailableLinkInfo link : registry.rifts.get(rift).availableLinks) { - if (link.id.equals(id)) { - removeAvailableLink(rift, link); - return; - } - } - }*/ - - public static RiftRegistry getRegistry(Location rift) { - return getForDim(rift.getDim()); - } - - public Location getPrivatePocketEntrance(String playerUUID) { - Location entrance = privatePocketEntrances.get(playerUUID); - List<Location> entrances = privatePocketEntranceLists.computeIfAbsent(playerUUID, k -> new ArrayList<>()); - while ((entrance == null || !(entrance.getTileEntity() instanceof TileEntityRift)) && entrances.size() > 0) { - if (entrance != null) entrances.remove(entrance); - if (entrances.size() > 0) entrance = entrances.get(0); - } - privatePocketEntrances.put(playerUUID, entrance); - return entrance; - } - - public void addPrivatePocketEntrance(String playerUUID, Location rift) { - DimDoors.log.info("Private pocket entrance added for " + playerUUID + " at " + rift); - privatePocketEntranceLists.computeIfAbsent(playerUUID, k -> new ArrayList<>()).add(rift); - } - - public void setPrivatePocketEntrance(String playerUUID, Location rift) { - DimDoors.log.info("Last private pocket entrance set for " + playerUUID + " at " + rift); - privatePocketEntrances.put(playerUUID, rift); - markDirty(); - } - - public Location getPrivatePocketExit(String playerUUID) { - return privatePocketExits.get(playerUUID); - } - - public void setPrivatePocketExit(String playerUUID, Location rift) { - DimDoors.log.info("Last private pocket exit set for " + playerUUID + " at " + rift); - if (rift != null) { - privatePocketExits.put(playerUUID, rift); - } else { - privatePocketExits.remove(playerUUID); - } - markDirty(); - } - - public static Location getOverworldRift(String playerUUID) { // TODO: since this is per-world, move to different registry? - return getForDim(0).overworldRifts.get(playerUUID); // store in overworld, since that's where per-world player data is stored - } - - public static void setOverworldRift(String playerUUID, Location rift) { - DimDoors.log.info("Overworld rift set for " + playerUUID + " at " + rift); - if (rift != null) { - getForDim(0).overworldRifts.put(playerUUID, rift); - } else { - getForDim(0).overworldRifts.remove(playerUUID); - } - getForDim(0).markDirty(); - } - - public static List<AvailableLink> getAvailableLinks() { // TODO: cache this - List<AvailableLink> availableLinks = new ArrayList<>(); - for (int dim: DimensionManager.getStaticDimensionIDs()) { // TODO: don't create worlds - RiftRegistry registry = getForDim(dim); - for (Map.Entry<Location, RiftInfo> rift : registry.rifts.entrySet()) { - for (AvailableLink availableLink : rift.getValue().availableLinks) { - availableLinks.add(availableLink.withRift(rift.getKey())); - } - } - } - return availableLinks; - } - - // TODO: rebuildRifts() function that scans the world and rebuilds the rift regestry -} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/TileEntityRift.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/TileEntityRift.java index 8cc081b0..44ea656d 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/TileEntityRift.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/TileEntityRift.java @@ -1,22 +1,5 @@ package org.dimdev.dimdoors.shared.rifts; -import org.dimdev.ddutils.nbt.NBTUtils; -import org.dimdev.annotatednbt.Saved; -import org.dimdev.annotatednbt.NBTSerializable; -import org.dimdev.ddutils.RGBA; -import org.dimdev.dimdoors.DimDoors; -import org.dimdev.dimdoors.shared.VirtualLocation; -import org.dimdev.dimdoors.shared.blocks.BlockDimensionalDoor; -import org.dimdev.dimdoors.shared.blocks.BlockFloatingRift; -import org.dimdev.dimdoors.shared.pockets.Pocket; -import org.dimdev.dimdoors.shared.pockets.PocketRegistry; -import org.dimdev.ddutils.EntityUtils; -import org.dimdev.ddutils.Location; -import org.dimdev.ddutils.math.MathUtils; -import org.dimdev.ddutils.TeleportUtils; -import org.dimdev.ddutils.WorldUtils; -import org.dimdev.dimdoors.shared.rifts.destinations.*; -import org.dimdev.dimdoors.shared.world.ModDimensions; import lombok.Getter; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; @@ -30,55 +13,53 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.dimdev.annotatednbt.NBTSerializable; +import org.dimdev.annotatednbt.Saved; +import org.dimdev.ddutils.*; +import org.dimdev.ddutils.nbt.NBTUtils; +import org.dimdev.dimdoors.DimDoors; +import org.dimdev.dimdoors.shared.blocks.BlockDimensionalDoor; +import org.dimdev.dimdoors.shared.blocks.BlockFloatingRift; +import org.dimdev.dimdoors.shared.rifts.registry.LinkProperties; +import org.dimdev.dimdoors.shared.rifts.registry.Rift; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; +import org.dimdev.dimdoors.shared.world.ModDimensions; import javax.annotation.Nonnull; -import java.util.*; @NBTSerializable public abstract class TileEntityRift extends TileEntity implements ITickable { // TODO: implement ITeleportSource and ITeleportDestination - @Saved@Getter protected VirtualLocation virtualLocation; - @Saved @Nonnull @Getter protected List<WeightedRiftDestination> destinations; // Not using a set because we can have duplicate destinations. Maybe use Multiset from Guava? - @Saved @Getter protected boolean makeDestinationPermanent; - @Saved @Getter protected boolean preserveRotation; + @Saved @Nonnull @Getter protected RiftDestination destination; + @Saved @Getter protected boolean relativeRotation; @Saved @Getter protected float yaw; @Saved @Getter protected float pitch; @Saved @Getter protected boolean alwaysDelete; // Delete the rift when an entrances rift is broken even if the state was changed or destinations link there. - @Saved @Getter protected float chaosWeight; @Saved @Getter protected boolean forcedColor; - @Saved @Getter protected RGBA color = null; // TODO: update AnnotatedNBT to be able to save these - @Saved @Getter protected Set<AvailableLink> availableLinks; - // TODO: option to convert to door on teleportTo? + @Saved @Getter protected RGBA color = null; + @Saved @Getter protected LinkProperties properties; protected boolean riftStateChanged; // not saved public TileEntityRift() { - destinations = new ArrayList<>(); - makeDestinationPermanent = true; - preserveRotation = true; + relativeRotation = true; pitch = 0; alwaysDelete = false; - chaosWeight = 1; - availableLinks = new HashSet<>(); } public void copyFrom(TileEntityRift oldRift) { - virtualLocation = oldRift.virtualLocation; - destinations = oldRift.destinations; - makeDestinationPermanent = oldRift.makeDestinationPermanent; - preserveRotation = oldRift.preserveRotation; + relativeRotation = oldRift.relativeRotation; yaw = oldRift.yaw; pitch = oldRift.pitch; - chaosWeight = oldRift.chaosWeight; + properties = oldRift.properties; if (oldRift.isFloating() != isFloating()) updateType(); markDirty(); } + // NBT @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); NBTUtils.readFromNBT(this, nbt); } - @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt = super.writeToNBT(nbt); - return NBTUtils.writeToNBT(this, nbt); - } + + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return NBTUtils.writeToNBT(this, nbt); } @Override public NBTTagCompound getUpdateTag() { @@ -101,6 +82,7 @@ import java.util.*; deserializeNBT(pkt.getNbtCompound()); } + // Tile entity properties // Use vanilla behavior of refreshing only when block changes, not state (otherwise, opening the door would destroy the tile entity) @Override @@ -108,71 +90,30 @@ import java.util.*; // newState is not accurate if we change the state during onBlockBreak newSate = world.getBlockState(pos); return oldState.getBlock() != newSate.getBlock() && - !(oldState.getBlock() instanceof BlockDimensionalDoor - && newSate.getBlock() instanceof BlockFloatingRift); + !(oldState.getBlock() instanceof BlockDimensionalDoor + && newSate.getBlock() instanceof BlockFloatingRift); } // Modification functions - public void setVirtualLocation(VirtualLocation virtualLocation) { - this.virtualLocation = virtualLocation; - updateType(); - // TODO: update available link virtual locations - markDirty(); - } public void setRotation(float yaw, float pitch) { this.yaw = yaw; this.pitch = pitch; - preserveRotation = false; markDirty(); } - public void clearRotation() { - preserveRotation = true; - } - - public void addWeightedDestination(WeightedRiftDestination destination) { - destinations.add(destination); + public void setRelativeRotation(boolean relativeRotation) { + this.relativeRotation = relativeRotation; markDirty(); } - public void addDestination(RiftDestination destination, float weight, int group) { - riftStateChanged = true; - destinations.add(new WeightedRiftDestination(destination, weight, group)); - if (isRegistered()) destination.register(this); - markDirty(); - } - - public void addDestination(RiftDestination destination, float weight, int group, RiftDestination oldDestination) { - riftStateChanged = true; - destinations.add(new WeightedRiftDestination(destination, weight, group, oldDestination)); - if (isRegistered()) destination.register(this); - markDirty(); - } - - public void removeDestination(WeightedRiftDestination dest) { - riftStateChanged = true; - destinations.remove(dest); - if (isRegistered()) dest.getDestination().unregister(this); - markDirty(); - } - - public void clearDestinations() { - if (isRegistered()) for (WeightedRiftDestination wdest : destinations) { - wdest.getDestination().unregister(this); + public void setDestination(RiftDestination destination) { + if (this.destination != null) { + this.destination.unregister(new Location(world, pos)); } - destinations.clear(); - markDirty(); - } - - public void setSingleDestination(RiftDestination destination) { - clearDestinations(); - addDestination(destination, 1, 0); - } - - public void setChaosWeight(float chaosWeight) { - this.chaosWeight = chaosWeight; + this.destination = destination; markDirty(); + updateColor(); } public void setColor(RGBA color) { @@ -181,15 +122,9 @@ import java.util.*; markDirty(); } - public void registerAvailableLink(AvailableLink link) { - if (!isRegistered()) return; - RiftRegistry.addAvailableLink(getLocation(), link); - } - - public void addAvailableLink(AvailableLink link) { - availableLinks.add(link); - link.rift = getLocation(); - registerAvailableLink(link); + public void setProperties(LinkProperties properties) { + this.properties = properties; + updateProperties(); markDirty(); } @@ -198,107 +133,65 @@ import java.util.*; markDirty(); } - public void makeDestinationPermanent(WeightedRiftDestination weightedDestination, Location destLoc) { - riftStateChanged = true; - RiftDestination newDest; - if (WorldUtils.getDim(world) == destLoc.getDim()) { - newDest = new LocalDestination(destLoc.getPos()); // TODO: RelativeDestination instead? - } else { - newDest = new GlobalDestination(destLoc); - } - removeDestination(weightedDestination); - addDestination(newDest, weightedDestination.getWeight(), weightedDestination.getGroup(), weightedDestination.getDestination()); - markDirty(); - } + // Registry TODO: merge most of these into one single updateRegistry() method - // Registry public boolean isRegistered() { - return world != null && RiftRegistry.getRiftInfo(new Location(world, pos)) != null; + return RiftRegistry.instance().isRiftAt(new Location(world, pos)); } public void register() { if (isRegistered()) return; Location loc = new Location(world, pos); - RiftRegistry.addRift(loc); - RiftRegistry.getRiftInfo(loc).virtualLocation = virtualLocation; - for (WeightedRiftDestination weightedDest : destinations) { - weightedDest.getDestination().register(this); - } - for (AvailableLink link : availableLinks) { - registerAvailableLink(link); - } + RiftRegistry.instance().addRift(loc); + destination.register(new Location(world, pos)); + updateProperties(); updateColor(); } + public void updateProperties() { + if (isRegistered()) RiftRegistry.instance().setProperties(new Location(world, pos), properties); + markDirty(); + } + public void unregister() { - if (!isRegistered()) return; - RiftRegistry.removeRift(new Location(world, pos)); // TODO: unregister destinations - if (ModDimensions.isDimDoorsPocketDimension(world)) { - PocketRegistry pocketRegistry = PocketRegistry.getForDim(WorldUtils.getDim(world)); - Pocket pocket = pocketRegistry.getPocketAt(pos); - if (pocket != null && pocket.getEntrance() != null && pocket.getEntrance().getPos().equals(pos)) { - pocket.setEntrance(null); - pocketRegistry.markDirty(); - } + if (isRegistered()) { + RiftRegistry.instance().removeRift(new Location(world, pos)); } - // TODO: inform pocket that entrances was destroyed (we'll probably need an isPrivate field on the pocket) } public void updateType() { if (!isRegistered()) return; - RiftRegistry.getRiftInfo(getLocation()).isEntrance = !isFloating(); - RiftRegistry.getForDim(getLocation().getDim()).markDirty(); + Rift rift = RiftRegistry.instance().getRift(new Location(world, pos)); + rift.isFloating = isFloating(); + rift.markDirty(); } - public void destinationGone(Location loc) { - ListIterator<WeightedRiftDestination> wdestIterator = destinations.listIterator(); - while (wdestIterator.hasNext()) { - WeightedRiftDestination wdest = wdestIterator.next(); - RiftDestination dest = wdest.getDestination(); - if (loc.equals(dest.getReferencedRift(getLocation()))) { - wdestIterator.remove(); // TODO: unregister* - RiftDestination oldDest = wdest.getOldDestination(); - if (oldDest != null) { - wdestIterator.add(new WeightedRiftDestination(oldDest, wdest.getWeight(), wdest.getGroup())); - if (isRegistered()) oldDest.register(this); - } - } - } - destinations.removeIf(weightedRiftDestination -> loc.equals(weightedRiftDestination.getDestination().getReferencedRift(getLocation()))); - markDirty(); + public void targetGone(Location loc) { + if (!destination.keepAfterTargetGone(loc)) setDestination(null); + updateColor(); + } + + public void sourceGone(Location loc) { + updateColor(); } // Teleport logic public boolean teleport(Entity entity) { riftStateChanged = false; - // Check that the rift has destinations - if (destinations.size() == 0) { - DimDoors.chat(entity, "This rift has no destinations!"); + // Check that the rift has as destination + if (destination == null) { + DimDoors.chat(entity, "This rift has no destination!"); return false; } - // Get a random destination based on the weights - Map<WeightedRiftDestination, Float> weightMap = new HashMap<>(); // TODO: cache this, faster implementation of single rift - for (WeightedRiftDestination destination : destinations) { - weightMap.put(destination, destination.getWeight()); - } - WeightedRiftDestination weightedDestination = MathUtils.weightedRandom(weightMap); - - // Remove destinations from other groups if makeDestinationPermanent is true - if(makeDestinationPermanent) { - destinations.removeIf(wdest -> wdest.getGroup() != weightedDestination.getGroup()); - markDirty(); - } - // Attempt a teleport try { - if (weightedDestination.getDestination().teleport(this, entity)) { - // Set last used rift if necessary - // TODO: What about player-owned entities? We should store their exit rift separately to avoid having problems if they enter different rifts - // TODO: use entity UUID rather than player UUID! - if (entity instanceof EntityPlayer && !ModDimensions.isDimDoorsPocketDimension(WorldUtils.getDim(world))) { - RiftRegistry.setOverworldRift(EntityUtils.getEntityOwnerUUID(entity), new Location(world, pos)); + if (destination.teleport(new RotatedLocation(new Location(world, pos), yaw, pitch), entity)) { + // Set last used rift for players (don't set for other entities to avoid filling the registry too much) + // TODO: it should maybe be set for some non-player entities too + if (!ModDimensions.isDimDoorsPocketDimension(WorldUtils.getDim(world)) && entity instanceof EntityPlayer) { + RiftRegistry.instance().setOverworldRift(entity.getUniqueID(), new Location(world, pos)); } return true; } @@ -309,45 +202,30 @@ import java.util.*; return false; } - public void teleportTo(Entity entity) { // TODO: new velocity angle if !preserveRotation? - float newYaw = entity.rotationYaw; - float newPitch = entity.rotationYaw; - if (!preserveRotation) { - newYaw = yaw; - newPitch = pitch; + public void teleportTo(Entity entity, float fromYaw, float fromPitch) { + if (relativeRotation) { + TeleportUtils.teleport(entity, new Location(world, pos), yaw + entity.rotationYaw - fromYaw, pitch + entity.rotationPitch - fromPitch); + } else { + TeleportUtils.teleport(entity, new Location(world, pos), yaw, pitch); } - TeleportUtils.teleport(entity, new Location(world, pos), newYaw, newPitch); } - public void updateColor() { // TODO: have the registry call this method too + public void teleportTo(Entity entity) { + TeleportUtils.teleport(entity, new Location(world, pos), yaw, pitch); + } + + public void updateColor() { + if (forcedColor) return; if (!isRegistered()) { color = new RGBA(0, 0, 0, 1); - return; - } - if (destinations.size() == 0) { + } else if (destination == null) { color = new RGBA(0.7f, 0.7f, 0.7f, 1); - return; - } - boolean safe = true; - for (WeightedRiftDestination weightedDestination : destinations) { - boolean destSafe = false; - RiftDestination destination = weightedDestination.getDestination(); - if (destination instanceof PrivateDestination - || destination instanceof PocketExitDestination - || destination instanceof PrivatePocketExitDestination) destSafe = true; - - if (!destSafe && destination.getReferencedRift(getLocation()) != null) { - RiftRegistry.RiftInfo riftInfo = RiftRegistry.getRiftInfo(destination.getReferencedRift(getLocation())); - destSafe = riftInfo != null - && riftInfo.destinations.size() == 1 - && riftInfo.destinations.iterator().next().equals(getLocation()); - } - safe &= destSafe; - } - if (safe) { - color = new RGBA(0, 1, 0, 1); } else { - color = new RGBA(1, 0, 0, 1); + RGBA newColor = destination.getColor(new Location(world, pos)); + if (!color.equals(newColor)) { + color = newColor; + markDirty(); + } } } @@ -358,25 +236,5 @@ import java.util.*; } // Info - protected abstract boolean isFloating(); // TODO: make non-abstract? - - public Location getLocation() { - return new Location(world, pos); - } - - public WeightedRiftDestination getDestination(UUID id) { - for (WeightedRiftDestination wdest : destinations) { - if (wdest.getId().equals(id)) { - return wdest; - } - } - return null; - } - - public AvailableLink getAvailableLink(UUID linkId) { - for (AvailableLink link : availableLinks) { - if (link.id.equals(linkId)) return link; - } - return null; - } + protected abstract boolean isFloating(); } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/WeightedRiftDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/WeightedRiftDestination.java deleted file mode 100644 index 926f8286..00000000 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/WeightedRiftDestination.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.dimdev.dimdoors.shared.rifts; - -import lombok.AllArgsConstructor; -import org.dimdev.ddutils.nbt.INBTStorable; -import lombok.Getter; -import net.minecraft.nbt.NBTTagCompound; - -import java.util.UUID; - -public class WeightedRiftDestination implements INBTStorable { // TODO: generics - @Getter private RiftDestination destination; - @Getter private float weight; - @Getter private int group; - @Getter private RiftDestination oldDestination; // TODO: move to RiftDestination? - @Getter private UUID id; - - public WeightedRiftDestination() { - id = UUID.randomUUID(); - } - - public WeightedRiftDestination(RiftDestination destination, float weight, int group, RiftDestination oldDestination) { - this(); - this.destination = destination; - this.weight = weight; - this.group = group; - this.oldDestination = oldDestination; - if (destination != null) destination.weightedDestination = this; - if (oldDestination != null) oldDestination.weightedDestination = this; - } - - public WeightedRiftDestination(RiftDestination destination, float weight, int group, RiftDestination oldDestination, UUID id) { - this(destination, weight, group, oldDestination); - this.id = id; - } - - public WeightedRiftDestination(RiftDestination destination, float weight, int group) { - this(destination, weight, group, null); - } - - @Override - public void readFromNBT(NBTTagCompound nbt) { - destination = RiftDestination.readDestinationNBT(nbt); // TODO: subtag? - weight = nbt.getFloat("weight"); - group = nbt.getInteger("group"); - if (nbt.hasKey("oldDestination")) oldDestination = RiftDestination.readDestinationNBT(nbt.getCompoundTag("oldDestination")); - if (destination != null) destination.weightedDestination = this; - if (oldDestination != null) oldDestination.weightedDestination = this; - } - - @Override - public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt = destination.writeToNBT(nbt); - nbt.setFloat("weight", weight); - nbt.setInteger("group", group); - if (oldDestination != null) nbt.setTag("oldDestination", oldDestination.writeToNBT(new NBTTagCompound())); - return nbt; - } -} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/AvailableLinkDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/AvailableLinkDestination.java index adf0ad49..69c03975 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/AvailableLinkDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/AvailableLinkDestination.java @@ -11,6 +11,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.dimdev.annotatednbt.NBTSerializable; import org.dimdev.annotatednbt.Saved; +import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.ddutils.WorldUtils; import org.dimdev.ddutils.math.MathUtils; import org.dimdev.ddutils.nbt.NBTUtils; @@ -18,10 +20,10 @@ import org.dimdev.dimdoors.shared.VirtualLocation; import org.dimdev.dimdoors.shared.blocks.ModBlocks; import org.dimdev.dimdoors.shared.pockets.Pocket; import org.dimdev.dimdoors.shared.pockets.PocketGenerator; -import org.dimdev.dimdoors.shared.rifts.AvailableLink; -import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.RiftRegistry; -import org.dimdev.dimdoors.shared.rifts.TileEntityRift; +import org.dimdev.dimdoors.shared.rifts.*; +import org.dimdev.dimdoors.shared.rifts.registry.LinkProperties; +import org.dimdev.dimdoors.shared.rifts.registry.Rift; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; import org.dimdev.dimdoors.shared.tileentities.TileEntityFloatingRift; import java.util.HashMap; @@ -30,7 +32,7 @@ import java.util.Set; import java.util.UUID; @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString -@NBTSerializable public class AvailableLinkDestination extends RiftDestination { // TODO: increase link count on unregister +@NBTSerializable public class AvailableLinkDestination extends RiftDestination { @Saved protected float newRiftWeight; @Saved protected double weightMaximum; @Saved protected double coordFactor; @@ -39,7 +41,7 @@ import java.util.UUID; @Saved protected Set<Integer> acceptedGroups; // TODO: this should be immutable @Saved protected boolean noLink; @Builder.Default @Saved protected boolean noLinkBack; - @Builder.Default @Saved protected UUID linkId = UUID.randomUUID(); + // TODO: better depth calculation public AvailableLinkDestination() {} @@ -47,25 +49,23 @@ import java.util.UUID; @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return NBTUtils.writeToNBT(this, nbt); } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { - if (rift.getVirtualLocation() == null) return false; - AvailableLink thisLink = rift.getAvailableLink(linkId); - thisLink.linksRemaining--; - RiftRegistry.getRegistry(rift.getLocation()).markDirty(); - Map<AvailableLink, Float> possibleDestWeightMap = new HashMap<>(); - if (newRiftWeight > 0) possibleDestWeightMap.put(null, newRiftWeight); + public boolean teleport(RotatedLocation location, Entity entity) { + VirtualLocation virtualLocationHere = VirtualLocation.fromLocation(location.getLocation()); - for (AvailableLink link : RiftRegistry.getAvailableLinks()) { - RiftRegistry.RiftInfo otherRift = RiftRegistry.getRiftInfo(link.rift); - double otherWeight = otherRift.isEntrance ? link.entranceWeight : link.floatingWeight; - if (otherWeight == 0 || Sets.intersection(acceptedGroups, link.groups).isEmpty()) continue; + Map<Location, Float> riftWeights = new HashMap<>(); + if (newRiftWeight > 0) riftWeights.put(null, newRiftWeight); + + for (Rift otherRift : RiftRegistry.instance().getRifts()) { + VirtualLocation otherVirtualLocation = VirtualLocation.fromLocation(otherRift.location); + double otherWeight = otherRift.isFloating ? otherRift.properties.floatingWeight : otherRift.properties.entranceWeight; + if (otherWeight == 0 || Sets.intersection(acceptedGroups, otherRift.properties.groups).isEmpty()) continue; // Calculate the distance as sqrt((coordFactor * coordDistance)^2 + (depthFactor * depthDifference)^2) - if (otherRift.virtualLocation == null || link.linksRemaining == 0) continue; - double depthDifference = otherRift.virtualLocation.getDepth() - rift.getVirtualLocation().getDepth(); - double coordDistance = Math.sqrt(sq(rift.getVirtualLocation().getX() - otherRift.virtualLocation.getX()) - + sq(rift.getVirtualLocation().getZ() - otherRift.virtualLocation.getZ())); - double depthFactor = depthDifference > 0 ? positiveDepthFactor : negativeDepthFactor; // TODO: (|depthDiff| - depthFavor * depthDiff)? + if (otherVirtualLocation == null || otherRift.properties.linksRemaining == 0) continue; + double depthDifference = otherVirtualLocation.getDepth() - virtualLocationHere.getDepth(); + double coordDistance = Math.sqrt(sq(otherVirtualLocation.getX() - virtualLocationHere.getX()) + + sq(otherVirtualLocation.getZ() - virtualLocationHere.getZ())); + double depthFactor = depthDifference > 0 ? positiveDepthFactor : negativeDepthFactor; double distance = sq(coordFactor * coordDistance) + sq(depthFactor * depthDifference); // Calculate the weight as 4m/pi w/(m^2/d + d)^2. This is similar to how gravitational/electromagnetic attraction @@ -77,18 +77,18 @@ import java.util.UUID; // of 1 is equivalent to having a total link weight of 1 distributed equally across all layers. // TODO: We might want an a larger than 1 to make the function closer to 1/d^2 double weight = 4 * weightMaximum / Math.PI * otherWeight / sq(sq(weightMaximum) / distance + distance); - possibleDestWeightMap.put(link, (float) weight); + riftWeights.put(otherRift.location, (float) weight); } - AvailableLink selectedLink; - if (possibleDestWeightMap.size() == 0) { + Location selectedLink; + if (riftWeights.size() == 0) { if (newRiftWeight == -1) { selectedLink = null; } else { return false; } } else { - selectedLink = MathUtils.weightedRandom(possibleDestWeightMap); + selectedLink = MathUtils.weightedRandom(riftWeights); } // Check if we have to generate a new rift @@ -121,10 +121,10 @@ import java.util.UUID; depth /= depth > 0 ? positiveDepthFactor : negativeDepthFactor; double x = Math.cos(theta) * Math.cos(phi) * distance / coordFactor; double z = Math.cos(theta) * Math.sin(phi) * distance / coordFactor; - VirtualLocation virtualLocation = new VirtualLocation(rift.getVirtualLocation().getDim(), - rift.getVirtualLocation().getX() + (int) Math.round(x), - rift.getVirtualLocation().getZ() + (int) Math.round(z), - rift.getVirtualLocation().getDepth() + (int) Math.round(depth)); + VirtualLocation virtualLocation = new VirtualLocation(virtualLocationHere.getDim(), + virtualLocationHere.getX() + (int) Math.round(x), + virtualLocationHere.getZ() + (int) Math.round(z), + virtualLocationHere.getDepth() + (int) Math.round(depth)); if (virtualLocation.getDepth() <= 0) { // This will lead to the overworld @@ -132,43 +132,51 @@ import java.util.UUID; BlockPos pos = world.getTopSolidOrLiquidBlock(new BlockPos(virtualLocation.getX(), 0, virtualLocation.getZ())); world.setBlockState(pos, ModBlocks.RIFT.getDefaultState()); + TileEntityRift thisRift = (TileEntityRift) location.getLocation().getTileEntity(); TileEntityFloatingRift riftEntity = (TileEntityFloatingRift) world.getTileEntity(pos); // TODO: Should the rift not be configured like the other link - rift.markDirty(); - AvailableLink newLink = thisLink.toBuilder().linksRemaining(0).id(UUID.randomUUID()).build(); - riftEntity.addAvailableLink(newLink); - if (!noLinkBack) riftEntity.addDestination(new GlobalDestination(rift.getLocation()), 1, 0, toBuilder().linkId(newLink.id).build()); - if (!noLink) rift.makeDestinationPermanent(weightedDestination, riftEntity.getLocation()); - riftEntity.teleportTo(entity); + riftEntity.setProperties(thisRift.getProperties().toBuilder().linksRemaining(1).id(UUID.randomUUID()).build()); + + if (!noLinkBack && !riftEntity.getProperties().oneWay) linkRifts(selectedLink, location.getLocation()); + if (!noLink) linkRifts(location.getLocation(), selectedLink); + riftEntity.teleportTo(entity, thisRift.getYaw(), thisRift.getPitch()); } else { // Make a new dungeon pocket //Pocket pocket = PocketGenerator.generateDungeonPocket(virtualLocation); Pocket pocket = PocketGenerator.generatePublicPocket(virtualLocation); pocket.setup(); - rift.markDirty(); - AvailableLink newLink = thisLink.toBuilder().linksRemaining(0).build(); - pocket.linkPocketTo(new GlobalDestination(/*noLinkBack ? null :*/ rift.getLocation()), toBuilder().linkId(newLink.id).build(), newLink); // TODO: linkId - if (!noLink) rift.makeDestinationPermanent(weightedDestination, pocket.getEntrance()); - ((TileEntityRift) pocket.getEntrance().getTileEntity()).teleportTo(entity); + + // Link the pocket back + TileEntityRift thisRift = (TileEntityRift) location.getLocation().getTileEntity(); + TileEntityRift riftEntity = (TileEntityRift) pocket.getEntrance().getTileEntity(); + LinkProperties newLink = thisRift.getProperties().toBuilder().linksRemaining(0).id(UUID.randomUUID()).build(); + pocket.linkPocketTo(new GlobalDestination(!noLinkBack && !riftEntity.getProperties().oneWay ? location.getLocation() : null), newLink); // TODO: linkId + + // Link the rift if necessary and teleport the entity + if (!noLink) linkRifts(location.getLocation(), selectedLink); + ((TileEntityRift) pocket.getEntrance().getTileEntity()).teleportTo(entity, location.getYaw(), location.getPitch()); } } else { // An existing rift was selected - TileEntityRift riftEntity = (TileEntityRift) selectedLink.rift.getTileEntity(); + TileEntityRift riftEntity = (TileEntityRift) selectedLink.getTileEntity(); - selectedLink.linksRemaining--; - RiftRegistry.getRegistry(riftEntity.getLocation()).markDirty(); - - // Link the selected rift back if necessary - if (selectedLink.replaceDestination != null) { - riftEntity.makeDestinationPermanent(riftEntity.getDestination(selectedLink.replaceDestination), rift.getLocation()); - } - - // Link this rift if necessary and teleport the entity - if (!noLink) rift.makeDestinationPermanent(weightedDestination, selectedLink.rift); - riftEntity.teleportTo(entity); + // Link the rifts if necessary and teleport the entity + if (!noLink) linkRifts(location.getLocation(), selectedLink); + if (!noLinkBack && !riftEntity.getProperties().oneWay) linkRifts(selectedLink, location.getLocation()); + riftEntity.teleportTo(entity, location.getYaw(), location.getPitch()); } return true; } + private static void linkRifts(Location from, Location to) { + TileEntityRift tileEntityFrom = (TileEntityRift) from.getTileEntity(); + TileEntityRift tileEntityTo = (TileEntityRift) to.getTileEntity(); + tileEntityFrom.setDestination(new GlobalDestination(to)); // TODO: local if possible + tileEntityTo.getProperties().linksRemaining--; + tileEntityTo.updateProperties(); + tileEntityFrom.markDirty(); + tileEntityTo.markDirty(); + } + private double sq(double a) { return a * a; } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/EscapeDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/EscapeDestination.java index 3671a364..02639dda 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/EscapeDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/EscapeDestination.java @@ -1,8 +1,9 @@ package org.dimdev.dimdoors.shared.rifts.destinations; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.dimdoors.DimDoors; import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.RiftRegistry; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; import org.dimdev.dimdoors.shared.rifts.TileEntityRift; import org.dimdev.dimdoors.shared.world.ModDimensions; import org.dimdev.dimdoors.shared.world.limbodimension.WorldProviderLimbo; @@ -15,6 +16,8 @@ import lombok.ToString; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; +import java.util.UUID; + @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString public class EscapeDestination extends RiftDestination { //public EscapeDestination() {} @@ -31,14 +34,14 @@ public class EscapeDestination extends RiftDestination { } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { + public boolean teleport(RotatedLocation loc, Entity entity) { if (!ModDimensions.isDimDoorsPocketDimension(entity.world)) { DimDoors.chat(entity, "Can't escape from a non-pocket dimension!"); return false; } - String uuid = entity.getCachedUniqueIdString(); + UUID uuid = entity.getUniqueID(); if (uuid != null) { - Location destLoc = RiftRegistry.getOverworldRift(uuid); + Location destLoc = RiftRegistry.instance().getOverworldRift(uuid); if (destLoc != null && destLoc.getTileEntity() instanceof TileEntityRift) { //TeleportUtils.teleport(entity, new VirtualLocation(destLoc, rift.virtualLocation.getDepth()).projectToWorld()); // TODO // TODO diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/GlobalDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/GlobalDestination.java index 6dfd5e2a..1f78e912 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/GlobalDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/GlobalDestination.java @@ -7,6 +7,7 @@ import lombok.Getter; import lombok.ToString; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.ddutils.nbt.NBTUtils; import org.dimdev.annotatednbt.Saved; import org.dimdev.annotatednbt.NBTSerializable; @@ -15,7 +16,7 @@ import org.dimdev.dimdoors.shared.rifts.TileEntityRift; @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString @NBTSerializable public class GlobalDestination extends RiftDestination { // TODO: location directly in nbt like minecraft? - @Saved @Getter protected Location loc; + @Saved protected Location loc; public GlobalDestination() {} @@ -23,13 +24,13 @@ import org.dimdev.dimdoors.shared.rifts.TileEntityRift; @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return NBTUtils.writeToNBT(this, nbt); } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { - ((TileEntityRift) loc.getTileEntity()).teleportTo(entity); + public boolean teleport(RotatedLocation loc, Entity entity) { + ((TileEntityRift) this.loc.getTileEntity()).teleportTo(entity, loc.getYaw(), loc.getPitch()); return true; } @Override - public Location getReferencedRift(Location rift) { + public Location getFixedTarget(Location location) { return loc; } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LimboDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LimboDestination.java index 59f3c888..63087fa9 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LimboDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LimboDestination.java @@ -1,7 +1,7 @@ package org.dimdev.dimdoors.shared.rifts.destinations; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.TileEntityRift; import org.dimdev.dimdoors.shared.world.limbodimension.WorldProviderLimbo; import org.dimdev.ddutils.TeleportUtils; import lombok.AllArgsConstructor; @@ -27,7 +27,7 @@ public class LimboDestination extends RiftDestination { } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { + public boolean teleport(RotatedLocation loc, Entity entity) { TeleportUtils.teleport(entity, WorldProviderLimbo.getLimboSkySpawn(entity)); // TODO: do we really want to spam Limbo with items? return false; } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LinkingDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LinkingDestination.java new file mode 100644 index 00000000..c5bd250d --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LinkingDestination.java @@ -0,0 +1,60 @@ +package org.dimdev.dimdoors.shared.rifts.destinations; + +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.RGBA; +import org.dimdev.ddutils.RotatedLocation; +import org.dimdev.dimdoors.shared.rifts.RiftDestination; + +public abstract class LinkingDestination extends RiftDestination { + + private RiftDestination wrappedDestination; + + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return nbt; } + + @Override + public boolean teleport(RotatedLocation loc, Entity entity) { + if (wrappedDestination != null) wrappedDestination.teleport(loc, entity); + + Location linkTarget = makeLinkTarget(loc, entity); + if (linkTarget != null) { + wrappedDestination = new GlobalDestination(); + wrappedDestination.register(loc.getLocation()); + + wrappedDestination.teleport(loc, entity); + return true; + } else { + return false; + } + } + + @Override + public boolean keepAfterTargetGone(Location location) { + if (!wrappedDestination.keepAfterTargetGone(location)) { + wrappedDestination.unregister(location); + } + return true; + } + + @Override + public void unregister(Location location) { + if (wrappedDestination != null) wrappedDestination.unregister(location); + } + + @Override + public RGBA getColor(Location location) { + if (wrappedDestination != null) { + return wrappedDestination.getColor(location); + } else { + return getUnlinkedColor(location); + } + } + + protected RGBA getUnlinkedColor(Location location) { + return new RGBA(0, 1, 1, 1); + } + + public abstract Location makeLinkTarget(RotatedLocation rift, Entity entity); +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LocalDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LocalDestination.java index e4c59a43..9a294c24 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LocalDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/LocalDestination.java @@ -1,6 +1,7 @@ package org.dimdev.dimdoors.shared.rifts.destinations; import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.ddutils.nbt.NBTUtils; import lombok.AllArgsConstructor; import lombok.Builder; @@ -24,13 +25,13 @@ import org.dimdev.dimdoors.shared.rifts.TileEntityRift; @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return NBTUtils.writeToNBT(this, nbt); } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { - ((TileEntityRift) rift.getWorld().getTileEntity(pos)).teleportTo(entity); + public boolean teleport(RotatedLocation loc, Entity entity) { + ((TileEntityRift) loc.getLocation().getWorld().getTileEntity(pos)).teleportTo(entity, loc.getYaw(), loc.getPitch()); return true; } @Override - public Location getReferencedRift(Location rift) { - return new Location(rift.getDim(), pos); + public Location getFixedTarget(Location location) { + return new Location(location.getDim(), pos); } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/NewPublicDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/NewPublicDestination.java deleted file mode 100644 index ea775301..00000000 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/NewPublicDestination.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.dimdev.dimdoors.shared.rifts.destinations; - -import org.dimdev.dimdoors.shared.VirtualLocation; -import org.dimdev.dimdoors.shared.pockets.Pocket; -import org.dimdev.dimdoors.shared.pockets.PocketGenerator; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.ToString; -import net.minecraft.entity.Entity; -import net.minecraft.nbt.NBTTagCompound; -import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.TileEntityRift; - -@Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString -public class NewPublicDestination extends RiftDestination { // TODO: more config options such as non-default size, etc. - //public NewPublicDestination() {} - - @Override - public void readFromNBT(NBTTagCompound nbt) { - super.readFromNBT(nbt); - } - - @Override - public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt = super.writeToNBT(nbt); - return nbt; - } - - @Override - public boolean teleport(TileEntityRift rift, Entity entity) { - VirtualLocation newVirtualLocation = null; - if (rift.getVirtualLocation() != null) { - int depth = rift.getVirtualLocation().getDepth(); - if (depth == 0) depth++; - newVirtualLocation = rift.getVirtualLocation().toBuilder().depth(depth).build(); - } - Pocket pocket = PocketGenerator.generatePublicPocket(newVirtualLocation); - pocket.setup(); - pocket.linkPocketTo(new GlobalDestination(rift.getLocation()), null, null); - rift.makeDestinationPermanent(weightedDestination, pocket.getEntrance()); - ((TileEntityRift) pocket.getEntrance().getTileEntity()).teleportTo(entity); - return true; - } -} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketEntranceDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketEntranceDestination.java index 0a48188b..a14fcab2 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketEntranceDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketEntranceDestination.java @@ -1,5 +1,6 @@ package org.dimdev.dimdoors.shared.rifts.destinations; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.ddutils.nbt.NBTUtils; import org.dimdev.annotatednbt.Saved; import org.dimdev.annotatednbt.NBTSerializable; @@ -12,17 +13,13 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.TileEntityRift; -import org.dimdev.dimdoors.shared.rifts.WeightedRiftDestination; - -import java.util.LinkedList; -import java.util.List; @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString -@NBTSerializable public class PocketEntranceDestination extends RiftDestination { - @Saved protected float weight; - @Saved @SuppressWarnings({"UnusedAssignment", "RedundantSuppression"}) @Builder.Default protected List<WeightedRiftDestination> ifDestinations = new LinkedList<>(); // TODO addIfDestination method in builder - @Saved @SuppressWarnings({"UnusedAssignment", "RedundantSuppression"}) @Builder.Default protected List<WeightedRiftDestination> otherwiseDestinations = new LinkedList<>(); // TODO addOtherwiseDestination method in builder +@NBTSerializable public class PocketEntranceDestination extends RiftDestination { // TODO: not exactly a destination + @Builder.Default @Saved protected float weight = 1; + @Saved protected RiftDestination ifDestination; + @Saved protected RiftDestination otherwiseDestination; + @Saved boolean hasBeenChosen; public PocketEntranceDestination() {} @@ -30,7 +27,7 @@ import java.util.List; @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return NBTUtils.writeToNBT(this, nbt); } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { + public boolean teleport(RotatedLocation loc, Entity entity) { if (entity instanceof EntityPlayer) DimDoors.chat(entity, "The entrances of this dungeon has not been linked. Either this is a bug or you are in dungeon-building mode."); return false; } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketExitDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketExitDestination.java index 2b562cb2..ed78973e 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketExitDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PocketExitDestination.java @@ -1,5 +1,6 @@ package org.dimdev.dimdoors.shared.rifts.destinations; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.dimdoors.DimDoors; import lombok.AllArgsConstructor; import lombok.Builder; @@ -9,10 +10,9 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.TileEntityRift; @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString -public class PocketExitDestination extends RiftDestination { +public class PocketExitDestination extends RiftDestination { // TODO: not exactly a destination //public PocketExitDestination() {} @Override @@ -27,7 +27,7 @@ public class PocketExitDestination extends RiftDestination { } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { + public boolean teleport(RotatedLocation loc, Entity entity) { if (entity instanceof EntityPlayer) DimDoors.chat(entity, "The exit of this dungeon has not been linked. Either this is a bug or you are in dungeon-building mode."); return false; } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivateDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivateDestination.java index 2cb17602..8b9972ef 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivateDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivateDestination.java @@ -1,11 +1,14 @@ package org.dimdev.dimdoors.shared.rifts.destinations; +import org.dimdev.ddutils.RGBA; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.dimdoors.DimDoors; +import org.dimdev.dimdoors.shared.VirtualLocation; import org.dimdev.dimdoors.shared.pockets.Pocket; import org.dimdev.dimdoors.shared.pockets.PocketGenerator; import org.dimdev.dimdoors.shared.pockets.PocketRegistry; import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.RiftRegistry; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; import org.dimdev.dimdoors.shared.rifts.TileEntityRift; import org.dimdev.dimdoors.shared.world.ModDimensions; import org.dimdev.ddutils.EntityUtils; @@ -17,51 +20,51 @@ import lombok.ToString; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; +import java.util.UUID; + @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString public class PrivateDestination extends RiftDestination { //public PrivateDestination() {} - @Override - public void readFromNBT(NBTTagCompound nbt) { - super.readFromNBT(nbt); - } + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return nbt; } @Override - public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - nbt = super.writeToNBT(nbt); - return nbt; - } - - @Override - public boolean teleport(TileEntityRift rift, Entity entity) { - String uuid = EntityUtils.getEntityOwnerUUID(entity); + public boolean teleport(RotatedLocation loc, Entity entity) { + UUID uuid = EntityUtils.getEntityOwnerUUID(entity); + VirtualLocation virtualLocation = VirtualLocation.fromLocation(loc.getLocation()); if (uuid != null) { - PocketRegistry privatePocketRegistry = PocketRegistry.getForDim(ModDimensions.getPrivateDim()); - RiftRegistry privateRiftRegistry = RiftRegistry.getForDim(ModDimensions.getPrivateDim()); + PocketRegistry privatePocketRegistry = PocketRegistry.instance(ModDimensions.getPrivateDim()); Pocket pocket = privatePocketRegistry.getPocket(privatePocketRegistry.getPrivatePocketID(uuid)); if (pocket == null) { // generate the private pocket and get its entrances - pocket = PocketGenerator.generatePrivatePocket(rift.getVirtualLocation() != null ? rift.getVirtualLocation().toBuilder().depth(-1).build() : null); // set to where the pocket was first created + // set to where the pocket was first created + pocket = PocketGenerator.generatePrivatePocket(virtualLocation != null ? virtualLocation.toBuilder().depth(-1).build() : null); pocket.setup(); privatePocketRegistry.setPrivatePocketID(uuid, pocket.getId()); - ((TileEntityRift) pocket.getEntrance().getTileEntity()).teleportTo(entity); - privateRiftRegistry.setPrivatePocketExit(uuid, rift.getLocation()); + ((TileEntityRift) pocket.getEntrance().getTileEntity()).teleportTo(entity, loc.getYaw(), loc.getPitch()); + RiftRegistry.instance().setLastPrivatePocketExit(uuid, loc.getLocation()); return true; } else { - Location destLoc = privateRiftRegistry.getPrivatePocketEntrance(uuid); // get the last used entrances + Location destLoc = RiftRegistry.instance().getPrivatePocketEntrance(uuid); // get the last used entrances if (destLoc == null) destLoc = pocket.getEntrance(); // if there's none, then set the target to the main entrances if (destLoc == null) { // if the pocket entrances is gone, then create a new private pocket DimDoors.log.info("All entrances are gone, creating a new private pocket!"); - pocket = PocketGenerator.generatePrivatePocket(rift.getVirtualLocation() != null ? rift.getVirtualLocation().toBuilder().depth(-1).build() : null); + pocket = PocketGenerator.generatePrivatePocket(virtualLocation != null ? virtualLocation.toBuilder().depth(-1).build() : null); pocket.setup(); privatePocketRegistry.setPrivatePocketID(uuid, pocket.getId()); destLoc = pocket.getEntrance(); } - ((TileEntityRift) destLoc.getTileEntity()).teleportTo(entity); - privateRiftRegistry.setPrivatePocketExit(uuid, rift.getLocation()); + ((TileEntityRift) destLoc.getTileEntity()).teleportTo(entity, loc.getYaw(), loc.getPitch()); + RiftRegistry.instance().setLastPrivatePocketExit(uuid, loc.getLocation()); return true; } } else { return false; // TODO: There should be a way to get other entities into your private pocket, though. Add API for other mods. } } + + @Override + public RGBA getColor(Location location) { + return new RGBA(0, 1, 0, 1); + } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivatePocketExitDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivatePocketExitDestination.java index 81043d00..7e7f8a15 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivatePocketExitDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PrivatePocketExitDestination.java @@ -1,26 +1,26 @@ package org.dimdev.dimdoors.shared.rifts.destinations; -import org.dimdev.dimdoors.DimDoors; -import org.dimdev.dimdoors.shared.pockets.Pocket; -import org.dimdev.dimdoors.shared.pockets.PocketRegistry; -import org.dimdev.dimdoors.shared.rifts.RiftDestination; -import org.dimdev.dimdoors.shared.rifts.RiftRegistry; -import org.dimdev.dimdoors.shared.rifts.TileEntityRift; -import org.dimdev.dimdoors.shared.world.ModDimensions; -import org.dimdev.dimdoors.shared.world.limbodimension.WorldProviderLimbo; -import org.dimdev.dimdoors.shared.world.pocketdimension.WorldProviderPersonalPocket; -import org.dimdev.ddutils.EntityUtils; -import org.dimdev.ddutils.Location; -import org.dimdev.ddutils.TeleportUtils; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.ToString; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; +import org.dimdev.ddutils.*; +import org.dimdev.dimdoors.DimDoors; +import org.dimdev.dimdoors.shared.pockets.Pocket; +import org.dimdev.dimdoors.shared.pockets.PocketRegistry; +import org.dimdev.dimdoors.shared.rifts.RiftDestination; +import org.dimdev.dimdoors.shared.rifts.TileEntityRift; +import org.dimdev.dimdoors.shared.rifts.registry.RiftRegistry; +import org.dimdev.dimdoors.shared.world.ModDimensions; +import org.dimdev.dimdoors.shared.world.limbodimension.WorldProviderLimbo; +import org.dimdev.dimdoors.shared.world.pocketdimension.WorldProviderPersonalPocket; + +import java.util.UUID; @Getter @AllArgsConstructor @Builder(toBuilder = true) @ToString -public class PrivatePocketExitDestination extends RiftDestination { // TODO: merge into PocketExit or Escape? +public class PrivatePocketExitDestination extends RiftDestination { //public PrivatePocketExitDestination() {} @Override @@ -35,15 +35,14 @@ public class PrivatePocketExitDestination extends RiftDestination { // TODO: mer } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { + public boolean teleport(RotatedLocation loc, Entity entity) { Location destLoc; - String uuid = EntityUtils.getEntityOwnerUUID(entity); + UUID uuid = EntityUtils.getEntityOwnerUUID(entity); if (uuid != null) { - PocketRegistry privatePocketRegistry = PocketRegistry.getForDim(ModDimensions.getPrivateDim()); - RiftRegistry privateRiftRegistry = RiftRegistry.getForDim(ModDimensions.getPrivateDim()); - destLoc = privateRiftRegistry.getPrivatePocketExit(uuid); - if (rift.getWorld().provider instanceof WorldProviderPersonalPocket && privatePocketRegistry.getPrivatePocketID(uuid) == privatePocketRegistry.posToID(rift.getPos())) { - privateRiftRegistry.setPrivatePocketEntrance(uuid, rift.getLocation()); // Remember which exit was used for next time the pocket is entered + PocketRegistry privatePocketRegistry = PocketRegistry.instance(ModDimensions.getPrivateDim()); + destLoc = RiftRegistry.instance().getPrivatePocketExit(uuid); + if (loc.getLocation().getWorld().provider instanceof WorldProviderPersonalPocket && privatePocketRegistry.getPrivatePocketID(uuid) == privatePocketRegistry.posToID(loc.getLocation().getPos())) { + RiftRegistry.instance().setLastPrivatePocketEntrance(uuid, loc.getLocation()); // Remember which exit was used for next time the pocket is entered } if (destLoc == null || !(destLoc.getTileEntity() instanceof TileEntityRift)) { if (destLoc == null) { @@ -54,7 +53,7 @@ public class PrivatePocketExitDestination extends RiftDestination { // TODO: mer TeleportUtils.teleport(entity, WorldProviderLimbo.getLimboSkySpawn(entity)); return false; } else { - ((TileEntityRift) destLoc.getTileEntity()).teleportTo(entity); + ((TileEntityRift) destLoc.getTileEntity()).teleportTo(entity, loc.getYaw(), loc.getPitch()); return true; } } else { @@ -63,14 +62,15 @@ public class PrivatePocketExitDestination extends RiftDestination { // TODO: mer } @Override - public void register(TileEntityRift rift) { - PocketRegistry privatePocketRegistry = PocketRegistry.getForDim(rift.getLocation().getDim()); - Pocket pocket = privatePocketRegistry.getPocketAt(rift.getPos()); - String uuid = privatePocketRegistry.getPrivatePocketOwner(pocket.getId()); - if (uuid != null) { - RiftRegistry.getForDim(ModDimensions.getPrivateDim()).addPrivatePocketEntrance(uuid, rift.getLocation()); - } + public void register(Location location) { + super.register(location); + PocketRegistry privatePocketRegistry = PocketRegistry.instance(location.getDim()); + Pocket pocket = privatePocketRegistry.getPocketAt(location.getPos()); + RiftRegistry.instance().addPocketEntrance(pocket, location); } - // TODO: unregister + @Override + public RGBA getColor(Location location) { + return new RGBA(0, 1, 0, 1); + } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PublicPocketDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PublicPocketDestination.java new file mode 100644 index 00000000..b8c0fc9e --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/PublicPocketDestination.java @@ -0,0 +1,33 @@ +package org.dimdev.dimdoors.shared.rifts.destinations; + +import lombok.*; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.RotatedLocation; +import org.dimdev.dimdoors.shared.VirtualLocation; +import org.dimdev.dimdoors.shared.pockets.Pocket; +import org.dimdev.dimdoors.shared.pockets.PocketGenerator; + +@Getter @AllArgsConstructor @NoArgsConstructor @Builder(toBuilder = true) @ToString +public class PublicPocketDestination extends LinkingDestination { + + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return nbt; } + + @Override + public Location makeLinkTarget(RotatedLocation loc, Entity entity) { + VirtualLocation riftVirtualLocation = VirtualLocation.fromLocation(loc.getLocation()); + VirtualLocation newVirtualLocation = null; + if (riftVirtualLocation != null) { + int depth = Math.min(riftVirtualLocation.getDepth(), 1); + newVirtualLocation = riftVirtualLocation.toBuilder().depth(depth).build(); + } + Pocket pocket = PocketGenerator.generatePublicPocket(newVirtualLocation); + pocket.setup(); + + pocket.linkPocketTo(new GlobalDestination(loc.getLocation()), null); + + return pocket.getEntrance(); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/RelativeDestination.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/RelativeDestination.java index 564d5cbb..6976d89b 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/RelativeDestination.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/destinations/RelativeDestination.java @@ -1,6 +1,7 @@ package org.dimdev.dimdoors.shared.rifts.destinations; import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.RotatedLocation; import org.dimdev.ddutils.nbt.NBTUtils; import lombok.AllArgsConstructor; import lombok.Builder; @@ -24,13 +25,13 @@ import org.dimdev.dimdoors.shared.rifts.TileEntityRift; @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt = super.writeToNBT(nbt); return NBTUtils.writeToNBT(this, nbt); } @Override - public boolean teleport(TileEntityRift rift, Entity entity) { - rift.getWorld().getTileEntity(rift.getPos().add(offset)); + public boolean teleport(RotatedLocation loc, Entity entity) { + ((TileEntityRift) loc.getLocation().getWorld().getTileEntity(loc.getLocation().getPos().add(offset))).teleportTo(entity, loc.getPitch(), loc.getYaw()); return true; } @Override - public Location getReferencedRift(Location rift) { - return new Location(rift.getDim(), rift.getPos().add(offset)); + public Location getFixedTarget(Location location) { + return new Location(location.getDim(), location.getPos().add(offset)); } } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/AvailableLink.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/LinkProperties.java similarity index 86% rename from src/main/java/org/dimdev/dimdoors/shared/rifts/AvailableLink.java rename to src/main/java/org/dimdev/dimdoors/shared/rifts/registry/LinkProperties.java index fe90c22f..308f18d4 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/rifts/AvailableLink.java +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/LinkProperties.java @@ -1,4 +1,4 @@ -package org.dimdev.dimdoors.shared.rifts; +package org.dimdev.dimdoors.shared.rifts.registry; import lombok.*; import lombok.experimental.Wither; @@ -14,7 +14,7 @@ import java.util.Set; import java.util.UUID; @NBTSerializable @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode @Builder(toBuilder = true) @ToString -public class AvailableLink implements INBTStorable { +public class LinkProperties implements INBTStorable { @Wither public Location rift; @Saved @Builder.Default public UUID id = UUID.randomUUID(); @@ -23,6 +23,7 @@ public class AvailableLink implements INBTStorable { @Saved @Builder.Default public Set<Integer> groups = new HashSet<>(); @Saved public UUID replaceDestination; @Saved @Builder.Default public int linksRemaining = 1; + @Saved @Builder.Default public boolean oneWay = false; @Override public void readFromNBT(NBTTagCompound nbt) { NBTUtils.readFromNBT(this, nbt); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { return NBTUtils.writeToNBT(this, nbt); } diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PlayerRiftPointer.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PlayerRiftPointer.java new file mode 100644 index 00000000..5ba480c4 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PlayerRiftPointer.java @@ -0,0 +1,13 @@ +package org.dimdev.dimdoors.shared.rifts.registry; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.dimdev.annotatednbt.NBTSerializable; +import org.dimdev.annotatednbt.Saved; + +import java.util.UUID; + +@AllArgsConstructor @NoArgsConstructor +@NBTSerializable public class PlayerRiftPointer extends RegistryVertex { + @Saved public UUID player; +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PocketEntrancePointer.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PocketEntrancePointer.java new file mode 100644 index 00000000..3eac9759 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/PocketEntrancePointer.java @@ -0,0 +1,12 @@ +package org.dimdev.dimdoors.shared.rifts.registry; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.dimdev.annotatednbt.NBTSerializable; +import org.dimdev.annotatednbt.Saved; + +@AllArgsConstructor @NoArgsConstructor @NBTSerializable +public class PocketEntrancePointer extends RegistryVertex { // TODO: PocketRiftPointer superclass? + @Saved public int pocketDim; + @Saved public int pocketId; +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RegistryVertex.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RegistryVertex.java new file mode 100644 index 00000000..f2f823f5 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RegistryVertex.java @@ -0,0 +1,26 @@ +package org.dimdev.dimdoors.shared.rifts.registry; + +import org.dimdev.annotatednbt.Saved; + +import java.util.UUID; + +public abstract class RegistryVertex { + public int dim; // The dimension to store this object in. Links are stored in both registries. + @Saved public UUID id = UUID.randomUUID(); // Used to create pointers to registry vertices. Should not be used for anything other than saving. + + public void sourceGone(RegistryVertex source) { + RiftRegistry.instance().markSubregistryDirty(dim); + } + + public void targetGone(RegistryVertex target) { + RiftRegistry.instance().markSubregistryDirty(dim); + } + + public void sourceAdded(RegistryVertex to) { + RiftRegistry.instance().markSubregistryDirty(dim); + } + + public void targetAdded(RegistryVertex to) { + RiftRegistry.instance().markSubregistryDirty(dim); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/Rift.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/Rift.java new file mode 100644 index 00000000..a18227b7 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/Rift.java @@ -0,0 +1,57 @@ +package org.dimdev.dimdoors.shared.rifts.registry; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.dimdev.annotatednbt.NBTSerializable; +import org.dimdev.annotatednbt.Saved; +import org.dimdev.ddutils.Location; +import org.dimdev.dimdoors.shared.rifts.TileEntityRift; + +@NoArgsConstructor @AllArgsConstructor +@NBTSerializable public class Rift extends RegistryVertex { + public @Saved Location location; + public @Saved boolean isFloating; + public @Saved LinkProperties properties; + // TODO: receiveDungeonLink + + public Rift(Location location) { + this.location = location; + } + + @Override + public void sourceGone(RegistryVertex source) { + super.sourceGone(source); + TileEntityRift riftTileEntity = (TileEntityRift) location.getTileEntity(); + if (source instanceof Rift) { + riftTileEntity.sourceGone(((Rift) source).location); + } + riftTileEntity.updateColor(); + } + + @Override + public void targetGone(RegistryVertex target) { + super.targetGone(target); + TileEntityRift riftTileEntity = (TileEntityRift) location.getTileEntity(); + if (target instanceof Rift) { + riftTileEntity.targetGone(((Rift) target).location); + } + riftTileEntity.updateColor(); + } + + @Override + public void sourceAdded(RegistryVertex source) { + super.sourceAdded(source); + ((TileEntityRift) location.getTileEntity()).updateColor(); + } + + @Override + public void targetAdded(RegistryVertex target) { + super.targetAdded(target); + ((TileEntityRift) location.getTileEntity()).updateColor(); + } + + public void markDirty() { + RiftRegistry.instance().markSubregistryDirty(dim); + ((TileEntityRift) location.getTileEntity()).updateColor(); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftPlaceholder.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftPlaceholder.java new file mode 100644 index 00000000..89c3b307 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftPlaceholder.java @@ -0,0 +1,3 @@ +package org.dimdev.dimdoors.shared.rifts.registry; + +public class RiftPlaceholder extends Rift {} // TODO: don't extend rift diff --git a/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftRegistry.java b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftRegistry.java new file mode 100644 index 00000000..9e53eb1e --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/shared/rifts/registry/RiftRegistry.java @@ -0,0 +1,416 @@ +package org.dimdev.dimdoors.shared.rifts.registry; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.world.storage.MapStorage; +import net.minecraft.world.storage.WorldSavedData; +import net.minecraftforge.common.DimensionManager; +import org.dimdev.ddutils.Location; +import org.dimdev.ddutils.WorldUtils; +import org.dimdev.ddutils.nbt.NBTUtils; +import org.dimdev.dimdoors.DimDoors; +import org.dimdev.dimdoors.ddutils.GraphUtils; +import org.dimdev.dimdoors.shared.pockets.Pocket; +import org.dimdev.dimdoors.shared.pockets.PocketRegistry; +import org.dimdev.dimdoors.shared.world.ModDimensions; +import org.jgrapht.graph.DefaultDirectedGraph; +import org.jgrapht.graph.DefaultEdge; + +import java.util.*; +import java.util.stream.Collectors; + +public class RiftRegistry extends WorldSavedData { + + private static final String DATA_NAME = DimDoors.MODID + "_global_rifts"; // TODO: can we use the same name as subregistries? + private static final String SUBREGISTRY_DATA_NAME = DimDoors.MODID + "_rifts"; + + protected Map<Integer, RiftSubregistry> subregistries = new HashMap<>(); + protected DefaultDirectedGraph<RegistryVertex, DefaultEdge> graph = new DefaultDirectedGraph<>(DefaultEdge.class); + // TODO: add methods that automatically add vertices/edges and mark appropriate subregistries as dirty + + // Caches to avoid looping through vertices to find specific vertices + protected Map<Location, Rift> locationMap = new HashMap<>(); + protected Map<Pocket, PocketEntrancePointer> pocketEntranceMap = new HashMap<>(); // TODO: We're going to want to move all pocket entrance info to the rift registry later to make PocketLib independent of DimDoors. + protected Map<UUID, RegistryVertex> uuidMap = new HashMap<>(); + + // These are stored in the main registry + protected Map<UUID, PlayerRiftPointer> lastPrivatePocketEntrances = new HashMap<>(); // Player UUID -> last rift used to exit pocket + protected Map<UUID, PlayerRiftPointer> lastPrivatePocketExits = new HashMap<>(); // Player UUID -> last rift used to enter pocket + protected Map<UUID, PlayerRiftPointer> overworldRifts = new HashMap<>(); // Player UUID -> rift used to exit the overworld + + // <editor-fold defaultstate="collapsed" desc="Code for reading/writing/getting the registry"> + + public class RiftSubregistry extends WorldSavedData { + private int dim; + + public RiftSubregistry() { + super(SUBREGISTRY_DATA_NAME); + } + + public RiftSubregistry(String s) { + super(s); + } + + @Override public void readFromNBT(NBTTagCompound nbt) { + // Registry is already loaded + if (subregistries.get(dim) != null) return; + + // Read rifts in this dimension + NBTTagList riftsNBT = (NBTTagList) nbt.getTag("rifts"); + for (NBTBase riftNBT : riftsNBT) { + Rift rift = NBTUtils.readFromNBT(new Rift(), (NBTTagCompound) riftNBT); + rift.dim = dim; + graph.addVertex(rift); + uuidMap.put(rift.id, rift); + locationMap.put(rift.location, rift); + } + + NBTTagList pocketsNBT = (NBTTagList) nbt.getTag("pockets"); + for (NBTBase pocketNBT : pocketsNBT) { + PocketEntrancePointer pocket = NBTUtils.readFromNBT(new PocketEntrancePointer(), (NBTTagCompound) pocketNBT); + pocket.dim = dim; + graph.addVertex(pocket); + uuidMap.put(pocket.id, pocket); + pocketEntranceMap.put(PocketRegistry.instance(pocket.dim).getPocket(pocket.pocketId), pocket); + } + + // Read the connections between links that have a source or destination in this dimension + NBTTagList linksNBT = (NBTTagList) nbt.getTag("links"); + for (NBTBase linkNBT : linksNBT) { + RegistryVertex from = uuidMap.get(((NBTTagCompound) linkNBT).getUniqueId("from")); + RegistryVertex to = uuidMap.get(((NBTTagCompound) linkNBT).getUniqueId("to")); + if (from != null && to != null) { + graph.addEdge(from, to); + // We need a system for detecting links that are incomplete after processing them in the other subregistry too + } + } + } + + // Even though it seems like we could loop only once over the vertices and edges (in the RiftRegistry's writeToNBT + // method rather than RiftSubregistry) and save each in the appropriate registry, we can't do this because it is not + // always the case that all worlds will be saved at once. + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + // Write rifts in this dimension + NBTTagList riftsNBT = new NBTTagList(); + NBTTagList pocketsNBT = new NBTTagList(); + for (RegistryVertex vertex : graph.vertexSet()) { + if (vertex.dim == dim) { + NBTTagCompound vertexNBT = NBTUtils.writeToNBT(vertex, new NBTTagCompound()); + if (vertex instanceof Rift) { + riftsNBT.appendTag(vertexNBT); + } else if (vertex instanceof PocketEntrancePointer) { + pocketsNBT.appendTag(vertexNBT); + } else if (!(vertex instanceof PlayerRiftPointer)) { + throw new RuntimeException("Unsupported registry vertex type " + vertex.getClass().getName()); + } + } + } + nbt.setTag("rifts", riftsNBT); + nbt.setTag("pockets", pocketsNBT); + + // Write the connections between links that have a source or destination in this dimension + NBTTagList linksNBT = new NBTTagList(); + for (DefaultEdge edge : graph.edgeSet()) { + RegistryVertex from = graph.getEdgeSource(edge); + RegistryVertex to = graph.getEdgeTarget(edge); + if (from.dim == dim || to.dim == dim && !(from instanceof PlayerRiftPointer)) { + NBTTagCompound linkNBT = new NBTTagCompound(); + linkNBT.setUniqueId("from", from.id); + linkNBT.setUniqueId("to", to.id); + NBTUtils.writeToNBT(edge, linkNBT); // Write in both registries, we might want to notify when there's a missing world later + linksNBT.appendTag(linkNBT); + } + } + nbt.setTag("links", riftsNBT); + + return nbt; + } + } + + public RiftRegistry() { + super(DATA_NAME); + } + + public RiftRegistry(String s) { + super(s); + } + + public static RiftRegistry instance() { + MapStorage storage = WorldUtils.getWorld(0).getMapStorage(); + RiftRegistry instance = (RiftRegistry) storage.getOrLoadData(RiftRegistry.class, DATA_NAME); + + if (instance == null) { + instance = new RiftRegistry(); + storage.setData(DATA_NAME, instance); + } + + return instance; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + // Trigger the subregistry reading code for all dimensions. It would be better if there was some way of forcing + // them to be read from somewhere else, since this is technically more than just reading the NBT. This has to be + // done last since links are only in the subregistries. + // TODO: If non-dirty but new WorldSavedDatas aren't automatically saved, then create the subregistries here + // TODO: rather then in the markSubregistryDirty method. + for (int dim : DimensionManager.getStaticDimensionIDs()) { + MapStorage storage = WorldUtils.getWorld(dim).getPerWorldStorage(); + RiftSubregistry instance = (RiftSubregistry) storage.getOrLoadData(RiftSubregistry.class, SUBREGISTRY_DATA_NAME); + if (instance != null) { + instance.dim = dim; + subregistries.put(dim, instance); + } + } + + // Read player to rift maps (this has to be done after the uuidMap has been filled by the subregistry code) + lastPrivatePocketEntrances = readPlayerRiftPointers((NBTTagList) nbt.getTag("lastPrivatePocketEntrances")); + lastPrivatePocketExits = readPlayerRiftPointers((NBTTagList) nbt.getTag("lastPrivatePocketExits")); + overworldRifts = readPlayerRiftPointers((NBTTagList) nbt.getTag("overworldRifts")); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + // Subregistries are written automatically when the worlds are saved. + nbt.setTag("lastPrivatePocketEntrances", writePlayerRiftPointers(lastPrivatePocketEntrances)); + nbt.setTag("lastPrivatePocketExits", writePlayerRiftPointers(lastPrivatePocketExits)); + nbt.setTag("overworldRifts", writePlayerRiftPointers(overworldRifts)); + return nbt; + } + + private Map<UUID, PlayerRiftPointer> readPlayerRiftPointers(NBTTagList playerRiftPointersNBT) { + Map<UUID, PlayerRiftPointer> pointerMap = new HashMap<>(); + for (NBTBase entryNBT : playerRiftPointersNBT) { + UUID player = ((NBTTagCompound) entryNBT).getUniqueId("player"); + UUID rift = ((NBTTagCompound) entryNBT).getUniqueId("rift"); + PlayerRiftPointer pointer = new PlayerRiftPointer(player); + pointerMap.put(player, pointer); + uuidMap.put(pointer.id, pointer); + graph.addVertex(pointer); + graph.addEdge(pointer, uuidMap.get(rift)); + } + return pointerMap; + } + + private NBTTagList writePlayerRiftPointers(Map<UUID, PlayerRiftPointer> playerRiftPointerMap) { + NBTTagList pointers = new NBTTagList(); + for (Map.Entry<UUID, PlayerRiftPointer> entry : playerRiftPointerMap.entrySet()) { + NBTTagCompound entryNBT = new NBTTagCompound(); + entryNBT.setUniqueId("player", entry.getKey()); + int count = 0; + for (DefaultEdge edge : graph.outgoingEdgesOf(entry.getValue())) { + entryNBT.setUniqueId("rift", graph.getEdgeTarget(edge).id); + count++; + } + if (count != 1) throw new RuntimeException("PlayerRiftPointer points to more than one rift"); + pointers.appendTag(entryNBT); + } + return pointers; + } + + public void markSubregistryDirty(int dim) { + RiftSubregistry subregistry = subregistries.get(dim); + if (subregistry != null) { + subregistry.markDirty(); + } else { + // Create the subregistry + MapStorage storage = WorldUtils.getWorld(dim).getPerWorldStorage(); + RiftSubregistry instance = new RiftSubregistry(); + instance.dim = dim; + instance.markDirty(); + storage.setData(SUBREGISTRY_DATA_NAME, instance); + subregistries.put(dim, instance); + } + } + + // </editor-fold> + + public boolean isRiftAt(Location location) { + return locationMap.get(location) != null; + } + + public Rift getRift(Location location) { + Rift rift = locationMap.get(location); + if (rift == null) throw new IllegalArgumentException("There is no rift registered at " + location); + return rift; + } + + public void addRift(Location location) { + DimDoors.log.info("Adding rift at " + location); + RegistryVertex currentRift = getRift(location); + Rift rift; + if (currentRift instanceof RiftPlaceholder) { + rift = new Rift(location); + rift.dim = location.getDim(); + rift.id = currentRift.id; + GraphUtils.replaceVertex(graph, currentRift, rift); + } else if (currentRift == null) { + rift = new Rift(location); + rift.dim = location.getDim(); + graph.addVertex(rift); + } else { + throw new IllegalArgumentException("There is already a rift registered at " + location); + } + uuidMap.put(rift.id, rift); + locationMap.put(location, rift); + rift.markDirty(); + } + + public void removeRift(Location location) { + DimDoors.log.info("Removing rift at " + location); + + Rift rift = getRift(location); + + // Notify the adjacent vertices of the change + for (DefaultEdge edge : graph.incomingEdgesOf(rift)) graph.getEdgeSource(edge).targetGone(rift); + for (DefaultEdge edge : graph.outgoingEdgesOf(rift)) graph.getEdgeTarget(edge).sourceGone(rift); + + graph.removeVertex(rift); + locationMap.remove(location); + uuidMap.remove(rift.id); + rift.markDirty(); + } + + private void addEdge(RegistryVertex from, RegistryVertex to) { + graph.addEdge(from, to); + if (from instanceof PlayerRiftPointer) { + markDirty(); + } else { + markSubregistryDirty(from.dim); + } + markSubregistryDirty(to.dim); + } + + public void addLink(Location locationFrom, Location locationTo) { + DimDoors.log.info("Adding link " + locationFrom + " -> " + locationTo); + Rift from = getRift(locationFrom); + + Rift to = getRift(locationTo); + + addEdge(from, to); + + // Notify the linked vertices of the change + from.targetAdded(to); + to.sourceAdded(from); + } + + public void removeLink(Location locationFrom, Location locationTo) { + DimDoors.log.info("Removing link " + locationFrom + " -> " + locationTo); + + Rift from = getRift(locationFrom); + Rift to = getRift(locationTo); + + addEdge(from, to); + + // Notify the linked vertices of the change + from.targetGone(to); + to.sourceGone(from); + } + + public void setProperties(Location location, LinkProperties properties) { + DimDoors.log.info("Setting DungeonLinkProperties for rift at " + location + " to " + properties); + Rift rift = getRift(location); + rift.properties = properties; + rift.markDirty(); + } + + public Set<Location> getPocketEntrances(Pocket pocket) { + PocketEntrancePointer pointer = pocketEntranceMap.get(pocket); + if (pointer == null) { + return Collections.emptySet(); + } else { + return graph.outgoingEdgesOf(pointer).stream() + .map(graph::getEdgeTarget) + .map(Rift.class::cast) + .map(rift -> rift.location) + .collect(Collectors.toSet()); + } + } + + public void addPocketEntrance(Pocket pocket, Location location) { + DimDoors.log.info("Adding pocket entrance for pocket " + pocket.getId() + " in dimension " + pocket.getDim() + " at " + location); + PocketEntrancePointer pointer = pocketEntranceMap.get(pocket); + if (pointer == null) { + pointer = new PocketEntrancePointer(pocket.getDim(), pocket.getId()); + pointer.dim = pocket.getDim(); + graph.addVertex(pointer); + pocketEntranceMap.put(pocket, pointer); + uuidMap.put(pointer.id, pointer); + } + Rift rift = getRift(location); + addEdge(pointer, rift); + } + + public Location getPrivatePocketEntrance(UUID playerUUID) { + // Try to get the last used entrance + PlayerRiftPointer entrancePointer = lastPrivatePocketEntrances.get(playerUUID); + Rift entrance = (Rift) GraphUtils.followPointer(graph, entrancePointer); + if (entrance != null) return entrance.location; + + // If there was no last used private entrance, get one of the player's private pocket entrances + PocketRegistry privatePocketRegistry = PocketRegistry.instance(ModDimensions.getPrivateDim()); + Pocket pocket = privatePocketRegistry.getPocket(privatePocketRegistry.getPrivatePocketID(playerUUID)); + return getPocketEntrances(pocket).stream().findFirst().orElse(null); + } + + private void setPlayerRiftPointer(UUID playerUUID, Location rift, Map<UUID, PlayerRiftPointer> map) { + PlayerRiftPointer pointer = map.get(playerUUID); + if (pointer == null) { + pointer = new PlayerRiftPointer(playerUUID); + graph.addVertex(pointer); + map.put(playerUUID, pointer); + uuidMap.put(pointer.id, pointer); + } else { + graph.removeAllEdges(graph.outgoingEdgesOf(pointer)); + } + addEdge(pointer, getRift(rift)); + } + + public void setLastPrivatePocketEntrance(UUID playerUUID, Location rift) { + DimDoors.log.info("Setting last used private pocket entrance for " + playerUUID + " at " + rift); + setPlayerRiftPointer(playerUUID, rift, lastPrivatePocketEntrances); + } + + public Location getPrivatePocketExit(UUID playerUUID) { + PlayerRiftPointer entrancePointer = lastPrivatePocketExits.get(playerUUID); + Rift entrance = (Rift) GraphUtils.followPointer(graph, entrancePointer); + return entrance.location; + } + + public void setLastPrivatePocketExit(UUID playerUUID, Location rift) { + DimDoors.log.info("Setting last used private pocket entrance for " + playerUUID + " at " + rift); + setPlayerRiftPointer(playerUUID, rift, lastPrivatePocketExits); + } + + public Location getOverworldRift(UUID playerUUID) { + PlayerRiftPointer entrancePointer = overworldRifts.get(playerUUID); + Rift entrance = (Rift) GraphUtils.followPointer(graph, entrancePointer); + return entrance.location; + } + + public void setOverworldRift(UUID playerUUID, Location rift) { + DimDoors.log.info("Setting last used private pocket entrance for " + playerUUID + " at " + rift); + setPlayerRiftPointer(playerUUID, rift, overworldRifts); + } + + public Collection<Rift> getRifts() { + return locationMap.values(); + } + + public Set<Location> getTargets(Location location) { + return graph.outgoingEdgesOf(locationMap.get(location)).stream() + .map(graph::getEdgeTarget) + .map(Rift.class::cast) + .map(rift -> rift.location) + .collect(Collectors.toSet()); + } + + public Set<Location> getSources(Location location) { + return graph.incomingEdgesOf(locationMap.get(location)).stream() + .map(graph::getEdgeTarget) + .map(Rift.class::cast) + .map(rift -> rift.location) + .collect(Collectors.toSet()); + } +} diff --git a/src/main/java/org/dimdev/dimdoors/shared/tools/PocketSchematicGenerator.java b/src/main/java/org/dimdev/dimdoors/shared/tools/PocketSchematicGenerator.java index d7a82330..322ab506 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/tools/PocketSchematicGenerator.java +++ b/src/main/java/org/dimdev/dimdoors/shared/tools/PocketSchematicGenerator.java @@ -10,6 +10,7 @@ import org.dimdev.dimdoors.shared.rifts.*; import org.dimdev.dimdoors.shared.rifts.destinations.PocketEntranceDestination; import org.dimdev.dimdoors.shared.rifts.destinations.PocketExitDestination; import org.dimdev.dimdoors.shared.rifts.destinations.PrivatePocketExitDestination; +import org.dimdev.dimdoors.shared.rifts.registry.LinkProperties; import org.dimdev.dimdoors.shared.tileentities.TileEntityEntranceRift; import org.dimdev.ddutils.schem.Schematic; import net.minecraft.block.BlockDoor; @@ -30,10 +31,7 @@ import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @author Robijnvogel @@ -158,10 +156,15 @@ public final class PocketSchematicGenerator { // Generate the rift TileEntities schematic.tileEntities = new ArrayList<>(); TileEntityEntranceRift rift = (TileEntityEntranceRift) doorBlock.createTileEntity(null, doorBlock.getDefaultState()); - rift.setSingleDestination(PocketEntranceDestination.builder() - .ifDestinations(Collections.singletonList(new WeightedRiftDestination(exitDest, 1, 0))) + rift.setDestination(PocketEntranceDestination.builder() + .ifDestination(exitDest) + .build()); + rift.setProperties(LinkProperties.builder() + .groups(Collections.singleton(1)) + .linksRemaining(1) + .entranceWeight(chaosWeight) + .floatingWeight(chaosWeight) .build()); - rift.setChaosWeight(chaosWeight); rift.setPlaceRiftOnBreak(true); NBTTagCompound tileNBT = rift.serializeNBT(); diff --git a/src/main/java/org/dimdev/dimdoors/shared/world/limbodimension/BiomeLimbo.java b/src/main/java/org/dimdev/dimdoors/shared/world/limbodimension/BiomeLimbo.java index 57bedd2c..118ee0fa 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/world/limbodimension/BiomeLimbo.java +++ b/src/main/java/org/dimdev/dimdoors/shared/world/limbodimension/BiomeLimbo.java @@ -4,7 +4,6 @@ import org.dimdev.dimdoors.shared.entities.EntityMonolith; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeDecorator; import net.minecraft.world.chunk.ChunkPrimer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; diff --git a/src/main/java/org/dimdev/dimdoors/shared/world/pocketdimension/BiomeBlank.java b/src/main/java/org/dimdev/dimdoors/shared/world/pocketdimension/BiomeBlank.java index f812661e..c4b16714 100644 --- a/src/main/java/org/dimdev/dimdoors/shared/world/pocketdimension/BiomeBlank.java +++ b/src/main/java/org/dimdev/dimdoors/shared/world/pocketdimension/BiomeBlank.java @@ -1,6 +1,5 @@ package org.dimdev.dimdoors.shared.world.pocketdimension; -import org.dimdev.dimdoors.shared.entities.EntityMonolith; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World;