refactoring: abstract Gate base class; native bukkit serialization

This commit is contained in:
Tobias Ottenweller 2012-05-13 17:05:31 +02:00
parent 3d6b5fe1c6
commit 7e300d9c03
2 changed files with 274 additions and 287 deletions

View File

@ -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<Location> 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<Location> 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<Block> gateBlocks = FloodUtil.getGateFrameBlocks(location.getBlock());
if (gateBlocks == null) {
gateBlockLocations = null;
}
else {
gateBlockLocations = new HashSet<Location>();
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;
}
}
}
}
}

View File

@ -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<String, Gate> instances = new TreeMap<String, Gate>(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<String, Gate> instances = new HashMap<String, Gate>();
// -------------------------------------------- //
// 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<Block> 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<Block> 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<Block> 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<Block> 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<String, Object> map)
{
id = (String)map.get(idKey);
location = LocationSerializer.deserializeLocation((Map<String, Object>) map.get(locationKey));
exit = LocationSerializer.deserializeLocation((Map<String, Object>) map.get(exitKey));
isHidden = (Boolean)map.get(isHiddenKey);
isOpen = (Boolean)map.get(isOpenKey);
gateBlockLocations = new HashSet<Location>();
List<Map<String, Object>> serializedGateBlocks = (List<Map<String, Object>>)map.get(gateBlocksKey);
for (Map<String, Object> sgb : serializedGateBlocks) {
gateBlockLocations.add(LocationSerializer.deserializeLocation(sgb));
}
instances.put(id, this);
}
//----------------------------------------------//
// Persistance and entity management
//----------------------------------------------//
public Map<String, Object> serialize()
{
Map<String, Object> retVal = new HashMap<String, Object>();
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<Map<String, Object>> serializedGateBlocks = new ArrayList<Map<String, Object>>();
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<Map<String, Gate>>(){}.getType();
Map<String, Gate> 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<Block> 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<Gate> getAll()
{
return instances.values();
}
public static void fillIds()
{
for(Entry<String, Gate> entry : instances.entrySet())
entry.getValue().setId(entry.getKey());
}
}