Using PersistRealms and experimenting with TextDesign.

This commit is contained in:
Olof Larsson 2011-12-08 05:03:52 +01:00
parent 9eceaa6e47
commit 6ffb71676b
11 changed files with 839 additions and 211 deletions

View File

@ -1,6 +1,6 @@
name: mcore
version: 1.0.0
main: com.massivecraft.core.MCore
main: com.massivecraft.core.plugin.MCore
authors: [Olof Larsson]
softdepend: [Vault, Spout]
commands:

View File

@ -1,209 +1,17 @@
package com.massivecraft.core.persist;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
public class Persist
{
private Map<Class<?>, IClassManager<?>> classManagers = new HashMap<Class<?>, IClassManager<?>>();
public <T> void setManager(Class<T> clazz, IClassManager<T> manager)
private static Map<Object, PersistRealm> realms = new HashMap<Object, PersistRealm>();
public static Map<Object, PersistRealm> getRealms() { return realms; }
public static PersistRealm getRealm(Object realmOwner) { return realms.get(realmOwner); }
public static void createRealm(Object realmOwner)
{
this.classManagers.put(clazz, manager);
};
public Map<Class<?>, IClassManager<?>> getClassManagers()
{
return this.classManagers;
}
protected Timer timer = new Timer();
private Map<Class<?>, SaveTask<?>> classSaveTasks = new HashMap<Class<?>, SaveTask<?>>();
@SuppressWarnings("unchecked")
public <T> void setSaveInterval(Class<T> clazz, long interval)
{
// Fetch the task or create a new one.
SaveTask<T> task = (SaveTask<T>) this.classSaveTasks.get(clazz);
if (task == null)
{
task = new SaveTask<T>(this, clazz);
this.classSaveTasks.put(clazz, task);
}
else
{
task.cancel();
}
// Schedule the task
timer.scheduleAtFixedRate(task, interval, interval);
};
@SuppressWarnings("unchecked")
public <T> IClassManager<T> getManager(Class<T> clazz)
{
return (IClassManager<T>) this.classManagers.get(clazz);
}
@SuppressWarnings("unchecked")
public <T extends Object> IClassManager<T> getManager(T entity)
{
return (IClassManager<T>) this.getManager(entity.getClass());
}
// -------------------------------------------- //
// SAVE ALL
// -------------------------------------------- //
public void saveAll()
{
for (IClassManager<?> m : this.classManagers.values())
{
m.saveAll();
}
}
// -------------------------------------------- //
// UTILS
// -------------------------------------------- //
public static void write(File file, String content) throws IOException
{
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, false), "UTF8"));
out.write(content);
out.close();
}
public static String read(File file) throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
String ret = new String(new byte[0], "UTF-8");
String line;
while ((line = in.readLine()) != null)
{
ret += line;
}
in.close();
return ret;
}
public static boolean writeCatch(File file, String content)
{
try
{
write(file, content);
return true;
}
catch (Exception e)
{
return false;
}
}
public static String readCatch(File file)
{
try
{
return read(file);
}
catch (IOException e)
{
return null;
}
}
public static <T> ArrayList<T> uglySQL(Collection<T> items, Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
{
ArrayList<T> ret = new ArrayList<T>(items.size());
// WHERE
for (T item : items)
{
if (where.apply(item))
{
ret.add(item);
}
}
// ORDERBY
Collections.sort(ret, orderby);
// LIMIT AND OFFSET
// Parse args
int fromIndex = 0;
if (offset != null)
{
fromIndex = offset;
}
int toIndex = ret.size()-1;
if (limit != null)
{
toIndex = offset+limit;
}
// Clean args
if (fromIndex < 0)
{
fromIndex = 0;
}
else if (fromIndex > ret.size()-1)
{
fromIndex = ret.size()-1;
}
if (toIndex < fromIndex)
{
toIndex = fromIndex;
}
else if (toIndex > ret.size()-1)
{
toIndex = ret.size()-1;
}
// No limit?
if (fromIndex == 0 && toIndex == ret.size()-1) return ret;
return new ArrayList<T>(ret.subList(fromIndex, toIndex));
}
public static String getBestCIStart(Collection<String> candidates, String start)
{
String ret = null;
int best = 0;
start = start.toLowerCase();
int minlength = start.length();
for (String candidate : candidates)
{
if (candidate.length() < minlength) continue;
if ( ! candidate.toLowerCase().startsWith(start)) continue;
// The closer to zero the better
int lendiff = candidate.length() - minlength;
if (lendiff == 0)
{
return candidate;
}
if (lendiff < best || best == 0)
{
best = lendiff;
ret = candidate;
}
}
return ret;
if (realms.containsKey(realmOwner)) return;
realms.put(realmOwner, new PersistRealm());
}
public static void removeRealm(Object realmOwner) { realms.remove(realmOwner); }
}

