/* * 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); } }); } }