From 7e300d9c03cf1ba064d308138bb6e733edff26f5 Mon Sep 17 00:00:00 2001 From: Tobias Ottenweller Date: Sun, 13 May 2012 17:05:31 +0200 Subject: [PATCH] refactoring: abstract Gate base class; native bukkit serialization --- src/org/mcteam/ancientgates/BaseGate.java | 187 +++++++++++ src/org/mcteam/ancientgates/Gate.java | 374 +++++----------------- 2 files changed, 274 insertions(+), 287 deletions(-) create mode 100644 src/org/mcteam/ancientgates/BaseGate.java diff --git a/src/org/mcteam/ancientgates/BaseGate.java b/src/org/mcteam/ancientgates/BaseGate.java new file mode 100644 index 0000000..06ebdcd --- /dev/null +++ b/src/org/mcteam/ancientgates/BaseGate.java @@ -0,0 +1,187 @@ +package org.mcteam.ancientgates; + +import java.util.HashSet; +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.mcteam.ancientgates.util.FloodUtil; + + + +public abstract class BaseGate +{ + /* + * ATTRIBUTES + */ + protected Location location; /* saving both location and gateBlockLocations is redundant but makes it easy to allow players to reshape gates */ + protected Set gateBlockLocations; /* Locations of the blocks inside the gate */ + + protected Location exit; + + protected boolean isHidden; + protected boolean isOpen; + + + /* + * SETTER & GETTER + */ + + public Location getLocation() + { + return location; + } + + + public void setLocation(Location location) + { + this.location = location; + + if (isOpen) { + findPortalBlocks(); + validate(); + } + } + + + public Location getExit() + { + return exit; + } + + + public void setExit(Location exit) + { + this.exit = exit; + validate(); + } + + + public boolean isHidden() + { + return isHidden; + } + + + public void setHidden(boolean isHidden) + { + this.isHidden = isHidden; + + if (isHidden == true) { + emptyGate(); + } + else if (isOpen()) { + fillGate(); + } + + validate(); + } + + + public boolean isOpen() + { + return isOpen; + } + + + public void setOpen(boolean isOpen) + { + if (isOpen == true && this.isOpen == false) { + findPortalBlocks(); + + if (!isHidden) { + fillGate(); + } + + validate(); + } + else if (isOpen == false && this.isOpen == true) { + emptyGate(); + } + + this.isOpen = isOpen; + } + + + public Set getGateBlocks() + { + return gateBlockLocations; + } + + + /* + * GATE BLOCK HANDLING + */ + + protected void fillGate() + { + // This is not to do an effect + // It is to stop portal blocks from destroying themself as they cant rely on non created blocks :P + for (Location l : gateBlockLocations) { + l.getBlock().setType(Material.GLOWSTONE); + } + + for (Location l : gateBlockLocations) { + l.getBlock().setType(Material.PORTAL); + } + } + + + protected void emptyGate() + { + for (Location l : gateBlockLocations) { + if (l.getBlock().getType() == Material.PORTAL) { + l.getBlock().setType(Material.AIR); + } + } + } + + + protected void findPortalBlocks() + { + Set gateBlocks = FloodUtil.getGateFrameBlocks(location.getBlock()); + + if (gateBlocks == null) { + gateBlockLocations = null; + } + else { + gateBlockLocations = new HashSet(); + + for (Block b : gateBlocks) { + gateBlockLocations.add(b.getLocation()); + } + } + } + + + /* + * VALIDATION + */ + + /** + * Checks if valus attributes do add up; will close gate on wrong values. + */ + protected void validate() + { + if (!isOpen) { + return; + } + + if (location == null || exit == null) { + isOpen = false; + emptyGate(); + return; + } + + if (isHidden == false) { + for (Location l : gateBlockLocations) { + if (l.getBlock().getType() != Material.PORTAL) { + isOpen = false; + emptyGate(); + return; + } + } + } + } +} diff --git a/src/org/mcteam/ancientgates/Gate.java b/src/org/mcteam/ancientgates/Gate.java index aea1b16..df0dc25 100644 --- a/src/org/mcteam/ancientgates/Gate.java +++ b/src/org/mcteam/ancientgates/Gate.java @@ -1,234 +1,114 @@ package org.mcteam.ancientgates; -import java.io.File; -import java.io.IOException; - -import java.lang.reflect.Type; - +import java.util.ArrayList; import java.util.Collection; -import java.util.Map.Entry; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.TreeMap; import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; - -import org.mcteam.ancientgates.gson.reflect.TypeToken; -import org.mcteam.ancientgates.util.DiscUtil; -import org.mcteam.ancientgates.util.FloodUtil; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.mcteam.ancientgates.util.LocationSerializer; -public class Gate + +public class Gate extends BaseGate implements ConfigurationSerializable { - private static transient TreeMap instances = new TreeMap(String.CASE_INSENSITIVE_ORDER); - private static transient File file = new File(Plugin.instance.getDataFolder(), "gates.json"); + /* + * ATTRIBUTES + */ - private transient String id; - private Location from; - private Location to; - private boolean isHidden = false; - private boolean isOpen = false; - - private Integer[][] gateBlocks; - - - public Gate() - { - } + protected String id; + + protected static Map instances = new HashMap(); - // -------------------------------------------- // - // Getters And Setters - // -------------------------------------------- // + /* + * CONSTRUCTORS + */ - public void setId(String id) + public Gate() { - this.id = id; } - + + + /* + * SETTER & GETTER + */ public String getId() { return id; } - - public void setFrom(Location from) - { - this.from = from; - setGateBlocks(FloodUtil.getGateFrameBlocks(from.getBlock())); - } - - public Location getFrom() + public void setId(String id) throws Exception { - return from; - } - - public void setTo(Location to) - { - this.to = to; - } - - - public Location getTo() - { - return to; - } - - - public Integer[][] getGateBlocks() - { - return gateBlocks; - } - - - private void setGateBlocks(Set gateBlocks) - { - if (gateBlocks == null) - return; - - this.gateBlocks = new Integer[gateBlocks.size()][3]; - - int blockcount = 0; - for (Block b : gateBlocks) - { - if (b != null) - { - this.gateBlocks[blockcount][0] = b.getX(); - this.gateBlocks[blockcount][1] = b.getY(); - this.gateBlocks[blockcount][2] = b.getZ(); - } - blockcount++; - } - } - - - //----------------------------------------------// - // The Open And Close Methods - //----------------------------------------------// - - public boolean open() - { - Set blocks = FloodUtil.getGateFrameBlocks(from.getBlock()); - setGateBlocks(blocks); - - if (blocks == null) - { - return false; - } - - if (isHidden() == false) - { - fillGate(blocks); - } - - setOpen(true); - - return true; - } - - - private void fillGate(Set blocks) - { - // This is not to do an effect - // It is to stop portal blocks from destroying themself as they cant rely on non created blocks :P - for (Block block : blocks) - block.setType(Material.GLOWSTONE); - - for (Block block : blocks) - block.setType(Material.PORTAL); - } - - - public void close() - { - removeGateBlocks(); - setOpen(false); - } - - - private void removeGateBlocks() - { - if (from != null) - { - Set blocks = FloodUtil.getGateFrameBlocks(from.getBlock()); - - if (blocks != null) - { - for (Block block : blocks) - block.setType(Material.AIR); - } - } - } - - - //----------------------------------------------// - // isHidden Setter and Getter - //----------------------------------------------// - - public boolean setHidden(boolean isHidden) - { - this.isHidden = isHidden; - - if (isHidden == true) - { - removeGateBlocks(); - } - else if (this.isOpen && !open()) - { - // cannot open that gate (no frame!) - this.isHidden = false; - return false; - } - - return true; - } - - - public boolean isHidden() - { - return this.isHidden; - } - - - //----------------------------------------------// - // isOpen Setter and Getter - //----------------------------------------------// - - private void setOpen(boolean isOpen) - { - this.isOpen = isOpen; - } - - - public boolean isOpen() - { - // check if gate is really open - if (getGateBlocks() == null) - { - isOpen = false; - } - else if (!isHidden()) - { - Integer[] gateBlock = getGateBlocks()[0]; - Block b = new Location(from.getWorld(), gateBlock[0], gateBlock[1], gateBlock[2]).getBlock(); - - if (b.getType() != Material.PORTAL) - { - isOpen = false; - } + if (instances.get(id) != null) { + throw new Exception("Cannot set new ID: this ID is already in use"); } - return this.isOpen; + this.id = id; + } + + + /* + * INTERFACE: ConfigurationSerializable + */ + static String idKey = "id"; + static String locationKey = "location"; + static String gateBlocksKey = "gateBlocks"; + static String exitKey = "exit"; + static String isHiddenKey = "hidden"; + static String isOpenKey = "open"; + + + @SuppressWarnings("unchecked") + public Gate(Map map) + { + id = (String)map.get(idKey); + location = LocationSerializer.deserializeLocation((Map) map.get(locationKey)); + exit = LocationSerializer.deserializeLocation((Map) map.get(exitKey)); + isHidden = (Boolean)map.get(isHiddenKey); + isOpen = (Boolean)map.get(isOpenKey); + + gateBlockLocations = new HashSet(); + List> serializedGateBlocks = (List>)map.get(gateBlocksKey); + + for (Map sgb : serializedGateBlocks) { + gateBlockLocations.add(LocationSerializer.deserializeLocation(sgb)); + } + + instances.put(id, this); } - //----------------------------------------------// - // Persistance and entity management - //----------------------------------------------// + public Map serialize() + { + Map retVal = new HashMap(); + + retVal.put(idKey, id); + retVal.put(locationKey, LocationSerializer.serializeLocation(location)); + retVal.put(exitKey, LocationSerializer.serializeLocation(exit)); + retVal.put(isHiddenKey, isHidden); + retVal.put(isOpenKey, isOpen); + + List> serializedGateBlocks = new ArrayList>(); + + for (Location l : gateBlockLocations) { + serializedGateBlocks.add(LocationSerializer.serializeLocation(l)); + } + + retVal.put(gateBlocksKey, serializedGateBlocks); + + return retVal; + } + + + /* + * PERSISTANCE and ENTITY MANAGEMENT + */ public static Gate get(String id) { @@ -253,11 +133,13 @@ public class Gate } - public static void rename(Gate gate, String newId) + public static void rename(Gate gate, String newId) throws Exception { - delete(gate.id); + String oldId = gate.id; gate.setId(newId); + + delete(oldId); instances.put(gate.id, gate); } @@ -269,90 +151,8 @@ public class Gate } - public static boolean save() - { - try - { - DiscUtil.write(file, Plugin.gson.toJson(instances)); - Plugin.log("Saved gates to disk"); - } - catch (IOException e) - { - Plugin.log("Failed to save the gates to disk due to I/O exception."); - e.printStackTrace(); - return false; - } - catch (NullPointerException e) - { - Plugin.log("Failed to save the gates to disk due to NPE."); - e.printStackTrace(); - return false; - } - - - return true; - } - - - public static boolean load() - { - Plugin.log("Loading gates from disk"); - if ( ! file.exists()) { - Plugin.log("No gates to load from disk. Creating new file."); - save(); - return true; - } - - try - { - Type type = new TypeToken>(){}.getType(); - Map instancesFromFile = Plugin.gson.fromJson(DiscUtil.read(file), type); - instances.clear(); - instances.putAll(instancesFromFile); - } - catch (IOException e) - { - e.printStackTrace(); - return false; - } - - fillIds(); - - // old releases did not save gate blocks - this fixes the problem - for (Gate g : getAll()) - { - if (g.getGateBlocks() == null && g.getFrom() != null) - { - Plugin.log("Fixing problems with old gate: " + g.getId()); - - Set gateBlocks = FloodUtil.getGateFrameBlocks(g.getFrom().getBlock()); - - if (gateBlocks == null) - continue; - - g.setGateBlocks(gateBlocks); - - if (((Block) gateBlocks.toArray()[0]).getType() == Material.PORTAL ) - g.setOpen(true); - } - - } - save(); - // end of fix - - return true; - } - - public static Collection getAll() { return instances.values(); } - - - public static void fillIds() - { - for(Entry entry : instances.entrySet()) - entry.getValue().setId(entry.getKey()); - } }