2013-04-22 09:37:53 +02:00
|
|
|
package com.massivecraft.factions.entity;
|
2013-04-11 08:49:14 +02:00
|
|
|
|
2013-04-11 10:11:14 +02:00
|
|
|
import java.lang.reflect.Type;
|
2013-04-11 08:49:14 +02:00
|
|
|
import java.util.ArrayList;
|
2013-04-11 09:38:08 +02:00
|
|
|
import java.util.Collections;
|
2013-04-11 08:49:14 +02:00
|
|
|
import java.util.HashMap;
|
2013-04-24 11:16:37 +02:00
|
|
|
import java.util.HashSet;
|
2013-04-11 08:49:14 +02:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map.Entry;
|
2013-04-24 11:16:37 +02:00
|
|
|
import java.util.Set;
|
2013-04-11 08:49:14 +02:00
|
|
|
import java.util.concurrent.ConcurrentSkipListMap;
|
|
|
|
|
|
|
|
import org.bukkit.ChatColor;
|
|
|
|
|
2013-04-22 09:37:53 +02:00
|
|
|
import com.massivecraft.factions.Const;
|
|
|
|
import com.massivecraft.factions.Factions;
|
|
|
|
import com.massivecraft.factions.RelationParticipator;
|
|
|
|
import com.massivecraft.factions.TerritoryAccess;
|
2013-04-11 08:49:14 +02:00
|
|
|
import com.massivecraft.factions.util.AsciiCompass;
|
2014-06-04 14:02:23 +02:00
|
|
|
import com.massivecraft.massivecore.ps.PS;
|
|
|
|
import com.massivecraft.massivecore.store.Entity;
|
|
|
|
import com.massivecraft.massivecore.util.Txt;
|
2014-09-13 10:24:49 +02:00
|
|
|
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
|
2013-04-11 08:49:14 +02:00
|
|
|
|
2013-04-12 15:10:11 +02:00
|
|
|
public class Board extends Entity<Board> implements BoardInterface
|
2013-04-11 08:49:14 +02:00
|
|
|
{
|
2013-04-11 10:11:14 +02:00
|
|
|
public static final transient Type MAP_TYPE = new TypeToken<Map<PS, TerritoryAccess>>(){}.getType();
|
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
// -------------------------------------------- //
|
|
|
|
// META
|
|
|
|
// -------------------------------------------- //
|
|
|
|
|
|
|
|
public static Board get(Object oid)
|
|
|
|
{
|
2014-09-17 13:17:33 +02:00
|
|
|
return BoardColl.get().get(oid);
|
2013-04-11 08:49:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------------------------- //
|
2013-04-11 09:25:26 +02:00
|
|
|
// OVERRIDE: ENTITY
|
2013-04-11 08:49:14 +02:00
|
|
|
// -------------------------------------------- //
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Board load(Board that)
|
|
|
|
{
|
|
|
|
this.map = that.map;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isDefault()
|
|
|
|
{
|
|
|
|
if (this.map == null) return true;
|
|
|
|
if (this.map.isEmpty()) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------------------------- //
|
|
|
|
// FIELDS
|
|
|
|
// -------------------------------------------- //
|
|
|
|
|
2013-04-11 09:38:08 +02:00
|
|
|
// TODO: Make TerritoryAccess immutable.
|
|
|
|
|
|
|
|
private ConcurrentSkipListMap<PS, TerritoryAccess> map;
|
|
|
|
public Map<PS, TerritoryAccess> getMap() { return Collections.unmodifiableMap(this.map); }
|
|
|
|
|
|
|
|
// -------------------------------------------- //
|
|
|
|
// CONSTRUCT
|
|
|
|
// -------------------------------------------- //
|
|
|
|
|
|
|
|
public Board()
|
|
|
|
{
|
|
|
|
this.map = new ConcurrentSkipListMap<PS, TerritoryAccess>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Board(Map<PS, TerritoryAccess> map)
|
|
|
|
{
|
|
|
|
this.map = new ConcurrentSkipListMap<PS, TerritoryAccess>(map);
|
|
|
|
}
|
2013-04-11 08:49:14 +02:00
|
|
|
|
|
|
|
// -------------------------------------------- //
|
2013-04-11 09:25:26 +02:00
|
|
|
// OVERRIDE: BOARD
|
2013-04-11 08:49:14 +02:00
|
|
|
// -------------------------------------------- //
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
// GET
|
|
|
|
|
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public TerritoryAccess getTerritoryAccessAt(PS ps)
|
|
|
|
{
|
2013-04-11 09:25:26 +02:00
|
|
|
if (ps == null) return null;
|
2013-04-11 08:49:14 +02:00
|
|
|
ps = ps.getChunkCoords(true);
|
|
|
|
TerritoryAccess ret = this.map.get(ps);
|
2014-10-01 22:00:08 +02:00
|
|
|
if (ret == null) ret = TerritoryAccess.valueOf(Factions.ID_NONE);
|
2013-04-11 08:49:14 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public Faction getFactionAt(PS ps)
|
|
|
|
{
|
2013-04-11 09:25:26 +02:00
|
|
|
if (ps == null) return null;
|
2013-04-29 10:23:39 +02:00
|
|
|
TerritoryAccess ta = this.getTerritoryAccessAt(ps);
|
2014-09-17 13:29:58 +02:00
|
|
|
return ta.getHostFaction();
|
2013-04-11 08:49:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SET
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public void setTerritoryAccessAt(PS ps, TerritoryAccess territoryAccess)
|
|
|
|
{
|
|
|
|
ps = ps.getChunkCoords(true);
|
|
|
|
|
2014-10-01 22:00:08 +02:00
|
|
|
if (territoryAccess == null || (territoryAccess.getHostFactionId().equals(Factions.ID_NONE) && territoryAccess.isDefault()))
|
2013-04-24 11:30:00 +02:00
|
|
|
{
|
2013-04-11 08:49:14 +02:00
|
|
|
this.map.remove(ps);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.map.put(ps, territoryAccess);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.changed();
|
|
|
|
}
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public void setFactionAt(PS ps, Faction faction)
|
|
|
|
{
|
|
|
|
TerritoryAccess territoryAccess = null;
|
|
|
|
if (faction != null)
|
|
|
|
{
|
2013-04-29 10:23:39 +02:00
|
|
|
territoryAccess = TerritoryAccess.valueOf(faction.getId());
|
2013-04-11 08:49:14 +02:00
|
|
|
}
|
|
|
|
this.setTerritoryAccessAt(ps, territoryAccess);
|
|
|
|
}
|
|
|
|
|
|
|
|
// REMOVE
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public void removeAt(PS ps)
|
|
|
|
{
|
|
|
|
this.setTerritoryAccessAt(ps, null);
|
|
|
|
}
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
|
|
|
public void removeAll(Faction faction)
|
2013-04-11 08:49:14 +02:00
|
|
|
{
|
2013-04-11 09:25:26 +02:00
|
|
|
String factionId = faction.getId();
|
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
for (Entry<PS, TerritoryAccess> entry : this.map.entrySet())
|
|
|
|
{
|
|
|
|
TerritoryAccess territoryAccess = entry.getValue();
|
|
|
|
if ( ! territoryAccess.getHostFactionId().equals(factionId)) continue;
|
|
|
|
|
|
|
|
PS ps = entry.getKey();
|
|
|
|
this.removeAt(ps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Removes orphaned foreign keys
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public void clean()
|
|
|
|
{
|
|
|
|
for (Entry<PS, TerritoryAccess> entry : this.map.entrySet())
|
|
|
|
{
|
|
|
|
TerritoryAccess territoryAccess = entry.getValue();
|
2013-04-26 10:32:02 +02:00
|
|
|
String factionId = territoryAccess.getHostFactionId();
|
2014-09-17 13:17:33 +02:00
|
|
|
|
|
|
|
if (FactionColl.get().containsId(factionId)) continue;
|
2013-04-11 08:49:14 +02:00
|
|
|
|
|
|
|
PS ps = entry.getKey();
|
|
|
|
this.removeAt(ps);
|
|
|
|
|
2013-04-26 10:32:02 +02:00
|
|
|
Factions.get().log("Board cleaner removed "+factionId+" from "+ps);
|
2013-04-11 08:49:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-24 11:16:37 +02:00
|
|
|
// CHUNKS
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Set<PS> getChunks(Faction faction)
|
|
|
|
{
|
|
|
|
return this.getChunks(faction.getId());
|
|
|
|
}
|
|
|
|
|
|
|
|
public Set<PS> getChunks(String factionId)
|
|
|
|
{
|
|
|
|
Set<PS> ret = new HashSet<PS>();
|
|
|
|
for (Entry<PS, TerritoryAccess> entry : this.map.entrySet())
|
|
|
|
{
|
|
|
|
TerritoryAccess ta = entry.getValue();
|
|
|
|
if (!ta.getHostFactionId().equals(factionId)) continue;
|
|
|
|
|
|
|
|
PS ps = entry.getKey();
|
|
|
|
ps = ps.withWorld(this.getId());
|
|
|
|
ret.add(ps);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
// COUNT
|
2013-04-11 09:25:26 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getCount(Faction faction)
|
|
|
|
{
|
|
|
|
return this.getCount(faction.getId());
|
|
|
|
}
|
2013-04-11 08:49:14 +02:00
|
|
|
|
2014-10-18 18:30:13 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public int getCount(String factionId)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2013-04-24 11:16:37 +02:00
|
|
|
for (TerritoryAccess ta : this.map.values())
|
2013-04-11 08:49:14 +02:00
|
|
|
{
|
2013-04-24 11:16:37 +02:00
|
|
|
if (!ta.getHostFactionId().equals(factionId)) continue;
|
|
|
|
ret += 1;
|
2013-04-11 08:49:14 +02:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NEARBY DETECTION
|
2013-04-11 09:25:26 +02:00
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
// Is this coord NOT completely surrounded by coords claimed by the same faction?
|
|
|
|
// Simpler: Is there any nearby coord with a faction other than the faction here?
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public boolean isBorderPs(PS ps)
|
|
|
|
{
|
2013-05-17 08:37:32 +02:00
|
|
|
ps = ps.getChunk(true);
|
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
PS nearby = null;
|
|
|
|
Faction faction = this.getFactionAt(ps);
|
|
|
|
|
|
|
|
nearby = ps.withChunkX(ps.getChunkX() +1);
|
|
|
|
if (faction != this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
nearby = ps.withChunkX(ps.getChunkX() -1);
|
|
|
|
if (faction != this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
nearby = ps.withChunkZ(ps.getChunkZ() +1);
|
|
|
|
if (faction != this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
nearby = ps.withChunkZ(ps.getChunkZ() -1);
|
|
|
|
if (faction != this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2014-10-13 11:42:40 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isAnyBorderPs(Set<PS> pss)
|
|
|
|
{
|
|
|
|
for (PS ps : pss)
|
|
|
|
{
|
|
|
|
if (this.isBorderPs(ps)) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2013-04-11 08:49:14 +02:00
|
|
|
|
|
|
|
// Is this coord connected to any coord claimed by the specified faction?
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2013-04-11 08:49:14 +02:00
|
|
|
public boolean isConnectedPs(PS ps, Faction faction)
|
|
|
|
{
|
2013-05-17 08:37:32 +02:00
|
|
|
ps = ps.getChunk(true);
|
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
PS nearby = null;
|
|
|
|
|
|
|
|
nearby = ps.withChunkX(ps.getChunkX() +1);
|
|
|
|
if (faction == this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
nearby = ps.withChunkX(ps.getChunkX() -1);
|
|
|
|
if (faction == this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
nearby = ps.withChunkZ(ps.getChunkZ() +1);
|
|
|
|
if (faction == this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
nearby = ps.withChunkZ(ps.getChunkZ() -1);
|
|
|
|
if (faction == this.getFactionAt(nearby)) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-10-13 11:42:40 +02:00
|
|
|
@Override
|
|
|
|
public boolean isAnyConnectedPs(Set<PS> pss, Faction faction)
|
|
|
|
{
|
|
|
|
for (PS ps : pss)
|
|
|
|
{
|
|
|
|
if (this.isConnectedPs(ps, faction)) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-04-11 08:49:14 +02:00
|
|
|
// MAP GENERATION
|
|
|
|
|
2013-04-11 09:25:26 +02:00
|
|
|
@Override
|
2014-10-14 09:09:37 +02:00
|
|
|
public ArrayList<String> getMap(RelationParticipator observer, PS centerPs, double inDegrees, int width, int height)
|
2013-04-11 08:49:14 +02:00
|
|
|
{
|
|
|
|
centerPs = centerPs.getChunkCoords(true);
|
|
|
|
|
|
|
|
ArrayList<String> ret = new ArrayList<String>();
|
|
|
|
Faction centerFaction = this.getFactionAt(centerPs);
|
|
|
|
|
2013-04-24 19:01:17 +02:00
|
|
|
ret.add(Txt.titleize("("+centerPs.getChunkX() + "," + centerPs.getChunkZ()+") "+centerFaction.getName(observer)));
|
2013-04-11 08:49:14 +02:00
|
|
|
|
2014-10-14 09:09:37 +02:00
|
|
|
int halfWidth = width / 2;
|
|
|
|
int halfHeight = height / 2;
|
|
|
|
width = halfWidth * 2 + 1;
|
|
|
|
height = halfHeight * 2 + 1;
|
2013-04-11 08:49:14 +02:00
|
|
|
|
|
|
|
PS topLeftPs = centerPs.plusChunkCoords(-halfWidth, -halfHeight);
|
|
|
|
|
2013-04-24 19:01:17 +02:00
|
|
|
// Make room for the list of names
|
2013-04-11 08:49:14 +02:00
|
|
|
height--;
|
|
|
|
|
|
|
|
Map<Faction, Character> fList = new HashMap<Faction, Character>();
|
|
|
|
int chrIdx = 0;
|
|
|
|
|
|
|
|
// For each row
|
|
|
|
for (int dz = 0; dz < height; dz++)
|
|
|
|
{
|
|
|
|
// Draw and add that row
|
|
|
|
String row = "";
|
|
|
|
for (int dx = 0; dx < width; dx++)
|
|
|
|
{
|
|
|
|
if(dx == halfWidth && dz == halfHeight)
|
|
|
|
{
|
|
|
|
row += ChatColor.AQUA+"+";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
PS herePs = topLeftPs.plusChunkCoords(dx, dz);
|
|
|
|
Faction hereFaction = this.getFactionAt(herePs);
|
|
|
|
if (hereFaction.isNone())
|
|
|
|
{
|
|
|
|
row += ChatColor.GRAY+"-";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!fList.containsKey(hereFaction))
|
|
|
|
fList.put(hereFaction, Const.MAP_KEY_CHARS[chrIdx++]);
|
|
|
|
char fchar = fList.get(hereFaction);
|
|
|
|
row += hereFaction.getColorTo(observer) + "" + fchar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret.add(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the compass
|
|
|
|
ArrayList<String> asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.RED, Txt.parse("<a>"));
|
|
|
|
|
|
|
|
// Add the compass
|
|
|
|
ret.set(1, asciiCompass.get(0)+ret.get(1).substring(3*3));
|
|
|
|
ret.set(2, asciiCompass.get(1)+ret.get(2).substring(3*3));
|
|
|
|
ret.set(3, asciiCompass.get(2)+ret.get(3).substring(3*3));
|
|
|
|
|
|
|
|
String fRow = "";
|
|
|
|
for (Faction keyfaction : fList.keySet())
|
|
|
|
{
|
2013-04-24 19:01:17 +02:00
|
|
|
fRow += ""+keyfaction.getColorTo(observer) + fList.get(keyfaction) + ": " + keyfaction.getName() + " ";
|
2013-04-11 08:49:14 +02:00
|
|
|
}
|
|
|
|
fRow = fRow.trim();
|
|
|
|
ret.add(fRow);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|