summaryrefslogtreecommitdiff
path: root/NET/worlds/scape/TeleportAction.java
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-12 22:33:32 -0800
committerFuwn <[email protected]>2026-02-12 22:33:32 -0800
commitc7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch)
treedf9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape/TeleportAction.java
downloadworldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz
worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip
Initial commit
Diffstat (limited to 'NET/worlds/scape/TeleportAction.java')
-rw-r--r--NET/worlds/scape/TeleportAction.java539
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;
+ }
+}