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/TeleportAction.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/scape/TeleportAction.java')
| -rw-r--r-- | NET/worlds/scape/TeleportAction.java | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/NET/worlds/scape/TeleportAction.java b/NET/worlds/scape/TeleportAction.java new file mode 100644 index 0000000..c73dada --- /dev/null +++ b/NET/worlds/scape/TeleportAction.java @@ -0,0 +1,539 @@ +package NET.worlds.scape; + +import NET.worlds.console.Console; +import NET.worlds.console.DialogReceiver; +import NET.worlds.console.Main; +import NET.worlds.console.MainCallback; +import NET.worlds.console.WorldsMarkPart; +import NET.worlds.core.IniFile; +import NET.worlds.network.NetUpdate; +import NET.worlds.network.URL; +import java.awt.Frame; +import java.io.IOException; +import java.net.MalformedURLException; +import java.text.MessageFormat; + +public class TeleportAction extends Action implements LoadedURLSelf, MainCallback, DialogReceiver { + private Point3 targetCoords = new Point3(); + private float targetRot = 0.0F; + private Point3 targetAxis = new Point3(0.0F, 0.0F, -1.0F); + private String targetRoomName = null; + private String targetDimension = null; + private URL targetWorldURL = null; + private boolean useDefCoordinates = false; + private boolean done = false; + private boolean showDialog = true; + private boolean forceWorldLoad = false; + private boolean forceNoWorldLoad = false; + private String targetURL; + private static TeleportAction activeTeleport = null; + private TeleportDialog dialog = null; + private TeleportStatus doneCallback; + String tempParseStr; + private static Object classCookie = new Object(); + + public TeleportAction() { + } + + @Override + public Persister trigger(Event e, Persister seqID) { + if (activeTeleport != this) { + this.targetURL = this.asURL(); + this.startTeleport(); + } + + return !this.done && activeTeleport != this ? this : null; + } + + public void stopLoading() { + this.done = true; + if (activeTeleport == this) { + this.stopTeleport(null); + } + } + + public static boolean isTeleporting() { + return activeTeleport != null; + } + + public static void teleport(String url, TeleportStatus callback) { + TeleportAction t = new TeleportAction(url, callback); + if (Main.isMainThread()) { + t.startTeleport(); + } else { + Main.register(t); + } + } + + public static void teleport(String url, TeleportStatus callback, boolean forceWorldLoad) { + TeleportAction t = new TeleportAction(url, callback); + t.forceWorldLoad = forceWorldLoad; + t.forceNoWorldLoad = !forceWorldLoad; + if (Main.isMainThread()) { + t.startTeleport(); + } else { + Main.register(t); + } + } + + public static void teleport(String url, TeleportStatus callback, boolean forceWorldLoad, boolean pShowDialog) { + TeleportAction t = new TeleportAction(url, callback); + t.showDialog = pShowDialog; + t.forceWorldLoad = forceWorldLoad; + t.forceNoWorldLoad = !forceWorldLoad; + if (Main.isMainThread()) { + t.startTeleport(); + } else { + Main.register(t); + } + } + + @Override + public void mainCallback() { + Main.unregister(this); + this.startTeleport(); + } + + public static String toURLString(String url) { + if (url == null || url.equals("world:")) { + url = WorldsMarkPart.getFirstSystemMarkURL(); + } + + if (url == null) { + url = "home:NewWorld.world"; + } + + if (url.startsWith("world:")) { + if (url.equals("world:restart")) { + url = IniFile.gamma().getIniString("RestartAt", WorldsMarkPart.getFirstSystemMarkURL()); + } else if (url.equals("world:store")) { + url = World.getHomeStore().getAbsolute(); + } else { + url = url.substring(6); + } + + int i = url.indexOf(".world?"); + if (i >= 0) { + url = url.substring(0, i) + ".world#" + url.substring(i + 7); + } + } + + if (url.indexOf(58) < 0) { + if (url.indexOf(47) < 0 && url.indexOf(92) < 0 && !url.endsWith(".world")) { + url = "home:" + url + "/" + url + ".world"; + } else { + url = "file:" + url; + } + } + + return url; + } + + private TeleportAction(String url, TeleportStatus callback) { + this.doneCallback = callback; + this.targetURL = toURLString(url); + url = this.setFromURL(this.targetURL); + + try { + if (this.targetURL.startsWith("http://")) { + this.targetWorldURL = new URL(url); + } else { + this.targetWorldURL = new URL(URL.getCurDir(), URL.maybeAddExt(url, ".world")); + } + } catch (MalformedURLException var4) { + this.targetWorldURL = URL.make("error:\"" + url + '"'); + } + } + + private float getNextFloat(float def) { + String s = this.tempParseStr; + int end = this.tempParseStr.indexOf(44); + if (end == -1) { + end = this.tempParseStr.length(); + this.tempParseStr = ""; + } else { + this.tempParseStr = this.tempParseStr.substring(end + 1); + } + + try { + return Float.valueOf(s.substring(0, end)); + } catch (NumberFormatException var5) { + return def; + } + } + + private String setFromURL(String url) { + this.useDefCoordinates = true; + int roomNameStart = url.lastIndexOf(35); + if (roomNameStart >= 0) { + String rest = url.substring(roomNameStart + 1); + url = url.substring(0, roomNameStart); + int roomNameEnd = rest.lastIndexOf(64); + if (roomNameEnd < 0) { + this.targetRoomName = rest; + } else { + this.useDefCoordinates = false; + this.targetRoomName = rest.substring(0, roomNameEnd); + this.tempParseStr = rest.substring(roomNameEnd + 1); + this.targetCoords.x = this.getNextFloat(this.targetCoords.x); + this.targetCoords.y = this.getNextFloat(this.targetCoords.y); + this.targetCoords.z = this.getNextFloat(this.targetCoords.z); + this.targetRot = this.getNextFloat(this.targetRot); + this.targetAxis.x = this.getNextFloat(this.targetAxis.x); + this.targetAxis.y = this.getNextFloat(this.targetAxis.y); + this.targetAxis.z = this.getNextFloat(this.targetAxis.z); + this.tempParseStr = null; + } + } + + if (this.targetRoomName != null) { + int rightAngle = this.targetRoomName.lastIndexOf(62); + int leftAngle = this.targetRoomName.lastIndexOf(60); + if (rightAngle + 1 == this.targetRoomName.length() && leftAngle >= 0) { + this.targetDimension = this.targetRoomName.substring(leftAngle + 1, rightAngle); + this.targetRoomName = this.targetRoomName.substring(0, leftAngle); + } + } + + return url; + } + + private void makeTeleportDialog(URL url) { + if (this.showDialog) { + Frame gf = Console.getFrame(); + if (gf != null && gf.isShowing()) { + this.dialog = new TeleportDialog(gf, this); + } + } + } + + private void startTeleport() { + if (activeTeleport != null) { + if (activeTeleport.doneCallback != null) { + activeTeleport.doneCallback.teleportStatus("overridden by new teleport", activeTeleport.targetURL); + } + + activeTeleport.stopTeleport(null); + } + + activeTeleport = this; + Console.setFreezeFrameEvents(true); + this.done = false; + Console.teleportNotification("", this.targetURL); + if (this.targetWorldURL != null) { + this.makeTeleportDialog(this.targetWorldURL); + World.load(this.targetWorldURL, this, this.forceWorldLoad); + } else { + Pilot pilot = Pilot.getActive(); + World w; + if (pilot != null && (w = pilot.getWorld()) != null) { + this.makeTeleportDialog(w.getSourceURL()); + this.loadedURLSelf(w, this.targetWorldURL, null); + } else { + this.stopTeleport("Pilot not in a room for intraworld teleport"); + } + } + } + + private Room stopTeleport(String err) { + assert this == activeTeleport; + + this.done = true; + activeTeleport = null; + Console.setFreezeFrameEvents(false); + if (this.doneCallback != null) { + this.doneCallback.teleportStatus(err, this.targetURL); + } + + if (err != null && !this.forceNoWorldLoad) { + Console.teleportNotification(err, this.targetURL); + Console.println(err); + } + + if (this.dialog != null) { + this.dialog.closeIt(true); + this.dialog = null; + } + + return null; + } + + @Override + public synchronized void dialogDone(Object who, boolean confirmed) { + if (activeTeleport != null) { + activeTeleport.stopTeleport(null); + } + } + + public static String getReadableNameOfWorld(URL url) { + String worldDir = url.getAbsolute(); + String readable = worldDir; + String packageName = null; + if (worldDir.startsWith("home:") && worldDir.length() > 6) { + readable = worldDir.substring(worldDir.charAt(5) == '/' ? 6 : 5); + int slash = readable.indexOf(47); + if (slash > 0) { + packageName = readable.substring(0, slash); + if (readable.regionMatches(true, slash + 1, readable, 0, slash)) { + readable = packageName; + String s = WorldsMarkPart.getExternalName(packageName); + if (s != null) { + readable = s; + } + } + } + + int tail = readable.indexOf(".world"); + if (tail > 0) { + readable = readable.substring(0, tail); + } + + readable = "the " + readable + " world"; + } + + return readable; + } + + public static String getPackageNameOfWorld(URL url) { + String worldDir = url.getAbsolute(); + String packageName = null; + if (worldDir.startsWith("home:") && worldDir.length() > 6) { + String readable = worldDir.substring(worldDir.charAt(5) == '/' ? 6 : 5); + int slash = readable.indexOf(47); + if (slash > 0) { + packageName = readable.substring(0, slash); + } + } + + return packageName; + } + + @Override + public void loadedURLSelf(URLSelf o, URL url, String err) { + if (activeTeleport != this) { + if (o != null) { + o.decRef(); + } + } else if (err == null && o instanceof World) { + String roomName = this.targetRoomName; + if (roomName == null) { + roomName = ((World)o).getDefaultRoomName(); + } + + Room room = ((World)o).getRoom(roomName); + if (room == null) { + this.stopTeleport("Error finding room " + this.targetRoomName); + } else if (room.getVIPOnly() && !((World)o).getConsole().getVIP()) { + this.stopTeleport("Only VIPs may go there."); + if (this.forceNoWorldLoad) { + Console.println(Console.message("Only-VIPs-there")); + } + } else { + Console.teleportNotification(null, this.targetURL); + Pilot pilot = Pilot.changeActiveRoom(room); + if (this.targetDimension != null) { + pilot.changeChannel(this.targetDimension); + } + + pilot.makeIdentity(); + if (this.useDefCoordinates) { + pilot.moveTo(room.getDefaultPosition()).spin(room.getDefaultOrientationAxis(), room.getDefaultOrientation()); + } else { + pilot.moveTo(this.targetCoords).spin(this.targetAxis, this.targetRot); + } + + this.stopTeleport(null); + } + } else { + if (err == null) { + err = "file " + url + " doesn't contain a World"; + o.decRef(); + } + + String readable = getReadableNameOfWorld(url); + String packageName = getPackageNameOfWorld(url); + Object[] arguments = new Object[]{new String(readable)}; + this.stopTeleport(MessageFormat.format(Console.message("cant-teleport"), arguments)); + if (packageName != null && !this.forceNoWorldLoad) { + NetUpdate.loadWorld(packageName, this.forceWorldLoad); + } + } + } + + @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 = Point3PropertyEditor.make(new Property(this, index, "X, Y, Z")); + } else if (mode == 1) { + ret = new Point3(this.targetCoords); + } else if (mode == 2) { + this.targetCoords.copy((Point3)value); + } + break; + case 1: + if (mode == 0) { + ret = FloatPropertyEditor.make(new Property(this, index, "Dir")); + } else if (mode == 1) { + ret = new Float(this.targetRot); + } else if (mode == 2) { + this.targetRot = (Float)value; + } + break; + case 2: + if (mode == 0) { + ret = StringPropertyEditor.make(new Property(this, index, "Room Name").allowSetNull()); + } else if (mode == 1) { + if (this.targetRoomName == null) { + ret = ""; + } else { + ret = new String(this.targetRoomName); + } + } else if (mode == 2) { + this.targetRoomName = (String)value; + this.stopLoading(); + } + break; + case 3: + if (mode == 0) { + ret = URLPropertyEditor.make(new Property(this, index, "World URL").allowSetNull(), "world"); + } else if (mode == 1) { + ret = this.targetWorldURL; + } else if (mode == 2) { + this.targetWorldURL = (URL)value; + this.stopLoading(); + } + break; + case 4: + if (mode == 0) { + ret = BooleanPropertyEditor.make(new Property(this, index, "Use default coordinates"), "No", "Yes"); + } else if (mode == 1) { + ret = new Boolean(this.useDefCoordinates); + } else if (mode == 2) { + this.useDefCoordinates = (Boolean)value; + } + break; + case 5: + if (mode == 0) { + ret = StringPropertyEditor.make(new Property(this, index, "Dimension Name").allowSetNull()); + } else if (mode == 1) { + if (this.targetDimension == null) { + ret = ""; + } else { + ret = new String(this.targetDimension); + } + } else if (mode == 2) { + this.targetDimension = (String)value; + if (this.targetDimension.equals("")) { + this.targetDimension = null; + } + + this.stopLoading(); + } + break; + case 6: + if (mode == 0) { + ret = BooleanPropertyEditor.make(new Property(this, index, "Show dialog"), "No", "Yes"); + } else if (mode == 1) { + ret = new Boolean(this.showDialog); + } else if (mode == 2) { + this.showDialog = (Boolean)value; + } + break; + default: + ret = super.properties(index, offset + 7, mode, value); + } + + return ret; + } + + @Override + public void saveState(Saver s) throws IOException { + s.saveVersion(3, classCookie); + super.saveState(s); + s.save(this.targetCoords); + s.saveFloat(this.targetRot); + s.save(this.targetAxis); + s.saveString(this.targetRoomName); + URL.save(s, this.targetWorldURL); + s.saveBoolean(this.useDefCoordinates); + s.saveString(this.targetDimension); + } + + @Override + public void restoreState(Restorer r) throws IOException, TooNewException { + int vers = r.restoreVersion(classCookie); + switch (vers) { + case 0: + super.restoreState(r); + this.targetCoords = (Point3)r.restore(); + this.targetRot = r.restoreInt(); + this.targetRoomName = r.restoreString(); + this.targetWorldURL = URL.restore(r, ".world"); + this.useDefCoordinates = r.restoreBoolean(); + this.targetDimension = null; + break; + case 1: + case 2: + super.restoreState(r); + this.targetCoords = (Point3)r.restore(); + this.targetRot = r.restoreFloat(); + this.targetAxis = (Point3)r.restore(); + this.targetRoomName = r.restoreString(); + this.targetWorldURL = URL.restore(r, ".world"); + this.useDefCoordinates = r.restoreBoolean(); + this.targetDimension = null; + break; + case 3: + super.restoreState(r); + this.targetCoords = (Point3)r.restore(); + this.targetRot = r.restoreFloat(); + this.targetAxis = (Point3)r.restore(); + this.targetRoomName = r.restoreString(); + this.targetWorldURL = URL.restore(r, ".world"); + this.useDefCoordinates = r.restoreBoolean(); + this.targetDimension = r.restoreString(); + break; + default: + throw new TooNewException(); + } + + if (vers < 2 && this.targetAxis.x == 0.0F && this.targetAxis.y == 0.0F && this.targetAxis.z == 1.0F) { + this.targetAxis.z = -1.0F; + this.targetRot = 360.0F - this.targetRot; + } + } + + @Override + public String toString() { + return super.toString() + "[" + this.asURL() + "]"; + } + + public String asURL() { + String url; + if (this.targetWorldURL != null) { + url = this.targetWorldURL.getRelativeTo(this) + "#"; + } else { + url = "#"; + } + + if (this.targetRoomName != null) { + url = url + this.targetRoomName; + } + + if (this.targetDimension != null) { + url = url + "<" + this.targetDimension + ">"; + } + + if (!this.useDefCoordinates) { + url = url + "@" + this.targetCoords + "," + this.targetRot; + if (this.targetAxis.x != 0.0F || this.targetAxis.y != 0.0F || this.targetAxis.z != 1.0F) { + url = url + "," + this.targetAxis; + } + } + + return url; + } +} |