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; } }