From e665a49f0300a6cc8a979c0d29d6fc534df3bd2a Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 <kristian.knarvik@knett.no> Date: Mon, 22 Feb 2021 20:25:07 +0100 Subject: [PATCH] Adds missing comments to Gate and changes the matches function from n^2 to n execution time --- .../net/knarcraft/stargate/portal/Gate.java | 216 +++++++++++++----- 1 file changed, 160 insertions(+), 56 deletions(-) diff --git a/src/main/java/net/knarcraft/stargate/portal/Gate.java b/src/main/java/net/knarcraft/stargate/portal/Gate.java index f2fce39..f129ce0 100644 --- a/src/main/java/net/knarcraft/stargate/portal/Gate.java +++ b/src/main/java/net/knarcraft/stargate/portal/Gate.java @@ -1,8 +1,9 @@ package net.knarcraft.stargate.portal; import net.knarcraft.stargate.BlockLocation; -import net.knarcraft.stargate.EconomyHandler; +import net.knarcraft.stargate.RelativeBlockVector; import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.utility.EconomyHandler; import org.bukkit.Material; import java.io.BufferedWriter; @@ -37,16 +38,16 @@ public class Gate { /** * Instantiates a new gate * - * @param filename <p>The name of the gate which equal the name of the file</p> - * @param layout <p>The character layout defined in the gate file</p> - * @param types <p>The block types the different layout characters represent</p> - * @param portalOpenBlock <p>The material to set the non-frame to when the portal is open</p> + * @param filename <p>The name of the gate which equal the name of the file</p> + * @param layout <p>The character layout defined in the gate file</p> + * @param types <p>The block types the different layout characters represent</p> + * @param portalOpenBlock <p>The material to set the non-frame to when the portal is open</p> * @param portalClosedBlock <p>The material to set the non-frame to when the portal is closed</p> - * @param portalButton <p>The material to use for the portal button</p> - * @param useCost <p>The cost of using a portal with this gate layout (-1 to disable)</p> - * @param createCost <p>The cost of creating a portal with this gate layout (-1 to disable)</p> - * @param destroyCost <p>The cost of destroying a portal with this gate layout (-1 to disable)</p> - * @param toOwner <p>Whether any payment should go to the owner of the gate, as opposed to just disappearing</p> + * @param portalButton <p>The material to use for the portal button</p> + * @param useCost <p>The cost of using a portal with this gate layout (-1 to disable)</p> + * @param createCost <p>The cost of creating a portal with this gate layout (-1 to disable)</p> + * @param destroyCost <p>The cost of destroying a portal with this gate layout (-1 to disable)</p> + * @param toOwner <p>Whether any payment should go to the owner of the gate, as opposed to just disappearing</p> */ public Gate(String filename, GateLayout layout, HashMap<Character, Material> types, Material portalOpenBlock, Material portalClosedBlock, Material portalButton, int useCost, int createCost, int destroyCost, @@ -81,95 +82,198 @@ public class Gate { return types; } + /** + * Gets the material type used for this gate's control blocks + * + * @return <p>The material type used for control blocks</p> + */ public Material getControlBlock() { - return types.get('-'); + return types.get(GateHandler.getControlBlockCharacter()); } + /** + * Gets the filename of this gate + * + * @return <p>The filename of this gate</p> + */ public String getFilename() { return filename; } + /** + * Gets the block type to use for the opening when a portal using this gate is open + * + * @return <p>The block type to use for the opening when open</p> + */ public Material getPortalOpenBlock() { return portalOpenBlock; } + /** + * Sets the block to use for the opening when a portal using this gate is open + * + * @param type <p>The block type to use for the opening when open</p> + */ public void setPortalOpenBlock(Material type) { portalOpenBlock = type; } + /** + * Gets the block type to use for the opening when a portal using this gate is closed + * + * @return <p>The block type to use for the opening when closed</p> + */ public Material getPortalClosedBlock() { return portalClosedBlock; } + /** + * Sets the block type to use for the opening when a portal using this gate is closed + * + * @param type <p>The block type to use for the opening when closed</p> + */ public void setPortalClosedBlock(Material type) { portalClosedBlock = type; } + /** + * Gets the material to use for a portal's button if using this gate type + * + * @return <p>The material to use for a portal's button if using this gate type</p> + */ public Material getPortalButton() { return portalButton; } + /** + * Gets the cost of using a portal with this gate + * + * @return <p>The cost of using a portal with this gate</p> + */ public int getUseCost() { - if (useCost < 0) return EconomyHandler.useCost; - return useCost; + return useCost < 0 ? EconomyHandler.getUseCost() : useCost; } + /** + * Gets the cost of creating a portal with this gate + * + * @return <p>The cost of creating a portal with this gate</p> + */ public Integer getCreateCost() { - if (createCost < 0) return EconomyHandler.createCost; - return createCost; + return createCost < 0 ? EconomyHandler.getCreateCost() : createCost; } + /** + * Gets the cost of destroying a portal with this gate + * + * @return <p>The cost of destroying a portal with this gate</p> + */ public Integer getDestroyCost() { - if (destroyCost < 0) return EconomyHandler.destroyCost; + if (destroyCost < 0) return EconomyHandler.getDestroyCost(); return destroyCost; } + /** + * Gets whether portal payments go to this portal's owner + * + * @return <p>Whether portal payments go to the owner</p> + */ public Boolean getToOwner() { return toOwner; } + /** + * Checks whether a portal's gate matches this gate type + * + * @param topLeft <p>The top-left block of the portal's gate</p> + * @param modX <p>The x modifier used</p> + * @param modZ <p>The z modifier used</p> + * @return <p>True if this gate matches the portal</p> + */ public boolean matches(BlockLocation topLeft, int modX, int modZ) { return matches(topLeft, modX, modZ, false); } + /** + * Checks whether a portal's gate matches this gate type + * + * @param topLeft <p>The top-left block of the portal's gate</p> + * @param modX <p>The x modifier used</p> + * @param modZ <p>The z modifier used</p> + * @param onCreate <p>Whether this is used in the context of creating a new gate</p> + * @return <p>True if this gate matches the portal</p> + */ public boolean matches(BlockLocation topLeft, int modX, int modZ, boolean onCreate) { - HashMap<Character, Material> portalTypes = new HashMap<>(types); - Character[][] layout = this.layout.getLayout(); - for (int y = 0; y < layout.length; y++) { - for (int x = 0; x < layout[y].length; x++) { - Character key = layout[y][x]; + return verifyGateEntrancesMatch(topLeft, modX, modZ, onCreate) && verifyGateBorderMatches(topLeft, modX, modZ); + } - if (key.equals(GateHandler.getEntranceCharacter()) || key.equals(GateHandler.getExitCharacter())) { - if (Stargate.ignoreEntrance) { - continue; - } + /** + * Verifies that all border blocks of a portal gate matches this gate type + * + * @param topLeft <p>The top-left block of the portal</p> + * @param modX <p>The x modifier used</p> + * @param modZ <p>The z modifier used</p> + * @return <p>True if all border blocks of the gate match the layout</p> + */ + private boolean verifyGateBorderMatches(BlockLocation topLeft, int modX, int modZ) { + Map<Character, Material> portalTypes = new HashMap<>(types); + for (RelativeBlockVector borderVector : layout.getBorder()) { + int rowIndex = borderVector.getRight(); + int lineIndex = borderVector.getDepth(); + Character key = layout.getLayout()[lineIndex][rowIndex]; - Material type = topLeft.modRelative(x, y, 0, modX, 1, modZ).getType(); - - // Ignore entrance if it's air and we're creating a new gate - if (onCreate && type == Material.AIR) { - continue; - } - - if (type != portalClosedBlock && type != portalOpenBlock) { - Stargate.debug("Gate::Matches", "Entrance/Exit Material Mismatch: " + type); - return false; - } - } else if (!key.equals(GateHandler.getAnythingCharacter())) { - Material id = portalTypes.get(key); - if (id == null) { - portalTypes.put(key, topLeft.modRelative(x, y, 0, modX, 1, modZ).getType()); - } else if (topLeft.modRelative(x, y, 0, modX, 1, modZ).getType() != id) { - Stargate.debug("Gate::Matches", "Block Type Mismatch: " + topLeft.modRelative(x, y, 0, modX, 1, modZ).getType() + " != " + id); - return false; - } - } + Material materialInLayout = portalTypes.get(key); + Material materialAtLocation = getBlockAt(topLeft, borderVector, modX, modZ).getType(); + if (materialInLayout == null) { + portalTypes.put(key, materialAtLocation); + } else if (materialAtLocation != materialInLayout) { + Stargate.debug("Gate::Matches", String.format("Block Type Mismatch: %s != %s", + materialAtLocation, materialInLayout)); + return false; } } - return true; } + /** + * Verifies that all entrances of a portal gate matches this gate type + * + * @param topLeft <p>The top-left block of this portal</p> + * @param modX <p>The x modifier used</p> + * @param modZ <p>The z modifier used</p> + * @param onCreate <p>Whether this is used in the context of creating a new gate</p> + * @return <p>Whether this is used in the context of creating a new gate</p> + */ + private boolean verifyGateEntrancesMatch(BlockLocation topLeft, int modX, int modZ, boolean onCreate) { + if (Stargate.ignoreEntrance) { + return true; + } + for (RelativeBlockVector entranceVector : layout.getEntrances()) { + Material type = getBlockAt(topLeft, entranceVector, modX, modZ).getType(); + + // Ignore entrance if it's air and we're creating a new gate + if (onCreate && type == Material.AIR) { + continue; + } + + if (type != portalClosedBlock && type != portalOpenBlock) { + Stargate.debug("Gate::Matches", "Entrance/Exit Material Mismatch: " + type); + return false; + } + } + return true; + } + + /** + * Gets the block at a relative block vector location + * + * @param vector <p>The relative block vector</p> + * @return <p>The block at the given relative position</p> + */ + private BlockLocation getBlockAt(BlockLocation topLeft, RelativeBlockVector vector, int modX, int modZ) { + return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ); + } + /** * Saves this gate to a file * @@ -206,7 +310,7 @@ public class Gate { * Saves current economy related values using a buffered writer * * @param bufferedWriter <p>The buffered writer to write to</p> - * * @throws IOException <p>If unable to write to the buffered writer</p> + * * @throws IOException <p>If unable to write to the buffered writer</p> */ private void saveEconomyValues(BufferedWriter bufferedWriter) throws IOException { if (useCost != -1) { @@ -251,8 +355,8 @@ public class Gate { * Writes an integer to a config * * @param bufferedWriter <p>The buffered writer to write the config to</p> - * @param key <p>The config key to save</p> - * @param value <p>The value of the config key</p> + * @param key <p>The config key to save</p> + * @param value <p>The value of the config key</p> * @throws IOException <p>If unable to write to the buffered writer</p> */ private void writeConfig(BufferedWriter bufferedWriter, String key, int value) throws IOException { @@ -263,8 +367,8 @@ public class Gate { * Writes a boolean to a config * * @param bufferedWriter <p>The buffered writer to write the config to</p> - * @param key <p>The config key to save</p> - * @param value <p>The value of the config key</p> + * @param key <p>The config key to save</p> + * @param value <p>The value of the config key</p> * @throws IOException <p>If unable to write to the buffered writer</p> */ private void writeConfig(BufferedWriter bufferedWriter, String key, boolean value) throws IOException { @@ -275,8 +379,8 @@ public class Gate { * Writes a string to a config * * @param bufferedWriter <p>The buffered writer to write the config to</p> - * @param key <p>The config key to save</p> - * @param value <p>The value of the config key</p> + * @param key <p>The config key to save</p> + * @param value <p>The value of the config key</p> * @throws IOException <p>If unable to write to the buffered writer</p> */ private void writeConfig(BufferedWriter bufferedWriter, String key, String value) throws IOException { @@ -287,9 +391,9 @@ public class Gate { * Writes a formatted string to a buffered writer * * @param bufferedWriter <p>The buffered writer to write the formatted string to</p> - * @param format <p>The format to use</p> - * @param key <p>The config key to save</p> - * @param value <p>The config value to save</p> + * @param format <p>The format to use</p> + * @param key <p>The config key to save</p> + * @param value <p>The config value to save</p> * @throws IOException <p>If unable to write to the buffered writer</p> */ private void writeConfig(BufferedWriter bufferedWriter, String format, String key, Object value) throws IOException {