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/Drone.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/Drone.java')
| -rw-r--r-- | NET/worlds/scape/Drone.java | 864 |
1 files changed, 864 insertions, 0 deletions
diff --git a/NET/worlds/scape/Drone.java b/NET/worlds/scape/Drone.java new file mode 100644 index 0000000..d930b61 --- /dev/null +++ b/NET/worlds/scape/Drone.java @@ -0,0 +1,864 @@ +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<String, String> employeeHash = null; + public static Vector<Drone> usableDrones = new Vector<Drone>(); + 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<String, String>(); + + 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<String> getAnimationList() { + return new Vector<String>(); + } + + 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); + } + } +} |