refactoring: abstract Gate base class; native bukkit serialization
This commit is contained in:
parent
3d6b5fe1c6
commit
7e300d9c03
187
src/org/mcteam/ancientgates/BaseGate.java
Normal file
187
src/org/mcteam/ancientgates/BaseGate.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user