Adds more comments, simplifies some code and improves positioning of teleported large entities, like horses

This commit is contained in:
Kristian Knarvik 2021-02-27 21:17:36 +01:00
parent 79703e49af
commit ba64572254
3 changed files with 359 additions and 82 deletions

View File

@ -3,6 +3,7 @@ package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.BlockLocation; import net.knarcraft.stargate.BlockLocation;
import net.knarcraft.stargate.RelativeBlockVector; import net.knarcraft.stargate.RelativeBlockVector;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.EconomyHandler; import net.knarcraft.stargate.utility.EconomyHandler;
import org.bukkit.Material; import org.bukkit.Material;
@ -271,7 +272,7 @@ public class Gate {
* @return <p>The block at the given relative position</p> * @return <p>The block at the given relative position</p>
*/ */
private BlockLocation getBlockAt(BlockLocation topLeft, RelativeBlockVector vector, int modX, int modZ) { private BlockLocation getBlockAt(BlockLocation topLeft, RelativeBlockVector vector, int modX, int modZ) {
return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ); return DirectionHelper.getBlockAt(topLeft, vector, modX, modZ);
} }
/** /**

View File

@ -18,7 +18,7 @@ import java.util.List;
public class GateLayout { public class GateLayout {
private Character [][] layout; private Character [][] layout;
private final HashMap<RelativeBlockVector, Integer> exits = new HashMap<>(); private final List<RelativeBlockVector> exits = new ArrayList<>();
private RelativeBlockVector[] entrances = new RelativeBlockVector[0]; private RelativeBlockVector[] entrances = new RelativeBlockVector[0];
private RelativeBlockVector[] border = new RelativeBlockVector[0]; private RelativeBlockVector[] border = new RelativeBlockVector[0];
private RelativeBlockVector[] controls = new RelativeBlockVector[0]; private RelativeBlockVector[] controls = new RelativeBlockVector[0];
@ -78,7 +78,7 @@ public class GateLayout {
* *
* @return <p>Other possible gate exits</p> * @return <p>Other possible gate exits</p>
*/ */
public HashMap<RelativeBlockVector, Integer> getExits() { public List<RelativeBlockVector> getExits() {
return exits; return exits;
} }
@ -134,7 +134,7 @@ public class GateLayout {
} }
if (exitDepths[x] > 0) { if (exitDepths[x] > 0) {
this.exits.put(relativeExits[x], x); this.exits.add(relativeExits[x]);
} }
} }

View File

