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
This commit is contained in:
Runemoro 2018-01-17 00:44:44 -05:00
parent a9a780c64c
commit 27cec3bcad
52 changed files with 1033 additions and 918 deletions

View file

@ -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'
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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());

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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() {

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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();

View file

@ -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
}

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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<>();

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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
}

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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; }
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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));
}
}

View file

@ -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); }

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -0,0 +1,3 @@
package org.dimdev.dimdoors.shared.rifts.registry;
public class RiftPlaceholder extends Rift {} // TODO: don't extend rift

View file

@ -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());
}
}

View file

@ -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();

View file

@ -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;

View file

@ -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;