/*
* This file is part of the Haven & Hearth game client.
* Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and
* Björn Johannessen <johannessen.bjorn@gmail.com>
*
* Redistribution and/or modification of this file is subject to the
* terms of the GNU Lesser General Public License, version 3, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Other parts of this source tree adhere to other copying
* rights. Please see the file `COPYING' in the root directory of the
* source tree for details.
*
* A copy the GNU Lesser General Public License is distributed along
* with the source tree of which this file is a part in the file
* `doc/LPGL-3'. If it is missing for any reason, please see the Free
* Software Foundation's website at <http://www.fsf.org/>, or write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
package haven;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;
import java.util.prefs.Preferences;
public class Utils {
private static Preferences prefs = null;
public static java.awt.image.ColorModel rgbm = java.awt.image.ColorModel.getRGBdefault();
private static Background bgworker = null;
public static Coord imgsz(BufferedImage img) {
return (new Coord(img.getWidth(), img.getHeight()));
}
public static class Background extends HackThread {
Queue<Runnable> q = new LinkedList<Runnable>();
public Background() {
super("Haven deferred procedure thread");
setDaemon(true);
start();
}
public void run() {
try {
while (true) {
Runnable cur;
synchronized (q) {
while ((cur = q.poll()) == null)
q.wait();
}
cur.run();
cur = null;
}
} catch (InterruptedException e) {
}
}
public void defer(Runnable r) {
synchronized (q) {
q.add(r);
q.notify();
}
}
}
public static String sessdate(long sess) {
return (new SimpleDateFormat("yyyy-MM-dd HH.mm.ss")).format(new Date(sess));
}
public static String timestamp() {
return (new SimpleDateFormat("[HH:mm] ")).format(new Date());
}
public static String getClipboard() {
Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
try {
if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String text = (String) t.getTransferData(DataFlavor.stringFlavor);
return text;
}
} catch (UnsupportedFlavorException e) {
} catch (IOException e) {
}
return "";
}
public static void defer(Runnable r) {
synchronized (Utils.class) {
if (bgworker == null)
bgworker = new Background();
}
bgworker.defer(r);
}
static void drawgay(BufferedImage t, BufferedImage img, Coord c) {
Coord sz = imgsz(img);
for (int y = 0; y < sz.y; y++) {
for (int x = 0; x < sz.x; x++) {
int p = img.getRGB(x, y);
if (Utils.rgbm.getAlpha(p) > 128) {
if ((p & 0x00ffffff) == 0x00ff0080)
t.setRGB(x + c.x, y + c.y, 0);
else
t.setRGB(x + c.x, y + c.y, p);
}
}
}
}
public static int drawtext(Graphics g, String text, Coord c) {
java.awt.FontMetrics m = g.getFontMetrics();
g.drawString(text, c.x, c.y + m.getAscent());
return (m.getHeight());
}
static Coord textsz(Graphics g, String text) {
java.awt.FontMetrics m = g.getFontMetrics();
java.awt.geom.Rectangle2D ts = m.getStringBounds(text, g);
return (new Coord((int) ts.getWidth(), (int) ts.getHeight()));
}
static void aligntext(Graphics g, String text, Coord c, double ax, double ay) {
java.awt.FontMetrics m = g.getFontMetrics();
java.awt.geom.Rectangle2D ts = m.getStringBounds(text, g);
g.drawString(text, (int) (c.x - ts.getWidth() * ax), (int) (c.y + m.getAscent() - ts.getHeight() * ay));
}
static void line(Graphics g, Coord c1, Coord c2) {
g.drawLine(c1.x, c1.y, c2.x, c2.y);
}
static void AA(Graphics g) {
java.awt.Graphics2D g2 = (java.awt.Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
static synchronized String getpref(String prefname, String def) {
try {
if (prefs == null)
prefs = Preferences.userNodeForPackage(Utils.class);
return (prefs.get(prefname, def));
} catch (SecurityException e) {
return (def);
}
}
static synchronized void setpref(String prefname, String val) {
try {
if (prefs == null)
prefs = Preferences.userNodeForPackage(Utils.class);
prefs.put(prefname, val);
} catch (SecurityException e) {
}
}
static synchronized byte[] getprefb(String prefname, byte[] def) {
try {
if (prefs == null)
prefs = Preferences.userNodeForPackage(Utils.class);
return (prefs.getByteArray(prefname, def));
} catch (SecurityException e) {
return (def);
}
}
static synchronized void setprefb(String prefname, byte[] val) {
try {
if (prefs == null)
prefs = Preferences.userNodeForPackage(Utils.class);
prefs.putByteArray(prefname, val);
} catch (SecurityException e) {
}
}
public static String getprop(String propname, String def) {
try {
return (System.getProperty(propname, def));
} catch (SecurityException e) {
return (def);
}
}
static int ub(byte b) {
if (b < 0)
return (256 + b);
else
return (b);
}
static byte sb(int b) {
if (b > 127)
return ((byte) (-256 + b));
else
return ((byte) b);
}
static int uint16d(byte[] buf, int off) {
return (ub(buf[off]) + (ub(buf[off + 1]) * 256));
}
static int int16d(byte[] buf, int off) {
int u = uint16d(buf, off);
if (u > 32767)
return (-65536 + u);
else
return (u);
}
static long uint32d(byte[] buf, int off) {
return (ub(buf[off]) + (ub(buf[off + 1]) * 256) + (ub(buf[off + 2]) * 65536) + (ub(buf[off + 3]) * 16777216));
}
static void uint32e(long num, byte[] buf, int off) {
buf[off] = sb((int) (num & 0xff));
buf[off + 1] = sb((int) ((num & 0xff00) >> 8));
buf[off + 2] = sb((int) ((num & 0xff0000) >> 16));
buf[off + 3] = sb((int) ((num & 0xff000000) >> 24));
}
static int int32d(byte[] buf, int off) {
long u = uint32d(buf, off);
if (u > Integer.MAX_VALUE)
return ((int) ((((long) Integer.MIN_VALUE) * 2) - u));
else
return ((int) u);
}
static void int32e(int num, byte[] buf, int off) {
if (num < 0)
uint32e(0x100000000L + ((long) num), buf, off);
else
uint32e(num, buf, off);
}
static void uint16e(int num, byte[] buf, int off) {
buf[off] = sb(num & 0xff);
buf[off + 1] = sb((num & 0xff00) >> 8);
}
static String strd(byte[] buf, int[] off) {
int i;
for (i = off[0]; buf[i] != 0; i++)
;
String ret;
try {
ret = new String(buf, off[0], i - off[0], "utf-8");
} catch (UnsupportedEncodingException e) {
throw (new IllegalArgumentException(e));
}
off[0] = i + 1;
return (ret);
}
static char num2hex(int num) {
if (num < 10)
return ((char) ('0' + num));
else
return ((char) ('A' + num - 10));
}
static int hex2num(char hex) {
if ((hex >= '0') && (hex <= '9'))
return (hex - '0');
else if ((hex >= 'a') && (hex <= 'f'))
return (hex - 'a' + 10);
else if ((hex >= 'A') && (hex <= 'F'))
return (hex - 'A' + 10);
else
throw (new IllegalArgumentException());
}
static String byte2hex(byte[] in) {
StringBuilder buf = new StringBuilder();
for (byte b : in) {
buf.append(num2hex((b & 0xf0) >> 4));
buf.append(num2hex(b & 0x0f));
}
return (buf.toString());
}
static byte[] hex2byte(String hex) {
if (hex.length() % 2 != 0)
throw (new IllegalArgumentException("Invalid hex-encoded string"));
byte[] ret = new byte[hex.length() / 2];
for (int i = 0, o = 0; i < hex.length(); i += 2, o++)
ret[o] = (byte) ((hex2num(hex.charAt(i)) << 4) | hex2num(hex.charAt(i + 1)));
return (ret);
}
public static String[] splitwords(String text) {
ArrayList<String> words = new ArrayList<String>();
StringBuilder buf = new StringBuilder();
String st = "ws";
int i = 0;
while (i < text.length()) {
char c = text.charAt(i);
if (st == "ws") {
if (!Character.isWhitespace(c))
st = "word";
else
i++;
} else if (st == "word") {
if (c == '"') {
st = "quote";
i++;
} else if (c == '\\') {
st = "squote";
i++;
} else if (Character.isWhitespace(c)) {
words.add(buf.toString());
buf = new StringBuilder();
st = "ws";
} else {
buf.append(c);
i++;
}
} else if (st == "quote") {
if (c == '"') {
st = "word";
i++;
} else if (c == '\\') {
st = "sqquote";
i++;
} else {
buf.append(c);
i++;
}
} else if (st == "squote") {
buf.append(c);
i++;
st = "word";
} else if (st == "sqquote") {
buf.append(c);
i++;
st = "quote";
}
}
if (st == "word")
words.add(buf.toString());
if ((st != "ws") && (st != "word"))
return (null);
return (words.toArray(new String[0]));
}
public static String[] splitlines(String text) {
ArrayList<String> ret = new ArrayList<String>();
int p = 0;
while (true) {
int p2 = text.indexOf('\n', p);
if (p2 < 0) {
ret.add(text.substring(p));
break;
}
ret.add(text.substring(p, p2));
p = p2 + 1;
}
return (ret.toArray(new String[0]));
}
static int atoi(String a) {
try {
return (Integer.parseInt(a));
} catch (NumberFormatException e) {
return (0);
}
}
static void readtileof(InputStream in) throws IOException {
byte[] buf = new byte[4096];
while (true) {
if (in.read(buf, 0, buf.length) < 0)
return;
}
}
static byte[] readall(InputStream in) throws IOException {
byte[] buf = new byte[4096];
int off = 0;
while (true) {
if (off == buf.length) {
byte[] n = new byte[buf.length * 2];
System.arraycopy(buf, 0, n, 0, buf.length);
buf = n;
}
int ret = in.read(buf, off, buf.length - off);
if (ret < 0) {
byte[] n = new byte[off];
System.arraycopy(buf, 0, n, 0, off);
return (n);
}
off += ret;
}
}
private static void dumptg(ThreadGroup tg, PrintWriter out, int indent) {
for (int o = 0; o < indent; o++)
out.print("\t");
out.println("G: \"" + tg.getName() + "\"");
Thread[] ths = new Thread[tg.activeCount() * 2];
ThreadGroup[] tgs = new ThreadGroup[tg.activeGroupCount() * 2];
int nt = tg.enumerate(ths, false);
int ng = tg.enumerate(tgs, false);
for (int i = 0; i < nt; i++) {
Thread ct = ths[i];
for (int o = 0; o < indent + 1; o++)
out.print("\t");
out.println("T: \"" + ct.getName() + "\"");
}
for (int i = 0; i < ng; i++) {
ThreadGroup cg = tgs[i];
dumptg(cg, out, indent + 1);
}
}
public static void dumptg(ThreadGroup tg, PrintWriter out) {
if (tg == null) {
tg = Thread.currentThread().getThreadGroup();
while (tg.getParent() != null)
tg = tg.getParent();
}
dumptg(tg, out, 0);
out.flush();
}
public static Resource myres(Class<?> c) {
ClassLoader cl = c.getClassLoader();
if (cl instanceof Resource.ResClassLoader) {
return (((Resource.ResClassLoader) cl).getres());
} else {
return (null);
}
}
public static String titlecase(String str) {
return (Character.toTitleCase(str.charAt(0)) + str.substring(1));
}
public static Color contrast(Color col) {
int max = Math.max(col.getRed(), Math.max(col.getGreen(), col.getBlue()));
if (max > 128) {
return (new Color(col.getRed() / 4, col.getGreen() / 4, col.getBlue() / 4, col.getAlpha()));
} else if (max == 0) {
return (Color.WHITE);
} else {
int f = 128 / max;
return (new Color(col.getRed() * f, col.getGreen() * f, col.getBlue() * f, col.getAlpha()));
}
}
public static Color clipcol(int r, int g, int b, int a) {
if (r < 0)
r = 0;
if (r > 255)
r = 255;
if (g < 0)
g = 0;
if (g > 255)
g = 255;
if (b < 0)
b = 0;
if (b > 255)
b = 255;
if (a < 0)
a = 0;
if (a > 255)
a = 255;
return (new Color(r, g, b, a));
}
public static BufferedImage outline(BufferedImage img, Color col) {
return outline(img, col, false);
}
public static BufferedImage outline(BufferedImage img, Color col, boolean thick) {
Coord sz = imgsz(img).add(2, 2);
BufferedImage ol = TexI.mkbuf(sz);
for (int y = 0; y < sz.y; y++) {
for (int x = 0; x < sz.x; x++) {
boolean t;
if ((y == 0) || (x == 0) || (y == sz.y - 1) || (x == sz.x - 1)) {
t = true;
} else {
int cl = img.getRGB(x - 1, y - 1);
t = Utils.rgbm.getAlpha(cl) < 250;
}
if (!t)
continue;
if (((x > 1) && (y > 0) && (y < sz.y - 1) && (Utils.rgbm.getAlpha(img.getRGB(x - 2, y - 1)) >= 250))
|| ((x > 0) && (y > 1) && (x < sz.x - 1) && (Utils.rgbm.getAlpha(img.getRGB(x - 1, y - 2)) >= 250))
|| ((x < sz.x - 2) && (y > 0) && (y < sz.y - 1) && (Utils.rgbm.getAlpha(img.getRGB(x, y - 1)) >= 250))
|| ((x > 0) && (y < sz.y - 2) && (x < sz.x - 1) && (Utils.rgbm.getAlpha(img.getRGB(x - 1, y)) >= 250)))
ol.setRGB(x, y, col.getRGB());
if (thick) {
if (((x > 1) && (y > 1) && (Utils.rgbm.getAlpha(img.getRGB(x - 2, y - 2)) >= 250))
|| ((x < sz.x - 2) && (y < sz.y - 2) && (Utils.rgbm.getAlpha(img.getRGB(x, y)) >= 250))
|| ((x < sz.x - 2) && (y > 1) && (Utils.rgbm.getAlpha(img.getRGB(x, y - 2)) >= 250))
|| ((x > 1) && (y < sz.y - 2) && (Utils.rgbm.getAlpha(img.getRGB(x - 2, y)) >= 250)))
ol.setRGB(x, y, col.getRGB());
}
}
}
return (ol);
}
public static BufferedImage outline2(BufferedImage img, Color col) {
return outline2(img, col, false);
}
public static BufferedImage outline2(BufferedImage img, Color col, boolean thick) {
BufferedImage ol = outline(img, col, thick);
Graphics g = ol.getGraphics();
g.drawImage(img, 1, 1, null);
g.dispose();
return (ol);
}
public static int floordiv(int a, int b) {
if (a < 0)
return (((a + 1) / b) - 1);
else
return (a / b);
}
public static int floormod(int a, int b) {
int r = a % b;
if (r < 0)
r += b;
return (r);
}
public static int floordiv(float a, float b) {
return ((int) Math.floor(a / b));
}
public static float floormod(float a, float b) {
float r = a % b;
if (r < 0)
r += b;
return (r);
}
public static double clip(double d, double min, double max) {
if (d < min)
return (min);
if (d > max)
return (max);
return (d);
}
public static int clip(int i, int min, int max) {
if (i < min)
return (min);
if (i > max)
return (max);
return (i);
}
public static Color blendcol(Color in, Color bl) {
int f1 = bl.getAlpha();
int f2 = 255 - bl.getAlpha();
return (new Color(((in.getRed() * f2) + (bl.getRed() * f1)) / 255, ((in.getGreen() * f2) + (bl.getGreen() * f1)) / 255,
((in.getBlue() * f2) + (bl.getBlue() * f1)) / 255, in.getAlpha()));
}
public static void serialize(Object obj, OutputStream out) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(obj);
oout.flush();
}
public static byte[] serialize(Object obj) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
serialize(obj, out);
} catch (IOException e) {
throw (new RuntimeException(e));
}
return (out.toByteArray());
}
public static Object deserialize(InputStream in) throws IOException {
ObjectInputStream oin = new ObjectInputStream(in);
try {
return (oin.readObject());
} catch (ClassNotFoundException e) {
return (null);
}
}
public static Object deserialize(byte[] buf) {
if (buf == null)
return (null);
InputStream in = new ByteArrayInputStream(buf);
try {
return (deserialize(in));
} catch (IOException e) {
return (null);
}
}
public static boolean parsebool(String s, boolean def) {
if (s == null)
return (def);
else if (s.equalsIgnoreCase("1") || s.equalsIgnoreCase("on") || s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes"))
return (true);
else if (s.equalsIgnoreCase("0") || s.equalsIgnoreCase("off") || s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no"))
return (false);
return (def);
}
static {
Console.setscmd("die", new Console.Command() {
public void run(Console cons, String[] args) {
throw (new Error("Triggered death"));
}
});
Console.setscmd("threads", new Console.Command() {
public void run(Console cons, String[] args) {
Utils.dumptg(null, cons.out);
}
});
}
}