View File

@ -0,0 +1,209 @@
package com.massivecraft.core.persist;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
public class PersistRealm
{
private Map<Class<?>, IClassManager<?>> classManagers = new HashMap<Class<?>, IClassManager<?>>();
public <T> void setManager(Class<T> clazz, IClassManager<T> manager)
{
this.classManagers.put(clazz, manager);
};
public Map<Class<?>, IClassManager<?>> getClassManagers()
{
return this.classManagers;
}
protected Timer timer = new Timer();
private Map<Class<?>, SaveTask<?>> classSaveTasks = new HashMap<Class<?>, SaveTask<?>>();
@SuppressWarnings("unchecked")
public <T> void setSaveInterval(Class<T> clazz, long interval)
{
// Fetch the task or create a new one.
SaveTask<T> task = (SaveTask<T>) this.classSaveTasks.get(clazz);
if (task == null)
{
task = new SaveTask<T>(this, clazz);
this.classSaveTasks.put(clazz, task);
}
else
{
task.cancel();
}
// Schedule the task
timer.scheduleAtFixedRate(task, interval, interval);
};
@SuppressWarnings("unchecked")
public <T> IClassManager<T> getManager(Class<T> clazz)
{
return (IClassManager<T>) this.classManagers.get(clazz);
}
@SuppressWarnings("unchecked")
public <T extends Object> IClassManager<T> getManager(T entity)
{
return (IClassManager<T>) this.getManager(entity.getClass());
}
// -------------------------------------------- //
// SAVE ALL
// -------------------------------------------- //
public void saveAll()
{
for (IClassManager<?> m : this.classManagers.values())
{
m.saveAll();
}
}
// -------------------------------------------- //
// UTILS
// -------------------------------------------- //
public static void write(File file, String content) throws IOException
{
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, false), "UTF8"));
out.write(content);
out.close();
}
public static String read(File file) throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
String ret = new String(new byte[0], "UTF-8");
String line;
while ((line = in.readLine()) != null)
{
ret += line;
}
in.close();
return ret;
}
public static boolean writeCatch(File file, String content)
{
try
{
write(file, content);
return true;
}
catch (Exception e)
{
return false;
}
}
public static String readCatch(File file)
{
try
{
return read(file);
}
catch (IOException e)
{
return null;
}
}
public static <T> ArrayList<T> uglySQL(Collection<T> items, Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
{
ArrayList<T> ret = new ArrayList<T>(items.size());
// WHERE
for (T item : items)
{
if (where.apply(item))
{
ret.add(item);
}
}
// ORDERBY
Collections.sort(ret, orderby);
// LIMIT AND OFFSET
// Parse args
int fromIndex = 0;
if (offset != null)
{
fromIndex = offset;
}
int toIndex = ret.size()-1;
if (limit != null)
{
toIndex = offset+limit;
}
// Clean args
if (fromIndex < 0)
{
fromIndex = 0;
}
else if (fromIndex > ret.size()-1)
{
fromIndex = ret.size()-1;
}
if (toIndex < fromIndex)
{
toIndex = fromIndex;
}
else if (toIndex > ret.size()-1)
{
toIndex = ret.size()-1;
}
// No limit?
if (fromIndex == 0 && toIndex == ret.size()-1) return ret;
return new ArrayList<T>(ret.subList(fromIndex, toIndex));
}
public static String getBestCIStart(Collection<String> candidates, String start)
{
String ret = null;
int best = 0;
start = start.toLowerCase();
int minlength = start.length();
for (String candidate : candidates)
{
if (candidate.length() < minlength) continue;
if ( ! candidate.toLowerCase().startsWith(start)) continue;
// The closer to zero the better
int lendiff = candidate.length() - minlength;
if (lendiff == 0)
{
return candidate;
}
if (lendiff < best || best == 0)
{
best = lendiff;
ret = candidate;
}
}
return ret;
}
}

