diff --git a/src/main/java/net/knarcraft/stargate/Stargate.java b/src/main/java/net/knarcraft/stargate/Stargate.java index 2eecae4..547cdd3 100644 --- a/src/main/java/net/knarcraft/stargate/Stargate.java +++ b/src/main/java/net/knarcraft/stargate/Stargate.java @@ -513,7 +513,7 @@ public class Stargate extends JavaPlugin { public void closeAllPortals() { // Close all gates prior to reloading for (Portal openPortal : openPortalsQueue) { - openPortal.close(true); + openPortal.getPortalOpener().closePortal(true); } } @@ -563,7 +563,7 @@ public class Stargate extends JavaPlugin { public void reload(CommandSender sender) { // Deactivate portals for (Portal activePortal : activePortalsQueue) { - activePortal.deactivate(); + activePortal.getPortalActivator().deactivate(); } // Close portals closeAllPortals(); diff --git a/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java index 8ed2e48..fef005d 100644 --- a/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java @@ -4,6 +4,7 @@ import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.portal.PlayerTeleporter; import net.knarcraft.stargate.portal.Portal; +import net.knarcraft.stargate.portal.PortalActivator; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.VehicleTeleporter; import net.knarcraft.stargate.utility.BungeeHelper; @@ -81,7 +82,7 @@ public class PlayerEventListener implements Listener { return; } Portal entrancePortal = PortalHandler.getByEntrance(toLocation); - Portal destination = entrancePortal.getDestination(player); + Portal destination = entrancePortal.getPortalActivator().getDestination(player); //Teleport the vehicle to the player Entity playerVehicle = player.getVehicle(); @@ -99,7 +100,7 @@ public class PlayerEventListener implements Listener { new PlayerTeleporter(destination, player).teleport(entrancePortal, event); } Stargate.sendSuccessMessage(player, Stargate.getString("teleportMsg")); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); } /** @@ -124,7 +125,7 @@ public class PlayerEventListener implements Listener { return false; } - Portal destination = entrancePortal.getDestination(player); + Portal destination = entrancePortal.getPortalActivator().getDestination(player); //Catch always open portals without a valid destination to prevent the user for being teleported and denied if (destination == null) { @@ -200,10 +201,11 @@ public class PlayerEventListener implements Listener { //Cycle portal destination if ((!portal.isOpen()) && (!portal.getOptions().isFixed())) { + PortalActivator destinations = portal.getPortalActivator(); if (leftClick) { - portal.cycleDestination(player, -1); + destinations.cycleDestination(player, -1); } else { - portal.cycleDestination(player); + destinations.cycleDestination(player); } } } @@ -260,7 +262,7 @@ public class PlayerEventListener implements Listener { } PermissionHelper.openPortal(player, portal); - if (portal.isOpenFor(player)) { + if (portal.getPortalOpener().isOpenFor(player)) { event.setUseInteractedBlock(Event.Result.ALLOW); } } @@ -302,7 +304,7 @@ public class PlayerEventListener implements Listener { //Check if bungee is actually enabled if (!Stargate.enableBungee) { Stargate.sendErrorMessage(player, Stargate.getString("bungeeDisabled")); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); return false; } @@ -323,7 +325,7 @@ public class PlayerEventListener implements Listener { // Close portal if required (Should never be) Stargate.debug("bungeeTeleport", "Teleported player to another server"); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); return true; } diff --git a/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java index e484895..fd26668 100644 --- a/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java @@ -64,11 +64,11 @@ public class PortalEventListener implements Listener { //Remove any old player teleportations in case weird things happen playersFromTheEnd.removeIf((teleportation -> teleportation.getPlayer() == player)); //Decide if the anything stops the player from teleporting - if (PermissionHelper.playerCannotTeleport(portal, portal.getDestination(), player, null)) { + if (PermissionHelper.playerCannotTeleport(portal, portal.getPortalActivator().getDestination(), player, null)) { //Teleport the player back to the portal they came in, just in case playersFromTheEnd.add(new FromTheEndTeleportation(player, portal)); } - playersFromTheEnd.add(new FromTheEndTeleportation(player, portal.getDestination())); + playersFromTheEnd.add(new FromTheEndTeleportation(player, portal.getPortalActivator().getDestination())); } } @@ -92,7 +92,7 @@ public class PortalEventListener implements Listener { event.setRespawnLocation(new PlayerTeleporter(exitPortal, respawningPlayer).getExit(respawningPlayer, respawningPlayer.getLocation())); //Properly close the portal to prevent it from staying in a locked state until it times out - exitPortal.close(false); + exitPortal.getPortalOpener().closePortal(false); } } diff --git a/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java b/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java index 5a131f7..6d10ec4 100644 --- a/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java @@ -68,7 +68,7 @@ public class VehicleEventListener implements Listener { teleportPlayerAndVehicle(entrancePortal, vehicle, passengers); } else { Stargate.debug(route, prefix + "Found empty vehicle"); - Portal destinationPortal = entrancePortal.getDestination(); + Portal destinationPortal = entrancePortal.getPortalActivator().getDestination(); if (destinationPortal == null) { Stargate.debug(route, prefix + "Unable to find portal destination"); return; @@ -90,13 +90,13 @@ public class VehicleEventListener implements Listener { Player player = (Player) passengers.get(0); //On the assumption that a non-player cannot sit in the driver's seat and since some portals can only be open // to one player at a time, we only need to check if the portal is open to the driver. - if (!entrancePortal.isOpenFor(player)) { + if (!entrancePortal.getPortalOpener().isOpenFor(player)) { Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); return; } //If no destination exists, the teleportation cannot happen - Portal destinationPortal = entrancePortal.getDestination(player); + Portal destinationPortal = entrancePortal.getPortalActivator().getDestination(player); if (destinationPortal == null) { return; } @@ -119,7 +119,7 @@ public class VehicleEventListener implements Listener { Stargate.sendSuccessMessage(player, Stargate.getString("teleportMsg")); new VehicleTeleporter(destinationPortal, vehicle).teleport(entrancePortal); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); } /** @@ -152,7 +152,7 @@ public class VehicleEventListener implements Listener { //Make sure the user can access the portal if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destinationPortal)) { Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); return false; } diff --git a/src/main/java/net/knarcraft/stargate/portal/Portal.java b/src/main/java/net/knarcraft/stargate/portal/Portal.java index cce7cb3..2ea0332 100644 --- a/src/main/java/net/knarcraft/stargate/portal/Portal.java +++ b/src/main/java/net/knarcraft/stargate/portal/Portal.java @@ -1,24 +1,11 @@ package net.knarcraft.stargate.portal; -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.RelativeBlockVector; -import net.knarcraft.stargate.event.StargateActivateEvent; -import net.knarcraft.stargate.event.StargateCloseEvent; -import net.knarcraft.stargate.event.StargateDeactivateEvent; -import net.knarcraft.stargate.event.StargateOpenEvent; -import org.bukkit.Axis; -import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.block.data.Orientable; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.Map; -import java.util.Random; import java.util.UUID; /** @@ -26,59 +13,77 @@ import java.util.UUID; */ public class Portal { - // Gate location block info + // Gate information + private final String name; + private final String network; + private final String ownerName; + private final UUID ownerUUID; + + private final PortalOptions options; + private final PortalOpener portalOpener; private final PortalLocation location; private final PortalSignDrawer signDrawer; - - // Block references - private final Gate gate; - private BlockLocation button; - private BlockLocation[] frame; - private BlockLocation[] entrances; - - // Gate information - private String name; - private String destination; - private String lastDestination = ""; - private String network; - private final String ownerName; - private UUID ownerUUID; - private boolean verified; - private final PortalOptions options; - - // In-use information - private Player player; - private Player activePlayer; - private List destinations = new ArrayList<>(); - private boolean isOpen = false; - private long openTime; + private final PortalStructure structure; + private final PortalActivator portalActivator; /** * Instantiates a new portal * * @param portalLocation

Object containing locations of all relevant blocks

* @param button

The location of the portal's open button

- * @param destination

The destination defined on the sign's destination line

+ * @param destination

The destination defined on the sign's destination line. "" for non-fixed gates

* @param name

The name of the portal defined on the sign's first line

- * @param network

The network the portal belongs to, defined on the sign's network line

- * @param gate

The gate template this portal uses

+ * @param network

The network the portal belongs to, defined on the sign's third

+ * @param gate

The gate type to use for this portal

* @param ownerUUID

The UUID of the gate's owner

* @param ownerName

The name of the gate's owner

- * @param options

A map containing all possible portal options

+ * @param options

A map containing all possible portal options, with true for the ones enabled

*/ - Portal(PortalLocation portalLocation, BlockLocation button, String destination, String name, String network, - Gate gate, UUID ownerUUID, String ownerName, Map options) { + public Portal(PortalLocation portalLocation, BlockLocation button, String destination, String name, String network, + Gate gate, UUID ownerUUID, String ownerName, Map options) { this.location = portalLocation; - this.destination = destination; - this.button = button; - this.verified = false; this.network = network; this.name = name; - this.gate = gate; this.ownerUUID = ownerUUID; this.ownerName = ownerName; this.options = new PortalOptions(options, destination.length() > 0); this.signDrawer = new PortalSignDrawer(this); + this.portalOpener = new PortalOpener(this, destination); + this.structure = new PortalStructure(this, gate, button); + this.portalActivator = portalOpener.getPortalOpener(); + } + + /** + * Gets the location data for this portal + * + * @return

This portal's location data

+ */ + public PortalLocation getLocation() { + return this.location; + } + + /** + * Gets the structure of this portal + * + *

The structure contains information about the portal's gate, button and real locations of frames and + * entrances. The structure is also responsible for verifying built StarGates to make sure they match the gate.

+ * + * @return

This portal's structure

+ */ + public PortalStructure getStructure() { + return this.structure; + } + + /** + * Gets this portal's activator + * + *

The activator is responsible for activating/de-activating the portal and contains information about + * available destinations and which player activated the portal.

+ * + * @return

This portal's activator

+ */ + public PortalActivator getPortalActivator() { + return this.portalActivator; } /** @@ -103,7 +108,7 @@ public class Portal { * @return

Whether this portal is open

*/ public boolean isOpen() { - return isOpen || options.isAlwaysOn(); + return portalOpener.isOpen(); } /** @@ -112,35 +117,28 @@ public class Portal { * @return

The player currently using this portal

*/ public Player getActivePlayer() { - return activePlayer; + return portalActivator.getActivePlayer(); } /** - * Gets the network this gate belongs to + * Gets the network this portal belongs to * - * @return

The network this gate belongs to

+ * @return

The network this portal belongs to

*/ public String getNetwork() { return network; } - /** - * Sets the network this gate belongs to - * - * @param network

The new network for this gate

- */ - @SuppressWarnings("unused") - public void setNetwork(String network) { - this.network = network; - } - /** * Gets the time this portal opened * + *

The time is given in the equivalent of a Unix timestamp. It's used to decide when a portal times out and + * automatically closes.

+ * * @return

The time this portal opened

*/ public long getOpenTime() { - return openTime; + return portalOpener.getOpenTime(); } /** @@ -153,94 +151,39 @@ public class Portal { } /** - * Sets the name of this portal + * Gets the portal opener used by this portal * - * @param name

The new name of this portal

+ *

The portal opener is responsible for opening and closing this portal.

+ * + * @return

This portal's portal opener

*/ - @SuppressWarnings("unused") - public void setName(String name) { - this.name = filterName(name); - this.drawSign(); + public PortalOpener getPortalOpener() { + return portalOpener; } /** - * Gets the destinations of this portal + * Gets the name of this portal's destination portal * - * @return

The destinations of this portal

- */ - public List getDestinations() { - return new ArrayList<>(this.destinations); - } - - /** - * Gets the portal destination given a player - * - * @param player

Used for random gates to determine which destinations are available

- * @return

The destination portal the player should teleport to

- */ - public Portal getDestination(Player player) { - if (options.isRandom()) { - destinations = PortalHandler.getDestinations(this, player, getNetwork()); - if (destinations.size() == 0) { - return null; - } - String destination = destinations.get((new Random()).nextInt(destinations.size())); - destinations.clear(); - return PortalHandler.getByName(destination, getNetwork()); - } - return PortalHandler.getByName(destination, getNetwork()); - } - - /** - * Gets the portal destination - * - *

If this portal is random, a player should be given to get correct destinations.

- * - * @return

The portal destination

- */ - public Portal getDestination() { - return getDestination(null); - } - - /** - * Sets the destination of this portal - * - * @param destination

The new destination of this portal

- */ - public void setDestination(Portal destination) { - setDestination(destination.getName()); - } - - /** - * Sets the destination of this portal - * - * @param destination

The new destination of this portal

- */ - public void setDestination(String destination) { - this.destination = destination; - } - - /** - * Gets the name of the destination of this portal - * - * @return

The name of this portal's destination

+ * @return

The name of this portal's destination portal

*/ public String getDestinationName() { - return destination; + return portalOpener.getPortalOpener().getDestinationName(); } /** - * Gets the gate used by this portal + * Gets the gate type used by this portal * - * @return

The gate used by this portal

+ * @return

The gate type used by this portal

*/ public Gate getGate() { - return gate; + return structure.getGate(); } /** * Gets the name of this portal's owner * + *

The owner is the player which created the portal.

+ * * @return

The name of this portal's owner

*/ public String getOwnerName() { @@ -250,22 +193,14 @@ public class Portal { /** * Gets the UUID of this portal's owner * + *

The owner is the player which created the portal.

+ * * @return

The UUID of this portal's owner

*/ public UUID getOwnerUUID() { return ownerUUID; } - /** - * Sets the UUId of this portal's owner - * - * @param owner

The new UUID of this portal's owner

- */ - @SuppressWarnings("unused") - public void setOwner(UUID owner) { - this.ownerUUID = owner; - } - /** * Checks whether a given player is the owner of this portal * @@ -280,30 +215,6 @@ public class Portal { } } - /** - * Gets the locations of this portal's entrances - * - * @return

The locations of this portal's entrances

- */ - public BlockLocation[] getEntrances() { - if (entrances == null) { - entrances = relativeBlockVectorsToBlockLocations(gate.getLayout().getEntrances()); - } - return entrances; - } - - /** - * Gets the locations of this portal's frame - * - * @return

The locations of this portal's frame

- */ - public BlockLocation[] getFrame() { - if (frame == null) { - frame = relativeBlockVectorsToBlockLocations(gate.getLayout().getBorder()); - } - return frame; - } - /** * Gets the world this portal belongs to * @@ -314,167 +225,21 @@ public class Portal { } /** - * Gets the location of this portal's button + * Gets the location of this portal's sign * - * @return

The location of this portal's button

- */ - public BlockLocation getButton() { - return button; - } - - /** - * Sets the location of this portal's button - * - * @param button

The location of this portal's button

- */ - public void setButton(BlockLocation button) { - this.button = button; - } - - /** - * Open this portal - * - * @param force

Whether to force this portal open, even if it's already open for some player

- */ - public void open(boolean force) { - open(null, force); - } - - /** - * Open this portal - * - * @param force

Whether to force this portal open, even if it's already open for some player

- */ - public void open(Player openFor, boolean force) { - //Call the StargateOpenEvent - StargateOpenEvent event = new StargateOpenEvent(openFor, this, force); - Stargate.server.getPluginManager().callEvent(event); - if (event.isCancelled() || (isOpen() && !event.getForce())) { - return; - } - - //Change the opening blocks to the correct type - Material openType = gate.getPortalOpenBlock(); - Axis axis = (openType.createBlockData() instanceof Orientable) ? location.getRotationAxis() : null; - for (BlockLocation inside : getEntrances()) { - Stargate.blockChangeRequestQueue.add(new BlockChangeRequest(inside, openType, axis)); - } - - updatePortalOpenState(openFor); - } - - /** - * Updates this portal to be recognized as open and opens its destination portal - * - * @param openFor

The player to open this portal for

- */ - private void updatePortalOpenState(Player openFor) { - //Update the open state of this portal - isOpen = true; - openTime = System.currentTimeMillis() / 1000; - Stargate.openPortalsQueue.add(this); - Stargate.activePortalsQueue.remove(this); - - //Open remote portal - if (!options.isAlwaysOn()) { - player = openFor; - - Portal destination = getDestination(); - //Only open destination if it's not-fixed or points at this portal - if (!options.isRandom() && destination != null && (!destination.options.isFixed() || - destination.getDestinationName().equalsIgnoreCase(getName())) && !destination.isOpen()) { - destination.open(openFor, false); - destination.setDestination(this); - if (destination.isVerified()) { - destination.drawSign(); - } - } - } - } - - /** - * Closes this portal - * - * @param force

Whether to force this portal closed, even if it's set as always on

- */ - public void close(boolean force) { - if (!isOpen) { - return; - } - //Call the StargateCloseEvent - StargateCloseEvent event = new StargateCloseEvent(this, force); - Stargate.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - force = event.getForce(); - - //Only close always-open if forced to - if (options.isAlwaysOn() && !force) { - return; - } - - //Close this gate, then the dest gate. - Material closedType = gate.getPortalClosedBlock(); - for (BlockLocation inside : getEntrances()) { - Stargate.blockChangeRequestQueue.add(new BlockChangeRequest(inside, closedType, null)); - } - - 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; - isOpen = false; - Stargate.openPortalsQueue.remove(this); - Stargate.activePortalsQueue.remove(this); - - //Close remote portal - if (!options.isAlwaysOn()) { - Portal end = getDestination(); - - if (end != null && end.isOpen()) { - //Clear its destination first - end.deactivate(); - end.close(false); - } - } - } - - /** - * Gets whether this portal is open for the given player - * - * @param player

The player to check portal state for

- * @return

True if this portal is open to the given player

- */ - public boolean isOpenFor(Player player) { - if (!isOpen) { - return false; - } - if (options.isAlwaysOn() || this.player == null) { - return true; - } - return player != null && player.getName().equalsIgnoreCase(this.player.getName()); - } - - /** - * Gets the identity (sign) location of the portal - * - * @return

The identity location of the portal

+ * @return

The location of this portal's sign

*/ public BlockLocation getSignLocation() { return this.location.getSignLocation(); } /** - * Gets the rotation of this portal + * Gets the rotation (yaw) of this portal * - * @return

The rotation of this portal

+ *

The yaw is used to calculate all kinds of directions. See DirectionHelper to see how the yaw is used to + * calculate to/from other direction types.

+ * + * @return

The rotation (yaw) of this portal

*/ public float getYaw() { return this.location.getYaw(); @@ -490,213 +255,19 @@ public class Portal { } /** - * Verifies that all control blocks in this portal follows its gate template + * Gets the block at the given location relative to this portal's top-left block * - * @return

True if all control blocks were verified

- */ - public boolean isVerified() { - verified = true; - if (!Stargate.verifyPortals) { - return true; - } - for (RelativeBlockVector control : gate.getLayout().getControls()) { - verified = verified && getBlockAt(control).getBlock().getType().equals(gate.getControlBlock()); - } - return verified; - } - - /** - * Gets the result of the last portal verification - * - * @return

True if this portal was verified

- */ - public boolean wasVerified() { - if (!Stargate.verifyPortals) { - return true; - } - return verified; - } - - /** - * Checks if all blocks in a gate matches the gate template - * - * @return

True if all blocks match the gate template

- */ - public boolean checkIntegrity() { - if (!Stargate.verifyPortals) { - return true; - } - return gate.matches(getTopLeft(), getYaw()); - } - - /** - * Activates this portal for the given player - * - * @param player

The player to activate the portal for

- * @return

True if the portal was activated

- */ - private boolean activate(Player player) { - destinations.clear(); - destination = ""; - Stargate.activePortalsQueue.add(this); - activePlayer = player; - String network = getNetwork(); - destinations = PortalHandler.getDestinations(this, player, network); - if (Stargate.sortNetworkDestinations) { - Collections.sort(destinations); - } - if (Stargate.rememberDestination && !lastDestination.isEmpty() && destinations.contains(lastDestination)) { - destination = lastDestination; - } - - StargateActivateEvent event = new StargateActivateEvent(this, player, destinations, destination); - Stargate.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - Stargate.activePortalsQueue.remove(this); - return false; - } - destination = event.getDestination(); - destinations = event.getDestinations(); - this.drawSign(); - return true; - } - - /** - * Deactivates this portal - */ - public void deactivate() { - StargateDeactivateEvent event = new StargateDeactivateEvent(this); - Stargate.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - - Stargate.activePortalsQueue.remove(this); - if (options.isFixed()) { - return; - } - destinations.clear(); - destination = ""; - activePlayer = null; - this.drawSign(); - } - - /** - * Gets whether this portal is active - * - * @return

Whether this portal is active

- */ - public boolean isActive() { - return options.isFixed() || (destinations.size() > 0); - } - - /** - * Cycles destination for a network gate forwards - * - * @param player

The player to cycle the gate for

- */ - public void cycleDestination(Player player) { - cycleDestination(player, 1); - } - - /** - * Cycles destination for a network gate - * - * @param player

The player cycling destinations

- * @param direction

The direction of the cycle (+1 for next, -1 for previous)

- */ - public void cycleDestination(Player player, int direction) { - if (direction != 1 && direction != -1) { - throw new IllegalArgumentException("The destination direction must be 1 or -1."); - } - - boolean activate = false; - if (!isActive() || getActivePlayer() != player) { - //If the stargate activate event is cancelled, return - if (!activate(player)) { - return; - } - Stargate.debug("cycleDestination", "Network Size: " + PortalHandler.getNetwork(network).size()); - Stargate.debug("cycleDestination", "Player has access to: " + destinations.size()); - activate = true; - } - - if (destinations.size() == 0) { - Stargate.sendErrorMessage(player, Stargate.getString("destEmpty")); - return; - } - - if (!Stargate.rememberDestination || !activate || lastDestination.isEmpty()) { - cycleDestination(direction); - } - openTime = System.currentTimeMillis() / 1000; - this.drawSign(); - } - - /** - * Performs the actual destination cycling with no input checks - * - * @param direction

The direction of the cycle (+1 for next, -1 for previous)

- */ - private void cycleDestination(int direction) { - int index = destinations.indexOf(destination); - index += direction; - - //Wrap around if the last destination has been reached - if (index >= destinations.size()) { - index = 0; - } else if (index < 0) { - index = destinations.size() - 1; - } - //Store selected destination - destination = destinations.get(index); - lastDestination = destination; - } - - /** - * Gets the block at the given location relative to this portal's location - * - * @param vector

The relative block vector

+ * @param vector

The relative block vector explaining the position of the block

* @return

The block at the given relative position

*/ public BlockLocation getBlockAt(RelativeBlockVector vector) { return getTopLeft().getRelativeLocation(vector, getYaw()); } - /** - * Removes the special characters |, : and # from a portal name - * - * @param input

The name to filter

- * @return

The filtered name

- */ - 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 - * - *

The block locations will be calculated by using this portal's top-left block as the origin for the relative - * vectors..

- * - * @param vectors

The relative block vectors to convert

- * @return

A list of block locations

- */ - private BlockLocation[] relativeBlockVectorsToBlockLocations(RelativeBlockVector[] vectors) { - BlockLocation[] locations = new BlockLocation[vectors.length]; - for (int i = 0; i < vectors.length; i++) { - locations[i] = getBlockAt(vectors[i]); - } - return locations; - } - @Override public String toString() { return String.format("Portal [id=%s, network=%s name=%s, type=%s]", getSignLocation(), network, name, - gate.getFilename()); + structure.getGate().getFilename()); } @Override diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java b/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java new file mode 100644 index 0000000..c8ca84e --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java @@ -0,0 +1,241 @@ +package net.knarcraft.stargate.portal; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.event.StargateActivateEvent; +import net.knarcraft.stargate.event.StargateDeactivateEvent; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +/** + * The portal destinations contain information about a portal's destinations, and is responsible for cycling destinations + * + *

The activator is responsible for activating/de-activating the portal and contains information about + * available destinations and which player activated the portal.

+ */ +public class PortalActivator { + + private String destination; + private String lastDestination = ""; + private List destinations = new ArrayList<>(); + private final Portal portal; + private final PortalOpener activator; + private Player activePlayer; + + /** + * Instantiates a new portal destinations object + * + * @param portal

The portal which this this object stores destinations for

+ * @param activator

The activator to use when a player activates a portal

+ * @param destination

+ */ + public PortalActivator(Portal portal, PortalOpener activator, String destination) { + this.portal = portal; + this.activator = activator; + this.destination = destination; + } + + /** + * Gets the player currently using this portal activator's portal + * + * @return

The player currently using this portal activator's portal

+ */ + public Player getActivePlayer() { + return activePlayer; + } + + /** + * Gets the destinations of this portal + * + * @return

The destinations of this portal

+ */ + public List getDestinations() { + return new ArrayList<>(this.destinations); + } + + /** + * Gets the portal destination given a player + * + * @param player

Used for random gates to determine which destinations are available

+ * @return

The destination portal the player should teleport to

+ */ + public Portal getDestination(Player player) { + if (portal.getOptions().isRandom()) { + destinations = PortalHandler.getDestinations(portal, player, portal.getNetwork()); + if (destinations.size() == 0) { + return null; + } + String destination = destinations.get((new Random()).nextInt(destinations.size())); + destinations.clear(); + return PortalHandler.getByName(destination, portal.getNetwork()); + } + return PortalHandler.getByName(destination, portal.getNetwork()); + } + + /** + * Activates this portal for the given player + * + * @param player

The player to activate the portal for

+ * @return

True if the portal was activated

+ */ + boolean activate(Player player) { + this.destination = ""; + this.destinations.clear(); + Stargate.activePortalsQueue.add(portal); + activePlayer = player; + String network = portal.getNetwork(); + destinations = PortalHandler.getDestinations(portal, player, network); + if (Stargate.sortNetworkDestinations) { + Collections.sort(destinations); + } + if (Stargate.rememberDestination && !lastDestination.isEmpty() && destinations.contains(lastDestination)) { + destination = lastDestination; + } + + StargateActivateEvent event = new StargateActivateEvent(portal, player, destinations, destination); + Stargate.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + Stargate.activePortalsQueue.remove(portal); + return false; + } + destination = event.getDestination(); + destinations = event.getDestinations(); + portal.drawSign(); + return true; + } + + /** + * Deactivates this portal + */ + public void deactivate() { + StargateDeactivateEvent event = new StargateDeactivateEvent(portal); + Stargate.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + + Stargate.activePortalsQueue.remove(portal); + if (portal.getOptions().isFixed()) { + return; + } + destinations.clear(); + destination = ""; + activePlayer = null; + portal.drawSign(); + } + + /** + * Gets whether this portal is active + * + * @return

Whether this portal is active

+ */ + public boolean isActive() { + return portal.getOptions().isFixed() || (destinations.size() > 0); + } + + /** + * Gets the portal destination + * + *

If this portal is random, a player should be given to get correct destinations.

+ * + * @return

The portal destination

+ */ + public Portal getDestination() { + return getDestination(null); + } + + /** + * Sets the destination of this portal + * + * @param destination

The new destination of this portal

+ */ + public void setDestination(Portal destination) { + setDestination(destination.getName()); + } + + /** + * Sets the destination of this portal + * + * @param destination

The new destination of this portal

+ */ + public void setDestination(String destination) { + this.destination = destination; + } + + /** + * Gets the name of the destination of this portal + * + * @return

The name of this portal's destination

+ */ + public String getDestinationName() { + return destination; + } + + /** + * Cycles destination for a network gate forwards + * + * @param player

The player to cycle the gate for

+ */ + public void cycleDestination(Player player) { + cycleDestination(player, 1); + } + + /** + * Cycles destination for a network gate + * + * @param player

The player cycling destinations

+ * @param direction

The direction of the cycle (+1 for next, -1 for previous)

+ */ + public void cycleDestination(Player player, int direction) { + if (direction != 1 && direction != -1) { + throw new IllegalArgumentException("The destination direction must be 1 or -1."); + } + + boolean activate = false; + if (!isActive() || getActivePlayer() != player) { + //If the stargate activate event is cancelled, return + if (!activate(player)) { + return; + } + Stargate.debug("cycleDestination", "Network Size: " + + PortalHandler.getNetwork(portal.getNetwork()).size()); + Stargate.debug("cycleDestination", "Player has access to: " + destinations.size()); + activate = true; + } + + if (destinations.size() == 0) { + Stargate.sendErrorMessage(player, Stargate.getString("destEmpty")); + return; + } + + if (!Stargate.rememberDestination || !activate || lastDestination.isEmpty()) { + cycleDestination(direction); + } + activator.setOpenTime(System.currentTimeMillis() / 1000); + portal.drawSign(); + } + + /** + * Performs the actual destination cycling with no input checks + * + * @param direction

The direction of the cycle (+1 for next, -1 for previous)

+ */ + private void cycleDestination(int direction) { + int index = destinations.indexOf(destination); + index += direction; + + //Wrap around if the last destination has been reached + if (index >= destinations.size()) { + index = 0; + } else if (index < 0) { + index = destinations.size() - 1; + } + //Store selected destination + destination = destinations.get(index); + lastDestination = destination; + } + +} diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java index 1ff3bb6..71740d5 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java @@ -119,26 +119,28 @@ public class PortalHandler { */ public static void unregisterPortal(Portal portal, boolean removeAll) { Stargate.debug("Unregister", "Unregistering gate " + portal.getName()); - portal.close(true); + portal.getPortalOpener().closePortal(true); String portalName = portal.getName().toLowerCase(); String networkName = portal.getNetwork().toLowerCase(); //Remove portal from lookup blocks - for (BlockLocation block : portal.getFrame()) { + for (BlockLocation block : portal.getStructure().getFrame()) { lookupBlocks.remove(block); } //Remove registered info about the lookup controls and blocks lookupBlocks.remove(portal.getSignLocation()); lookupControls.remove(portal.getSignLocation()); - if (portal.getButton() != null) { - lookupBlocks.remove(portal.getButton()); - lookupControls.remove(portal.getButton()); + + BlockLocation button = portal.getStructure().getButton(); + if (button != null) { + lookupBlocks.remove(button); + lookupControls.remove(button); } //Remove entrances - for (BlockLocation entrance : portal.getEntrances()) { + for (BlockLocation entrance : portal.getStructure().getEntrances()) { lookupEntrances.remove(entrance); } @@ -158,7 +160,8 @@ public class PortalHandler { //Update all portals in the same network with this portal as its destination for (String originName : allPortalNetworks.get(networkName)) { Portal origin = getByName(originName, portal.getNetwork()); - if (origin == null || !origin.getDestinationName().equalsIgnoreCase(portalName) || !origin.isVerified()) { + if (origin == null || !origin.getDestinationName().equalsIgnoreCase(portalName) || + !origin.getStructure().isVerified()) { continue; } //Update the portal's sign @@ -167,7 +170,7 @@ public class PortalHandler { } //Close portal without destination if (origin.getOptions().isAlwaysOn()) { - origin.close(true); + origin.getPortalOpener().closePortal(true); } } } @@ -218,19 +221,21 @@ public class PortalHandler { } //Register all frame blocks to the lookup list - for (BlockLocation block : portal.getFrame()) { + for (BlockLocation block : portal.getStructure().getFrame()) { lookupBlocks.put(block, portal); } //Register the sign and button to the lookup lists lookupBlocks.put(portal.getSignLocation(), portal); lookupControls.put(portal.getSignLocation(), portal); - if (portal.getButton() != null) { - lookupBlocks.put(portal.getButton(), portal); - lookupControls.put(portal.getButton(), portal); + + BlockLocation button = portal.getStructure().getButton(); + if (button != null) { + lookupBlocks.put(button, portal); + lookupControls.put(button, portal); } //Register entrances to the lookup list - for (BlockLocation entrance : portal.getEntrances()) { + for (BlockLocation entrance : portal.getStructure().getEntrances()) { lookupEntrances.put(entrance, portal); } @@ -574,7 +579,7 @@ public class PortalHandler { Directional buttonData = (Directional) Bukkit.createBlockData(portal.getGate().getPortalButton()); buttonData.setFacing(buttonFacing); button.getBlock().setBlockData(buttonData); - portal.setButton(button); + portal.getStructure().setButton(button); } /** @@ -587,16 +592,16 @@ public class PortalHandler { portal.drawSign(); //Open an always on portal if (portal.getOptions().isRandom() || portal.getOptions().isBungee()) { - portal.open(true); + portal.getPortalOpener().openPortal(true); } else if (portal.getOptions().isAlwaysOn()) { Portal destinationPortal = getByName(destinationName, portal.getNetwork()); if (destinationPortal != null) { - portal.open(true); + portal.getPortalOpener().openPortal(true); destinationPortal.drawSign(); } } else { //Update the block type for the portal's opening to the closed block - for (BlockLocation entrance : portal.getEntrances()) { + for (BlockLocation entrance : portal.getStructure().getEntrances()) { entrance.setType(portal.getGate().getPortalClosedBlock()); } } @@ -612,7 +617,7 @@ public class PortalHandler { Portal origin = getByName(originName, portal.getNetwork()); if (origin == null || !origin.getDestinationName().equalsIgnoreCase(portal.getName()) || - !origin.isVerified()) { + !origin.getStructure().isVerified()) { continue; } //Update sign of fixed gates pointing at this gate @@ -621,7 +626,7 @@ public class PortalHandler { } //Open any always on portal pointing at this portal if (origin.getOptions().isAlwaysOn()) { - origin.open(true); + origin.getPortalOpener().openPortal(true); } } } @@ -791,7 +796,7 @@ public class PortalHandler { String wName = portal.getWorld().getName(); if (!wName.equalsIgnoreCase(world.getName())) continue; StringBuilder builder = new StringBuilder(); - BlockLocation button = portal.getButton(); + BlockLocation button = portal.getStructure().getButton(); builder.append(portal.getName()).append(':'); builder.append(portal.getSignLocation().toString()).append(':'); @@ -1007,7 +1012,7 @@ public class PortalHandler { network, gate, ownerUUID, ownerName, getPortalOptions(portalData)); registerPortal(portal); - portal.close(true); + portal.getPortalOpener().closePortal(true); } /** @@ -1040,7 +1045,8 @@ public class PortalHandler { } // Verify portal integrity/register portal - if (!portal.wasVerified() && (!portal.isVerified() || !portal.checkIntegrity())) { + PortalStructure structure = portal.getStructure(); + if (!structure.wasVerified() && (!structure.isVerified() || !structure.checkIntegrity())) { destroyInvalidPortal(portal); iterator.remove(); continue; @@ -1049,8 +1055,8 @@ public class PortalHandler { //Open the gate if it's set as always open or if it's a bungee gate if (portal.getOptions().isFixed() && (Stargate.enableBungee && portal.getOptions().isBungee() || - portal.getDestination() != null && portal.getOptions().isAlwaysOn())) { - portal.open(true); + portal.getPortalActivator().getDestination() != null && portal.getOptions().isAlwaysOn())) { + portal.getPortalOpener().openPortal(true); openCount++; } } @@ -1080,7 +1086,7 @@ public class PortalHandler { Stargate.logger.info("Closing all stargates."); for (Portal portal : allPortals) { if (portal != null) { - portal.close(true); + portal.getPortalOpener().closePortal(true); } } } diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalOpener.java b/src/main/java/net/knarcraft/stargate/portal/PortalOpener.java new file mode 100644 index 0000000..c169c6f --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/portal/PortalOpener.java @@ -0,0 +1,203 @@ +package net.knarcraft.stargate.portal; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.container.BlockChangeRequest; +import net.knarcraft.stargate.container.BlockLocation; +import net.knarcraft.stargate.event.StargateCloseEvent; +import net.knarcraft.stargate.event.StargateOpenEvent; +import org.bukkit.Axis; +import org.bukkit.Material; +import org.bukkit.block.data.Orientable; +import org.bukkit.entity.Player; + +/** + * The portal opener is responsible for opening and closing a portal + */ +public class PortalOpener { + + private boolean isOpen = false; + private final Portal portal; + private long openTime; + private Player player; + private final PortalActivator portalActivator; + + /** + * Instantiates a new portal opener + * + * @param portal

The portal this portal opener should open

+ * @param destination

The fixed destination defined on the portal's sign

+ */ + public PortalOpener(Portal portal, String destination) { + this.portal = portal; + this.portalActivator = new PortalActivator(portal, this, destination); + } + + /** + * Gets whether this portal activator's portal is currently open + * + * @return

Whether this portal activator's portal is open

+ */ + public boolean isOpen() { + return isOpen || portal.getOptions().isAlwaysOn(); + } + + /** + * Sets the time when this portal was activated + * + * @param openTime

Unix timestamp when portal was activated

+ */ + public void setOpenTime(long openTime) { + this.openTime = openTime; + } + + /** + * Gets the destinations this portal activator has available + * + * @return

The available destinations

+ */ + public PortalActivator getPortalOpener() { + return this.portalActivator; + } + + /** + * Open this portal + * + * @param force

Whether to force this portal open, even if it's already open for some player

+ */ + public void openPortal(boolean force) { + openPortal(null, force); + } + + /** + * Open this portal + * + * @param force

Whether to force this portal open, even if it's already open for some player

+ */ + public void openPortal(Player openFor, boolean force) { + //Call the StargateOpenEvent + StargateOpenEvent event = new StargateOpenEvent(openFor, portal, force); + Stargate.server.getPluginManager().callEvent(event); + if (event.isCancelled() || (isOpen() && !event.getForce())) { + return; + } + + //Change the opening blocks to the correct type + Material openType = portal.getGate().getPortalOpenBlock(); + Axis axis = (openType.createBlockData() instanceof Orientable) ? portal.getLocation().getRotationAxis() : null; + for (BlockLocation inside : portal.getStructure().getEntrances()) { + Stargate.blockChangeRequestQueue.add(new BlockChangeRequest(inside, openType, axis)); + } + + updatePortalOpenState(openFor); + } + + /** + * Updates this portal to be recognized as open and opens its destination portal + * + * @param openFor

The player to open this portal for

+ */ + private void updatePortalOpenState(Player openFor) { + //Update the open state of this portal + isOpen = true; + openTime = System.currentTimeMillis() / 1000; + Stargate.openPortalsQueue.add(portal); + Stargate.activePortalsQueue.remove(portal); + PortalOptions options = portal.getOptions(); + + //Open remote portal + if (!options.isAlwaysOn()) { + player = openFor; + + Portal destination = portal.getPortalActivator().getDestination(); + //Only open destination if it's not-fixed or points at this portal + if (!options.isRandom() && destination != null && (!destination.getOptions().isFixed() || + destination.getDestinationName().equalsIgnoreCase(portal.getName())) && !destination.isOpen()) { + destination.getPortalOpener().openPortal(openFor, false); + destination.getPortalActivator().setDestination(portal); + if (destination.getStructure().isVerified()) { + destination.drawSign(); + } + } + } + } + + /** + * Closes this portal + * + * @param force

Whether to force this portal closed, even if it's set as always on

+ */ + public void closePortal(boolean force) { + if (!isOpen) { + return; + } + //Call the StargateCloseEvent + StargateCloseEvent event = new StargateCloseEvent(portal, force); + Stargate.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + force = event.getForce(); + + //Only close always-open if forced to + if (portal.getOptions().isAlwaysOn() && !force) { + return; + } + + //Close this gate, then the dest gate. + Material closedType = portal.getGate().getPortalClosedBlock(); + for (BlockLocation inside : portal.getStructure().getEntrances()) { + Stargate.blockChangeRequestQueue.add(new BlockChangeRequest(inside, closedType, null)); + } + + updatePortalClosedState(); + portalActivator.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; + isOpen = false; + Stargate.openPortalsQueue.remove(portal); + Stargate.activePortalsQueue.remove(portal); + + //Close remote portal + if (!portal.getOptions().isAlwaysOn()) { + Portal end = portal.getPortalActivator().getDestination(); + + if (end != null && end.isOpen()) { + //Clear its destination first + end.getPortalActivator().deactivate(); + end.getPortalOpener().closePortal(false); + } + } + } + + /** + * Gets whether this portal is open for the given player + * + * @param player

The player to check portal state for

+ * @return

True if this portal is open to the given player

+ */ + public boolean isOpenFor(Player player) { + if (!isOpen) { + return false; + } + if (portal.getOptions().isAlwaysOn() || this.player == null) { + return true; + } + return player != null && player.getName().equalsIgnoreCase(this.player.getName()); + } + + /** + * Gets the time this portal activator's portal opened + * + * @return

The time this portal activator's portal opened

+ */ + public long getOpenTime() { + return openTime; + } + +} diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java b/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java index 9b85e0b..0467f4d 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java @@ -53,7 +53,7 @@ public class PortalSignDrawer { Stargate.setLine(sign, 0, ChatColor.WHITE + "-" + Stargate.signColor + portal.getName() + ChatColor.WHITE + "-"); - if (!portal.isActive()) { + if (!portal.getPortalActivator().isActive()) { //Default sign text drawInactiveSign(sign); } else { @@ -78,9 +78,10 @@ public class PortalSignDrawer { * @param sign

The sign to re-draw

*/ private void drawNetworkSign(Sign sign) { - int maxIndex = portal.getDestinations().size() - 1; + PortalActivator destinations = portal.getPortalActivator(); + int maxIndex = destinations.getDestinations().size() - 1; int signLineIndex = 0; - int destinationIndex = portal.getDestinations().indexOf(portal.getDestinationName()); + int destinationIndex = destinations.getDestinations().indexOf(portal.getDestinationName()); boolean freeGatesGreen = EconomyHandler.useEconomy() && EconomyHandler.freeGatesGreen; //Last, and not only entry. Draw the entry two back @@ -131,12 +132,15 @@ public class PortalSignDrawer { * @param destinationIndex

The index of the destination to draw

*/ private void drawNetworkSignLine(boolean freeGatesGreen, Sign sign, int signLineIndex, int destinationIndex) { + PortalActivator destinations = portal.getPortalActivator(); if (freeGatesGreen) { - Portal destination = PortalHandler.getByName(portal.getDestinations().get(destinationIndex), portal.getNetwork()); + Portal destination = PortalHandler.getByName(destinations.getDestinations().get(destinationIndex), + portal.getNetwork()); boolean green = PermissionHelper.isFree(portal.getActivePlayer(), portal, destination); - Stargate.setLine(sign, signLineIndex, (green ? ChatColor.DARK_GREEN : "") + portal.getDestinations().get(destinationIndex)); + Stargate.setLine(sign, signLineIndex, (green ? ChatColor.DARK_GREEN : "") + + destinations.getDestinations().get(destinationIndex)); } else { - Stargate.setLine(sign, signLineIndex, portal.getDestinations().get(destinationIndex)); + Stargate.setLine(sign, signLineIndex, destinations.getDestinations().get(destinationIndex)); } } diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalStructure.java b/src/main/java/net/knarcraft/stargate/portal/PortalStructure.java new file mode 100644 index 0000000..73509b7 --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/portal/PortalStructure.java @@ -0,0 +1,147 @@ +package net.knarcraft.stargate.portal; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.container.BlockLocation; +import net.knarcraft.stargate.container.RelativeBlockVector; + +/** + * The portal structure is responsible for the physical properties of a portal + * + *

The portal structure knows which gate type is used, where the real locations of buttons, frames and entrances are + * and whether the portal is verified.

+ */ +public class PortalStructure { + + private final Portal portal; + private final Gate gate; + private BlockLocation button; + private BlockLocation[] frame; + private BlockLocation[] entrances; + private boolean verified; + + /** + * Instantiates a new portal structure + * + * @param portal

The portal whose structure to store

+ * @param gate

The gate type used by this portal structure

+ * @param button

The real location of the portal's button

+ */ + public PortalStructure(Portal portal, Gate gate, BlockLocation button) { + this.portal = portal; + this.gate = gate; + this.verified = false; + this.button = button; + } + + /** + * Gets the gate used by this portal structure + * + * @return

The gate used by this portal structure

+ */ + public Gate getGate() { + return gate; + } + + /** + * Gets the location of this portal's button + * + * @return

The location of this portal's button

+ */ + public BlockLocation getButton() { + return button; + } + + /** + * Sets the location of this portal's button + * + * @param button

The location of this portal's button

+ */ + public void setButton(BlockLocation button) { + this.button = button; + } + + /** + * Verifies that all control blocks in this portal follows its gate template + * + * @return

True if all control blocks were verified

+ */ + public boolean isVerified() { + boolean verified = true; + if (!Stargate.verifyPortals) { + return true; + } + for (RelativeBlockVector control : gate.getLayout().getControls()) { + verified = verified && portal.getBlockAt(control).getBlock().getType().equals(gate.getControlBlock()); + } + this.verified = verified; + return verified; + } + + /** + * Gets the result of the last portal verification + * + * @return

True if this portal was verified

+ */ + public boolean wasVerified() { + if (!Stargate.verifyPortals) { + return true; + } + return verified; + } + + /** + * Checks if all blocks in a gate matches the gate template + * + * @return

True if all blocks match the gate template

+ */ + public boolean checkIntegrity() { + if (!Stargate.verifyPortals) { + return true; + } + return gate.matches(portal.getTopLeft(), portal.getYaw()); + } + + /** + * Gets a list of block locations from a list of relative block vectors + * + *

The block locations will be calculated by using this portal's top-left block as the origin for the relative + * vectors..

+ * + * @param vectors

The relative block vectors to convert

+ * @return

A list of block locations

+ */ + private BlockLocation[] relativeBlockVectorsToBlockLocations(RelativeBlockVector[] vectors) { + BlockLocation[] locations = new BlockLocation[vectors.length]; + for (int i = 0; i < vectors.length; i++) { + locations[i] = portal.getBlockAt(vectors[i]); + } + return locations; + } + + /** + * Gets the locations of this portal's entrances + * + * @return

The locations of this portal's entrances

+ */ + public BlockLocation[] getEntrances() { + if (entrances == null) { + //Get the locations of the entrances once, and only if necessary as it's an expensive operation + entrances = relativeBlockVectorsToBlockLocations(gate.getLayout().getEntrances()); + } + return entrances; + } + + /** + * Gets the locations of this portal's frame + * + * @return

The locations of this portal's frame

+ */ + public BlockLocation[] getFrame() { + if (frame == null) { + //Get the locations of the frame blocks once, and only if necessary as it's an expensive operation + frame = relativeBlockVectorsToBlockLocations(gate.getLayout().getBorder()); + } + return frame; + } + +} diff --git a/src/main/java/net/knarcraft/stargate/thread/StarGateThread.java b/src/main/java/net/knarcraft/stargate/thread/StarGateThread.java index b869971..6ddd63e 100644 --- a/src/main/java/net/knarcraft/stargate/thread/StarGateThread.java +++ b/src/main/java/net/knarcraft/stargate/thread/StarGateThread.java @@ -21,18 +21,18 @@ public class StarGateThread implements Runnable { continue; } if (time > portal.getOpenTime() + Stargate.getOpenTime()) { - portal.close(false); + portal.getPortalOpener().closePortal(false); iterator.remove(); } } //Deactivate active portals for (Iterator iterator = Stargate.activePortalsQueue.iterator(); iterator.hasNext(); ) { Portal portal = iterator.next(); - if (!portal.isActive()) { + if (!portal.getPortalActivator().isActive()) { continue; } if (time > portal.getOpenTime() + Stargate.getActiveTime()) { - portal.deactivate(); + portal.getPortalActivator().deactivate(); iterator.remove(); } } diff --git a/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java b/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java index 68ffcff..1481970 100644 --- a/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java @@ -35,7 +35,7 @@ public final class EconomyHelper { // Insufficient Funds if (!success) { sendInsufficientFundsMessage(entrancePortal.getName(), player, cost); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); return true; } diff --git a/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java b/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java index b0b5c38..454787f 100644 --- a/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java @@ -24,7 +24,7 @@ public final class PermissionHelper { * @param portal

The portal to open

*/ public static void openPortal(Player player, Portal portal) { - Portal destination = portal.getDestination(); + Portal destination = portal.getPortalActivator().getDestination(); //Always-open gate -- Do nothing if (portal.getOptions().isAlwaysOn()) { @@ -46,13 +46,14 @@ public final class PermissionHelper { if (portal.isOpen()) { // Close if this player opened the gate if (portal.getActivePlayer() == player) { - portal.close(false); + portal.getPortalOpener().closePortal(false); } return; } //Gate that someone else is using -- Deny access - if ((!portal.getOptions().isFixed()) && portal.isActive() && (portal.getActivePlayer() != player)) { + if ((!portal.getOptions().isFixed()) && portal.getPortalActivator().isActive() && + (portal.getActivePlayer() != player)) { Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); return; } @@ -70,7 +71,7 @@ public final class PermissionHelper { } //Open gate - portal.open(player, false); + portal.getPortalOpener().openPortal(player, false); } /** @@ -388,7 +389,7 @@ public final class PermissionHelper { } // Not open for this player - if (!entrancePortal.isOpenFor(player)) { + if (!entrancePortal.getPortalOpener().isOpenFor(player)) { Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); new PlayerTeleporter(entrancePortal, player).teleport(entrancePortal, event); return true; @@ -403,7 +404,7 @@ public final class PermissionHelper { if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destination)) { Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); new PlayerTeleporter(entrancePortal, player).teleport(entrancePortal, event); - entrancePortal.close(false); + entrancePortal.getPortalOpener().closePortal(false); return true; }