package NET.worlds.scape; import NET.worlds.console.AvMenu; import NET.worlds.console.Console; import NET.worlds.console.DefaultConsole; import NET.worlds.core.IniFile; import NET.worlds.core.ServerTableManager; import NET.worlds.core.Std; import NET.worlds.core.Timer; import NET.worlds.core.TimerCallback; import NET.worlds.network.Cache; import NET.worlds.network.CacheFile; import NET.worlds.network.NetUpdate; import NET.worlds.network.URL; import NET.worlds.network.WorldServer; import java.awt.Color; import java.io.IOException; import java.io.RandomAccessFile; import java.net.MalformedURLException; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import java.util.Vector; public class PosableShape extends Shape implements FrameHandler, Prerenderable, MouseDownHandler, ShapeLoaderListener, TimerCallback { protected int figureType = -1; private float closestView = 10000.0F; private int farViewCount; private Vector animationList; private boolean COG; private boolean setPrepFigure = true; private boolean runPrepFigure = this.setPrepFigure; private static URL defaultURL = URL.make("avatar:aura.0PG.rwg"); protected DroneAnimator animator = null; private boolean recomputeHeight = false; private boolean firstURL = true; private Shape subparts; public static Color[] colorTable = new Color[]{ new Color(0, 0, 0), new Color(51, 102, 204), new Color(234, 162, 115), new Color(255, 102, 51), new Color(255, 153, 204), new Color(139, 232, 0), new Color(43, 131, 0), new Color(51, 51, 153), new Color(145, 51, 204), new Color(153, 204, 255), new Color(204, 51, 102), new Color(0, 204, 102), new Color(255, 204, 102), new Color(102, 102, 102), new Color(254, 123, 26), new Color(255, 51, 153), new Color(188, 51, 204), new Color(204, 0, 38), new Color(118, 0, 0), new Color(153, 102, 51), new Color(196, 196, 196), new Color(204, 153, 255), new Color(255, 255, 255), new Color(255, 179, 2), new Color(247, 227, 2), new Color(255, 255, 153) }; private Hashtable> actions; private int scanPos; private static Material origMat = new Material((Texture)null); public static String base64 = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+"; private static String[] permittedList = ServerTableManager.instance().getTable("permittedList"); private static String[] faceList = ServerTableManager.instance().getTable("faceList"); private static String[] humanList = ServerTableManager.instance().getTable("humanList"); private static String[] secretList = ServerTableManager.instance().getTable("secretList"); private static Hashtable permittedHash = new Hashtable(); private static Vector permittedNames = new Vector(); private static Vector faceNames = new Vector(); private static Hashtable humanHash = new Hashtable(); private static Hashtable> worldHash = new Hashtable>(); private static Hashtable secretNames = new Hashtable(); private static Hashtable faceTextures = new Hashtable(); static boolean gotServerAvatarList; static boolean serverAvatarListError; private Enumeration animations; private boolean doLOD = false; protected int expressionStart; protected int nextChange; protected Vector expressionChanges; private static Object classCookie; static { if (!NetUpdate.isInternalVersion()) { for (int i = 0; i < secretList.length; i++) { secretNames.put(secretList[i], secretList[i]); } } for (int i = 0; i < permittedList.length; i += 2) { if (secretNames.get(permittedList[i]) == null) { permittedNames.addElement(permittedList[i]); if (permittedList[i + 1].indexOf("DgT") >= 0) { faceNames.addElement(permittedList[i]); } } if (permittedList[i + 1] != null) { permittedHash.put(permittedList[i], permittedList[i + 1]); } } for (int i = 1; i < humanList.length; i += 2) { humanHash.put(humanList[i - 1], humanList[i]); } for (int i = 0; i < faceList.length; i += 2) { faceTextures.put(faceList[i], faceList[i + 1]); } gotServerAvatarList = false; serverAvatarListError = false; classCookie = new Object(); } public static URL getDefaultURL() { return defaultURL; } public PosableShape(URL url) { this.setURL(url); } public PosableShape(URL url, boolean isAW) { this.setPrepFigure = isAW; this.runPrepFigure = this.setPrepFigure; this.setURL(url); } public PosableShape() { } @Override public void loadInit() { this.setURL(defaultURL); } @Override public void markVoid() throws ClassCastException { if (this.animator != null) { this.animator.endanimations(); if (this.figureType != -1) { this.animator.delayedDeltype(this.figureType); } } this.animator = null; this.getRoom().removePrerenderHandler(this); super.markVoid(); } @Override public synchronized void recursiveAddRwChildren(WObject parent) { if (!this.hasClump()) { super.recursiveAddRwChildren(parent); this.getRoom().addPrerenderHandler(this); if (this.isFullyLoaded() && this.figureType != -1) { DroneAnimator.addtype(this.figureType); if (this.runPrepFigure) { DroneAnimator.prepFigure(this, this.COG); } this.animator = new DroneAnimator(); } } } @Override public void notifyShapeLoaded(Shape s) { this.recomputeHeight = true; } @Override public Transform getObjectToWorldMatrix() { return this.clumpID != 0 ? this.getJointedObjectToWorldMatrix(Transform.make()) : super.getObjectToWorldMatrix(); } public static int getFigureType(URL url) { String bodyType = getBodyType(url); return bodyType == null ? -1 : DroneAnimator.getnameindex(bodyType); } public static int getFigureType(String bodyType) { bodyType = getBodyType(bodyType); return bodyType == null ? -1 : DroneAnimator.getnameindex(bodyType); } protected void download(URL pUrl) { PendingDrone pd = PosableDroneLoader.makePendingDrone(null, pUrl); Enumeration e = getComponentAvatars(pd.getUrl()); if (e != null) { while (e.hasMoreElements()) { String avURL = e.nextElement(); pd.download(URL.make(avURL)); } } } @Override public synchronized void setURL(URL newName) { if (newName != this.url && (newName == null || !newName.equals(this.url))) { if (newName == null || !newName.toString().startsWith("avatar:lod")) { if (newName != null) { this.download(newName); int newType = getFigureType(newName); if (newType != this.figureType) { if (this.animator != null) { this.animator.endanimations(); if (this.figureType != -1) { this.animator.delayedDeltype(this.figureType); } } this.animator = null; this.figureType = newType; this.animationList = null; } } this.setBaseLODURL(newName); if (forceLODLevel != -1 && this.numDetailLevels > 0 && this.doLOD) { this.setLOD(0.0F); return; } } this.removeSubparts(); if (newName != null && newName.getAbsolute().startsWith("avatar:")) { try { this.createSubparts(newName); } catch (MalformedURLException var3) { System.out.println("Received bogus PosableShape URL: " + newName); return; } } super.setURL(newName); } } private String scanName(String s) { int start = this.scanPos; char c; while ((c = s.charAt(this.scanPos)) >= 'a' && c <= 'z' || c == '_') { this.scanPos++; } return s.substring(start, this.scanPos); } public static String readName(String s, int pos) { int start = pos; char c; try { while ((c = s.charAt(pos)) >= 'a' && c <= 'z' || c == '_') { pos++; } } catch (StringIndexOutOfBoundsException var4) { } return s.substring(start, pos); } private int scanInt(String s) { int start = this.scanPos; int val; char c; for (val = 0; (c = s.charAt(this.scanPos)) >= '0' && c <= '9'; this.scanPos++) { val = 10 * val + (c - '0'); } return val; } private static Material scanTexture(String name, int frame) { if (frame <= 0) { name = "avatar:" + name + ".cmp"; } else { name = "avatar:" + name + frame + "s*.mov"; } Material m = new Material(0.32F, 0.55F, 0.0F, colorTable[3], null, 1.0F, true, false); m.loadTexture(URL.make(name)); return m; } public static Material readTexture(String s, int p) { int frame = 0; char c; while ((c = s.charAt(p)) >= '0' && c <= '9') { frame = 10 * frame + (c - '0'); p++; } return scanTexture(readName(s, p), frame); } public static boolean isValidTexture(String s) { int len = s.length(); int i = 0; char c; while (i < len && (c = s.charAt(i)) >= '0' && c <= '9') { i++; } while (i < len) { if (((c = s.charAt(i)) < 'a' || c > 'z') && c != '_') { return false; } i++; } return true; } private static int scanBase64(char c) { int i = base64.indexOf(c); return i < 0 ? 0 : i; } public static Material readColor(String s, int p) { char c = s.charAt(p++); Material m = null; if (c == '_') { int color = s.charAt(p++) - 'A'; if (color >= 0 && color < colorTable.length) { m = new Material(0.32F, 0.55F, 0.0F, colorTable[color], null, 1.0F, true, false); } else { m = origMat; } } else { int r = 4 * scanBase64(c); int g = 4 * scanBase64(s.charAt(p++)); int b = 4 * scanBase64(s.charAt(p++)); m = new Material(0.32F, 0.55F, 0.0F, new Color(r, g, b), null, 1.0F, true, false); } return m; } private Material scanColor(String s) { Material m = readColor(s, this.scanPos); if (s.charAt(this.scanPos) == '_') { this.scanPos += 2; } else { this.scanPos += 3; } return m; } private float getScale(char c) { if (c >= 'a' && c <= 'z') { return 1.0F - (c - 'a' + 1) * 0.025615385F; } else { return c >= 'A' && c <= 'Z' ? 1.0F / (1.0F - (c - 'A' + 1) * 0.025615385F) : 1.0F; } } private Material getMat(char c, Vector mats) { int matNum = c - 'a'; if (matNum < mats.size()) { Material m = mats.elementAt(matNum); return m == origMat ? origMat : (Material)m.clone(); } else { return null; } } private Shape getLimb(String s, String bodyType, int pos, int partNum, Shape parent, Vector mats, boolean loadNow) { int end = s.length() - 4; if (bodyType == null) { if (parent instanceof PosableShape) { bodyType = ""; } else { bodyType = Shape.getBodBase(parent.getURL()); if (parent.getURL().toString().indexOf("lod/") != -1) { bodyType = "lod/" + bodyType; } } } Shape shape = new Shape(); Shape subshape = shape; shape.setURL(URL.make("avatar:" + bodyType + partNum / 10 + partNum % 10 + ".bod")); int clumpsUsed = 0; Material lastMat = null; int delay = 0; int lastTime = 0; String actName = null; boolean haveAddedChange = false; if (pos > 0) { this.scanPos = pos + 1; while (true) { char c = s.charAt(this.scanPos++); if (c >= 'A' && c <= 'Z') { if (c == 'G') { int num = this.scanInt(s); if (num <= 0 || num > 99) { num = partNum; } bodyType = this.scanName(s); if (bodyType.equals("")) { break; } subshape.setURL(URL.make("avatar:" + bodyType + num / 10 + num % 10 + ".bod")); } else if (c == 'S') { char xScale = s.charAt(this.scanPos++); char yScale = s.charAt(this.scanPos++); char zScale = s.charAt(this.scanPos++); if (xScale == 'Z' && yScale == 'Z' && zScale == 'Z') { this.runPrepFigure = false; } subshape.scale(this.getScale(xScale), this.getScale(yScale), this.getScale(zScale)); } else if (c != 'Q') { if (c == 'C') { assert false; } else if (c == 'D') { delay += (int)(1000.0 * (Math.pow(1.0932, scanBase64(s.charAt(this.scanPos++))) - 0.9F)); } else if (c == 'A') { actName = this.scanName(s); this.animationList = null; } else { if (c != 'T' && c != 'C') { this.scanPos--; break; } System.out.println("Illegal av " + this.url); } } } else if (c >= 'a') { Material m = this.getMat(c, mats); if (m != null) { if (delay == 0) { delay = 50; } lastTime += delay; if (lastMat != null) { if (!haveAddedChange) { haveAddedChange = true; this.addChange(lastTime - delay, lastMat, subshape); } this.addChange(lastTime, m, subshape); } if (m != origMat) { subshape.setMaterial(m); } lastMat = m; delay = 0; } } else { if (c < '0' || c > '9') { break; } this.scanPos--; int clumpNum = this.scanInt(s) - clumpsUsed; clumpsUsed++; subshape = new SubclumpShape(); subshape.setURL(URL.make("system:subclump" + clumpNum)); shape.add(subshape); lastMat = null; haveAddedChange = false; lastTime = 0; delay = 0; } if (this.scanPos > end) { this.scanPos = end; return parent; } } } if (bodyType.equals("")) { return parent; } else { shape.addLoadListener(this); if (ProgressiveAdder.get().enabled() && !loadNow) { ProgressiveAdder.get().scheduleForAdd(parent, shape); } else { parent.add(shape); } if (this.subparts == null) { this.subparts = shape; } return shape; } } private void addChange(int when, Material mat, Shape s) { PosableShape.TimedMatChange t = new PosableShape.TimedMatChange(); t.when = when; t.mat = mat; t.limb = s; mat.setKeepLoaded(true); int i = 0; if (this.expressionChanges == null) { this.expressionChanges = new Vector(); this.expressionStart = Std.getRealTime(); this.nextChange = 0; } else { for (i = this.expressionChanges.size(); i > 0; i--) { PosableShape.TimedMatChange o = this.expressionChanges.elementAt(i - 1); if (when >= o.when) { break; } } } this.expressionChanges.insertElementAt(t, i); } public static Enumeration getComponentAvatars(URL pUrl) { if (pUrl == null) { return null; } else { Vector v = new Vector(); String urlString = pUrl.getAbsolute(); if (urlString.startsWith("avatar:") && urlString.endsWith(".rwg")) { String baseAv = urlString.substring(7, urlString.indexOf(46)); v.addElement("avatar:" + baseAv + ".rwg"); int pos = urlString.indexOf(46); int len = urlString.length() - 4; label82: while (pos < len) { char c = urlString.charAt(pos++); if (c >= 'A' && c <= 'Z') { switch (c) { case 'A': case 'Q': case 'T': default: break; case 'C': c = urlString.charAt(pos++); if (c == '_') { pos++; } else { pos += 2; } break; case 'D': pos++; break; case 'G': while (pos < len) { c = urlString.charAt(pos); if (c < '0' || c > '9') { break; } pos++; } String bodyType = ""; while (true) { if (pos < len) { c = urlString.charAt(pos); if ((c < '0' || c > '9') && c >= 'a' && c <= 'z') { bodyType = bodyType + c; pos++; continue; } } if (bodyType != "" && bodyType.length() > 1) { v.addElement("avatar:" + bodyType + ".rwg"); } continue label82; } case 'S': pos += 3; } } } return v.elements(); } else { return null; } } } public static int skipLimb(String s, int pos) { int len = s.length() - 4; while (pos < len) { char c = s.charAt(pos++); if (c >= 'A' && c <= 'Z') { switch (c) { case 'A': case 'G': case 'Q': case 'T': break; case 'C': c = s.charAt(pos++); if (c == '_') { pos++; } else { pos += 2; } break; case 'D': pos++; break; case 'S': pos += 3; break; default: return pos - 1; } } else if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) { break; } } return -1; } private String findStarts(String s, int end, int[] offs, String bodyType, Vector mats) { String lastTextureName = bodyType; while (this.scanPos < end) { char section = s.charAt(this.scanPos); if (section < 'A' || section > 'Z') { return s; } offs[section - 'A'] = this.scanPos++; while (this.scanPos < end) { char c = s.charAt(this.scanPos++); if (c < 'A' || c > 'Z') { if ((c < '0' || c > '9') && (c < 'a' || c > 'z')) { return s.substring(0, this.scanPos - 1) + ".rwg"; } } else if (c == 'G') { this.scanInt(s); this.scanName(s); } else if (c == 'S') { this.scanPos += 3; } else if (c != 'Q') { if (c == 'C' || c == 'T') { int start = this.scanPos - 1; char letter = (char)(97 + mats.size()); Material mat; if (c == 'C') { mat = this.scanColor(s); } else { int num = this.scanInt(s); String name = this.scanName(s); if (name.equals("")) { name = lastTextureName; } else { lastTextureName = name; } mat = scanTexture(name, num); } mats.addElement(mat); s = s.substring(0, start) + 'Q' + letter + s.substring(this.scanPos); int cutLen = this.scanPos - start - 2; this.scanPos -= cutLen; end -= cutLen; } else if (c == 'D') { this.scanPos++; } else { if (c != 'A') { this.scanPos--; break; } this.scanName(s); } } } } return s; } public static Vector getPermittedNames() { return permittedNames; } public static String[] getPermittedList() { return permittedList; } public static void downloadPermittedNames() { if (!gotServerAvatarList) { serverAvatarListError = false; WorldServer w = Pilot.getActive().getServer(); if (w != null && w.getGalaxy() != null) { String avatarList = Console.getActive().getScriptServer() + "getavlist.pl?u=" + w.getGalaxy().getChatname(); if (w.getGalaxy().getSerialNum() != null) { avatarList = avatarList + "&s=" + w.getGalaxy().getSerialNum(); } URL avatarListURL = URL.make(avatarList); CacheFile cf = Cache.getFile(avatarListURL, true); cf.waitUntilLoaded(); if (!cf.error()) { permittedNames.removeAllElements(); humanHash.clear(); worldHash.clear(); try { RandomAccessFile f = new RandomAccessFile(cf.getLocalName(), "r"); while (f.getFilePointer() < f.length()) { String line = f.readLine(); if (!line.startsWith("//")) { StringTokenizer st = new StringTokenizer(line); if (st.countTokens() > 2) { String name = st.nextToken(); permittedNames.addElement(name); String gender = st.nextToken(); if (gender.equals("m") || gender.equals("f")) { humanHash.put(name, gender); } Vector worldList = new Vector(); while (st.hasMoreTokens()) { worldList.addElement(st.nextToken()); } worldHash.put(name, worldList); } } } f.close(); } catch (Exception var10) { System.out.println("Error parsing avatar list: " + var10.toString()); serverAvatarListError = true; return; } gotServerAvatarList = true; Console c = Console.getActive(); if (c instanceof DefaultConsole) { DefaultConsole dc = (DefaultConsole)c; dc.getAvatarMenu().rebuildVIPMenu(); } if (c.getPilot() != null) { c.getPilot().resetAvatarNow(); } AvMenu.rebuildHeadList(); } else { serverAvatarListError = true; } } } } public static URL getPermitted(URL in, World world) { if (in.endsWith(".mov")) { return in; } else if (NetUpdate.isInternalVersion()) { return in; } else if (!gotServerAvatarList && !serverAvatarListError) { return in; } else if (serverAvatarListError) { return validateAvatar(in.getAbsolute()) ? in : getDefAv(); } else { Enumeration e = getComponentAvatars(in); while (e != null && e.hasMoreElements()) { String baseAv = e.nextElement(); String s = getBodyType(URL.make(baseAv)); if (s == null) { return getDefAv(); } Vector allowedWorlds = worldHash.get(s); if (allowedWorlds == null) { return getDefAv(); } boolean worldOK = false; Enumeration we = allowedWorlds.elements(); while (true) { if (we.hasMoreElements()) { String thisWorld = we.nextElement(); if (thisWorld == null) { return getDefAv(); } if (thisWorld.equals("all")) { worldOK = true; } else { thisWorld = thisWorld.replace('_', ' ').toLowerCase().trim(); if (world == null) { worldOK = true; continue; } if (!thisWorld.equals(world.toString().toLowerCase().trim())) { continue; } worldOK = true; } } if (!worldOK) { return getDefAv(); } break; } } return in; } } public static Vector getFaceNames() { return faceNames; } public static URL getAvURL(String bodyType) { Object newName = permittedHash.get(bodyType); return newName instanceof String ? URL.make("avatar:" + (String)newName) : null; } public static boolean validateAvatar(String av) { System.out.println("Validating " + av); String baseAv = getBodyType(URL.make(av)); return baseAv == null ? false : permittedHash.get(baseAv) != null; } public static String convertLODToParent(String bodyType) { String result = bodyType; if (bodyType.startsWith("lod/")) { result = bodyType.substring(4, bodyType.length() - 1); } return result; } public static String getBodyType(URL url) { if (url == null) { return null; } else { String str = url.getAbsolute(); if (str.startsWith("avatar:") && (str.endsWith(".rwg") || str.endsWith(".RWG")) && str.charAt(7) != '.') { int pos = str.indexOf(".", 7); String bodyType = str.substring(7, pos).toLowerCase(); bodyType = convertLODToParent(bodyType); if (str.charAt(pos + 1) != '0') { bodyType = getBodyType(bodyType); } return bodyType; } else { return null; } } } static URL getDefAv() { return URL.make(IniFile.override().getIniString("DefaultArticAv", "avatar:willy.rwg")); } public static URL getHuman(URL url) { if (url.endsWith(".mov")) { return HoloDrone.getHuman(url); } else { String s = getBodyType(url); if (s == null) { return getDefAv(); } else { String gender = humanHash.get(s); if (gender == null) { return getDefAv(); } else { URL def = URL.make("avatar:" + s + ".rwg"); String str = url.getAbsolute(); int pos = str.indexOf(".0EC_"); if (pos >= 0 && str.length() >= pos + 7 && "_AC".indexOf(str.charAt(pos + 5)) >= 0) { if (!gender.equals("m") || str.indexOf("yank") < 0 || str.regionMatches(pos + 6, "TyankshirtC_", 0, 12) && str.regionMatches(pos + 19, "C-2bTyankstripe", 0, 15)) { pos = str.lastIndexOf("HDgT2"); if (pos >= 0 && str.length() >= pos + 7) { String faceGender = humanHash.get(readName(str, pos + 5)); if (faceGender != null && faceGender.equals(gender)) { pos = str.lastIndexOf("NS"); if (pos >= 0 && str.length() >= pos + 3 && "0abcdABCD".indexOf(str.charAt(pos + 2)) >= 0) { pos += 5; if (str.length() < pos + 2) { return def; } else { if (str.charAt(pos) == 'G') { String headGender = humanHash.get(readName(str, pos + 1)); if (headGender == null || !headGender.equals(gender)) { return def; } } return url; } } else { return def; } } else { return def; } } else { return def; } } else { return def; } } else { return def; } } } } } public URL getHuman() { return getHuman(this.getURL()); } public static String getBodyType(String basename) { String str = permittedHash.get(basename); if (str != null) { basename = str.substring(0, str.indexOf(".")); } return basename; } public static int getMatPosition(String str, char type) { int index = "abcdef".indexOf(type); if (index >= 0) { int p = str.indexOf(".0E"); if (p >= 0) { p += 3; for (int i = 0; i < index; i++) { p = skipMat(str, p); } } return p; } else { int p = str.indexOf(".0E"); if (p >= 0) { for (p += 2; p >= 0; p = skipLimb(str, p)) { if (str.charAt(p++) == type) { return p; } } } return p; } } public static String getCurrentAvCustomizable() { URL av = Pilot.getActive().getSourceURL(); String str = av.getAbsolute(); if (str.startsWith("avatar:") && (str.endsWith(".rwg") || str.endsWith(".RWG")) && str.charAt(7) != '.') { int pos = str.indexOf(".", 7); if (!str.regionMatches(pos, ".0E", 0, 3)) { av = getAvURL(str.substring(7, pos).toLowerCase()); if (av == null) { if (!str.substring(pos).equalsIgnoreCase(".rwg")) { Console.println(Console.message("cant-cust-av")); return null; } str = "avatar:" + str.substring(7, pos) + ".0EC__C__C__C__C__C__" + "PeBbLcMcOaRcUcVaWeXeYIeJeK" + "NS000QaHDgT2tonyT3T2T1Q0f.rwg"; } else { str = av.getAbsolute(); } } return str; } else { Console.println(Console.message("non-cust-av")); return null; } } public static int skipMat(String s, int i) { char c = s.charAt(i); int matEnd = i; if (c == 'C') { c = s.charAt(i + 1); if (c == '_') { matEnd = i + 3; } else { matEnd = i + 4; } } else if (c == 'T') { matEnd = i + 1; while ((c = s.charAt(matEnd)) >= '0' && c <= '9') { matEnd++; } while ((c = s.charAt(matEnd)) >= 'a' && c <= 'z') { matEnd++; } } else if (c >= 'a' && c <= 'z') { matEnd = i + 1; } return matEnd; } public static String getFace(String bodyType) { Object face = faceTextures.get(bodyType); return face != null ? (String)face : "1" + bodyType; } private void createSubparts(URL url) throws MalformedURLException { String str = url.getAbsolute(); int len = str.length(); String bodyType = null; this.runPrepFigure = this.setPrepFigure; if (str.startsWith("avatar:") && (str.endsWith(".rwg") || str.endsWith(".RWG")) && str.charAt(7) != '.') { this.scanPos = str.indexOf(".", 7); bodyType = str.substring(7, this.scanPos).toLowerCase(); if (str.charAt(this.scanPos + 1) != '0') { this.scanPos = len - 4; Object newName = permittedHash.get(bodyType); if (newName != null) { str = (String)newName; this.scanPos = 0; bodyType = this.scanName(str); if (str.charAt(this.scanPos) != '.') { throw new MalformedURLException(); } if (str.charAt(this.scanPos + 1) != '0') { throw new MalformedURLException(); } this.scanPos += 2; } } else { this.scanPos += 2; } } else { this.scanPos = 0; str = ".rwg"; bodyType = "aura"; } Vector mats = new Vector(); int[] offsets = new int[26]; str = this.findStarts(str, str.length() - 4, offsets, bodyType, mats); if (this.subparts != null) { throw new MalformedURLException(); } else { Shape groi = this.getLimb(str, bodyType, offsets[15], 1, this, mats, true); Shape back = this.getLimb(str, null, offsets[1], 2, groi, mats, false); Shape neck = this.getLimb(str, null, offsets[13], 3, back, mats, false); Shape head = this.getLimb(str, null, offsets[7], 4, neck, mats, false); Shape lupa = this.getLimb(str, null, offsets[11], 11, back, mats, false); Shape lfor = this.getLimb(str, null, offsets[12], 12, lupa, mats, false); Shape lhan = this.getLimb(str, null, offsets[14], 13, lfor, mats, false); Shape rupa = this.getLimb(str, null, offsets[17], 6, back, mats, false); Shape rfor = this.getLimb(str, null, offsets[20], 7, rupa, mats, false); Shape rhan = this.getLimb(str, null, offsets[21], 8, rfor, mats, false); Shape lthi = this.getLimb(str, null, offsets[8], 19, groi, mats, false); Shape lcal = this.getLimb(str, null, offsets[9], 20, lthi, mats, false); Shape lfoo = this.getLimb(str, null, offsets[10], 21, lcal, mats, false); Shape rthi = this.getLimb(str, null, offsets[22], 15, groi, mats, false); Shape rcal = this.getLimb(str, null, offsets[23], 16, rthi, mats, false); Shape rfoo = this.getLimb(str, null, offsets[24], 17, rcal, mats, false); Shape tail = this.getLimb(str, null, offsets[25], 24, groi, mats, false); } } protected void removeSubparts() { if (this.subparts != null) { this.subparts.discard(); this.subparts = null; this.actions = null; } } @Override public void prerender(Camera cam) { if (this.getVisible()) { Point3Temp p = this.inCamSpace(cam); boolean v = p != null && p.z > 1.0F && p.x < p.z && -p.x < p.z; if (v) { if (this.closestView > p.z) { this.closestView = p.z; } if (p.z > 700.0F && ++this.farViewCount > 10) { if (this.closestView > 400.0F) { this.closestView = 400.0F; } this.farViewCount = 0; } } } } public float animate(String action) { if (this.animator == null) { return 0.0F; } else { if (action.length() == 1) { char lower = action.toLowerCase().charAt(0); char upper = action.toUpperCase().charAt(0); Vector al = this.getAnimationList(); int len = al.size(); for (int i = 0; i < len; i++) { String[] actionAliases = ServerTableManager.instance().getTable("actionAliases"); String displayName = al.elementAt(i); if (actionAliases != null) { for (int j = 0; j < actionAliases.length; j += 2) { if (displayName.toLowerCase().equals(actionAliases[j].toLowerCase())) { displayName = actionAliases[j + 1]; break; } } } char c = displayName.charAt(0); if (c == lower || c == upper) { action = al.elementAt(i); break; } } } return this.performAnimationSequence(action); } } @Override public void timerDone() { if (this.animations.hasMoreElements()) { String nextAnim = this.animations.nextElement(); float time = this.animator.getAnimationTime(this.figureType, nextAnim); this.animator.animate(this.figureType, nextAnim, Std.getRealTime()); Timer tm = new Timer(time, this); tm.start(); } } private float performAnimationSequence(String action) { float totalTime = 0.0F; Vector vanimations = new Vector(); StringTokenizer tok = new StringTokenizer(action, "&\t\n\r"); while (tok.hasMoreTokens()) { String subAction = tok.nextToken(); totalTime += this.animator.getAnimationTime(this.figureType, subAction); vanimations.addElement(subAction); } this.animations = vanimations.elements(); this.timerDone(); return totalTime; } public Vector getAnimationList() { if (this.animationList != null) { return this.animationList; } else { this.animationList = DroneAnimator.getActionList(this.figureType); return this.animationList; } } public void enableLOD(boolean flag) { this.doLOD = flag; } @Override public boolean handle(MouseDownEvent e) { return false; } @Override public boolean handle(FrameEvent fe) { float dist = this.closestView; this.closestView = 10000.0F; if (this.animator != null && !(dist > 900.0F) && this.hasClump()) { if (this.recomputeHeight) { if (this.runPrepFigure) { DroneAnimator.prepFigure(this, this.COG); } this.recomputeHeight = false; } if (this.doLOD && this.setLOD(dist)) { return true; } else { int time = Std.getRealTime(); Transform t = this.getObjectToWorldMatrix(); this.animator.moveto(this.figureType, (short)t.getX(), (short)t.getY(), (short)t.getZ(), (short)(-t.getYaw()), time - 1); this.animator.update(null, this, time, t.getScaleX(), dist > 700.0F); t.recycle(); if (this.expressionStart > 0) { time -= this.expressionStart; while (true) { PosableShape.TimedMatChange tx = this.expressionChanges.elementAt(this.nextChange); if (time < tx.when) { break; } if (tx.mat != origMat) { tx.limb.setMaterial(tx.mat); } if (++this.nextChange >= this.expressionChanges.size()) { this.nextChange = 0; this.expressionStart += time; break; } } } return true; } } else { return true; } } @Override public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException { Object ret = null; switch (index - offset) { case 0: if (mode == 0) { ret = BooleanPropertyEditor.make(new Property(this, index, "Center of Gravity"), "No", "Yes"); } else if (mode == 1) { ret = new Boolean(this.COG); } else if (mode == 2) { this.COG = (Boolean)value; URL u = this.getURL(); this.setURL(defaultURL); this.setURL(u); } break; default: ret = super.properties(index, offset + 1, mode, value); } return ret; } @Override public void saveState(Saver s) throws IOException { s.saveVersion(1, classCookie); s.saveBoolean(this.COG); if (this.subparts != null) { this.subparts.detach(); super.saveState(s); this.add(this.subparts); } else { super.saveState(s); } } @Override public void restoreState(Restorer r) throws IOException, TooNewException { switch (r.restoreVersion(classCookie)) { case 1: this.COG = r.restoreBoolean(); case 0: super.restoreState(r); return; default: throw new TooNewException(); } } @Override public String toString() { return this.getName(); } class TimedMatChange { Shape limb; Material mat; int when; } }