View File

@ -4,18 +4,18 @@ import java.util.TimerTask;
public class SaveTask<T> extends TimerTask
{
private Persist persist;
private PersistRealm persist;
private Class<T> clazz;
public Class<T> getToBeSavedClass() { return clazz; }
public SaveTask(Persist persist, Class<T> clazz)
public SaveTask(PersistRealm persist, Class<T> clazz)
{
this.persist = persist;
this.clazz = clazz;
}
public SaveTask(Persist persist)
public SaveTask(PersistRealm persist)
{
this(persist, null);
}

View File

@ -13,7 +13,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
import com.massivecraft.core.lib.gson2.Gson;
import com.massivecraft.core.persist.IClassManager;
import com.massivecraft.core.persist.Persist;
import com.massivecraft.core.persist.PersistRealm;
import com.massivecraft.core.persist.Predictate;
public abstract class GsonClassManager<T> implements IClassManager<T>
@ -259,7 +259,7 @@ public abstract class GsonClassManager<T> implements IClassManager<T>
{
String json = this.getGson().toJson(entity);
File file = this.fileFromId(id);
return Persist.writeCatch(file, json);
return PersistRealm.writeCatch(file, json);
}
this.removeFile(id);
return true;
@ -305,7 +305,7 @@ public abstract class GsonClassManager<T> implements IClassManager<T>
if (entity != null) return entity;
if ( ! this.containsId(id)) return null;
File file = this.fileFromId(id);
String json = Persist.readCatch(file);
String json = PersistRealm.readCatch(file);
if (json == null) return null;
entity = this.getGson().fromJson(json, this.getManagedClass());
this.attach(entity, id, true);
@ -415,25 +415,25 @@ public abstract class GsonClassManager<T> implements IClassManager<T>
@Override
public Collection<T> getAll(Predictate<T> where)
{
return Persist.uglySQL(this.entities, where, null, null, null);
return PersistRealm.uglySQL(this.entities, where, null, null, null);
}
@Override
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby)
{
return Persist.uglySQL(this.entities, where, orderby, null, null);
return PersistRealm.uglySQL(this.entities, where, orderby, null, null);
}
@Override
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby, Integer limit)
{
return Persist.uglySQL(this.entities, where, orderby, limit, null);
return PersistRealm.uglySQL(this.entities, where, orderby, limit, null);
}
@Override
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
{
return Persist.uglySQL(this.entities, where, orderby, limit, offset);
return PersistRealm.uglySQL(this.entities, where, orderby, limit, offset);
}
@Override
@ -452,7 +452,7 @@ public abstract class GsonClassManager<T> implements IClassManager<T>
public T getBestMatch(Object oid)
{
String start = this.idFix(oid);
String id = Persist.getBestCIStart(this.ids, start);
String id = PersistRealm.getBestCIStart(this.ids, start);
return this.get(id);
}
}

View File

@ -0,0 +1,58 @@
package com.massivecraft.core.plugin;
import org.bukkit.Bukkit;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.Event.Type;
import org.bukkit.plugin.java.JavaPlugin;
import com.massivecraft.core.persist.Persist;
import com.massivecraft.core.persist.PersistRealm;
import com.massivecraft.core.plugin.listener.PluginPlayerListener;
import com.massivecraft.core.plugin.listener.PluginServerListener;
import com.massivecraft.core.plugin.listener.PluginServerListenerMonitor;
public class MCore extends JavaPlugin
{
PluginServerListener serverListener;
PluginServerListenerMonitor serverListenerMonitor;
PluginPlayerListener playerListener;
public static MCore p;
public static PersistRealm persist;
public MCore()
{
p = this;
Persist.createRealm(this);
persist = Persist.getRealm(this);
this.serverListener = new PluginServerListener(this);
this.serverListenerMonitor = new PluginServerListenerMonitor(this);
this.playerListener = new PluginPlayerListener(this);
}
public static PersistRealm getPersist()
{
return Persist.getRealm(p);
}
@Override
public void onDisable()
{
// Avoid memleak by clearing ???
// Or will this trigger errors???
//Persist.getRealms().clear();
}
@Override
public void onEnable()
{
// This is safe since all plugins using Persist should bukkit-depend this plugin.
Persist.getRealms().clear();
// Register events
//Bukkit.getPluginManager().registerEvent(Type.PLUGIN_ENABLE, this.serverListener, Priority.Lowest, this); // Dangerous!?!?!
//Bukkit.getPluginManager().registerEvent(Type.PLUGIN_DISABLE, this.serverListenerMonitor, Priority.Monitor, this); // Dangerous!?!?!
Bukkit.getPluginManager().registerEvent(Type.PLAYER_JOIN, this.playerListener, Priority.Lowest, this);
}
}

