Create AsciiMap and move map logic from Board to own class.

This commit is contained in:
ulumulu1510 2017-03-29 23:42:36 +02:00
parent edfabb7718
commit 577c164e2a
7 changed files with 244 additions and 158 deletions

View File

@ -1,20 +1,7 @@
package com.massivecraft.factions; package com.massivecraft.factions;
import org.bukkit.ChatColor;
public class Const public class Const
{ {
// ASCII Map
public static final int MAP_WIDTH = 48;
public static final int MAP_HEIGHT = 8;
public static final int MAP_HEIGHT_FULL = 17;
public static final char[] MAP_KEY_CHARS = "\\/#?笣$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZÄÖÜÆØÅ1234567890abcdeghjmnopqrsuvwxyÿzäöüæøåâêîûô".toCharArray();
public static final String MAP_KEY_WILDERNESS = ChatColor.GRAY.toString() + "-";
public static final String MAP_KEY_SEPARATOR = ChatColor.AQUA.toString() + "+";
public static final String MAP_KEY_OVERFLOW = ChatColor.MAGIC.toString() + "-" + ChatColor.RESET.toString();
public static final String MAP_OVERFLOW_MESSAGE = MAP_KEY_OVERFLOW + ": Too Many Factions (>" + MAP_KEY_CHARS.length + ") on this Map.";
// SHOW // SHOW
public static final String BASENAME = "factions"; public static final String BASENAME = "factions";
public static final String BASENAME_ = BASENAME+"_"; public static final String BASENAME_ = BASENAME+"_";

View File

@ -1,14 +1,10 @@
package com.massivecraft.factions.cmd; package com.massivecraft.factions.cmd;
import com.massivecraft.factions.Const; import com.massivecraft.factions.util.AsciiMap;
import com.massivecraft.factions.entity.BoardColl;
import com.massivecraft.massivecore.MassiveException; import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.requirement.RequirementIsPlayer; import com.massivecraft.massivecore.command.requirement.RequirementIsPlayer;
import com.massivecraft.massivecore.command.type.primitive.TypeBooleanYes; import com.massivecraft.massivecore.command.type.primitive.TypeBooleanYes;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.util.Txt;
import org.bukkit.Location;
import java.util.List;
public class CmdFactionsMap extends FactionsCommand public class CmdFactionsMap extends FactionsCommand
{ {
@ -32,34 +28,30 @@ public class CmdFactionsMap extends FactionsCommand
@Override @Override
public void perform() throws MassiveException public void perform() throws MassiveException
{ {
if ( ! this.argIsSet()) // NOTE: Map show is performed when auto == true || once
{ boolean argSet = this.argIsSet();
showMap(Const.MAP_WIDTH, Const.MAP_HEIGHT_FULL); boolean showMap = true;
return;
// Auto update
if (argSet) showMap = this.adjustAutoUpdating();
if (!showMap) return;
// Show Map
AsciiMap map = new AsciiMap(msender, me, !argSet);
message(map.render());
} }
if (this.readArg(!msender.isMapAutoUpdating())) private boolean adjustAutoUpdating() throws MassiveException
{ {
// And show the map once // Get
showMap(Const.MAP_WIDTH, Const.MAP_HEIGHT); boolean autoUpdating = this.readArg(!msender.isMapAutoUpdating());
// Turn on // Set
msender.setMapAutoUpdating(true); msender.setMapAutoUpdating(autoUpdating);
msg("<i>Map auto update <green>ENABLED.");
}
else
{
// Turn off
msender.setMapAutoUpdating(false);
msg("<i>Map auto update <red>DISABLED.");
}
}
public void showMap(int width, int height) // Inform
{ msg("<i>Map auto update %s<i>.", Txt.parse(autoUpdating ? "<green>ENABLED" : "<red>DISABLED"));
Location location = me.getLocation(); return autoUpdating;
List<Object> message = BoardColl.get().getMap(msenderFaction, PS.valueOf(location), location.getYaw(), width, height);
message(message);
} }
} }

View File

@ -1,11 +1,11 @@
package com.massivecraft.factions.engine; package com.massivecraft.factions.engine;
import com.massivecraft.factions.Const;
import com.massivecraft.factions.TerritoryAccess; import com.massivecraft.factions.TerritoryAccess;
import com.massivecraft.factions.entity.BoardColl; import com.massivecraft.factions.entity.BoardColl;
import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.MConf; import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MPlayer; import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.util.AsciiMap;
import com.massivecraft.massivecore.Engine; import com.massivecraft.massivecore.Engine;
import com.massivecraft.massivecore.mixin.MixinMessage; import com.massivecraft.massivecore.mixin.MixinMessage;
import com.massivecraft.massivecore.mixin.MixinTitle; import com.massivecraft.massivecore.mixin.MixinTitle;
@ -18,7 +18,6 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import java.util.Collections; import java.util.Collections;
import java.util.List;
public class EngineMoveChunk extends Engine public class EngineMoveChunk extends Engine
{ {
@ -64,8 +63,8 @@ public class EngineMoveChunk extends Engine
// send host faction info updates // send host faction info updates
if (mplayer.isMapAutoUpdating()) if (mplayer.isMapAutoUpdating())
{ {
List<Object> message = BoardColl.get().getMap(mplayer, chunkTo, player.getLocation().getYaw(), Const.MAP_WIDTH, Const.MAP_HEIGHT); AsciiMap map = new AsciiMap(mplayer, player, false);
mplayer.message(message); mplayer.message(map.render());
} }
else if (factionFrom != factionTo) else if (factionFrom != factionTo)
{ {

View File

@ -1,23 +1,16 @@
package com.massivecraft.factions.entity; package com.massivecraft.factions.entity;
import com.massivecraft.factions.Const;
import com.massivecraft.factions.Factions; import com.massivecraft.factions.Factions;
import com.massivecraft.factions.RelationParticipator;
import com.massivecraft.factions.TerritoryAccess; import com.massivecraft.factions.TerritoryAccess;
import com.massivecraft.factions.util.AsciiCompass;
import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.collections.MassiveSet; import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.store.Entity; import com.massivecraft.massivecore.store.Entity;
import com.massivecraft.massivecore.util.Txt;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken; import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -345,89 +338,4 @@ public class Board extends Entity<Board> implements BoardInterface
return false; return false;
} }
// MAP GENERATION
@Override
public List<Object> getMap(RelationParticipator observer, PS centerPs, double inDegrees, int width, int height)
{
centerPs = centerPs.getChunkCoords(true);
List<Object> ret = new ArrayList<>();
Faction centerFaction = this.getFactionAt(centerPs);
ret.add(Txt.titleize("(" + centerPs.getChunkX() + "," + centerPs.getChunkZ() + ") " + centerFaction.getName(observer)));
int halfWidth = width / 2;
int halfHeight = height / 2;
width = halfWidth * 2 + 1;
height = halfHeight * 2 + 1;
PS topLeftPs = centerPs.plusChunkCoords(-halfWidth, -halfHeight);
// Get the compass
List<String> asciiCompass = AsciiCompass.getAsciiCompass(inDegrees);
// Make room for the list of names
height--;
Map<Faction, Character> fList = new HashMap<>();
int chrIdx = 0;
boolean overflown = false;
// For each row
for (int dz = 0; dz < height; dz++)
{
// Draw and add that row
StringBuilder row = new StringBuilder();
for (int dx = 0; dx < width; dx++)
{
if (dx == halfWidth && dz == halfHeight)
{
row.append(Const.MAP_KEY_SEPARATOR);
continue;
}
if ( ! overflown && chrIdx >= Const.MAP_KEY_CHARS.length) overflown = true;
PS herePs = topLeftPs.plusChunkCoords(dx, dz);
Faction hereFaction = this.getFactionAt(herePs);
boolean contains = fList.containsKey(hereFaction);
if (hereFaction.isNone())
{
row.append(Const.MAP_KEY_WILDERNESS);
}
else if ( ! contains && overflown)
{
row.append(Const.MAP_KEY_OVERFLOW);
}
else
{
if ( ! contains) fList.put(hereFaction, Const.MAP_KEY_CHARS[chrIdx++]);
char fchar = fList.get(hereFaction);
row.append(hereFaction.getColorTo(observer).toString()).append(fchar);
}
}
String line = row.toString();
// Add the compass
if (dz == 0) line = asciiCompass.get(0) + line.substring(3*3);
if (dz == 1) line = asciiCompass.get(1) + line.substring(3*3);
if (dz == 2) line = asciiCompass.get(2) + line.substring(3*3);
ret.add(line);
}
String fRow = "";
for (Faction keyfaction : fList.keySet())
{
fRow += keyfaction.getColorTo(observer).toString() + fList.get(keyfaction) + ": " + keyfaction.getName() + " ";
}
if (overflown) fRow += Const.MAP_OVERFLOW_MESSAGE;
fRow = fRow.trim();
ret.add(fRow);
return ret;
}
} }

View File

@ -1,6 +1,5 @@
package com.massivecraft.factions.entity; package com.massivecraft.factions.entity;
import com.massivecraft.factions.RelationParticipator;
import com.massivecraft.factions.TerritoryAccess; import com.massivecraft.factions.TerritoryAccess;
import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.collections.MassiveSet; import com.massivecraft.massivecore.collections.MassiveSet;
@ -12,7 +11,6 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -302,17 +300,6 @@ public class BoardColl extends Coll<Board> implements BoardInterface
return false; return false;
} }
// MAP GENERATION
@Override
public List<Object> getMap(RelationParticipator observer, PS centerPs, double inDegrees, int width, int height)
{
if (centerPs == null) return null;
Board board = this.get(centerPs.getWorld());
if (board == null) return null;
return board.getMap(observer, centerPs, inDegrees, width, height);
}
// -------------------------------------------- // // -------------------------------------------- //
// WORLDS // WORLDS
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -1,10 +1,8 @@
package com.massivecraft.factions.entity; package com.massivecraft.factions.entity;
import com.massivecraft.factions.RelationParticipator;
import com.massivecraft.factions.TerritoryAccess; import com.massivecraft.factions.TerritoryAccess;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.ps.PS;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -42,8 +40,4 @@ public interface BoardInterface
boolean isConnectedPs(PS ps, Faction faction); boolean isConnectedPs(PS ps, Faction faction);
boolean isAnyConnectedPs(Set<PS> pss, Faction faction); boolean isAnyConnectedPs(Set<PS> pss, Faction faction);
// MAP
// TODO: Could the degrees be embedded in centerPs yaw instead?
List<Object> getMap(RelationParticipator observer, PS centerPs, double inDegrees, int width, int height);
} }

