package NET.worlds.scape; import NET.worlds.console.BBAppearDroneCommand; import NET.worlds.console.BBDisappearDroneCommand; import NET.worlds.console.BBDroneBitmapCommand; import NET.worlds.console.BBDroneDeltaPosCommand; import NET.worlds.console.BBMoveDroneCommand; import NET.worlds.console.BlackBox; import NET.worlds.console.Console; import NET.worlds.console.FriendsListPart; import NET.worlds.console.Main; import NET.worlds.console.MainCallback; import NET.worlds.console.MuteListPart; import NET.worlds.core.IniFile; import NET.worlds.core.ServerTableManager; import NET.worlds.core.Std; import NET.worlds.network.FilthFilter; import NET.worlds.network.Galaxy; import NET.worlds.network.InfiniteWaitException; import NET.worlds.network.NetworkObject; import NET.worlds.network.ObjID; import NET.worlds.network.OldPropertyList; import NET.worlds.network.PacketTooLargeException; import NET.worlds.network.PropertyList; import NET.worlds.network.URL; import NET.worlds.network.WorldServer; import NET.worlds.network.net2Property; import NET.worlds.network.netProperty; import NET.worlds.network.propReqCmd; import java.awt.Color; import java.io.IOException; import java.net.MalformedURLException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; public abstract class Drone extends WObject implements NetworkObject, WobLoaded, MouseDownHandler, FrameHandler { private int _last_FrameTime; private int _last_PosTime; private int _vel_x; private int _vel_y; private int _vel_z; private int _vel_yaw; private int _last_x; private int _last_y; private int _last_z; private int _last_yaw; private int _x; private int _y; private int _z; private int _yaw; private boolean inited = false; protected WObject tag; protected WObject tagbg; private Console console; private float tagHeight; private Shape sleepBox; static boolean showNametags = IniFile.gamma().getIniInt("SHOWNAMETAGS", 1) == 1; private static String[] employeeAccounts = ServerTableManager.instance().getTable("employeeAccounts"); private static Hashtable employeeHash = null; public static Vector usableDrones = new Vector(); private int lastUsed; protected WorldServer _server; private String sleepMode; private static Object classCookie = new Object(); private static Object classCookieInterpolatedDrone = new Object(); static { Main.register(new Drone.Flusher()); } public Drone(ObjID id, WorldServer serv) { if (serv != null) { assert id != null; this.attachToServer(serv.getLongID(id), serv); } } protected Drone(String longID, WorldServer serv) { assert longID != null; if (serv != null) { this.attachToServer(longID, serv); } } private void attachToServer(String longID, WorldServer serv) { if (serv != null) { assert Main.isMainThread(); String nameWas = null; if (this.tag != null) { nameWas = this.getLongID(); } this.getSharer().createDynamicFromNet(); this.setName(longID); String nameIs = this.getLongID(); this._server = serv; this._server.incRefCnt(this); this._server.regObject(nameIs, this); try { this._server.sendNetworkMsg(new propReqCmd(new ObjID(this.getLongID()))); } catch (InfiniteWaitException var6) { } catch (PacketTooLargeException var7) { assert false; } if (nameIs.equals(nameWas)) { this.avatarHeightChangedTo(189.0F); } else { this.makeTag(false); } Main.register(new Drone.MakeSleepBox()); } } private static void flushUnusedDrones() { synchronized (usableDrones) { int now = Std.getFastTime(); int i = usableDrones.size(); while (--i >= 0) { Drone d = usableDrones.elementAt(i); if (now > d.lastUsed + 2000) { usableDrones.removeElementAt(i); d.discard(); } } } } public static boolean isEmployeeAccount(String name) { if (employeeHash == null) { employeeHash = new Hashtable(); for (int i = 0; i < employeeAccounts.length; i++) { employeeHash.put(employeeAccounts[i], employeeAccounts[i]); } } return employeeHash.get(name) != null; } public void makeTag(boolean force) { this.tagHeight = 195.0F; if (this.tag != null) { this.tagHeight = this.tag.getPosition().z; this.tag.detach(); this.tag = null; } if (this.tagbg != null) { this.tagbg.detach(); this.tagbg = null; } if ((this._server != null || force) && !(this instanceof MutedDrone) && showNametags) { String unfilteredName = this.getLongID(); String name = FilthFilter.get().filterName(unfilteredName); if (name != null && !name.equals("")) { Texture[] tagText = new Texture[1]; boolean hw = RenderWare.get3DHardwareInUse(); boolean isHost = name.toLowerCase().startsWith(Console.message("host")) || name.toLowerCase().startsWith("host"); if (isHost) { name = Console.message("host-upper") + name.substring(4); } boolean isSpecialGuest = name.toLowerCase().startsWith(Console.message("guest-")) || name.toLowerCase().startsWith("guest-"); if (isSpecialGuest) { name = Console.message("guest-upper") + name.substring(5); } boolean isEmployee = isEmployeeAccount(name); Color bgColor; if (isSpecialGuest) { bgColor = Color.pink; } else if (isHost) { bgColor = Color.yellow; } else if (isEmployee) { bgColor = Color.cyan; } else { bgColor = Color.lightGray; } tagText[0] = new StringTexture(name, Console.message("TagFont"), 48, Color.black, hw ? new Color(254, 254, 254) : bgColor); int height = 14; int width = name.length() * 10; Hologram h = new Hologram(width, height, tagText); h.setViewplaneAligned(true); h.raise(this.tagHeight); h.setScaleDist(300.0F); this.tag = h; this.tag.setVisible(true); this.tag.setBumpable(false); this.tag.setLocalShadowed(false); this.tag.setShadowedLocally(true); this.add(this.tag); if (hw) { Texture[] bgText = new Texture[]{new StringTexture(name, Console.message("TagFont"), 48, Color.black, bgColor)}; Hologram h2 = new Hologram(width, height, bgText); h2.setViewplaneAligned(true); h2.raise(this.tagHeight); h2.setScaleDist(300.0F); h2.setMaterial(new Material(0.75F, 0.0F, 0.0F, Color.white, null, 0.5F, false, false)); this.tagbg = h2; this.tagbg.setVisible(true); this.tagbg.setBumpable(false); this.tagbg.setLocalShadowed(false); this.tagbg.setShadowedLocally(true); this.add(this.tagbg); } } } } protected void avatarHeightChangedTo(float h) { if (this.tag != null) { this.tag.raise(h + 1.0F + 5.0F - this.tag.getPosition().z); } if (this.tagbg != null) { this.tagbg.raise(h + 1.0F + 5.0F - this.tagbg.getPosition().z); } } public void detachFromServer(boolean reuse) { assert Main.isMainThread(); if (this._server != null) { this._server.delObject(new ObjID(this.getLongID())); this._server.decRefCnt(this); this._server = null; } if (reuse) { this.lastUsed = Std.getFastTime(); synchronized (usableDrones) { usableDrones.addElement(this); } } } public static Drone make(ObjID id, WorldServer serv) { synchronized (usableDrones) { if (!usableDrones.isEmpty() && id != null && serv != null) { String name = "!" + serv.getLongID(id); int i; for (i = usableDrones.size() - 1; i > 0; i--) { Drone d = usableDrones.elementAt(i); if (d.getName().equals(name)) { break; } } Drone d = usableDrones.elementAt(i); if (!d.getName().equals(name) && usableDrones.size() < 5) { return new HoloDrone(id, serv); } else { usableDrones.removeElementAt(i); d.attachToServer(serv.getLongID(id), serv); return d; } } else { return new HoloDrone(id, serv); } } } public Drone() { } @Override public boolean handle(MouseDownEvent event) { if (this._server != null && (event.key & 1) == 1) { FriendsListPart.droneClick(this, event); } return true; } public float animate(String action) { if (action.equalsIgnoreCase("_hdb")) { new Drone.BounceNametag(); } return 0.0F; } public Vector getAnimationList() { return new Vector(); } public void muteStateChanged() { this.setAvatarNow(this.getCurrentURL()); } public boolean shouldBeMuted() { return MuteListPart.isMuted(this._server, this.getLongID()); } private World getOwnerWorld() { WObject o = (WObject)this.getOwner(); Room room = o == null ? null : o.getRoom(); return room == null ? null : room.getWorld(); } public boolean shouldBeForcedHuman() { World w = this.getOwnerWorld(); return w != null && w.getForceHuman(); } public URL getCurrentURL() { return this instanceof PosableDrone ? ((PosableDrone)this).getPosableShapeURL() : this.getSourceURL(); } public Drone setAvatarNow(URL url) { if (url == null) { return this; } else { if (this.shouldBeForcedHuman()) { url = PosableShape.getHuman(url); if (Console.getActive() != null) { Console.getActive().pendingPilot = url.toString(); } } url = PosableShape.getPermitted(url, this.getWorld()); boolean muted = this.shouldBeMuted(); if (url.equals(this.getCurrentURL()) && muted == (this instanceof MutedDrone)) { return this; } else if (!url.endsWith(".rwx") && !url.endsWith(".rwg") && !url.endsWith(".mov")) { String s = url.getInternal(); if (s.endsWith(".pilot")) { s = s.substring(0, s.length() - 6) + ".drone"; } else if (!s.endsWith(".drone")) { s = s + ".drone"; } url = URL.make(s); if (url.equals(this.getSourceURL())) { return this; } else { new WobLoader(url, this); return this; } } else { WObject o = (WObject)this.getOwner(); if (o == null) { return this; } else { WorldServer serv = this._server; String longID = this.getLongID(); this.detachFromServer(false); this.detach(); Drone d; if (muted) { d = new MutedDrone(new ObjID(longID), serv, url); } else if (url.endsWith(".mov")) { d = new HoloDrone(new ObjID(longID), serv); d.setAvatarNow(url); } else { d = new PosableDrone(new ObjID(longID), serv, url); } if (serv != null) { d.transferFrom(this); d.addTo(o.getRoom()); } else { d.makeIdentity().post(this); d.setName(this.getLongID()); o.add(d); } return d; } } } } @Override public void wobLoaded(WobLoader loader, SuperRoot w) { if (w instanceof Drone) { assert w != null; Drone d = (Drone)w; d.setName(this.getLongID()); if (this._server == null) { WObject o = (WObject)this.getOwner(); this.detach(); d.makeIdentity().post(this); o.add(d); } else { WorldServer serv = this._server; String longID = this.getLongID(); this.detachFromServer(false); Room r = this.getRoom(); this.detach(); d.addTo(r); d.attachToServer(longID, serv); d.transferFrom(this); } } } public void addTo(Room r) { if (r != null) { Console c = r.getWorld().getConsole(); if (this.console == null) { this.console = c; if (c != null) { Pilot.copySoul(c.getDroneSoulTemplate(), this); } } r.add(this); } } @Override public void add(WObject w) { super.add(w); } @Override protected void noteUnadding(SuperRoot child) { if (child instanceof WObject) { WObject w = (WObject)child; if (w.isDynamic()) { w.setVisible(true); } } super.noteUnadding(child); } public void setSleepMode(String mode) { if (!mode.equals(this.sleepMode)) { this.sleepMode = mode; Main.register(new Drone.MakeSleepBox()); } } private void handleVAR_ASLEEP(String s) { if (s != null && s.length() > 2 && s.charAt(0) == 0) { s = s.substring(2); } this.setSleepMode(s); } public Drone handleVAR_BITMAP(String s) { if (s.equals("")) { return this; } else { BlackBox.getInstance().submitEvent(new BBDroneBitmapCommand(this.getName(), s)); if (s.charAt(0) == 0) { s = s.substring(2); } try { return this.setAvatarNow(new URL(URL.getAvatar(), s)); } catch (MalformedURLException var3) { Console.println(Console.message("Invalid-av") + s); return this; } } } public Point3Temp getVelocity() { return Point3Temp.make(this._vel_x, this._vel_y, this._vel_z); } public int getYawRate() { return this._vel_yaw; } @Override public boolean handle(FrameEvent fe) { if (this._server == null) { return true; } else { int timeNow = fe.time; this.interpolate(timeNow, this._server.getUpdateTime(), this); return true; } } public void interpolate(int timeNow, int updateTime, Transform target) { if (this.inited) { if (timeNow - this._last_PosTime > updateTime) { this._last_PosTime = timeNow; this._vel_x = this._last_x - this._x; this._vel_y = this._last_y - this._y; this._vel_z = this._last_z - this._z; this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360; assert this._vel_yaw >= 0; if (this._vel_yaw > 180) { this._vel_yaw -= 360; } } double timeDiff = (double)(timeNow - this._last_FrameTime) / updateTime; if (timeNow - this._last_FrameTime > updateTime) { timeDiff = 0.0; } this._x = this._x + (int)(timeDiff * this._vel_x); this._y = this._y + (int)(timeDiff * this._vel_y); this._z = this._z + (int)(timeDiff * this._vel_z); this._yaw = this._yaw + (int)(timeDiff * this._vel_yaw) % 360; target.makeIdentity().moveBy(this._x, this._y, this._z).yaw(this._yaw); this._last_FrameTime = timeNow; } } public void reset(short x, short y, short z, short yaw) { this._x = x; this._y = y; this._z = z; this._yaw = yaw; this._vel_x = this._vel_y = this._vel_z = 0; this._vel_yaw = 0; this._last_x = this._x; this._last_y = this._y; this._last_z = this._z; this._last_yaw = this._yaw; this._last_PosTime = this._last_FrameTime = Std.getRealTime(); this.inited = true; } protected void transferFrom(Drone i) { this.makeIdentity().post(i); this._x = i._x; this._y = i._y; this._z = i._z; this._yaw = i._yaw; this._vel_x = i._vel_x; this._vel_y = i._vel_y; this._vel_z = i._vel_z; this._vel_yaw = i._vel_yaw; this._last_x = i._last_x; this._last_y = i._last_y; this._last_z = i._last_z; this._last_yaw = i._last_yaw; this._last_PosTime = i._last_PosTime; this._last_FrameTime = i._last_FrameTime; this.inited = true; } public void appear(Room rm, short x, short y, short z, short yaw) { assert rm != null; BlackBox.getInstance().submitEvent(new BBAppearDroneCommand(rm.toString(), this.getName(), x, y, z, yaw)); if (this.getRoom() != rm) { this.detach(); rm.add(this); } this.makeIdentity().moveBy(x, y, z).yaw(yaw); this._x = x; this._y = y; this._z = z; this._yaw = yaw; this._vel_x = this._vel_y = this._vel_z = 0; this._vel_yaw = 0; this._last_x = x; this._last_y = y; this._last_z = z; this._last_yaw = yaw; this._last_PosTime = this._last_FrameTime = Std.getRealTime(); URL u = this.getCurrentURL(); if (u != null) { this.setAvatarNow(u); } this.inited = true; } public void disappear() { BlackBox.getInstance().submitEvent(new BBDisappearDroneCommand(this.getName())); this.detachFromServer(true); this.detach(); } public void longLoc(short x, short y, short z, short yaw) { if (!(this.getOwner() instanceof Pilot)) { BlackBox.getInstance().submitEvent(new BBMoveDroneCommand(this.getName(), x, y, z, yaw)); } this._last_x = x; this._last_y = y; this._last_z = z; this._last_yaw = yaw; this._vel_x = this._last_x - this._x; this._vel_y = this._last_y - this._y; this._vel_z = this._last_z - this._z; this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360; assert this._vel_yaw >= 0; if (this._vel_yaw > 180) { this._vel_yaw -= 360; } this._last_PosTime = Std.getRealTime(); this.inited = true; } @Override public void property(OldPropertyList propList) { int end = propList.size(); for (int i = 0; i < end; i++) { netProperty tmpProp = propList.elementAt(i); switch (tmpProp.property()) { case 5: this.handleVAR_BITMAP(tmpProp.value()); break; case 23: this.handleVAR_ASLEEP(tmpProp.value()); break; default: byte[] data = new byte[tmpProp.value().length()]; tmpProp.value().getBytes(0, tmpProp.value().length(), data, 0); this.getSharer().setFromNetData(tmpProp.property(), data); } } } @Override public void propertyUpdate(PropertyList propList) { int end = propList.size(); for (int i = 0; i < end; i++) { net2Property tmpProp = propList.elementAt(i); switch (tmpProp.property()) { case 5: this.handleVAR_BITMAP(tmpProp.value()); break; case 23: this.handleVAR_ASLEEP(tmpProp.value()); break; default: this.getSharer().setFromNetData(tmpProp.property(), tmpProp.data()); } } } public void roomChange(Room newRoom, short x, short y, short z, short yaw) { this.detach(); if (newRoom != null) { this.appear(newRoom, x, y, z, yaw); } } public void shortLoc(byte dx, byte dy, byte dyaw) { if (!(this.getOwner() instanceof Pilot)) { BlackBox.getInstance().submitEvent(new BBDroneDeltaPosCommand(this.getName(), dx, dy, dyaw)); } this._last_x += dx; this._last_y += dy; this._last_yaw += dyaw; this._last_yaw %= 360; this._vel_x = this._last_x - this._x; this._vel_y = this._last_y - this._y; this._vel_z = 0; this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360; assert this._vel_yaw >= 0; if (this._vel_yaw > 180) { this._vel_yaw -= 360; } this._last_PosTime = Std.getRealTime(); } public void teleport(WorldServer serv, byte exitType, byte entryType, Room newRoom, short x, short y, short z, short yaw) { assert serv.getObject(new ObjID(this.getLongID())) == this; Room curRoom = this.getRoom(); switch (exitType) { default: if (curRoom != null) { assert curRoom != null; this.detach(); } case 0: switch (entryType) { case 0: this.detachFromServer(true); this.detach(); break; default: if (newRoom == null) { this.detach(); } else { assert newRoom != null; this.appear(newRoom, x, y, z, yaw); } } } } @Override public WorldServer getServer() { return this._server; } @Override public String getLongID() { String name = this.getName(); if (name.startsWith("!")) { name = name.substring(1); } return name; } @Override public void register() { assert false; } @Override public void galaxyDisconnected() { assert false; } @Override public void reacquireServer(WorldServer oldServ) { assert false; } @Override public void changeChannel(Galaxy g, String oldChannel, String newChannel) { assert false; } @Override public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException { Object ret = null; int var10000 = index - offset; return super.properties(index, offset + 0, mode, value); } @Override public void saveState(Saver s) throws IOException { if (this.console != null) { System.out.println("Warning: saving drone " + this.getName() + " WITH soul, which won't restore correctly!"); } s.saveVersion(0, classCookieInterpolatedDrone); s.saveVersion(0, classCookie); super.saveState(s); } public void restoreStateDrone(Restorer r) throws IOException, TooNewException { r.restoreVersion(classCookieInterpolatedDrone); switch (r.restoreVersion(classCookie)) { case 0: super.restoreState(r); Enumeration e = this.getContents(); while (e.hasMoreElements()) { WObject w = (WObject)e.nextElement(); if (w instanceof Hologram) { Hologram h = (Hologram)w; if (h.getMovieName() == null) { this.tag = h; } } } return; default: throw new TooNewException(); } } @Override public void restoreState(Restorer r) throws IOException, TooNewException { this.restoreStateDrone(r); } class BounceNametag implements MainCallback { int start; WObject origTag; WObject origTagbg; BounceNametag() { if (Drone.this.tag != null) { this.start = Std.getFastTime(); this.origTag = Drone.this.tag; this.origTagbg = Drone.this.tagbg; Main.register(this); } } @Override public void mainCallback() { int now = Std.getFastTime(); float h = Drone.this.tagHeight; if (now > this.start + 6000 || this.origTag != Drone.this.tag || this.origTagbg != Drone.this.tagbg) { Main.unregister(this); } else if (now < this.start + 1500) { h = Drone.this.tagHeight + 200.0F * ((now - this.start) / 1500.0F); } else { float t = (now - this.start) / 1500.0F; h = (float)(200.0 * Math.pow(1.414F, t) * Math.cos(t * 3.14159F)); } this.origTag.setZ(h); if (this.origTagbg != null) { this.origTagbg.setZ(h); } } } static class Flusher implements MainCallback { int lastTime; @Override public void mainCallback() { int now = Std.getFastTime(); if (now > this.lastTime + 1000) { Drone.flushUnusedDrones(); this.lastTime = now; } } } class MakeSleepBox implements MainCallback { @Override public void mainCallback() { if (Drone.this.sleepMode != null && Drone.this.sleepMode.equals(Console.message("asleep")) && !(Drone.this instanceof MutedDrone)) { if (Drone.this.sleepBox == null) { Drone.this.sleepBox = new Shape(); Drone.this.sleepBox.setURL(URL.make("home:idle.rwg")); Drone.this.sleepBox.setBumpable(false); Drone.this.sleepBox.scale(100.0F); Drone.this.sleepBox.spin(0.0F, 1.0F, 1.0F, 180.0F); Drone.this.sleepBox.raise(189.0F); Drone.this.add(Drone.this.sleepBox); } } else if (Drone.this.sleepBox != null) { Drone.this.sleepBox.detach(); Drone.this.sleepBox = null; } Main.unregister(this); } } }