View File

@ -0,0 +1,36 @@
package com.massivecraft.core.plugin.listener;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerLoginEvent;
import com.massivecraft.core.persist.IClassManager;
import com.massivecraft.core.persist.Persist;
import com.massivecraft.core.persist.PersistRealm;
import com.massivecraft.core.plugin.MCore;
public class PluginPlayerListener extends PlayerListener
{
MCore p;
public PluginPlayerListener(MCore p)
{
this.p = p;
}
@Override
public void onPlayerLogin(PlayerLoginEvent event)
{
Player player = event.getPlayer();
for (PersistRealm realm : Persist.getRealms().values())
{
for (IClassManager<?> manager : realm.getClassManagers().values())
{
if (manager.idFix(player) == null) continue;
if (manager.containsId(player)) continue;
manager.create(player);
}
}
}
}

View File

@ -0,0 +1,24 @@
package com.massivecraft.core.plugin.listener;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.event.server.ServerListener;
import com.massivecraft.core.persist.Persist;
import com.massivecraft.core.plugin.MCore;
public class PluginServerListener extends ServerListener
{
MCore p;
public PluginServerListener(MCore p)
{
this.p = p;
}
@Override
public void onPluginEnable(PluginEnableEvent event)
{
// TODO: Is this run after or before???
Persist.createRealm(event.getPlugin());
}
}

View File

@ -0,0 +1,31 @@
package com.massivecraft.core.plugin.listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.event.server.ServerListener;
import com.massivecraft.core.persist.Persist;
import com.massivecraft.core.plugin.MCore;
public class PluginServerListenerMonitor extends ServerListener
{
MCore p;
public PluginServerListenerMonitor(MCore p)
{
this.p = p;
}
@Override
public void onPluginDisable(PluginDisableEvent event)
{
Persist.removeRealm(event.getPlugin());
}
@Override
public void onPluginEnable(PluginEnableEvent event)
{
// TODO: Is this run after or before???
Persist.createRealm(event.getPlugin());
}
}

View File