@ -9,6 +9,7 @@ import net.knarcraft.stargate.event.StargateCloseEvent;
import net.knarcraft.stargate.event.StargateDeactivateEvent; import net.knarcraft.stargate.event.StargateDeactivateEvent;
import net.knarcraft.stargate.event.StargateOpenEvent; import net.knarcraft.stargate.event.StargateOpenEvent;
import net.knarcraft.stargate.event.StargatePortalEvent; import net.knarcraft.stargate.event.StargatePortalEvent;
import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.EntityHelper; import net.knarcraft.stargate.utility.EntityHelper;
import net.knarcraft.stargate.utility.SignHelper; import net.knarcraft.stargate.utility.SignHelper;
import org.bukkit.Axis; import org.bukkit.Axis;
@ -19,6 +20,7 @@ import org.bukkit.block.BlockState;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Orientable;
import org.bukkit.block.data.Powerable; import org.bukkit.block.data.Powerable;
import org.bukkit.entity.Boat; import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -124,19 +126,6 @@ public class Portal {
} }
} }
/**
* Removes the special characters |, : and # from a portal name
*
* @param input <p>The name to filter</p>
* @return <p>The filtered name</p>
*/
public static String filterName(String input) {
if (input == null) {
return "";
}
return input.replaceAll("[|:#]", "").trim();
}
/** /**
* Gets whether this portal is currently open * Gets whether this portal is currently open
* *
@ -238,84 +227,181 @@ public class Portal {
return rotX; return rotX;
} }
/**
* Gets the axis the portal follows
*
* <p>If a relative vector's right is not zero, it will move along this axis.
* The axis is used to place the portal's open blocks correctly</p>
*
* @return <p>The axis the portal follows</p>
*/
public Axis getAxis() { public Axis getAxis() {
return rot; return rot;
} }
/**
* Gets the player currently using this portal
*
* @return <p>The player currently using this portal</p>
*/
public Player getActivePlayer() { public Player getActivePlayer() {
return activePlayer; return activePlayer;
} }
/**
* Gets the network this gate belongs to
*
* @return <p>The network this gate belongs to</p>
*/
public String getNetwork() { public String getNetwork() {
return network; return network;
} }
/**
* Sets the network this gate belongs to
*
* @param network <p>The new network for this gate</p>
*/
public void setNetwork(String network) { public void setNetwork(String network) {
this.network = network; this.network = network;
} }
/**
* Gets the time this portal opened
*
* @return <p>The time this portal opened</p>
*/
public long getOpenTime() { public long getOpenTime() {
return openTime; return openTime;
} }
/**
* Gets the name of this portal
*
* @return <p>The name of this portal</p>
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Sets the name of this portal
*
* @param name <p>The new name of this portal</p>
*/
public void setName(String name) { public void setName(String name) {
this.name = filterName(name); this.name = filterName(name);
drawSign(); drawSign();
} }
/**
* Gets the destinations of this portal
*
* @return <p>The destinations of this portal</p>
*/
public List<String> getDestinations() { public List<String> getDestinations() {
return new ArrayList<>(this.destinations); return new ArrayList<>(this.destinations);
} }
/**
* Gets the portal destination given a player
*
* @param player <p>Used for random gates to determine which destinations are available</p>
* @return <p>The destination portal the player should teleport to</p>
*/
public Portal getDestination(Player player) { public Portal getDestination(Player player) {
if (isRandom()) { if (isRandom()) {
destinations = PortalHandler.getDestinations(this, player, getNetwork()); destinations = PortalHandler.getDestinations(this, player, getNetwork());
if (destinations.size() == 0) { if (destinations.size() == 0) {
return null; return null;
} }
String dest = destinations.get((new Random()).nextInt(destinations.size())); String destination = destinations.get((new Random()).nextInt(destinations.size()));
destinations.clear(); destinations.clear();
return PortalHandler.getByName(dest, getNetwork()); return PortalHandler.getByName(destination, getNetwork());
} }
return PortalHandler.getByName(destination, getNetwork()); return PortalHandler.getByName(destination, getNetwork());
} }
/**
* Gets the portal destination
*
* <p>If this portal is random, a player should be given to get correct destinations.</p>
*
* @return <p>The portal destination</p>
*/
public Portal getDestination() { public Portal getDestination() {
return getDestination(null); return getDestination(null);
} }
/**
* Sets the destination of this portal
*
* @param destination <p>The new destination of this portal</p>
*/
public void setDestination(Portal destination) { public void setDestination(Portal destination) {
setDestination(destination.getName()); setDestination(destination.getName());
} }
/**
* Sets the destination of this portal
*
* @param destination <p>The new destination of this portal</p>
*/
public void setDestination(String destination) { public void setDestination(String destination) {
this.destination = destination; this.destination = destination;
} }
/**
* Gets the name of the destination of this portal
*
* @return <p>The name of this portal's destination</p>
*/
public String getDestinationName() { public String getDestinationName() {
return destination; return destination;
} }
/**
* Gets the gate used by this portal
*
* @return <p>The gate used by this portal</p>
*/
public Gate getGate() { public Gate getGate() {
return gate; return gate;
} }
/**
* Gets the name of this portal's owner
*
* @return <p>The name of this portal's owner</p>
*/
public String getOwnerName() { public String getOwnerName() {
return ownerName; return ownerName;
} }
/**
* Gets the UUID of this portal's owner
*
* @return <p>The UUID of this portal's owner</p>
*/
public UUID getOwnerUUID() { public UUID getOwnerUUID() {
return ownerUUID; return ownerUUID;
} }
/**
* Sets the UUId of this portal's owner
*
* @param owner <p>The new UUID of this portal's owner</p>
*/
public void setOwner(UUID owner) { public void setOwner(UUID owner) {
this.ownerUUID = owner; this.ownerUUID = owner;
} }
/**
* Checks whether a given player is the owner of this portal
*
* @param player <p>The player to check</p>
* @return <p>True if the player is the owner of this portal</p>
*/
public boolean isOwner(Player player) { public boolean isOwner(Player player) {
if (this.ownerUUID != null) { if (this.ownerUUID != null) {
return player.getUniqueId().compareTo(this.ownerUUID) == 0; return player.getUniqueId().compareTo(this.ownerUUID) == 0;
@ -324,93 +410,134 @@ public class Portal {
} }
} }
/**
* Gets the locations of this portal's entrances
*
* @return <p>The locations of this portal's entrances</p>
*/
public BlockLocation[] getEntrances() { public BlockLocation[] getEntrances() {
if (entrances == null) { if (entrances == null) {
RelativeBlockVector[] space = gate.getLayout().getEntrances(); entrances = relativeBlockVectorsToBlockLocations(gate.getLayout().getEntrances());
entrances = new BlockLocation[space.length];
int i = 0;
for (RelativeBlockVector vector : space) {
entrances[i++] = getBlockAt(vector);
}
} }
return entrances; return entrances;
} }
/**
* Gets the locations of this portal's frame
*
* @return <p>The locations of this portal's frame</p>
*/
public BlockLocation[] getFrame() { public BlockLocation[] getFrame() {
if (frame == null) { if (frame == null) {
RelativeBlockVector[] border = gate.getLayout().getBorder(); frame = relativeBlockVectorsToBlockLocations(gate.getLayout().getBorder());
frame = new BlockLocation[border.length];
int i = 0;
for (RelativeBlockVector vector : border) {
frame[i++] = getBlockAt(vector);
}
} }
return frame; return frame;
} }
/**
* Gets the location of this portal's sign
*
* @return <p>The location of this portal's sign</p>
*/
public BlockLocation getSign() { public BlockLocation getSign() {
return id; return id;
} }
/**
* Gets the world this portal belongs to
*
* @return <p>The world this portal belongs to</p>
*/
public World getWorld() { public World getWorld() {
return world; return world;
} }
/**
* Gets the location of this portal's button
*
* @return <p>The location of this portal's button</p>
*/
public BlockLocation getButton() { public BlockLocation getButton() {
return button; return button;
} }
/**
* Sets the location of this portal's button
*
* @param button <p>The location of this portal's button</p>
*/
public void setButton(BlockLocation button) { public void setButton(BlockLocation button) {
this.button = button; this.button = button;
} }
/**
* Open this portal
*
* @param force <p>Whether to force this portal open, even if it's already open for some player</p>
* @return <p>True if the portal was opened</p>
*/
public boolean open(boolean force) { public boolean open(boolean force) {
return open(null, force); return open(null, force);
} }
/**
* Open this portal
*
* @param force <p>Whether to force this portal open, even if it's already open for some player</p>
* @return <p>True if the portal was opened</p>
*/
public boolean open(Player openFor, boolean force) { public boolean open(Player openFor, boolean force) {
// Call the StargateOpenEvent //Call the StargateOpenEvent
StargateOpenEvent event = new StargateOpenEvent(openFor, this, force); StargateOpenEvent event = new StargateOpenEvent(openFor, this, force);
Stargate.server.getPluginManager().callEvent(event); Stargate.server.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled() || (isOpen() && !event.getForce())) {
return false;
}
force = event.getForce();
if (isOpen() && !force) {
return false; return false;
} }
//Change the opening blocks to the correct type
Material openType = gate.getPortalOpenBlock(); Material openType = gate.getPortalOpenBlock();
Axis axis = openType == Material.NETHER_PORTAL ? rot : null; Axis axis = (openType.createBlockData() instanceof Orientable) ? rot : null;
for (BlockLocation inside : getEntrances()) { for (BlockLocation inside : getEntrances()) {
Stargate.blockPopulatorQueue.add(new BloxPopulator(inside, openType, axis)); Stargate.blockPopulatorQueue.add(new BloxPopulator(inside, openType, axis));
} }
updatePortalOpenState(openFor);
return true;
}
/**
* Updates this portal to be recognized as open and opens its destination portal
*
* @param openFor <p>The player to open this portal for</p>
*/
private void updatePortalOpenState(Player openFor) {
//Update the open state of this portal
isOpen = true; isOpen = true;
openTime = System.currentTimeMillis() / 1000; openTime = System.currentTimeMillis() / 1000;
Stargate.openList.add(this); Stargate.openList.add(this);
Stargate.activeList.remove(this); Stargate.activeList.remove(this);
// Open remote gate //Open remote portal
if (!isAlwaysOn()) { if (!isAlwaysOn()) {
player = openFor; player = openFor;
Portal end = getDestination(); Portal destination = getDestination();
// Only open dest if it's not-fixed or points at this gate // Only open destination if it's not-fixed or points at this portal
if (!isRandom() && end != null && (!end.isFixed() || end.getDestinationName().equalsIgnoreCase(getName())) && !end.isOpen()) { if (!isRandom() && destination != null && (!destination.isFixed() ||
end.open(openFor, false); destination.getDestinationName().equalsIgnoreCase(getName())) && !destination.isOpen()) {
end.setDestination(this); destination.open(openFor, false);
if (end.isVerified()) end.drawSign(); destination.setDestination(this);
if (destination.isVerified()) destination.drawSign();
} }
} }
return true;
} }
/**
* Closes this portal
*
* @param force <p>Whether to force this portal closed, even if it's set as always on</p>
*/
public void close(boolean force) { public void close(boolean force) {
if (!isOpen) return; if (!isOpen) return;
// Call the StargateCloseEvent // Call the StargateCloseEvent
@ -427,11 +554,21 @@ public class Portal {
Stargate.blockPopulatorQueue.add(new BloxPopulator(inside, closedType)); Stargate.blockPopulatorQueue.add(new BloxPopulator(inside, closedType));
} }
updatePortalClosedState();
deactivate();
}
/**
* Updates this portal to be recognized as closed and closes its destination portal
*/
private void updatePortalClosedState() {
//Update the closed state of this portal
player = null; player = null;
isOpen = false; isOpen = false;
Stargate.openList.remove(this); Stargate.openList.remove(this);
Stargate.activeList.remove(this); Stargate.activeList.remove(this);
//Close remote portal
if (!isAlwaysOn()) { if (!isAlwaysOn()) {
Portal end = getDestination(); Portal end = getDestination();
@ -440,33 +577,51 @@ public class Portal {
end.close(false); end.close(false);
} }
} }
deactivate();
} }
/**
* Gets whether this portal is open for the given player
*
* @param player <p>The player to check portal state for</p>
* @return <p>True if this portal is open to the given player</p>
*/
public boolean isOpenFor(Player player) { public boolean isOpenFor(Player player) {
if (!isOpen) { if (!isOpen) {
return false; return false;
} }
if ((isAlwaysOn()) || (this.player == null)) { if (isAlwaysOn() || this.player == null) {
return true; return true;
} }
return (player != null) && (player.getName().equalsIgnoreCase(this.player.getName())); return player != null && player.getName().equalsIgnoreCase(this.player.getName());
} }
/** /**
* Gets whether this portal points to a fixed exit portal * Gets whether this portal points to a fixed exit portal
* *
* <p>A portal where portals can be chosen from a network is not fixed.</p>
*
* @return <p>True if this portal points to a fixed exit portal</p> * @return <p>True if this portal points to a fixed exit portal</p>
*/ */
public boolean isFixed() { public boolean isFixed() {
return fixed; return fixed;
} }
/**
* Sets whether this portal points to a fixed exit portal
*
* <p>A portal where portals can be chosen from a network is not fixed.</p>
*
* @param fixed <p>True if this portal points to a fixed exit portal</p>
*/
public void setFixed(boolean fixed) { public void setFixed(boolean fixed) {
this.fixed = fixed; this.fixed = fixed;
} }
/**
* Gets whether at least one of this portal's control blocks are powered
*
* @return <p>True if at least one control block is powered</p>
*/
public boolean isPowered() { public boolean isPowered() {
RelativeBlockVector[] controls = gate.getLayout().getControls(); RelativeBlockVector[] controls = gate.getLayout().getControls();
@ -521,8 +676,8 @@ public class Portal {
/** /**
* Adjusts the rotation of the player to face out from the portal * Adjusts the rotation of the player to face out from the portal
* *
* @param entry <p>The location the player entered from</p> * @param entry <p>The location the player entered from</p>
* @param exit <p>The location the player will exit from</p> * @param exit <p>The location the player will exit from</p>
* @param origin <p>The portal the player entered from</p> * @param origin <p>The portal the player entered from</p>
*/ */
private void adjustRotation(Location entry, Location exit, Portal origin) { private void adjustRotation(Location entry, Location exit, Portal origin) {
@ -573,8 +728,8 @@ public class Portal {
/** /**
* Teleport a vehicle which is not a minecart or a boat * Teleport a vehicle which is not a minecart or a boat
* *
* @param vehicle <p>The vehicle to teleport</p> * @param vehicle <p>The vehicle to teleport</p>
* @param exit <p>The location the vehicle will exit</p> * @param exit <p>The location the vehicle will exit</p>
* @param passengers <p>The passengers of the vehicle</p> * @param passengers <p>The passengers of the vehicle</p>
*/ */
private void teleportLivingVehicle(Vehicle vehicle, Location exit, List<Entity> passengers) { private void teleportLivingVehicle(Vehicle vehicle, Location exit, List<Entity> passengers) {
@ -586,11 +741,11 @@ public class Portal {
/** /**
* Creates a new vehicle equal to the player's previous vehicle and * Creates a new vehicle equal to the player's previous vehicle and
* *
* @param vehicle <p>The player's old vehicle</p> * @param vehicle <p>The player's old vehicle</p>
* @param passengers <p>A list of all passengers in the vehicle</p> * @param passengers <p>A list of all passengers in the vehicle</p>
* @param vehicleWorld <p>The world to spawn the new vehicle in</p> * @param vehicleWorld <p>The world to spawn the new vehicle in</p>
* @param exit <p>The exit location to spawn the new vehicle on</p> * @param exit <p>The exit location to spawn the new vehicle on</p>
* @param newVelocity <p>The new velocity of the new vehicle</p> * @param newVelocity <p>The new velocity of the new vehicle</p>
*/ */
private void putPassengersInNewVehicle(Vehicle vehicle, List<Entity> passengers, World vehicleWorld, Location exit, private void putPassengersInNewVehicle(Vehicle vehicle, List<Entity> passengers, World vehicleWorld, Location exit,
Vector newVelocity) { Vector newVelocity) {
@ -605,9 +760,9 @@ public class Portal {
/** /**
* Ejects, teleports and adds all passengers to the target vehicle * Ejects, teleports and adds all passengers to the target vehicle
* *
* @param passengers <p>The passengers to handle</p> * @param passengers <p>The passengers to handle</p>
* @param targetVehicle <p>The vehicle the passengers should be put into</p> * @param targetVehicle <p>The vehicle the passengers should be put into</p>
* @param exit <p>The exit location to teleport the passengers to</p> * @param exit <p>The exit location to teleport the passengers to</p>
*/ */
private void handleVehiclePassengers(List<Entity> passengers, Vehicle targetVehicle, Location exit) { private void handleVehiclePassengers(List<Entity> passengers, Vehicle targetVehicle, Location exit) {
for (Entity passenger : passengers) { for (Entity passenger : passengers) {
@ -629,17 +784,86 @@ public class Portal {
private Location getExit(Entity entity, Location traveller) { private Location getExit(Entity entity, Location traveller) {
Location exitLocation = null; Location exitLocation = null;
// Check if the gate has an exit block // Check if the gate has an exit block
if (gate.getLayout().getExit() != null) { RelativeBlockVector relativeExit = gate.getLayout().getExit();
BlockLocation exit = getBlockAt(gate.getLayout().getExit()); if (relativeExit != null) {
BlockLocation exit = getBlockAt(relativeExit);
int back = (isBackwards()) ? -1 : 1; int back = (isBackwards()) ? -1 : 1;
//TODO: Improve positioning to place the entity just far enough from the portal not to suffocate exitLocation = exit.modRelativeLoc(0D, 0D, 1, traveller.getYaw(),
double entitySize = EntityHelper.getEntityMaxSize(entity);
exitLocation = exit.modRelativeLoc(0D, 0D, entitySize, traveller.getYaw(),
traveller.getPitch(), modX * back, 1, modZ * back); traveller.getPitch(), modX * back, 1, modZ * back);
double entitySize = EntityHelper.getEntityMaxSize(entity);
if (entitySize > 1) {
exitLocation = preventExitSuffocation(relativeExit, exitLocation, entitySize);
}
} else { } else {
Stargate.log.log(Level.WARNING, Stargate.getString("prefix") + "Missing destination point in .gate file " + gate.getFilename()); Stargate.log.log(Level.WARNING, Stargate.getString("prefix") + "Missing destination point in .gate file " + gate.getFilename());
} }
return adjustExitLocation(traveller, exitLocation);
}
/**
* Adjusts the positioning of the portal exit to prevent the given entity from suffocating
*
* @param relativeExit <p>The relative exit defined as the portal's exit</p>
* @param exitLocation <p>The currently calculated portal exit</p>
* @param entitySize <p>The size of the travelling entity</p>
* @return <p>A location which won't suffocate the entity inside the portal</p>
*/
private Location preventExitSuffocation(RelativeBlockVector relativeExit, Location exitLocation, double entitySize) {
//Go left to find start of opening
RelativeBlockVector openingLeft = getPortalExitEdge(relativeExit, -1);
//Go right to find the end of the opening
RelativeBlockVector openingRight = getPortalExitEdge(relativeExit, 1);
//Get the width to check if the entity fits
int openingWidth = openingRight.getRight() - openingLeft.getRight() + 1;
int existingOffset = relativeExit.getRight() - openingLeft.getRight();
double newOffset = (openingWidth - existingOffset) / 2D;
//Remove the half offset for better centering
if (openingWidth > 1) {
newOffset -= 0.5;
}
exitLocation = DirectionHelper.adjustLocation(exitLocation, newOffset, 0, 0, modX, modZ);
if (entitySize > openingWidth) {
exitLocation = DirectionHelper.adjustLocation(exitLocation, 0, 0, (entitySize / 2D), modX, modZ);
}
return exitLocation;
}
/**
* Gets one of the edges of a portal's opening/exit
*
* @param relativeExit <p>The known exit to start from</p>
* @param direction <p>The direction to move (+1 for right, -1 for left)</p>
* @return <p>The right or left edge of the opening</p>
*/
private RelativeBlockVector getPortalExitEdge(RelativeBlockVector relativeExit, int direction) {
RelativeBlockVector openingEdge = relativeExit;
do {
RelativeBlockVector possibleOpening = new RelativeBlockVector(openingEdge.getRight() + direction,
openingEdge.getDepth(), openingEdge.getDistance());
if (gate.getLayout().getExits().contains(possibleOpening)) {
openingEdge = possibleOpening;
} else {
break;
}
} while (true);
return openingEdge;
}
/**
* Adjusts an exit location with rotation and slab height incrementation
*
* @param traveller <p>The location of the travelling entity</p>
* @param exitLocation <p>The exit location generated</p>
* @return <p>The location the travelling entity should be teleported to</p>
*/
private Location adjustExitLocation(Location traveller, Location exitLocation) {
if (exitLocation != null) { if (exitLocation != null) {
//Prevent traveller from spawning inside a slab //Prevent traveller from spawning inside a slab
BlockData blockData = getWorld().getBlockAt(exitLocation).getBlockData(); BlockData blockData = getWorld().getBlockAt(exitLocation).getBlockData();
@ -741,7 +965,7 @@ public class Portal {
* @param player <p>The player to activate the portal for</p> * @param player <p>The player to activate the portal for</p>
* @return <p>True if the portal was activated</p> * @return <p>True if the portal was activated</p>
*/ */
public boolean activate(Player player) { private boolean activate(Player player) {
destinations.clear(); destinations.clear();
destination = ""; destination = "";
Stargate.activeList.add(this); Stargate.activeList.add(this);
@ -787,10 +1011,20 @@ public class Portal {
drawSign(); drawSign();
} }
/**
* Gets whether this portal is active
*
* @return <p>Whether this portal is active</p>
*/
public boolean isActive() { public boolean isActive() {
return isFixed() || (destinations.size() > 0); return isFixed() || (destinations.size() > 0);
} }
/**
* Cycles destination for a network gate forwards
*
* @param player <p>The player to cycle the gate for</p>
*/
public void cycleDestination(Player player) { public void cycleDestination(Player player) {
cycleDestination(player, 1); cycleDestination(player, 1);
} }
@ -798,7 +1032,7 @@ public class Portal {
/** /**
* Cycles destination for a network gate * Cycles destination for a network gate
* *
* @param player <p>The player cycling destinations</p> * @param player <p>The player cycling destinations</p>
* @param direction <p>The direction of the cycle (+1 for next, -1 for previous)</p> * @param direction <p>The direction of the cycle (+1 for next, -1 for previous)</p>
*/ */
public void cycleDestination(Player player, int direction) { public void cycleDestination(Player player, int direction) {
@ -808,7 +1042,7 @@ public class Portal {
boolean activate = false; boolean activate = false;
if (!isActive() || getActivePlayer() != player) { if (!isActive() || getActivePlayer() != player) {
// If the event is cancelled, return //If the stargate activate event is cancelled, return
if (!activate(player)) { if (!activate(player)) {
return; return;
} }
@ -823,19 +1057,32 @@ public class Portal {
} }
if (!Stargate.destMemory || !activate || lastDestination.isEmpty()) { if (!Stargate.destMemory || !activate || lastDestination.isEmpty()) {
int index = destinations.indexOf(destination); cycleDestination(direction);
index += direction;
if (index >= destinations.size())
index = 0;
else if (index < 0)
index = destinations.size() - 1;
destination = destinations.get(index);
lastDestination = destination;
} }
openTime = System.currentTimeMillis() / 1000; openTime = System.currentTimeMillis() / 1000;
drawSign(); drawSign();
} }
/**
* Performs the actual destination cycling with no input checks
*
* @param direction <p>The direction of the cycle (+1 for next, -1 for previous)</p>
*/
private void cycleDestination(int direction) {
int index = destinations.indexOf(destination);
index += direction;
//Wrap around
if (index >= destinations.size()) {
index = 0;
} else if (index < 0) {
index = destinations.size() - 1;
}
//Store selected destination
destination = destinations.get(index);
lastDestination = destination;
}
/** /**
* Draws the sign on this portal * Draws the sign on this portal
*/ */
@ -857,8 +1104,37 @@ public class Portal {
* @param vector <p>The relative block vector</p> * @param vector <p>The relative block vector</p>
* @return <p>The block at the given relative position</p> * @return <p>The block at the given relative position</p>
*/ */
BlockLocation getBlockAt(RelativeBlockVector vector) { public BlockLocation getBlockAt(RelativeBlockVector vector) {
return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ); return DirectionHelper.getBlockAt(topLeft, vector, modX, modZ);
}
/**
* Removes the special characters |, : and # from a portal name
*
* @param input <p>The name to filter</p>
* @return <p>The filtered name</p>
*/
private static String filterName(String input) {
if (input == null) {
return "";
}
return input.replaceAll("[|:#]", "").trim();
}
/**
* Gets a list of block locations from a list of relative block vectors
*
* @param vectors <p>The relative block vectors to convert</p>
* @return <p>A list of block locations</p>
*/
private BlockLocation[] relativeBlockVectorsToBlockLocations(RelativeBlockVector[] vectors) {
BlockLocation[] locations = new BlockLocation[vectors.length];
int i = 0;
for (RelativeBlockVector vector : vectors) {
locations[i++] = getBlockAt(vector);
}
return locations;
} }
@Override @Override