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/Portal.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/Portal.java')
| -rw-r--r-- | NET/worlds/scape/Portal.java | 831 |
1 files changed, 831 insertions, 0 deletions
diff --git a/NET/worlds/scape/Portal.java b/NET/worlds/scape/Portal.java new file mode 100644 index 0000000..e2f05b6 --- /dev/null +++ b/NET/worlds/scape/Portal.java @@ -0,0 +1,831 @@ +package NET.worlds.scape; + +import NET.worlds.console.Console; +import NET.worlds.console.Main; +import NET.worlds.console.MainCallback; +import NET.worlds.network.NetUpdate; +import NET.worlds.network.URL; +import java.awt.Color; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Vector; + +public class Portal extends Rect implements BumpHandler, Prerenderable, Postrenderable, Properties, Persister, LoadedURLSelf { + static final int UNCONNECTED = -1; + static final int INITIAL = 0; + static final int DOWNLOADING = 1; + static final int DONE = 2; + private int _state = -1; + private Portal _farSidePortal = null; + String _farSidePortalName = null; + private boolean _farSideIsPortal = true; + private boolean _allowDownload = true; + String _farSideRoomName = null; + private URL _farSideWorld = null; + private Room _farSideRoom = null; + private float _farx; + private float _fary; + private float _farz; + private float _fartheta; + private float _userFarx; + private float _userFary; + private float _userFarz; + private float _userFartheta; + private boolean frozeFrameEvents; + private Transform _p2pxform = null; + private int _changeNum = 0; + private int _farChangeNum = -1; + static BumpCalc standardPassthroughBumpCalc = new PassthroughBumpCalc(); + private static Object classCookie = new Object(); + + static { + nativeInit(); + standardPassthroughBumpCalc.setName("defaultPassthroughBumpCalc"); + } + + protected Room getFarSideRoom() { + return this._farSideRoom; + } + + public Portal(float w, float h) { + super(w, h, null); + } + + public Portal(float llx, float lly, float llz, float urx, float ury, float urz) { + super(llx, lly, llz, urx, ury, urz, null); + } + + public Portal() { + } + + public void setFarSideInfo(URL world, String room, String portal) { + this._farSideWorld = world; + this._farSideRoomName = room; + this._farSidePortalName = portal; + } + + public Portal(Point3Temp llc, Point3Temp urc) { + super(llc, urc, null); + } + + public static Portal findByName(Room r, String portalName) { + SuperRoot sr = SuperRoot.nameSearch(r.getDeepOwned(), portalName); + return sr != null && sr instanceof Portal ? (Portal)sr : null; + } + + public Portal connectTo(Portal far) { + assert this._state == -1; + + this._farSideIsPortal = true; + this._farSidePortal = far; + this.newFarSide(); + return this; + } + + public Portal connectTo(URL farworld, String farroom, Point3Temp llc, Point3Temp urc) { + return this.connectTo(farworld, farroom, llc.x, llc.y, llc.z, urc.x, urc.y, urc.z); + } + + public Portal connectTo(Room r, Point3Temp llc, Point3Temp urc) { + System.out.println("Warning! Old style Portal.connectTo called!"); + Thread.dumpStack(); + + assert this._state == -1; + + this._farSideWorld = r.getWorld().getSourceURL(); + this._farSideRoomName = r.getName(); + this.setFarSideRoom(r); + this._farx = this._userFarx = urc.x; + this._fary = this._userFary = urc.y; + this._farz = this._userFarz = llc.z; + this._userFartheta = (float)(Math.atan2(llc.y - urc.y, llc.x - urc.x) * 180.0 / Math.PI); + this._fartheta = this._userFartheta; + this._state = 2; + this._farSideIsPortal = false; + this.setTransform(); + this.updateVisible(); + return this; + } + + public Portal connectTo(URL farworld, String farroom, float llx, float lly, float llz, float urx, float ury, float urz) { + float theta = (float)(Math.atan2(lly - ury, llx - urx) * 180.0 / Math.PI); + return this.connectTo(farworld, farroom, urx, ury, llz, theta); + } + + public Portal connectTo(URL farworld, String farroom, float x, float y, float z, float theta) { + assert this._state == -1; + + this._farSideWorld = farworld; + this._farSideRoomName = farroom; + this._farx = this._userFarx = x; + this._fary = this._userFary = y; + this._farz = this._userFarz = z; + this._fartheta = this._userFartheta = theta; + this._farSideIsPortal = false; + this.reset(); + return this; + } + + public Portal remotify() { + RPAction rpa = new RPAction(); + this.addAction(rpa); + this.addHandler(new SameRoomSensor(rpa)); + return this; + } + + private void findFarSidePortal(boolean showmessage) { + if (this._farSideIsPortal) { + if (this._farSidePortalName == null) { + this._state = -1; + } else { + this._farSidePortal = null; + Vector portals = this._farSideRoom.getOutgoingPortals(); + int len = portals.size(); + + for (int i = 0; i < len; i++) { + Portal p = (Portal)portals.elementAt(i); + if (p.getName().equals(this._farSidePortalName)) { + this._farSidePortal = p; + break; + } + } + + if (this._farSidePortal == null) { + if (showmessage) { + Object[] arguments = new Object[]{ + new String(this.getName()), new String("" + this._farSideWorld), new String(this._farSideRoomName), new String(this._farSidePortalName) + }; + Console.println(MessageFormat.format(Console.message("Portal-doesnt"), arguments)); + } + + this._state = -1; + } + } + + if (this._farSidePortal != null) { + this.newFarSide(); + } + } else { + this._farSidePortal = null; + this._farx = this._userFarx; + this._fary = this._userFary; + this._farz = this._userFarz; + this._fartheta = this._userFartheta; + this._p2pxform = null; + } + } + + public void reset() { + this.reset(true); + } + + public void reset(boolean showmessage) { + this.setFarSideRoom(null); + if (this._farSideRoomName == null || (this.flags & 262144) != 0) { + this._state = -1; + } else if (this._farSideWorld == null) { + Room r = this.getRoom(); + if (r != null) { + World w = r.getWorld(); + if (w != null) { + this.setFarSideRoom(w.getRoom(this._farSideRoomName)); + } + } + + if (this._farSideRoom != null) { + this.findFarSidePortal(showmessage); + } else { + this._state = -1; + this._farSidePortal = null; + if (showmessage) { + Object[] arguments = new Object[]{ + new String(this.getName()), new String("" + this.getRoom()), new String(this._farSideRoomName), new String(this._farSidePortalName) + }; + Console.println(MessageFormat.format(Console.message("Room-doesnt"), arguments)); + } + } + } else { + if (this._farSidePortalName == null) { + this._farSidePortal = null; + } + + this._state = 0; + } + + this.setTransform(); + this.updateVisible(); + } + + @Override + public void discard() { + Portal far = this._farSidePortal; + this.setFarSideRoom(null); + this._state = 0; + super.discard(); + if (far != null && far.getRoom() != null && this._farSideWorld != null) { + far.reset(); + } + } + + private void recomputeFarPosition() { + this.setFarSideRoom(this._farSidePortal.getRoom()); + if (this._farSideRoom != null) { + this._farSideRoomName = this._farSideRoom.getName(); + } + + this._farSidePortalName = this._farSidePortal.getName(); + Point3Temp farext = Point3Temp.make(1.0F, 0.0F, 1.0F).vectorTimes(this._farSidePortal); + Point3Temp farlrc = this._farSidePortal.getPosition(); + if ((this.flags & 4) == 0) { + farlrc.x = farlrc.x + farext.x; + farlrc.y = farlrc.y + farext.y; + } + + this._farx = farlrc.x; + this._fary = farlrc.y; + this._farz = farlrc.z; + this._fartheta = (-this._farSidePortal.getYaw() + 180.0F) % 360.0F; + this._farChangeNum = this._farSidePortal._changeNum; + this._p2pxform = null; + } + + public Portal biconnect(Portal far) { + this.connectTo(far); + far.connectTo(this); + return this; + } + + public void disconnect() { + this._farSideWorld = null; + this._farSideRoomName = null; + this.setFarSideRoom(null); + this._farSidePortal = null; + this._farSideIsPortal = true; + this._farSidePortalName = null; + this._state = -1; + this.updateVisible(); + this.discardTransform(); + } + + public void bidisconnect() { + this._farSidePortal.disconnect(); + this.disconnect(); + } + + public boolean connected() { + return this._farSidePortal != null || this._farSideRoomName != null && !this._farSideIsPortal; + } + + public boolean active() { + return this._state == 2; + } + + public boolean unconnected() { + return this._state == -1; + } + + public boolean remote() { + return this._farSideWorld != null; + } + + public Portal farSide() { + return this._farSideIsPortal ? this._farSidePortal : null; + } + + public Room farSideRoom() { + return this._farSideRoom; + } + + private void setFarSideRoom(Room far) { + this._farSideRoom = far; + } + + @Override + protected void noteAddingTo(SuperRoot s) { + this.addToRoom(s); + super.noteAddingTo(s); + } + + private void addToRoom(SuperRoot s) { + if (s instanceof WObject) { + Room r = ((WObject)s).getRoom(); + if (r != null) { + r.addOutgoingPortal(this); + } + } + } + + @Override + public void detach() { + Room r = this.getRoom(); + if (r != null) { + r.removeOutgoingPortal(this); + } + + super.detach(); + } + + public String farRoom() { + return this._farSideRoomName; + } + + public URL farWorld() { + return this._farSideWorld; + } + + public Transform p2pXform() { + return this._p2pxform; + } + + @Override + protected void addRwChildren(WObject parent) { + if (this._farSidePortal != null && this._farSidePortal instanceof TwoWayPortal && !this._farSidePortal.isActive()) { + Main.register(new MainCallback() { + @Override + public void mainCallback() { + Portal.this.detach(); + Main.unregister(this); + } + }); + } + + super.addRwChildren(parent); + this.updateVisible(); + this.setTransform(); + this.getRoom().prependPrerenderHandler(this); + this.getRoom().prependPostrenderHandler(this); + } + + @Override + protected void markVoid() { + this.getRoom().removePrerenderHandler(this); + this.getRoom().removePostrenderHandler(this); + super.markVoid(); + } + + @Override + protected void noteTransformChange() { + this._changeNum++; + super.noteTransformChange(); + this.discardTransform(); + } + + public static native void nativeInit(); + + @Override + protected native void updateVisible(); + + native void setTransform(); + + public void discardTransform() { + if (this._p2pxform != null) { + this._p2pxform = null; + if (this._farSidePortal != null) { + this._farSidePortal.discardTransform(); + } + } + } + + @Override + public native void prerender(Camera var1); + + @Override + public native void postrender(Camera var1); + + @Override + public BumpCalc getBumpCalc(BumpEventTemp b) { + if (this._farSidePortal == null + || !(b.source instanceof Camera) + || (this.flags & 4) == 0 && this._farSidePortal.active() && this._farSidePortal._p2pxform != null && this._farSidePortal.getVisible()) { + if (this.bumpCalc != null) { + return this.bumpCalc; + } else if (this._farSideRoomName == null) { + return standardPassthroughBumpCalc; + } else { + if (this.connected() && (this.flags & 262144) == 0) { + if (this._farSideRoom == null && this._farSideIsPortal && this._farSidePortal != null) { + this.setFarSideRoom(this._farSidePortal.getRoom()); + } + + if (this._farSideRoom != null && this._farSideRoom.isActive()) { + return standardPassthroughBumpCalc; + } + } + + return super.getBumpCalc(b); + } + } else { + return super.getBumpCalc(b); + } + } + + @Override + public boolean handle(BumpEventTemp b) { + if (this._farSidePortal == null + || !(b.source instanceof Camera) + || (this.flags & 4) == 0 && this._farSidePortal.active() && this._farSidePortal._p2pxform != null && this._farSidePortal.getVisible()) { + this.portalBumpHandler(b); + return true; + } else { + return true; + } + } + + public void portalBumpHandler(BumpEventTemp b) { + if (b.target == this && this._state == 2) { + if (this._farSideRoom == null && this._farSideIsPortal && this._farSidePortal != null) { + this.setFarSideRoom(this._farSidePortal.getRoom()); + } + + if (this._farSideRoom != null && this._farSideRoom.isActive()) { + if (this._p2pxform == null) { + this.setTransform(); + if (this._p2pxform == null) { + return; + } + } + + b.postBumpRoom = this._farSideRoom; + Transform t = ((WObject)b.source).getObjectToWorldMatrix(); + b.postBumpPosition.setTransform(t); + t.recycle(); + b.postBumpPosition.moveBy(b.path).post(this._p2pxform); + b.postBumpPath = new Point3(b.fullPath).times(1.0F - b.fraction).vectorTimes(this._p2pxform); + } + } else { + if (this._state == 1 && this._farSideWorld != null && !this._farSideWorld.isRemote() && !this.frozeFrameEvents) { + this.frozeFrameEvents = true; + Console.setFreezeFrameEvents(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 = URLPropertyEditor.make(new Property(this, index, "Destination World URL (null means this world)").allowSetNull(), "world"); + } else if (mode == 1) { + ret = this._farSideWorld; + } else if (mode == 2) { + this._farSideWorld = (URL)value; + this.reset(); + this.triggerLoad(); + } + break; + case 1: + if (mode == 0) { + ret = StringPropertyEditor.make(new Property(this, index, "Destination Room Name").allowSetNull()); + } else if (mode == 1) { + ret = this._farSideRoomName == null ? "" : this._farSideRoomName; + } else if (mode == 2) { + this._farSideRoomName = (String)value; + if ("".equals(this._farSideRoomName)) { + this._farSideRoomName = null; + } + + this.reset(); + this.triggerLoad(); + } + break; + case 2: + if (mode == 0) { + ret = BooleanPropertyEditor.make(new Property(this, index, "Connect to a portal"), "Use location and orientation", "Use portal"); + } else if (mode == 1) { + ret = new Boolean(this._farSideIsPortal); + } else if (mode == 2) { + boolean tmp = (Boolean)value; + this._farSideIsPortal = tmp; + this.reset(); + this.triggerLoad(); + } + break; + case 3: + if (mode == 0) { + ret = BooleanPropertyEditor.make(new Property(this, index, "Download if world not present"), "Never download", "Allow download"); + } else if (mode == 1) { + ret = new Boolean(this._allowDownload); + } else if (mode == 2) { + boolean tmp = (Boolean)value; + this._allowDownload = tmp; + } + break; + case 4: + if (mode == 0) { + ret = new Property(this, index, "Destination Portal Name"); + if (this._farSideIsPortal) { + ret = StringPropertyEditor.make((Property)ret); + } + } else if (mode == 1) { + ret = this._farSidePortalName == null ? "" : this._farSidePortalName; + } else if (mode == 2) { + this._farSidePortalName = (String)value; + if ("".equals(this._farSidePortalName)) { + this._farSidePortalName = null; + } + + this.reset(); + this.triggerLoad(); + } + break; + case 5: + if (mode == 0) { + ret = new Property(this, index, "Destination position"); + if (!this._farSideIsPortal) { + ret = Point3PropertyEditor.make((Property)ret); + } + } else if (mode == 1) { + ret = new Point3(this._userFarx, this._userFary, this._userFarz); + } else if (mode == 2) { + Point3 p = (Point3)value; + this._farx = this._userFarx = p.x; + this._fary = this._userFary = p.y; + this._farz = this._userFarz = p.z; + this.reset(); + this.triggerLoad(); + } + break; + case 6: + if (mode == 0) { + ret = new Property(this, index, "Destination orientation (degrees, clockwise from North)"); + if (!this._farSideIsPortal) { + ret = FloatPropertyEditor.make((Property)ret, 0.0F, 360.0F); + } + } else if (mode == 1) { + ret = new Float(this._userFartheta); + } else if (mode == 2) { + this._fartheta = this._userFartheta = (Float)value; + this.reset(); + this.triggerLoad(); + } + break; + case 7: + if (mode == 0) { + ret = BooleanPropertyEditor.make(new Property(this, index, "Mirrored"), "Normal", "Mirrored"); + } else if (mode == 1) { + ret = new Boolean((this.flags & 4) != 0); + } else if (mode == 2) { + if ((Boolean)value) { + this.flags |= 4; + } else { + this.flags &= -5; + } + + this.reset(); + this.triggerLoad(); + } + break; + default: + ret = super.properties(index, offset + 8, mode, value); + } + + return ret; + } + + private void newFarSide() { + this._farSidePortalName = this._farSidePortal.getName(); + if (this._state == -1 && (this.flags & 262144) == 0) { + this._state = 2; + } + + this.recomputeFarPosition(); + this.setTransform(); + this.updateVisible(); + } + + @Override + public void saveState(Saver s) throws IOException { + Portal tmp = null; + if (this._farSideWorld != null || this._farSidePortal != null && (!this._farSidePortal.isActive() || this._farSidePortal instanceof NonPersister)) { + tmp = this._farSidePortal; + this._farSidePortal = null; + } + + s.saveVersion(9, classCookie); + super.saveState(s); + s.saveBoolean(this._farSideIsPortal); + s.saveBoolean(this._allowDownload); + s.saveString(this._farSidePortalName); + s.saveMaybeNull(this._farSidePortal); + URL.save(s, this._farSideWorld); + s.saveString(this._farSideRoomName); + s.saveFloat(this._userFarx); + s.saveFloat(this._userFary); + s.saveFloat(this._userFarz); + s.saveFloat(this._userFartheta); + if (tmp != null) { + this._farSidePortal = tmp; + } + } + + public void superRestoreState(Restorer r) throws IOException, TooNewException { + this.restoreWObjectState(r); + this.setMaterial(new Material(Color.black)); + } + + @Override + public void restoreState(Restorer r) throws IOException, TooNewException { + float x = 0.0F; + float y = 0.0F; + float z = 0.0F; + int vers = r.restoreVersion(classCookie); + switch (vers) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + r.setOldFlag(); + this.superRestoreState(r); + if (vers < 6) { + if (vers == 0) { + r.restoreInt(); + } + + x = r.restoreFloat(); + y = r.restoreFloat(); + z = r.restoreFloat(); + this.scale(x, 1.0F, z); + } + + if (r.restoreBoolean()) { + this.flags |= 4; + } + + if (vers >= 4) { + this._farSidePortalName = r.restoreString(); + } + + this._farSidePortal = (Portal)r.restoreMaybeNull(); + if (vers == 1) { + String n = r.restoreString(); + if (!"".equals(n)) { + this.setName(n); + } + } else if (vers >= 3) { + if (vers >= 7) { + this._farSideWorld = URL.restore(r); + } else { + this._farSideWorld = URL.restore(r, ".world"); + } + + this._farSideRoomName = r.restoreString(); + this._farx = r.restoreFloat(); + this._fary = r.restoreFloat(); + this._farz = r.restoreFloat(); + this._fartheta = r.restoreFloat(); + Material initialCover = Material.restore(r); + Material downloadCover = Material.restore(r); + if (initialCover != null) { + this.setMaterial(initialCover); + if (downloadCover != null && (initialCover.textureName == null || !initialCover.textureName.equals(downloadCover.textureName))) { + System.out + .println( + "Both initial and download covers, " + + initialCover.textureName + + " and " + + downloadCover.textureName + + ", in " + + this.getName() + + " -- using initial." + ); + } + } else { + this.setMaterial(downloadCover); + } + + if (vers >= 5) { + this._farSideIsPortal = r.restoreBoolean(); + } + } + break; + case 8: + case 9: + super.restoreState(r); + this._farSideIsPortal = r.restoreBoolean(); + if (vers >= 9) { + this._allowDownload = r.restoreBoolean(); + } + + this._farSidePortalName = r.restoreString(); + this._farSidePortal = (Portal)r.restoreMaybeNull(); + this._farSideWorld = URL.restore(r); + this._farSideRoomName = r.restoreString(); + this._farx = r.restoreFloat(); + this._fary = r.restoreFloat(); + this._farz = r.restoreFloat(); + this._fartheta = r.restoreFloat(); + break; + default: + throw new TooNewException(); + } + + if (vers <= 4 && this._farSideRoomName != null && this._farSidePortal == null && this._farSidePortalName == null) { + this._farSideIsPortal = false; + } + + this._userFarx = this._farx; + this._userFary = this._fary; + this._userFarz = this._farz; + this._userFartheta = this._fartheta; + } + + @Override + public void postRestore(int version) { + super.postRestore(version); + if (this.getOwner() != null) { + this.addToRoom(this.getOwner()); + Room r = this.getOwner().getRoom(); + if (this._farSidePortal == null) { + this.reset(); + } else { + this.newFarSide(); + } + } + } + + @Override + public String toString() { + String to; + if (this._state == -1) { + to = "(not connected)"; + } else { + if (this._farSideWorld != null) { + to = this._farSideWorld.toString(); + } else { + to = ""; + } + + if (this._farSideRoom != null) { + to = to + "#" + this._farSideRoomName; + } + + if (this._farSidePortalName != null) { + to = to + "#" + this._farSidePortalName; + } + } + + return super.toString() + "[Connected To " + to + "]"; + } + + public Portal triggerLoad() { + if (this._farSideWorld != null && this._farSideRoomName != null) { + if (this._farSidePortal != null && !this._farSidePortal.isActive()) { + this.reset(); + } + + if (this._state == 0) { + this._state = 1; + World.load(this._farSideWorld, this); + } + } + + return this; + } + + @Override + public void loadedURLSelf(URLSelf o, URL url, String err) { + if (this.frozeFrameEvents) { + this.frozeFrameEvents = false; + Console.setFreezeFrameEvents(false); + } + + if (this._state == 1) { + if (err == null && o instanceof World) { + World w = (World)o; + this.setFarSideRoom(w.getRoom(this._farSideRoomName)); + if (this._farSideRoom != null) { + this._state = 2; + this.findFarSidePortal(true); + } else { + Object[] arguments = new Object[]{new String(this._farSideRoomName), new String("" + this._farSideWorld)}; + Console.println(MessageFormat.format(Console.message("Cant-find-remote"), arguments)); + this._state = -1; + } + } else { + if (err == null) { + err = "doesn't contain a World"; + o.decRef(); + } + + String readable = TeleportAction.getReadableNameOfWorld(url); + this._state = -1; + if (this._allowDownload && !World.isProscribed(url, false)) { + Object[] arguments = new Object[]{new String(readable)}; + Console.println(MessageFormat.format(Console.message("Dont-have-world"), arguments)); + String packageName = TeleportAction.getPackageNameOfWorld(url); + if (packageName != null) { + NetUpdate.loadWorld(packageName, false); + } + } + } + + this.updateVisible(); + } + } +} |