@ -0,0 +1,119 @@
package com.massivecraft.core.text;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.ChatColor;
// TODO: Add some more cool stuff.. like titelization design.
// TODO: Should they be color-parsed? or cashed color parsed?
public class TextDesign
{
public TextDesign()
{
}
// -------------------------------------------- //
// TITLE DESIGN
// -------------------------------------------- //
private String titleLeftInner;
public String getTitleLeftInner() { return this.titleLeftInner; }
public void setTitleLeftInner(String val) { this.titleLeftInner = val; }
private String titleLeftOuter;
public String getTitleLeftOuter() { return this.titleLeftOuter; }
public void setTitleLeftOuter(String val) { this.titleLeftOuter = val; }
private String titleRightInner;
public String getTitleRightInner() { return this.titleRightInner; }
public void setTitleRightInner(String val) { this.titleRightInner = val; }
private String titleRightOuter;
public String getTitleRightOuter() { return this.titleRightOuter; }
public void setTitleRightOuter(String val) { this.titleRightOuter = val; }
// -------------------------------------------- //
// COLOR THEME
// -------------------------------------------- //
private ChatColor logo = ChatColor.DARK_GREEN;
public ChatColor getColorLogo() { return this.logo; }
public void setColorLogo(ChatColor val) { this.logo = val; this.updateTag2Color(); }
private ChatColor art = ChatColor.GOLD;
public ChatColor getColorArt() { return this.art; }
public void setColorArt(ChatColor val) { this.art = val; this.updateTag2Color(); }
private ChatColor notice = ChatColor.GRAY;
public ChatColor getColorNotice() { return this.notice; }
public void setColorNotice(ChatColor val) { this.notice = val; this.updateTag2Color(); }
private ChatColor info = ChatColor.YELLOW;
public ChatColor getColorInfo() { return this.info; }
public void setColorInfo(ChatColor val) { this.info = val; this.updateTag2Color(); }
private ChatColor good = ChatColor.GREEN;
public ChatColor getColorGood() { return this.good; }
public void setColorGood(ChatColor val) { this.good = val; this.updateTag2Color(); }
private ChatColor bad = ChatColor.RED;
public ChatColor getColorBad() { return this.bad; }
public void setColorBad(ChatColor val) { this.bad = val; this.updateTag2Color(); }
private ChatColor hightlight = ChatColor.LIGHT_PURPLE;
public ChatColor getColorHighlight() { return this.hightlight; }
public void setColorHightlight(ChatColor val) { this.hightlight = val; this.updateTag2Color(); }
private ChatColor command = ChatColor.AQUA;
public ChatColor getColorCommand() { return this.command; }
public void setColorCommand(ChatColor val) { this.command = val; this.updateTag2Color(); }
private ChatColor parameter = ChatColor.DARK_AQUA;
public ChatColor getColorParameter() { return this.parameter; }
public void setColorParameter(ChatColor val) { this.parameter = val; this.updateTag2Color(); }
private Map<String, String> tag2color = null;
public Map<String, String> getTags()
{
if (tag2color == null)
{
this.updateTag2Color();
}
return this.tag2color;
}
private void updateTag2Color()
{
if (tag2color == null)
{
this.tag2color = new HashMap<String, String>();
}
this.tag2color.put("<l>", this.getColorLogo().toString());
this.tag2color.put("<logo>", this.getColorLogo().toString());
this.tag2color.put("<a>", this.getColorArt().toString());
this.tag2color.put("<art>", this.getColorArt().toString());
this.tag2color.put("<n>", this.getColorNotice().toString());
this.tag2color.put("<notice>", this.getColorNotice().toString());
this.tag2color.put("<i>", this.getColorInfo().toString());
this.tag2color.put("<info>", this.getColorInfo().toString());
this.tag2color.put("<g>", this.getColorGood().toString());
this.tag2color.put("<good>", this.getColorGood().toString());
this.tag2color.put("<b>", this.getColorBad().toString());
this.tag2color.put("<bad>", this.getColorBad().toString());
this.tag2color.put("<h>", this.getColorHighlight().toString());
this.tag2color.put("<highlight>", this.getColorHighlight().toString());
this.tag2color.put("<c>", this.getColorCommand().toString());
this.tag2color.put("<command>", this.getColorCommand().toString());
this.tag2color.put("<p>", this.getColorParameter().toString());
this.tag2color.put("<parameter>", this.getColorParameter().toString());
}
}

View File

