package net.knarcraft.stargate.portal; import net.knarcraft.stargate.BlockLocation; import net.knarcraft.stargate.RelativeBlockVector; import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.utility.DirectionHelper; import net.knarcraft.stargate.utility.EconomyHandler; import org.bukkit.Material; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; /** * A gate describes the physical structure of a stargate * *
While the portal class represents a portal in space, the Gate class represents the physical gate/portal entrance.
*/ public class Gate { private final String filename; private final GateLayout layout; private final MapThe name of the gate which equal the name of the file
* @param layoutThe character layout defined in the gate file
* @param typesThe block types the different layout characters represent
* @param portalOpenBlockThe material to set the non-frame to when the portal is open
* @param portalClosedBlockThe material to set the non-frame to when the portal is closed
* @param portalButtonThe material to use for the portal button
* @param useCostThe cost of using a portal with this gate layout (-1 to disable)
* @param createCostThe cost of creating a portal with this gate layout (-1 to disable)
* @param destroyCostThe cost of destroying a portal with this gate layout (-1 to disable)
* @param toOwnerWhether any payment should go to the owner of the gate, as opposed to just disappearing
*/ public Gate(String filename, GateLayout layout, MapThe layout of this gate
*/ public GateLayout getLayout() { return layout; } /** * Gets the material types each layout character represents * * @returnThe material types each layout character represents
*/ public MapThe material type used for control blocks
*/ public Material getControlBlock() { return types.get(GateHandler.getControlBlockCharacter()); } /** * Gets the filename of this gate * * @returnThe filename of this gate
*/ public String getFilename() { return filename; } /** * Gets the block type to use for the opening when a portal using this gate is open * * @returnThe block type to use for the opening when open
*/ public Material getPortalOpenBlock() { return portalOpenBlock; } /** * Sets the block to use for the opening when a portal using this gate is open * * @param typeThe block type to use for the opening when open
*/ public void setPortalOpenBlock(Material type) { portalOpenBlock = type; } /** * Gets the block type to use for the opening when a portal using this gate is closed * * @returnThe block type to use for the opening when closed
*/ public Material getPortalClosedBlock() { return portalClosedBlock; } /** * Sets the block type to use for the opening when a portal using this gate is closed * * @param typeThe block type to use for the opening when closed
*/ public void setPortalClosedBlock(Material type) { portalClosedBlock = type; } /** * Gets the material to use for a portal's button if using this gate type * * @returnThe material to use for a portal's button if using this gate type
*/ public Material getPortalButton() { return portalButton; } /** * Gets the cost of using a portal with this gate * * @returnThe cost of using a portal with this gate
*/ public int getUseCost() { return useCost < 0 ? EconomyHandler.getUseCost() : useCost; } /** * Gets the cost of creating a portal with this gate * * @returnThe cost of creating a portal with this gate
*/ public Integer getCreateCost() { return createCost < 0 ? EconomyHandler.getCreateCost() : createCost; } /** * Gets the cost of destroying a portal with this gate * * @returnThe cost of destroying a portal with this gate
*/ public Integer getDestroyCost() { if (destroyCost < 0) return EconomyHandler.getDestroyCost(); return destroyCost; } /** * Gets whether portal payments go to this portal's owner * * @returnWhether portal payments go to the owner
*/ public Boolean getToOwner() { return toOwner; } /** * Checks whether a portal's gate matches this gate type * * @param topLeftThe top-left block of the portal's gate
* @param modXThe x modifier used
* @param modZThe z modifier used
* @returnTrue if this gate matches the portal
*/ 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 topLeftThe top-left block of the portal's gate
* @param modXThe x modifier used
* @param modZThe z modifier used
* @param onCreateWhether this is used in the context of creating a new gate
* @returnTrue if this gate matches the portal
*/ public boolean matches(BlockLocation topLeft, int modX, int modZ, boolean onCreate) { return verifyGateEntrancesMatch(topLeft, modX, modZ, onCreate) && verifyGateBorderMatches(topLeft, modX, modZ); } /** * Verifies that all border blocks of a portal gate matches this gate type * * @param topLeftThe top-left block of the portal
* @param modXThe x modifier used
* @param modZThe z modifier used
* @returnTrue if all border blocks of the gate match the layout
*/ private boolean verifyGateBorderMatches(BlockLocation topLeft, int modX, int modZ) { MapThe top-left block of this portal
* @param modXThe x modifier used
* @param modZThe z modifier used
* @param onCreateWhether this is used in the context of creating a new gate
* @returnWhether this is used in the context of creating a new gate
*/ 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 vectorThe relative block vector
* @returnThe block at the given relative position
*/ private BlockLocation getBlockAt(BlockLocation topLeft, RelativeBlockVector vector, int modX, int modZ) { return DirectionHelper.getBlockAt(topLeft, vector, modX, modZ); } /** * Saves this gate to a file * *This method will save the gate to its filename in the given folder.
* * @param gateFolderThe folder to save the gate file in
*/ public void save(String gateFolder) { try { BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(gateFolder + filename)); writeConfig(bufferedWriter, "portal-open", portalOpenBlock.name()); writeConfig(bufferedWriter, "portal-closed", portalClosedBlock.name()); writeConfig(bufferedWriter, "button", portalButton.name()); //Save the values necessary for economy saveEconomyValues(bufferedWriter); //Store type material type to use for frame blocks saveFrameBlockTypes(bufferedWriter); bufferedWriter.newLine(); //Save the layout layout.save(bufferedWriter); bufferedWriter.close(); } catch (IOException ex) { Stargate.log.log(Level.SEVERE, "Could not save Gate " + filename + " - " + ex.getMessage()); } } /** * Saves current economy related values using a buffered writer * * @param bufferedWriterThe buffered writer to write to
* * @throws IOExceptionIf unable to write to the buffered writer
*/ private void saveEconomyValues(BufferedWriter bufferedWriter) throws IOException { if (useCost != -1) { writeConfig(bufferedWriter, "usecost", useCost); } if (createCost != -1) { writeConfig(bufferedWriter, "createcost", createCost); } if (destroyCost != -1) { writeConfig(bufferedWriter, "destroycost", destroyCost); } writeConfig(bufferedWriter, "toowner", toOwner); } /** * Saves the types of blocks used for the gate frame/border using a buffered writer * * @param bufferedWriterThe buffered writer to write to
* @throws IOExceptionIf unable to write to the buffered writer
*/ private void saveFrameBlockTypes(BufferedWriter bufferedWriter) throws IOException { for (Map.EntryThe buffered writer to write the config to
* @param keyThe config key to save
* @param valueThe value of the config key
* @throws IOExceptionIf unable to write to the buffered writer
*/ private void writeConfig(BufferedWriter bufferedWriter, String key, int value) throws IOException { writeConfig(bufferedWriter, "%s=%d", key, value); } /** * Writes a boolean to a config * * @param bufferedWriterThe buffered writer to write the config to
* @param keyThe config key to save
* @param valueThe value of the config key
* @throws IOExceptionIf unable to write to the buffered writer
*/ private void writeConfig(BufferedWriter bufferedWriter, String key, boolean value) throws IOException { writeConfig(bufferedWriter, "%s=%b", key, value); } /** * Writes a string to a config * * @param bufferedWriterThe buffered writer to write the config to
* @param keyThe config key to save
* @param valueThe value of the config key
* @throws IOExceptionIf unable to write to the buffered writer
*/ private void writeConfig(BufferedWriter bufferedWriter, String key, String value) throws IOException { writeConfig(bufferedWriter, "%s=%s", key, value); } /** * Writes a formatted string to a buffered writer * * @param bufferedWriterThe buffered writer to write the formatted string to
* @param formatThe format to use
* @param keyThe config key to save
* @param valueThe config value to save
* @throws IOExceptionIf unable to write to the buffered writer
*/ private void writeConfig(BufferedWriter bufferedWriter, String format, String key, Object value) throws IOException { bufferedWriter.append(String.format(format, key, value)); bufferedWriter.newLine(); } }