diff options
| author | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
| commit | c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch) | |
| tree | df9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/PosableShape.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/PosableShape.java')
| -rw-r--r-- | NET/worlds/scape/PosableShape.java | 1331 |
1 files changed, 1331 insertions, 0 deletions
diff --git a/NET/worlds/scape/PosableShape.java b/NET/worlds/scape/PosableShape.java new file mode 100644 index 0000000..7ed5610 --- /dev/null +++ b/NET/worlds/scape/PosableShape.java @@ -0,0 +1,1331 @@ +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<String> 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<Object, Vector<Object>> actions; + private int scanPos; + private static Material origMat = new Material(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<String, String> permittedHash = new Hashtable<String, String>(); + private static Vector<String> permittedNames = new Vector<String>(); + private static Vector<String> faceNames = new Vector<String>(); + private static Hashtable<String, String> humanHash = new Hashtable<String, String>(); + private static Hashtable<String, Vector<String>> worldHash = new Hashtable<String, Vector<String>>(); + private static Hashtable<String, String> secretNames = new Hashtable<String, String>(); + private static Hashtable<String, String> faceTextures = new Hashtable<String, String>(); + static boolean gotServerAvatarList; + static boolean serverAvatarListError; + private Enumeration<String> animations; + private boolean doLOD = false; + protected int expressionStart; + protected int nextChange; + protected Vector<PosableShape.TimedMatChange> 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<String> 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<Material> 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<Material> 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<PosableShape.TimedMatChange>(); + 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<String> getComponentAvatars(URL pUrl) { + if (pUrl == null) { + return null; + } else { + Vector<String> v = new Vector<String>(); + 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<Material> 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<String> 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<String> worldList = new Vector<String>(); + + 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<String> e = getComponentAvatars(in); + + while (e != null && e.hasMoreElements()) { + String baseAv = e.nextElement(); + String s = getBodyType(URL.make(baseAv)); + if (s == null) { + return getDefAv(); + } + + Vector<String> allowedWorlds = worldHash.get(s); + if (allowedWorlds == null) { + return getDefAv(); + } + + boolean worldOK = false; + Enumeration<String> 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<String> 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<Material> mats = new Vector<Material>(); + 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<String> 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<String> vanimations = new Vector<String>(); + 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<String> 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; + } +} |