@ -0,0 +1,343 @@
package com.massivecraft.core.text;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.craftbukkit.TextWrapper;
import com.massivecraft.core.plugin.MCore;
public class TextUtil
{
private TextDesign design = null;
public TextDesign getDesign()
{
if (design != null) return design;
return MCore.persist.getManager(TextDesign.class).get("default");
// TODO: The default should not have the name default.
// The default is set somewhere... as a static field?... in the MCore plugin???
}
public void setDesign(TextDesign design)
{
this.design = design;
}
// -------------------------------------------- //
// Top-level parsing functions.
// -------------------------------------------- //
public String parse(String str, Object... args)
{
return String.format(this.parse(str), args);
}
public String parse(String str)
{
return this.parseTags(parseColor(str));
}
// -------------------------------------------- //
// Tag parsing
// -------------------------------------------- //
public String parseTags(String str)
{
return replaceTags(str, this.getDesign().getTags());
}
public static final transient Pattern patternTag = Pattern.compile("<([a-zA-Z0-9_]*)>");
public static String replaceTags(String str, Map<String, String> tags)
{
StringBuffer ret = new StringBuffer();
Matcher matcher = patternTag.matcher(str);
while (matcher.find())
{
String tag = matcher.group(1);
String repl = tags.get(tag);
if (repl == null)
{
matcher.appendReplacement(ret, "<"+tag+">");
}
else
{
matcher.appendReplacement(ret, repl);
}
}
matcher.appendTail(ret);
return ret.toString();
}
// -------------------------------------------- //
// Color parsing
// -------------------------------------------- //
public static String parseColor(String string)
{
string = parseColorAmp(string);
string = parseColorAcc(string);
string = parseColorTags(string);
return string;
}
public static String parseColorAmp(String string)
{
string = string.replaceAll("(§([a-z0-9]))", "\u00A7$2");
string = string.replaceAll("(&([a-z0-9]))", "\u00A7$2");
string = string.replace("&&", "&");
return string;
}
public static String parseColorAcc(String string)
{
return string.replace("`e", "")
.replace("`r", ChatColor.RED.toString()) .replace("`R", ChatColor.DARK_RED.toString())
.replace("`y", ChatColor.YELLOW.toString()) .replace("`Y", ChatColor.GOLD.toString())
.replace("`g", ChatColor.GREEN.toString()) .replace("`G", ChatColor.DARK_GREEN.toString())
.replace("`a", ChatColor.AQUA.toString()) .replace("`A", ChatColor.DARK_AQUA.toString())
.replace("`b", ChatColor.BLUE.toString()) .replace("`B", ChatColor.DARK_BLUE.toString())
.replace("`p", ChatColor.LIGHT_PURPLE.toString()) .replace("`P", ChatColor.DARK_PURPLE.toString())
.replace("`k", ChatColor.BLACK.toString()) .replace("`s", ChatColor.GRAY.toString())
.replace("`S", ChatColor.DARK_GRAY.toString()) .replace("`w", ChatColor.WHITE.toString());
}
public static String parseColorTags(String string)
{
return string.replace("<empty>", "")
.replace("<black>", "\u00A70")
.replace("<navy>", "\u00A71")
.replace("<green>", "\u00A72")
.replace("<teal>", "\u00A73")
.replace("<red>", "\u00A74")
.replace("<purple>", "\u00A75")
.replace("<gold>", "\u00A76")
.replace("<silver>", "\u00A77")
.replace("<gray>", "\u00A78")
.replace("<blue>", "\u00A79")
.replace("<lime>", "\u00A7a")
.replace("<aqua>", "\u00A7b")
.replace("<rose>", "\u00A7c")
.replace("<pink>", "\u00A7d")
.replace("<yellow>", "\u00A7e")
.replace("<white>", "\u00A7f");
}
// -------------------------------------------- //
// Standard utils like UCFirst, implode and repeat.
// -------------------------------------------- //
public static String upperCaseFirst(String string)
{
return string.substring(0, 1).toUpperCase()+string.substring(1);
}
public static String repeat(String s, int times)
{
if (times <= 0) return "";
else return s + repeat(s, times-1);
}
public static String implode(List<String> list, String glue)
{
StringBuilder ret = new StringBuilder();
for (int i=0; i<list.size(); i++)
{
if (i!=0)
{
ret.append(glue);
}
ret.append(list.get(i));
}
return ret.toString();
}
public static String implodeCommaAnd(List<String> list, String comma, String and)
{
if (list.size() == 0) return "";
if (list.size() == 1) return list.get(0);
String lastItem = list.get(list.size()-1);
String nextToLastItem = list.get(list.size()-2);
String merge = nextToLastItem+and+lastItem;
list.set(list.size()-2, merge);
list.remove(list.size()-1);
return implode(list, comma);
}
public static String implodeCommaAnd(List<String> list)
{
return implodeCommaAnd(list, ", ", " and ");
}
// -------------------------------------------- //
// Material name tools
// -------------------------------------------- //
public static String getMaterialName(Material material)
{
return material.toString().replace('_', ' ').toLowerCase();
}
public static String getMaterialName(int materialId)
{
return getMaterialName(Material.getMaterial(materialId));
}
// -------------------------------------------- //
// Paging and chrome-tools like titleize
// -------------------------------------------- //
private final static String titleizeLine = repeat("_", 52);
private final static int titleizeBalance = -1;
public String titleize(String str)
{
String center = ".[ "+ parseTags("<l>") + str + parseTags("<a>")+ " ].";
int centerlen = ChatColor.stripColor(center).length();
int pivot = titleizeLine.length() / 2;
int eatLeft = (centerlen / 2) - titleizeBalance;
int eatRight = (centerlen - eatLeft) + titleizeBalance;
if (eatLeft < pivot)
return parseTags("<a>")+titleizeLine.substring(0, pivot - eatLeft) + center + titleizeLine.substring(pivot + eatRight);
else
return parseTags("<a>")+center;
}
public ArrayList<String> getPage(List<String> lines, int pageHumanBased, String title)
{
ArrayList<String> ret = new ArrayList<String>();
int pageZeroBased = pageHumanBased - 1;
int pageheight = 9;
int pagecount = (lines.size() / pageheight)+1;
ret.add(this.titleize(title+" "+pageHumanBased+"/"+pagecount));
if (pagecount == 0)
{
ret.add(this.parseTags("<i>Sorry. No Pages available."));
return ret;
}
else if (pageZeroBased < 0 || pageHumanBased > pagecount)
{
ret.add(this.parseTags("<i>Invalid page. Must be between 1 and "+pagecount));
return ret;
}
int from = pageZeroBased * pageheight;
int to = from+pageheight;
if (to > lines.size())
{
to = lines.size();
}
ret.addAll(lines.subList(from, to));
return ret;
}
// -------------------------------------------- //
// Describing Time
// -------------------------------------------- //
/**
* Using this function you transform a delta in milliseconds
* to a String like "2 weeks from now" or "7 days ago".
*/
public static final long millisPerSecond = 1000;
public static final long millisPerMinute = 60 * millisPerSecond;
public static final long millisPerHour = 60 * millisPerMinute;
public static final long millisPerDay = 24 * millisPerHour;
public static final long millisPerWeek = 7 * millisPerDay;
public static final long millisPerMonth = 31 * millisPerDay;
public static final long millisPerYear = 365 * millisPerDay;
public static Map<String, Long> unitMillis;
static
{
unitMillis = new LinkedHashMap<String, Long>();
unitMillis.put("years", millisPerYear);
unitMillis.put("months", millisPerMonth);
unitMillis.put("weeks", millisPerWeek);
unitMillis.put("days", millisPerDay);
unitMillis.put("hours", millisPerHour);
unitMillis.put("minutes", millisPerMinute);
unitMillis.put("seconds", millisPerSecond);
}
public static String getTimeDeltaDescriptionRelNow(long millis)
{
String ret = "";
double millisLeft = (double) Math.abs(millis);
List<String> unitCountParts = new ArrayList<String>();
for (Entry<String, Long> entry : unitMillis.entrySet())
{
if (unitCountParts.size() == 3 ) break;
String unitName = entry.getKey();
long unitSize = entry.getValue();
long unitCount = (long) Math.floor(millisLeft / unitSize);
if (unitCount < 1) continue;
millisLeft -= unitSize*unitCount;
unitCountParts.add(unitCount+" "+unitName);
}
if (unitCountParts.size() == 0) return "just now";
ret += implodeCommaAnd(unitCountParts);
ret += " ";
if (millis <= 0)
{
ret += "ago";
}
else
{
ret += "from now";
}
return ret;
}
// -------------------------------------------- //
// String comparison
// -------------------------------------------- //
public static String getBestCIStart(Collection<String> candidates, String start)
{
String ret = null;
int best = 0;
start = start.toLowerCase();
int minlength = start.length();
for (String candidate : candidates)
{
if (candidate.length() < minlength) continue;
if ( ! candidate.toLowerCase().startsWith(start)) continue;
// The closer to zero the better
int lendiff = candidate.length() - minlength;
if (lendiff == 0)
{
return candidate;
}
if (lendiff < best || best == 0)
{
best = lendiff;
ret = candidate;
}
}
return ret;
}
// -------------------------------------------- //
// Wrapping the Craftbukkit TextWrapper
// -------------------------------------------- //
public static ArrayList<String> wrapText(final String text)
{
return new ArrayList<String>(Arrays.asList(TextWrapper.wrapText(text)));
}
}