diff --git a/src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java b/src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java index 26da8b1..a1ca05d 100644 --- a/src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java @@ -3,6 +3,7 @@ package net.knarcraft.stargate.listener; import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.event.StargateDestroyEvent; import net.knarcraft.stargate.portal.Portal; +import net.knarcraft.stargate.portal.PortalCreator; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.utility.EconomyHandler; import net.knarcraft.stargate.utility.EconomyHelper; @@ -73,7 +74,7 @@ public class BlockEventListener implements Listener { return; } - final Portal portal = PortalHandler.createPortal(event, player); + final Portal portal = new PortalCreator(event, player).createPortal(); //Not creating a gate, just placing a sign if (portal == null) { return; diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java b/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java new file mode 100644 index 0000000..8f90732 --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java @@ -0,0 +1,311 @@ +package net.knarcraft.stargate.portal; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.container.BlockLocation; +import net.knarcraft.stargate.container.RelativeBlockVector; +import net.knarcraft.stargate.event.StargateCreateEvent; +import net.knarcraft.stargate.utility.DirectionHelper; +import net.knarcraft.stargate.utility.EconomyHandler; +import net.knarcraft.stargate.utility.EconomyHelper; +import net.knarcraft.stargate.utility.PermissionHelper; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Directional; +import org.bukkit.entity.Player; +import org.bukkit.event.block.SignChangeEvent; + +import java.util.List; +import java.util.Map; + +/** + * The portal creator can create and validate a new portal + */ +public class PortalCreator { + + private Portal portal; + private final SignChangeEvent event; + private final Player player; + + /** + * Instantiates a new portal creator + * + * @param event
The sign change event which initialized the creation
+ * @param playerThe player creating the portal
+ */ + public PortalCreator(SignChangeEvent event, Player player) { + this.event = event; + this.player = player; + } + + /** + * Creates a new portal + * + * @returnThe created portal
+ */ + public Portal createPortal() { + BlockLocation signLocation = new BlockLocation(event.getBlock()); + Block idParent = signLocation.getParent(); + + //Return early if the sign is not placed on a block, or the block is not a control block + if (idParent == null || GateHandler.getGatesByControlBlock(idParent).length == 0) { + Stargate.debug("createPortal", "Control block not registered"); + return null; + } + + //The control block is already part of another portal + if (PortalHandler.getByBlock(idParent) != null) { + Stargate.debug("createPortal", "idParent belongs to existing stargate"); + return null; + } + + //Get necessary information from the gate's sign + String portalName = PortalHandler.filterName(event.getLine(0)); + String destinationName = PortalHandler.filterName(event.getLine(1)); + String network = PortalHandler.filterName(event.getLine(2)); + String options = PortalHandler.filterName(event.getLine(3)).toLowerCase(); + + //Get portal options available to the player creating the portal + MapThe deny message to displayed if the creation has already been denied
+ * @param linesThe lines on the sign causing the portal to be created
+ * @param denyWhether the portal creation has already been denied
+ * @returnThe portal or null if its creation was denied
+ */ + public Portal validatePortal(String denyMessage, String[] lines, boolean deny) { + PortalLocation portalLocation = portal.getLocation(); + Gate gate = portal.getStructure().getGate(); + PortalOptions portalOptions = portal.getOptions(); + String portalName = portal.getName(); + String destinationName = portal.getDestinationName(); + + int createCost = EconomyHandler.getCreateCost(player, gate); + + //Call StargateCreateEvent to let other plugins cancel or overwrite denial + StargateCreateEvent stargateCreateEvent = new StargateCreateEvent(player, portal, lines, deny, + denyMessage, createCost); + Stargate.server.getPluginManager().callEvent(stargateCreateEvent); + if (stargateCreateEvent.isCancelled()) { + return null; + } + + //Tell the user why it was denied from creating the portal + if (stargateCreateEvent.getDeny()) { + Stargate.sendErrorMessage(player, stargateCreateEvent.getDenyReason()); + return null; + } + + createCost = stargateCreateEvent.getCost(); + + //Check if the new portal is valid + if (!checkIfNewPortalIsValid(createCost, portalName)) { + return null; + } + + //Add button if the portal is not always on + if (!portalOptions.isAlwaysOn()) { + generatePortalButton(portalLocation.getTopLeft(), portalLocation.getButtonVector(), + portalLocation.getButtonFacing()); + } + + //Register the new portal + PortalHandler.registerPortal(portal); + updateNewPortalOpenState(destinationName); + + //Update portals pointing at this one if it's not a bungee portal + if (!portal.getOptions().isBungee()) { + PortalHandler.updatePortalsPointingAtNewPortal(portal); + } + + PortalHandler.saveAllPortals(portal.getWorld()); + + return portal; + } + + /** + * Checks whether the newly created, but unregistered portal is valid + * + * @param costThe cost of creating the portal
+ * @param portalNameThe name of the newly created portal
+ * @returnTrue if the portal is completely valid
+ */ + private boolean checkIfNewPortalIsValid(int cost, String portalName) { + // Name & Network can be changed in the event, so do these checks here. + if (portal.getName().length() < 1 || portal.getName().length() > 11) { + Stargate.debug("createPortal", "Name length error"); + Stargate.sendErrorMessage(player, Stargate.getString("createNameLength")); + return false; + } + + //Don't do network checks for bungee portals + if (portal.getOptions().isBungee()) { + if (PortalHandler.getBungeePortals().get(portal.getName().toLowerCase()) != null) { + Stargate.debug("createPortal::Bungee", "Gate name duplicate"); + Stargate.sendErrorMessage(player, Stargate.getString("createExists")); + return false; + } + } else { + if (PortalHandler.getByName(portal.getName(), portal.getNetwork()) != null) { + Stargate.debug("createPortal", "Gate name duplicate"); + Stargate.sendErrorMessage(player, Stargate.getString("createExists")); + return false; + } + + //Check if there are too many gates in this network + ListThe top-left block of the portal
+ * @param buttonVectorA relative vector pointing at the button
+ * @param buttonFacingThe direction the button should be facing
+ */ + private void generatePortalButton(BlockLocation topLeft, RelativeBlockVector buttonVector, + BlockFace buttonFacing) { + //Go one block outwards to find the button's location rather than the control block's location + BlockLocation button = topLeft.getRelativeLocation(buttonVector.addToVector( + RelativeBlockVector.Property.DISTANCE, 1), portal.getYaw()); + + Directional buttonData = (Directional) Bukkit.createBlockData(portal.getGate().getPortalButton()); + buttonData.setFacing(buttonFacing); + button.getBlock().setBlockData(buttonData); + portal.getStructure().setButton(button); + } + + /** + * Updates the open state of the newly created portal + * + * @param destinationNameThe name of the destination portal. Only used if set as always on
+ */ + private void updateNewPortalOpenState(String destinationName) { + portal.drawSign(); + if (portal.getOptions().isRandom() || portal.getOptions().isBungee()) { + //Open the implicitly always on portal + portal.getPortalOpener().openPortal(true); + } else if (portal.getOptions().isAlwaysOn()) { + //For a normal always-on portal, open both the portal and the destination + Portal destinationPortal = PortalHandler.getByName(destinationName, portal.getNetwork()); + if (destinationPortal != null) { + portal.getPortalOpener().openPortal(true); + destinationPortal.drawSign(); + } + } else { + //Update the block type for the portal's opening to the closed block as the closed block can be anything, + // not just air or water + for (BlockLocation entrance : portal.getStructure().getEntrances()) { + entrance.setType(portal.getGate().getPortalClosedBlock()); + } + } + } + +} diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java index 71740d5..bfaa576 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java @@ -4,22 +4,15 @@ import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.RelativeBlockVector; import net.knarcraft.stargate.container.TwoTuple; -import net.knarcraft.stargate.event.StargateCreateEvent; -import net.knarcraft.stargate.utility.DirectionHelper; -import net.knarcraft.stargate.utility.EconomyHandler; -import net.knarcraft.stargate.utility.EconomyHelper; import net.knarcraft.stargate.utility.PermissionHelper; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.block.Sign; -import org.bukkit.block.data.Directional; import org.bukkit.block.data.type.WallSign; import org.bukkit.entity.Player; -import org.bukkit.event.block.SignChangeEvent; import java.io.BufferedWriter; import java.io.File; @@ -42,16 +35,32 @@ public class PortalHandler { private static final MapA copy of all portal networks
+ */ + public static MapA copy of all bungee portals
+ */ + public static MapThe portal to register
*/ - private static void registerPortal(Portal portal) { + static void registerPortal(Portal portal) { portal.getOptions().setFixed(portal.getDestinationName().length() > 0 || portal.getOptions().isRandom() || portal.getOptions().isBungee()); @@ -242,124 +251,6 @@ public class PortalHandler { allPortals.add(portal); } - /** - * Creates a new portal - * - * @param eventThe sign change event which initialized the creation
- * @param playerThe player who's creating the portal
- * @returnThe created portal
- */ - public static Portal createPortal(SignChangeEvent event, Player player) { - BlockLocation signLocation = new BlockLocation(event.getBlock()); - Block idParent = signLocation.getParent(); - - //Return early if the sign is not placed on a block, or the block is not a control block - if (idParent == null || GateHandler.getGatesByControlBlock(idParent).length == 0) { - Stargate.debug("createPortal", "Control block not registered"); - return null; - } - - //The control block is already part of another portal - if (getByBlock(idParent) != null) { - Stargate.debug("createPortal", "idParent belongs to existing stargate"); - return null; - } - - //Get necessary information from the gate's sign - String portalName = filterName(event.getLine(0)); - String destinationName = filterName(event.getLine(1)); - String network = filterName(event.getLine(2)); - String options = filterName(event.getLine(3)).toLowerCase(); - - //Get portal options available to the player creating the portal - MapThe name of the portal's network
* @returnFalse if the portal is an invalid bungee portal. True otherwise
*/ - private static boolean isValidBungeePortal(MapThe player trying to create the new portal
* @returnThe matching gate type, or null if no such gate could be found
*/ - private static Gate findMatchingGate(PortalLocation portalLocation, Player player) { + static Gate findMatchingGate(PortalLocation portalLocation, Player player) { Block signParent = portalLocation.getSignLocation().getParent(); BlockLocation parent = new BlockLocation(player.getWorld(), signParent.getX(), signParent.getY(), signParent.getZ()); @@ -432,7 +323,7 @@ public class PortalHandler { * @param playerThe player creating the new portal
* @returnTrue if a conflict was found. False otherwise
*/ - private static boolean conflictsWithExistingPortal(Gate gate, BlockLocation topLeft, double yaw, Player player) { + static boolean conflictsWithExistingPortal(Gate gate, BlockLocation topLeft, double yaw, Player player) { //TODO: Make a quicker check. Could just check for control block conflicts if all code is changed to account for // getting several hits at a single location when checking for the existence of a portal. May make // everything slower overall? Would make for cooler gates though. @@ -447,172 +338,12 @@ public class PortalHandler { return false; } - /** - * Creates and validates a new portal - * - * @param destinationNameThe name of the portal's destination
- * @param portalNameThe name of the new portal
- * @param networkThe name of the new portal's network
- * @param gateThe gate type used in the physical construction of the new portal
- * @param playerThe player creating the new portal
- * @param portalOptionsA map of enabled and disabled portal options
- * @param denyMessageThe deny message to display if the portal creation was denied
- * @param linesAll the lines of the sign which initiated the portal creation
- * @param denyWhether to deny the creation of the new portal
- * @returnA new portal, or null if the input cases the creation to be denied
- */ - private static Portal createAndValidateNewPortal(PortalLocation portalLocation, String destinationName, - String portalName, String network, Gate gate, Player player, - MapThe portal to validate
- * @param playerThe player creating the portal
- * @param costThe cost of creating the portal
- * @param portalNameThe name of the newly created portal
- * @returnTrue if the portal is completely valid
- */ - private static boolean checkIfNewPortalIsValid(Portal portal, Player player, int cost, String portalName) { - // Name & Network can be changed in the event, so do these checks here. - if (portal.getName().length() < 1 || portal.getName().length() > 11) { - Stargate.debug("createPortal", "Name length error"); - Stargate.sendErrorMessage(player, Stargate.getString("createNameLength")); - return false; - } - - //Don't do network checks for bungee portals - if (portal.getOptions().isBungee()) { - if (bungeePortals.get(portal.getName().toLowerCase()) != null) { - Stargate.debug("createPortal::Bungee", "Gate name duplicate"); - Stargate.sendErrorMessage(player, Stargate.getString("createExists")); - return false; - } - } else { - if (getByName(portal.getName(), portal.getNetwork()) != null) { - Stargate.debug("createPortal", "Gate name duplicate"); - Stargate.sendErrorMessage(player, Stargate.getString("createExists")); - return false; - } - - //Check if there are too many gates in this network - ListThe portal to generate a button for
- * @param topLeftThe top-left block of the portal
- * @param buttonVectorA relative vector pointing at the button
- * @param buttonFacingThe direction the button should be facing
- */ - private static void generatePortalButton(Portal portal, BlockLocation topLeft, RelativeBlockVector buttonVector, - BlockFace buttonFacing) { - //Go one block outwards to find the button's location rather than the control block's location - BlockLocation button = topLeft.getRelativeLocation(buttonVector.addToVector( - RelativeBlockVector.Property.DISTANCE, 1), portal.getYaw()); - - Directional buttonData = (Directional) Bukkit.createBlockData(portal.getGate().getPortalButton()); - buttonData.setFacing(buttonFacing); - button.getBlock().setBlockData(buttonData); - portal.getStructure().setButton(button); - } - - /** - * Updates the open state of the newly created portal - * - * @param portalThe portal newly created
- * @param destinationNameThe name of the destination portal
- */ - private static void updateNewPortal(Portal portal, String destinationName) { - portal.drawSign(); - //Open an always on portal - if (portal.getOptions().isRandom() || portal.getOptions().isBungee()) { - portal.getPortalOpener().openPortal(true); - } else if (portal.getOptions().isAlwaysOn()) { - Portal destinationPortal = getByName(destinationName, portal.getNetwork()); - if (destinationPortal != null) { - portal.getPortalOpener().openPortal(true); - destinationPortal.drawSign(); - } - } else { - //Update the block type for the portal's opening to the closed block - for (BlockLocation entrance : portal.getStructure().getEntrances()) { - entrance.setType(portal.getGate().getPortalClosedBlock()); - } - } - } - /** * Updates the sign and open state of portals pointing at the newly created portal * * @param portalThe newly created portal
*/ - private static void updatePortalsPointingAtNewPortal(Portal portal) { + static void updatePortalsPointingAtNewPortal(Portal portal) { for (String originName : allPortalNetworks.get(portal.getNetwork().toLowerCase())) { Portal origin = getByName(originName, portal.getNetwork()); if (origin == null || @@ -639,7 +370,7 @@ public class PortalHandler { * @param optionsThe string on the option line of the sign
* @returnA map containing all portal options and their values
*/ - private static Map