View File

@ -0,0 +1,219 @@
package com.massivecraft.factions.util;
import com.massivecraft.factions.RelationParticipator;
import com.massivecraft.factions.entity.Board;
import com.massivecraft.factions.entity.BoardColl;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.util.Txt;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static com.massivecraft.massivecore.mson.Mson.EMPTY;
import static com.massivecraft.massivecore.mson.Mson.SPACE;
import static com.massivecraft.massivecore.mson.Mson.mson;
public class AsciiMap
{
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final char[] FACTION_KEY_CHARS = "\\/#?笣$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZÄÖÜÆØÅ1234567890abcdeghjmnopqrsuvwxyÿzäöüæøåâêîûô".toCharArray();
private static final int KEY_SIZE = FACTION_KEY_CHARS.length;
// Map Heights & Widths
private static final int WIDTH = 49;
private static final int WIDTH_HALF = WIDTH / 2;
private static final int HEIGHT = 8;
private static final int HEIGHT_HALF = HEIGHT / 2;
private static final int HEIGHT_EXTRA = 17;
private static final int HEIGHT_EXTRA_HALF = HEIGHT_EXTRA / 2;
private static final String TITLE_FORMAT = "(%d,%d) %s";
private static final Mson KEY_MIDDLE = mson("+").color(ChatColor.AQUA);
private static final Mson KEY_WILDERNESS = mson("-").color(ChatColor.GRAY).tooltip();
private static final Mson KEY_OVERFLOW = mson("-").style(ChatColor.MAGIC).add(mson("").style(ChatColor.RESET));
private static final Mson OVERFLOW_MESSAGE = Mson.format("%s: Too Many Factions (>%d) on this Map.", KEY_OVERFLOW.toPlain(true), FACTION_KEY_CHARS.length);
private static final Mson LEGEND_SEPARATOR = mson(": ");
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final RelationParticipator relationParticipator;
public RelationParticipator getRelationParticipator() { return this.relationParticipator; }
private final double angle;
public double getAngle() { return this.angle; }
private final PS center;
public PS getCenter() { return this.center; }
private final PS topLeft;
public PS getTopLeft() { return this.topLeft; }
private final Board board;
public Board getBoard() { return this.board; }
private final Map<Faction, Mson> factionChars = new HashMap<>();
public Map<Faction, Mson> getFactionChars() { return this.factionChars; }
private final int height;
private int getHeight() { return this.height; }
private final int heightHalf;
private int getHeightHalf() { return this.heightHalf; }
private boolean overflown = false;
public boolean isOverflown() { return this.overflown; }
public void setOverflown(boolean overflown) { this.overflown = overflown; }
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public AsciiMap(RelationParticipator relationParticipator, Player player, boolean extraHeight)
{
this.relationParticipator = relationParticipator;
Location location = player.getLocation();
this.angle = location.getYaw();
this.center = PS.valueOf(location).getChunk(true);
this.height = extraHeight ? HEIGHT_EXTRA : HEIGHT;
this.heightHalf = extraHeight ? HEIGHT_EXTRA_HALF : HEIGHT_HALF;
this.topLeft = this.center.plusChunkCoords(-WIDTH_HALF, -this.heightHalf);
this.board = BoardColl.get().get(this.center.getWorld());
}
// -------------------------------------------- //
// RENDER
// -------------------------------------------- //
public List<Mson> render()
{
// Create
List<Mson> ret = new ArrayList<>();
// Fill
ret.add(this.getTitle());
ret.addAll(this.getLines());
ret.add(this.getFactionLegend());
// Return
return ret;
}
private Mson getTitle()
{
// Prepare
PS chunk = this.getCenter();
Faction faction = this.getBoard().getFactionAt(chunk);
int chunkX = chunk.getChunkX();
int chunkZ = chunk.getChunkZ();
String factionName = faction.getName(this.getRelationParticipator());
// Titleize
return Txt.titleize(String.format(TITLE_FORMAT, chunkX, chunkZ, factionName));
}
private List<Mson> getLines()
{
// Create
List<Mson> ret = new MassiveList<>();
List<String> asciiCompass = AsciiCompass.getAsciiCompass(this.getAngle());
// Fill
for (int deltaZ = 0; deltaZ < this.getHeight(); deltaZ++)
{
ret.add(this.getLine(deltaZ, asciiCompass));
}
// Return
return ret;
}
private Mson getLine(int deltaZ, List<String> asciiCompass)
{
// Create
boolean isCompassLine = deltaZ < asciiCompass.size();
int startX = isCompassLine ? 3 : 0;
Mson ret = isCompassLine ? mson(asciiCompass.get(deltaZ)) : EMPTY;
Mson factionChar;
// Fill
for (int deltaX = startX; deltaX < WIDTH; deltaX++)
{
boolean isMiddle = deltaX == WIDTH_HALF && deltaZ == this.getHeightHalf();
factionChar = isMiddle ? KEY_MIDDLE : this.getCharFaction(deltaZ, deltaX);
ret = ret.add(factionChar);
}
// Return
return ret;
}
private Mson getCharFaction(int deltaZ, int deltaX)
{
// Calculate overflow
int index = this.getFactionChars().size();
if (!this.isOverflown() && index >= KEY_SIZE) this.setOverflown(true);
PS herePs = this.getTopLeft().plusChunkCoords(deltaX, deltaZ);
Faction hereFaction = this.getBoard().getFactionAt(herePs);
Mson factionChar = this.getFactionChars().get(hereFaction);
// Is Wilderness or known?
if (hereFaction.isNone()) return KEY_WILDERNESS;
if (factionChar != null) return factionChar;
// Create descriptions
ChatColor color = hereFaction.getColorTo(this.getRelationParticipator());
String name = hereFaction.getName(this.getRelationParticipator());
String tooltip = color.toString() + name;
// Is overflown?
if (this.isOverflown()) return KEY_OVERFLOW.tooltip(tooltip);
// Create new one
factionChar = mson(String.valueOf(FACTION_KEY_CHARS[index])).color(color);
factionChar = factionChar.tooltip(tooltip);
// Store for later use
this.getFactionChars().put(hereFaction, factionChar);
// Return
return factionChar;
}
private Mson getFactionLegend()
{
// Create
List<Mson> ret = new MassiveList<>();
// Fill
for (Entry<Faction, Mson> entry : this.getFactionChars().entrySet())
{
Faction here = entry.getKey();
Mson factionChar = entry.getValue();
ChatColor color = here.getColorTo(this.getRelationParticipator());
ret.add(mson(factionChar, LEGEND_SEPARATOR, here.getName()).color(color));
}
// Add overflown message if needed
if (this.isOverflown()) ret.add(OVERFLOW_MESSAGE);
// Return
return Mson.implode(ret, SPACE);
}
}