summaryrefslogtreecommitdiff
path: root/NET/worlds/network
diff options
context:
space:
mode:
Diffstat (limited to 'NET/worlds/network')
-rw-r--r--NET/worlds/network/AnonRoomServer.java78
-rw-r--r--NET/worlds/network/AnonUserServer.java75
-rw-r--r--NET/worlds/network/AutoServer.java85
-rw-r--r--NET/worlds/network/BuddyListNotifyCmd.java30
-rw-r--r--NET/worlds/network/BuddyListUpdateCmd.java32
-rw-r--r--NET/worlds/network/Cache.java385
-rw-r--r--NET/worlds/network/CacheEntry.java479
-rw-r--r--NET/worlds/network/CacheFile.java91
-rw-r--r--NET/worlds/network/ChannelCmd.java29
-rw-r--r--NET/worlds/network/ConnectionWaiter.java5
-rw-r--r--NET/worlds/network/DDEMLClass.java23
-rw-r--r--NET/worlds/network/DNSLookup.java132
-rw-r--r--NET/worlds/network/DirTimeStamp.java102
-rw-r--r--NET/worlds/network/ExceptionCmd.java26
-rw-r--r--NET/worlds/network/FilthFilter.java210
-rw-r--r--NET/worlds/network/FilthyPhrase.java80
-rw-r--r--NET/worlds/network/FingerReplyCmd.java29
-rw-r--r--NET/worlds/network/FingerReqCmd.java33
-rw-r--r--NET/worlds/network/Galaxy.java768
-rw-r--r--NET/worlds/network/IPhone.java121
-rw-r--r--NET/worlds/network/InfiniteWaitException.java12
-rw-r--r--NET/worlds/network/InvalidServerURLException.java12
-rw-r--r--NET/worlds/network/LoginMode.java9
-rw-r--r--NET/worlds/network/NetUpdate.java919
-rw-r--r--NET/worlds/network/NetworkMulti.java106
-rw-r--r--NET/worlds/network/NetworkNobody.java67
-rw-r--r--NET/worlds/network/NetworkObject.java19
-rw-r--r--NET/worlds/network/NetworkRoom.java483
-rw-r--r--NET/worlds/network/NewVersionDialog.java83
-rw-r--r--NET/worlds/network/ObjID.java66
-rw-r--r--NET/worlds/network/ObjectMgr.java70
-rw-r--r--NET/worlds/network/OldPropertyList.java75
-rw-r--r--NET/worlds/network/P17UserServer.java12
-rw-r--r--NET/worlds/network/PacketTooLargeException.java14
-rw-r--r--NET/worlds/network/ProgressBar.java78
-rw-r--r--NET/worlds/network/ProgressDialog.java223
-rw-r--r--NET/worlds/network/PropertyList.java84
-rw-r--r--NET/worlds/network/PropertySetCmd.java58
-rw-r--r--NET/worlds/network/PropertyUpdateCmd.java33
-rw-r--r--NET/worlds/network/RedirectCmd.java40
-rw-r--r--NET/worlds/network/RedirectIDCmd.java31
-rw-r--r--NET/worlds/network/RemoteFileConst.java7
-rw-r--r--NET/worlds/network/RoomMgr.java82
-rw-r--r--NET/worlds/network/RoomServer.java68
-rw-r--r--NET/worlds/network/SMState.java59
-rw-r--r--NET/worlds/network/ServerInputStream.java248
-rw-r--r--NET/worlds/network/ServerOutputStream.java97
-rw-r--r--NET/worlds/network/ServerTracker.java202
-rw-r--r--NET/worlds/network/ServerURL.java59
-rw-r--r--NET/worlds/network/SubscribeDistCmd.java32
-rw-r--r--NET/worlds/network/SubscribeRoomCmd.java42
-rw-r--r--NET/worlds/network/Timer.java21
-rw-r--r--NET/worlds/network/URL.java604
-rw-r--r--NET/worlds/network/UnsubscribeRoomCmd.java29
-rw-r--r--NET/worlds/network/UpgradeDialog.java246
-rw-r--r--NET/worlds/network/UserServer.java73
-rw-r--r--NET/worlds/network/VarErrorException.java171
-rw-r--r--NET/worlds/network/WSConnecting.java147
-rw-r--r--NET/worlds/network/WaitList.java48
-rw-r--r--NET/worlds/network/WorldServer.java1319
-rw-r--r--NET/worlds/network/appInitCmd.java37
-rw-r--r--NET/worlds/network/appearActorCmd.java42
-rw-r--r--NET/worlds/network/disappearActorCmd.java29
-rw-r--r--NET/worlds/network/longLocCmd.java65
-rw-r--r--NET/worlds/network/net2Property.java171
-rw-r--r--NET/worlds/network/netCmds.java68
-rw-r--r--NET/worlds/network/netConst.java94
-rw-r--r--NET/worlds/network/netData.java114
-rw-r--r--NET/worlds/network/netPacket.java58
-rw-r--r--NET/worlds/network/netPacketReader.java160
-rw-r--r--NET/worlds/network/netProperty.java50
-rw-r--r--NET/worlds/network/propCmd.java58
-rw-r--r--NET/worlds/network/propReqCmd.java50
-rw-r--r--NET/worlds/network/receivedNetPacket.java20
-rw-r--r--NET/worlds/network/regObjIDCmd.java29
-rw-r--r--NET/worlds/network/roomChangeCmd.java77
-rw-r--r--NET/worlds/network/roomIDCmd.java29
-rw-r--r--NET/worlds/network/roomIDReqCmd.java29
-rw-r--r--NET/worlds/network/sessionExitCmd.java37
-rw-r--r--NET/worlds/network/sessionInitCmd.java120
-rw-r--r--NET/worlds/network/shortLocCmd.java45
-rw-r--r--NET/worlds/network/teleportCmd.java103
-rw-r--r--NET/worlds/network/textCmd.java141
-rw-r--r--NET/worlds/network/whisperCmd.java66
84 files changed, 10553 insertions, 0 deletions
diff --git a/NET/worlds/network/AnonRoomServer.java b/NET/worlds/network/AnonRoomServer.java
new file mode 100644
index 0000000..8f0d302
--- /dev/null
+++ b/NET/worlds/network/AnonRoomServer.java
@@ -0,0 +1,78 @@
+package NET.worlds.network;
+
+import NET.worlds.core.IniFile;
+
+public class AnonRoomServer extends WorldServer {
+ protected sessionInitCmd buildSessionInitCmd() {
+ OldPropertyList props = new OldPropertyList();
+ String username = null;
+
+ assert this._galaxy.getLoginMode() != 1;
+
+ assert this._galaxy.getPassword() == null;
+
+ assert this._galaxy.getSerialNum() == null;
+
+ props.addProperty(new netProperty(3, String.valueOf(this.getVersion())));
+ props.addProperty(new netProperty(9, String.valueOf(this._clientVersion)));
+ this._firstLogon = this._galaxy.addPendingServer(this);
+
+ assert this._firstLogon;
+
+ int avatars = IniFile.gamma().getIniInt("avatars", 24);
+ props.addProperty(new netProperty(7, Integer.toString(avatars)));
+ switch (this._galaxy.getLoginMode()) {
+ case 2:
+ assert this._galaxy.getChatname() != null;
+
+ username = this._galaxy.getChatname();
+ this.regShortID(1, username);
+ props.addProperty(new netProperty(2, username));
+ break;
+ case 3:
+ assert this._galaxy.getGuestExpiration() != null;
+
+ props.addProperty(new netProperty(14, this._galaxy.getGuestExpiration()));
+ props.addProperty(new netProperty(12, "1"));
+ break;
+ default:
+ assert false;
+ }
+
+ if ((getDebugLevel() & 4) > 0) {
+ synchronized (System.out) {
+ System.out.println(this._serverURL.getHost() + ": sending AnonRoomServer sessionInit.");
+ if (this._firstLogon && this._galaxy.getLoginMode() == 3) {
+ System.out.println(" VAR_GUEST");
+ } else {
+ assert username != null;
+
+ System.out.println(" username = \"" + username + "\"");
+ }
+ }
+ }
+
+ return new sessionInitCmd(props);
+ }
+
+ @Override
+ protected void state_XMIT_SI() {
+ if (this._requestOffline) {
+ this._state.setState(17);
+ } else {
+ sessionInitCmd SI = this.buildSessionInitCmd();
+ if (SI != null) {
+ try {
+ this.sendNetMsg(SI);
+ } catch (PacketTooLargeException var3) {
+ assert false;
+ }
+
+ this._state.setState(8);
+ } else {
+ this._lastError = new VarErrorException(204);
+ this._state.setState(17);
+ }
+ }
+ }
+}
diff --git a/NET/worlds/network/AnonUserServer.java b/NET/worlds/network/AnonUserServer.java
new file mode 100644
index 0000000..7a3d42b
--- /dev/null
+++ b/NET/worlds/network/AnonUserServer.java
@@ -0,0 +1,75 @@
+package NET.worlds.network;
+
+public class AnonUserServer extends WorldServer {
+ protected sessionInitCmd buildSessionInitCmd() {
+ OldPropertyList props = new OldPropertyList();
+ props.addProperty(new netProperty(3, String.valueOf(this.getVersion())));
+ props.addProperty(new netProperty(9, String.valueOf(this._clientVersion)));
+ this._firstLogon = this._galaxy.addPendingServer(this);
+
+ assert this._firstLogon;
+
+ assert this._galaxy.getPassword() == null;
+
+ assert this._galaxy.getLoginMode() != 1;
+
+ assert this._galaxy.getLoginMode() != 4;
+
+ assert this._galaxy.getSerialNum() == null;
+
+ switch (this._galaxy.getLoginMode()) {
+ case 2:
+ assert this._galaxy.getChatname() != null;
+
+ this.regShortID(1, this._galaxy.getChatname());
+ props.addProperty(new netProperty(2, this._galaxy.getChatname()));
+ if (this._firstLogon) {
+ props.addProperty(new netProperty(12, "1"));
+ }
+ break;
+ case 3:
+ assert this._galaxy.getGuestExpiration() != null;
+
+ props.addProperty(new netProperty(14, this._galaxy.getGuestExpiration()));
+ if (this._firstLogon) {
+ props.addProperty(new netProperty(12, "1"));
+ }
+ break;
+ default:
+ assert false;
+ }
+
+ if ((getDebugLevel() & 4) > 0) {
+ synchronized (System.out) {
+ System.out.println(this._serverURL.getHost() + ": sending sessionInit.");
+ System.out.println(" username = \"" + this._galaxy.getChatname() + "\"");
+ if (this._galaxy.getPassword() != null) {
+ System.out.println(" password = " + this._galaxy.getPassword());
+ }
+
+ if (this._galaxy.getLoginMode() == 3) {
+ System.out.println(" VAR_GUEST");
+ }
+ }
+ }
+
+ return new sessionInitCmd(props);
+ }
+
+ @Override
+ protected void state_XMIT_SI() {
+ if (this._requestOffline) {
+ this._state.setState(17);
+ } else {
+ sessionInitCmd SI = this.buildSessionInitCmd();
+
+ try {
+ this.sendNetMsg(SI);
+ } catch (PacketTooLargeException var3) {
+ assert false;
+ }
+
+ this._state.setState(8);
+ }
+ }
+}
diff --git a/NET/worlds/network/AutoServer.java b/NET/worlds/network/AutoServer.java
new file mode 100644
index 0000000..e4f84cf
--- /dev/null
+++ b/NET/worlds/network/AutoServer.java
@@ -0,0 +1,85 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+
+public class AutoServer extends WorldServer {
+ private static int counter = 0;
+
+ public AutoServer() {
+ if (counter++ > 0) {
+ System.out.println("DEBUG: Created second AutoServer class.");
+ Galaxy.printDebugging();
+ new Exception().printStackTrace(System.out);
+ }
+ }
+
+ @Override
+ public synchronized void incRefCnt(Object referrer) {
+ super.incRefCnt(referrer);
+ this.startConnect();
+ }
+
+ protected void state_Authprompt() {
+ this._state.setState(3);
+ }
+
+ @Override
+ protected void state_XMIT_SI() {
+ WorldServer newServer = null;
+ int servType = this.getServerType();
+ if ((getDebugLevel() & 32) > 0) {
+ System.out.println(this + ": AutoServer detected server type " + servType);
+ }
+
+ switch (servType) {
+ case 1:
+ newServer = new UserServer();
+ break;
+ case 2:
+ newServer = new AnonUserServer();
+ break;
+ case 3:
+ Console.println(this + Console.message("Error-in-server"));
+ Console.println(this + Console.message("Error-user-server"));
+ newServer = null;
+ break;
+ case 4:
+ newServer = new AnonRoomServer();
+ break;
+ default:
+ assert false;
+ }
+
+ if (newServer != null) {
+ newServer.reuseConnection(this);
+ newServer.initInstance(this._galaxy, this._serverURL);
+ newServer.propertyUpdate(this._propList);
+ }
+
+ this._galaxy.killServer(this);
+ this._galaxy.swapServer(this, newServer);
+ this._galaxy.setGalaxyType(servType);
+ if (this._refCnt - this._tmpRefCnt != 0) {
+ System.out.println(this + ": bad reference counts. DEBUG INFO:");
+ System.out.println("\t_refCnt = " + this._refCnt);
+ System.out.println("\t_tmpRefCnt = " + this._tmpRefCnt);
+ this.printReferrers();
+ }
+
+ assert this._refCnt - this._tmpRefCnt == 0;
+
+ this._state.setState(17);
+ }
+
+ @Override
+ public String toString() {
+ return "AutoServer(" + super.toString() + ")";
+ }
+
+ @Override
+ void goOnline() {
+ super.goOnline();
+ System.out.println("DEBUG: AutoServer going online!");
+ new Exception().printStackTrace(System.out);
+ }
+}
diff --git a/NET/worlds/network/BuddyListNotifyCmd.java b/NET/worlds/network/BuddyListNotifyCmd.java
new file mode 100644
index 0000000..6fefa2c
--- /dev/null
+++ b/NET/worlds/network/BuddyListNotifyCmd.java
@@ -0,0 +1,30 @@
+package NET.worlds.network;
+
+import NET.worlds.console.FriendsListPart;
+import java.io.IOException;
+
+public class BuddyListNotifyCmd extends receivedNetPacket {
+ public static final byte BUDDYLISTNOTIFYCMD = 30;
+ protected String buddyName;
+ protected int loggedOn;
+
+ public BuddyListNotifyCmd() {
+ this._commandType = 30;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this.buddyName = data.readUTF();
+ this.loggedOn = data.readByte();
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ FriendsListPart.processBuddyListNotify(serv, this.buddyName, this.loggedOn);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "BUDDYLISTNOTIFY " + this.buddyName + " " + this.loggedOn;
+ }
+}
diff --git a/NET/worlds/network/BuddyListUpdateCmd.java b/NET/worlds/network/BuddyListUpdateCmd.java
new file mode 100644
index 0000000..43cd3e2
--- /dev/null
+++ b/NET/worlds/network/BuddyListUpdateCmd.java
@@ -0,0 +1,32 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class BuddyListUpdateCmd extends netPacket {
+ public static final byte BUDDYLISTUPDATECMD = 29;
+ private String buddy;
+ private int add;
+
+ public BuddyListUpdateCmd(String buddy, int add) {
+ super(null, 29);
+ this.buddy = buddy;
+ this.add = add;
+ }
+
+ @Override
+ int packetSize() {
+ return super.packetSize() + ServerOutputStream.utfLength(this.buddy) + 2;
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeUTF(this.buddy);
+ o.writeByte(this.add);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "BUDDYLISTUPDATE " + this.buddy + " " + this.add;
+ }
+}
diff --git a/NET/worlds/network/Cache.java b/NET/worlds/network/Cache.java
new file mode 100644
index 0000000..aaf748d
--- /dev/null
+++ b/NET/worlds/network/Cache.java
@@ -0,0 +1,385 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Gamma;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.Std;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class Cache implements MainCallback, MainTerminalCallback, Serializable {
+ private static final long serialVersionUID = -7557149391688293661L;
+ private static final long CACHE_VERSION = 0L;
+ private static String CACHE_DIR = Gamma.earlyURLUnalias("home:cachedir/").replace('/', '\\');
+ static final int CACHE_MIN_CHANGE = IniFile.gamma().getIniInt("NetCacheMinChange", 50);
+ static final long CACHE_MAX_DELAY = IniFile.gamma().getIniInt("NetCacheMaxDelay", 5) * 1000L * 60L;
+ private Date lastCacheSave = new Date();
+ static transient Cache cache = initLoad();
+ private transient Hashtable<Object, CacheEntry> table = new Hashtable<Object, CacheEntry>();
+ private transient CacheEntry terminator = new CacheEntry();
+ transient long totalBytes;
+ transient int hasChanged;
+ private int nextAvailable = 1;
+
+ public static void ClearCustomAvatars() {
+ Collection<CacheEntry> c = cache.table.values();
+ Iterator<CacheEntry> it = c.iterator();
+ Vector<CacheEntry> tmp = new Vector<CacheEntry>();
+
+ while (it.hasNext()) {
+ CacheEntry ce = it.next();
+ if (ce != null && ce.url.toString().contains("custom")) {
+ tmp.add(ce);
+ }
+ }
+
+ for (int i = 0; i < tmp.size(); i++) {
+ removeEntry(tmp.get(i));
+ }
+ }
+
+ static Cache initLoad() {
+ System.out.println("Initializing cache...");
+ Cache c = new Cache();
+ FileInputStream in = null;
+ ObjectInputStream s = null;
+
+ try {
+ System.out.println("Restoring cache...");
+ File fi = new File(CACHE_DIR + "cache.index");
+ if (!fi.exists()) {
+ fi = new File(CACHE_DIR + "cache.index.new");
+ if (!fi.exists()) {
+ fi = new File(CACHE_DIR + "cache.index.old");
+ }
+ }
+
+ in = new FileInputStream(fi);
+ s = new ObjectInputStream(in);
+ long version = s.readLong();
+ if (version != 0L) {
+ throw new Exception("Wrong version of cache.index");
+ }
+
+ c = (Cache)s.readObject();
+ c.terminator = new CacheEntry();
+ c.table = new Hashtable<Object, CacheEntry>();
+
+ Object obj;
+ while ((obj = s.readObject()) != null && obj instanceof CacheEntry) {
+ if (((CacheEntry)obj).url != null && ((CacheEntry)obj).localName != null && ((CacheEntry)obj).state >= 7) {
+ c.add((CacheEntry)obj);
+ }
+ }
+
+ s.close();
+ s = null;
+ in.close();
+ in = null;
+ System.out.println("Marking cache as closed...");
+ } catch (OptionalDataException var22) {
+ } catch (Exception var23) {
+ System.out.println(var23);
+ System.out.println("Flushing cache index.");
+ File findex = new File(CACHE_DIR + "cache.index");
+ findex.mkdirs();
+ findex.delete();
+ } finally {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (Exception var21) {
+ }
+
+ ObjectInputStream var26 = null;
+ }
+
+ if (in != null) {
+ try {
+ in.close();
+ } catch (Exception var20) {
+ }
+
+ FileInputStream var25 = null;
+ }
+ }
+
+ String[] names = new File(CACHE_DIR).list();
+ Hashtable<String, String> files = new Hashtable<String, String>();
+ if (names != null) {
+ for (int i = 0; i < names.length; i++) {
+ files.put((CACHE_DIR + names[i]).toUpperCase(), "");
+ }
+
+ files.remove((CACHE_DIR + "cache.index").toUpperCase());
+ }
+
+ c.totalBytes = 0L;
+ c.hasChanged = 0;
+ CacheEntry p = c.terminator.next;
+
+ while (p != c.terminator) {
+ CacheEntry e = p;
+ p = p.next;
+ String name = e.localName.toUpperCase();
+ boolean isFile = files.get(name) != null;
+ files.remove(name);
+ c.totalBytes = c.totalBytes + e.bytes;
+ if (!e.done() || !isFile) {
+ c.remove(e);
+ if (isFile) {
+ new File(name).delete();
+ }
+ }
+ }
+
+ Enumeration<String> e = files.keys();
+
+ while (e.hasMoreElements()) {
+ new File(e.nextElement()).delete();
+ }
+
+ File f = new File("./avatars.zip");
+ if (f.exists()) {
+ cache = c;
+ InjectZipFile(f, "rel:avatar:");
+ }
+
+ c.lastCacheSave = new Date();
+ Main.register(c);
+ return c;
+ }
+
+ public static CacheFile getFile(URL url, boolean forceRecheck) {
+ return cache.getAFile(url, forceRecheck);
+ }
+
+ public static CacheFile getFile(URL url) {
+ return cache.getAFile(url, false);
+ }
+
+ public static CacheFile getFile(String url) {
+ return cache.getAFile(URL.make(url), false);
+ }
+
+ public static CacheEntry getEntry(URL url) {
+ return cache.get(url);
+ }
+
+ public static void removeEntry(CacheEntry ce) {
+ cache.remove(ce);
+ }
+
+ public static void InjectZipFile(File zipFile, String urlPrefix) {
+ long timeStamp = zipFile.lastModified();
+
+ try {
+ ZipFile zf = new ZipFile(zipFile);
+ System.out.println("Adding " + zf.size() + " entries from " + zipFile);
+ Enumeration<?> e = zf.entries();
+
+ while (e.hasMoreElements()) {
+ ZipEntry ze = (ZipEntry)e.nextElement();
+ InputStream is = zf.getInputStream(ze);
+ URL remoteName = URL.make(urlPrefix + ze.getName());
+ CacheEntry ce = cache.get(remoteName);
+ if (ce == null) {
+ String localName = assignLocalName(remoteName);
+ FileOutputStream fos = new FileOutputStream(localName);
+ byte[] buffer = new byte[4096];
+
+ while (true) {
+ try {
+ int bytesRead = is.read(buffer);
+ if (bytesRead == -1) {
+ break;
+ }
+
+ fos.write(buffer, 0, bytesRead);
+ } catch (IOException var14) {
+ break;
+ }
+ }
+
+ fos.close();
+ ce = new CacheEntry();
+ ce.localName = new String(localName);
+ ce.url = remoteName;
+ ce.state = 4;
+ ce.remoteTime = timeStamp;
+ ce.checkTime = new Date();
+ cache.add(ce);
+ }
+
+ is.close();
+ }
+
+ zf.close();
+ } catch (Exception var15) {
+ System.out.println("Error processing cache zip file: " + var15);
+ }
+ }
+
+ private synchronized CacheFile getAFile(URL url, boolean forceRecheck) {
+ CacheEntry e = null;
+ if (url.isRemote()) {
+ e = cache.get(url);
+ if (e == null) {
+ e = new CacheEntry(url);
+ cache.add(e);
+ } else if (forceRecheck) {
+ e.forceRecheck();
+ }
+ }
+
+ return new CacheFile(url, e);
+ }
+
+ private Cache() {
+ }
+
+ @Override
+ public void mainCallback() {
+ }
+
+ public synchronized void resyncIndex() {
+ if (this.hasChanged >= CACHE_MIN_CHANGE || this.lastCacheSave.before(new Date(new Date().getTime() - CACHE_MAX_DELAY))) {
+ this.saveIndex();
+ System.gc();
+ }
+ }
+
+ public void saveIndex() {
+ try {
+ System.out.println("Marking cache as open...");
+ File fin = new File(CACHE_DIR + "cache.index.new");
+ FileOutputStream o = new FileOutputStream(fin);
+ ObjectOutputStream s = new ObjectOutputStream(o);
+ s.writeLong(0L);
+ s.writeObject(this);
+
+ for (CacheEntry e = this.terminator.next; e != this.terminator; e = e.next) {
+ if (e.url != null && e.localName != null) {
+ s.writeObject(e);
+ }
+ }
+
+ s.writeInt(0);
+ s.flush();
+ s.close();
+ o.close();
+ this.lastCacheSave = new Date();
+ this.hasChanged = 0;
+ System.out.println("Marking cache as closed...");
+ File fi = new File(CACHE_DIR + "cache.index");
+ File fio = new File(CACHE_DIR + "cache.index.old");
+ fi.renameTo(fio);
+ fin.renameTo(fi);
+ fio.delete();
+ } catch (Exception var6) {
+ System.out.println("Error writing cache index: " + var6);
+ }
+ }
+
+ @Override
+ public void terminalCallback() {
+ Main.unregister(this);
+ this.saveIndex();
+ }
+
+ static String assignLocalName(URL url) {
+ String remoteName = url.unalias();
+ String ext = ".temp";
+ int lastDot = remoteName.lastIndexOf(46);
+ if (lastDot > remoteName.lastIndexOf(47) && remoteName.indexOf("?", lastDot) < 0 && remoteName.indexOf("#", lastDot) < 0) {
+ ext = remoteName.substring(lastDot);
+ }
+
+ return url.endsWith(".gr2") ? CACHE_DIR + url.getBase() : CACHE_DIR + Integer.toString(cache.nextAvailable++, 36) + ext;
+ }
+
+ public synchronized void add(CacheEntry e) {
+ this.table.put(e.url, e);
+ CacheEntry p = this.terminator.prev;
+ p.next = e;
+ e.prev = p;
+ e.next = this.terminator;
+ this.terminator.prev = e;
+ this.hasChanged++;
+ }
+
+ public int numEntries() {
+ return this.table.size();
+ }
+
+ public synchronized CacheEntry get(URL url) {
+ CacheEntry e = this.table.get(url);
+ if (e != null) {
+ this.markUsed(e);
+ }
+
+ return e;
+ }
+
+ private void markUsed(CacheEntry e) {
+ if (e != null && e.next != this.terminator) {
+ e.prev.next = e.next;
+ e.next.prev = e.prev;
+ this.terminator.prev.next = e;
+ e.prev = this.terminator.prev;
+ e.next = this.terminator;
+ this.terminator.prev = e;
+ }
+ }
+
+ public void remove(CacheEntry e) {
+ this.totalBytes = this.totalBytes - e.bytes;
+ e.prev.next = e.next;
+ e.next.prev = e.prev;
+ e.prev = null;
+ e.next = null;
+ this.table.remove(e.url);
+ this.hasChanged++;
+ new File(e.localName.toUpperCase()).delete();
+ }
+
+ private CacheEntry freeLRU() {
+ for (CacheEntry e = this.terminator.next; e != this.terminator; e = e.next) {
+ if (!e.inUse()) {
+ this.remove(e);
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ public synchronized void makeSpaceFor(int incomingSize) {
+ while (cache.numEntries() > CacheEntry.CACHE_MAX_ENTRIES && this.freeLRU() != null) {
+ }
+
+ while ((this.totalBytes + 2L * incomingSize) / 1024L > Std.GetDiskFreeSpace() && Std.GetDiskFreeSpace() > -1L) {
+ CacheEntry freed = this.freeLRU();
+ if (freed == null) {
+ break;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/network/CacheEntry.java b/NET/worlds/network/CacheEntry.java
new file mode 100644
index 0000000..b7675b4
--- /dev/null
+++ b/NET/worlds/network/CacheEntry.java
@@ -0,0 +1,479 @@
+package NET.worlds.network;
+
+import NET.worlds.core.IniFile;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.util.Date;
+import java.util.Observer;
+import java.util.Vector;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+public class CacheEntry implements Runnable, Serializable {
+ private static final long serialVersionUID = 4845526825815464122L;
+ static boolean httpFaulted = IniFile.override().getIniInt("Offline", 0) == 1 || IniFile.gamma().getIniInt("Offline", 0) == 1;
+ static boolean stopOnFault = IniFile.gamma().getIniInt("StopOnHttpFault", 0) == 1;
+ static final int CACHE_MAX_ENTRIES = IniFile.gamma().getIniInt("NetCacheEntries", 1000);
+ static final int MAX_THREADS = IniFile.gamma().getIniInt("NetCacheThreads", 2);
+ static final long CACHE_MOD_TIMEOUT = 3600000L * IniFile.gamma().getIniInt("NetCacheModifiedCheck", 8);
+ static final long CACHE_MOD_TIMEDELAY = 60000L * IniFile.gamma().getIniInt("NetCacheDelay", 5);
+ static final Date refreshStartDate = new Date(new Date().getTime() + CACHE_MOD_TIMEDELAY);
+ static Vector<CacheEntry> threadQueue = new Vector<CacheEntry>();
+ public static final int START = 0;
+ public static final int REFRESHING = 2;
+ public static final int LOADING = 3;
+ public static final int DONE = 4;
+ public static final int ERROR = 5;
+ public static final int NOSUCHFILE = 6;
+ public static final int LOADED = 7;
+ public transient CacheEntry next;
+ public transient CacheEntry prev;
+ int state;
+ private transient int count;
+ URL url;
+ transient int lastRefTime;
+ transient String encoding;
+ String localName;
+ transient Vector<Observer> observers;
+ public long remoteTime = 0L;
+ public Date checkTime;
+ public int netSize = -1;
+ public int bytes;
+ private transient CacheEntry nextDec;
+ private static CacheEntry endDec = new CacheEntry();
+ private static CacheEntry baseDec = endDec;
+ static int refTime = 0;
+ static int numActiveThreads = 0;
+ private static Object finalizeSafeLock = new Object();
+ private static int nextDownloader = 0;
+
+ public static int getConcurrentDownloads() {
+ return numActiveThreads;
+ }
+
+ public static synchronized void setOffline() {
+ httpFaulted = true;
+ stopOnFault = true;
+ }
+
+ public static boolean getOffline() {
+ return httpFaulted;
+ }
+
+ public boolean inUse() {
+ return this.count > 0 || this.state == 3 || this.state == 2;
+ }
+
+ private synchronized void setState(int val) {
+ this.state = val;
+ if (val >= 4) {
+ this.notifyAll();
+ }
+ }
+
+ boolean done() {
+ return this.state >= 4;
+ }
+
+ CacheEntry() {
+ this.next = this;
+ this.prev = this;
+ }
+
+ CacheEntry(URL u) {
+ this.url = u;
+ this.localName = Cache.assignLocalName(u);
+ this.setState(0);
+ }
+
+ public void incRef() {
+ synchronized (finalizeSafeLock) {
+ this.count++;
+ }
+
+ if (this.count == 1) {
+ this.load();
+ }
+ }
+
+ void safeDecRef() {
+ synchronized (finalizeSafeLock) {
+ if (this.nextDec == null) {
+ this.nextDec = baseDec;
+ baseDec = this;
+ } else {
+ this.count--;
+ this.lastRefTime = refTime++;
+ }
+ }
+ }
+
+ synchronized void fullDecRef() {
+ this.notifyAll();
+ synchronized (Cache.cache) {
+ synchronized (finalizeSafeLock) {
+ this.count--;
+ this.lastRefTime = refTime++;
+ }
+
+ if (this.count == 0 && this.remoteTime <= 0L && this.state == 7) {
+ Cache.cache.remove(this);
+ }
+ }
+ }
+
+ void addObserver(Observer o) {
+ if (this.state >= 4) {
+ o.update(null, this.url);
+ } else {
+ synchronized (this) {
+ if (this.observers == null) {
+ this.observers = new Vector<Observer>();
+ }
+
+ this.observers.addElement(o);
+ }
+ }
+ }
+
+ void notifyObservers() {
+ Vector<Observer> v;
+ synchronized (this) {
+ v = this.observers;
+ this.observers = null;
+ }
+
+ if (v != null) {
+ int len = v.size();
+
+ for (int i = 0; i < len; i++) {
+ v.elementAt(i).update(null, this.url);
+ }
+ }
+ }
+
+ URLConnection openURL() throws Exception {
+ int retryCount = IniFile.gamma().getIniInt("NetCacheRetries", 8);
+ java.net.URL u = null;
+ URLConnection uc = null;
+
+ while (!httpFaulted) {
+ try {
+ if (u == null) {
+ String us = this.url.unalias();
+ if (us.endsWith("upgrades.lst")) {
+ us = us + "?" + (int)(Math.random() * 1000000.0);
+ }
+
+ u = DNSLookup.lookup(new java.net.URL(us));
+ }
+
+ uc = u.openConnection();
+ uc.setRequestProperty("Accept-Encoding", "gzip,deflate");
+ if (this.remoteTime > 0L && this.bytes > 0) {
+ uc.setIfModifiedSince(this.remoteTime);
+ }
+
+ uc.connect();
+ this.encoding = uc.getContentEncoding();
+ if (this.encoding == null) {
+ this.encoding = new String("none");
+ }
+
+ this.remoteTime = uc.getLastModified();
+ this.netSize = uc.getContentLength();
+ return uc;
+ } catch (UnknownHostException var5) {
+ if (NetUpdate.isInternalVersion() || stopOnFault) {
+ httpFaulted = true;
+ }
+
+ throw var5;
+ } catch (IOException var6) {
+ retryCount--;
+ if (wasHttpNoSuchFile(var6, uc)) {
+ throw new FileNotFoundException("Http " + this.url);
+ }
+
+ if (retryCount <= 0 || var6 instanceof MalformedURLException) {
+ throw var6;
+ }
+
+ if (this.state == 2) {
+ throw var6;
+ }
+
+ System.out.println("Exception " + var6 + " opening " + this.url + ", retrying...");
+ }
+ }
+
+ throw new FileNotFoundException("Http " + this.url);
+ }
+
+ private static boolean wasHttpNoSuchFile(Exception e, URLConnection uc) {
+ try {
+ if (((HttpURLConnection)uc).getResponseCode() == 404) {
+ return true;
+ }
+ } catch (Exception var3) {
+ }
+
+ return false;
+ }
+
+ public void forceRecheck() {
+ this.checkTime = null;
+ }
+
+ public void load() {
+ if (this.state != 2 && this.state != 3) {
+ Date now = new Date();
+ if (this.state == 5 || this.state == 0) {
+ this.setState(3);
+ } else if (this.localName != null) {
+ if (this.checkTime != null && now.before(refreshStartDate)) {
+ this.notifyObservers();
+ return;
+ }
+
+ Date aWhileAgo = new Date(now.getTime() - CACHE_MOD_TIMEOUT);
+ if (this.checkTime != null && this.checkTime.after(aWhileAgo) && (this.remoteTime > 0L || this.state == 6)) {
+ this.notifyObservers();
+ return;
+ }
+
+ this.setState(2);
+ }
+
+ this.checkTime = now;
+ synchronized (threadQueue) {
+ if (numActiveThreads < MAX_THREADS) {
+ this.startThread();
+ } else {
+ threadQueue.addElement(this);
+ }
+ }
+ }
+ }
+
+ private void startThread() {
+ numActiveThreads++;
+ Thread t = new Thread(this, "File Downloader " + ++nextDownloader);
+ t.setDaemon(true);
+ t.start();
+ }
+
+ @Override
+ public void run() {
+ InputStream in = null;
+ FileOutputStream out = null;
+ URLConnection uc = null;
+
+ try {
+ try {
+ long oldRemoteTime = this.remoteTime;
+ int oldsize = this.netSize;
+ int oldbytes = this.bytes;
+ if (this.state == 2) {
+ if (getOffline()) {
+ this.setState(7);
+ return;
+ }
+
+ long dirTime = DirTimeStamp.request(this.url);
+ if (dirTime > 0L && dirTime <= oldRemoteTime && new Date().getTime() < oldRemoteTime) {
+ this.setState(7);
+ this.finishedLoad();
+ return;
+ }
+
+ uc = this.openURL();
+ if (this.remoteTime > 0L
+ && this.remoteTime <= oldRemoteTime
+ && (oldsize == -1 || this.netSize == -1 || oldsize == this.netSize || this.netSize == oldbytes)) {
+ in = uc.getInputStream();
+ if (in != null) {
+ in.close();
+ }
+
+ this.setState(7);
+ this.finishedLoad();
+ return;
+ }
+
+ if (uc instanceof HttpURLConnection) {
+ int responseCode = ((HttpURLConnection)uc).getResponseCode();
+ boolean keep = false;
+ switch (responseCode) {
+ case 304:
+ case 400:
+ case 500:
+ case 502:
+ case 503:
+ case 504:
+ keep = true;
+ }
+
+ if (keep) {
+ in = uc.getInputStream();
+ if (in != null) {
+ in.close();
+ }
+
+ this.setState(7);
+ this.finishedLoad();
+ return;
+ }
+ }
+
+ this.setState(3);
+ }
+
+ Cache.cache.totalBytes = Cache.cache.totalBytes - this.bytes;
+
+ int tries;
+ for (tries = 0; tries < 2; tries++) {
+ this.bytes = 0;
+ in = null;
+ out = null;
+ if (uc == null) {
+ uc = this.openURL();
+ uc.connect();
+ }
+
+ if (uc instanceof HttpURLConnection) {
+ int responseCode = ((HttpURLConnection)uc).getResponseCode();
+ boolean keep = false;
+ switch (responseCode) {
+ case 304:
+ case 500:
+ case 502:
+ case 503:
+ case 504:
+ keep = true;
+ }
+
+ if (keep) {
+ in = uc.getInputStream();
+ if (in != null) {
+ in.close();
+ }
+
+ this.bytes = oldbytes;
+ Cache.cache.totalBytes = Cache.cache.totalBytes + this.bytes;
+ this.netSize = oldsize;
+ this.setState(7);
+ this.finishedLoad();
+ return;
+ }
+ }
+
+ if (this.encoding != null && this.encoding.equalsIgnoreCase("gzip")) {
+ in = new GZIPInputStream(uc.getInputStream());
+ } else if (this.encoding != null && this.encoding.equalsIgnoreCase("deflate")) {
+ in = new InflaterInputStream(uc.getInputStream(), new Inflater(true));
+ } else {
+ in = uc.getInputStream();
+ }
+
+ Cache.cache.makeSpaceFor(this.netSize);
+ out = new FileOutputStream(this.localName);
+ byte[] buf = new byte[4096];
+
+ int count;
+ while ((count = in.read(buf)) > 0) {
+ out.write(buf, 0, count);
+ this.bytes += count;
+ }
+
+ in.close();
+ in = null;
+ out.close();
+ out = null;
+ if (this.netSize == -1 || this.bytes >= this.netSize || this.encoding.equalsIgnoreCase("gzip") || this.encoding.equalsIgnoreCase("deflate")) {
+ this.setState(7);
+ break;
+ }
+
+ if (tries == 0) {
+ System.out.println("Network error while downloading, trying again...");
+ }
+
+ uc = null;
+ }
+
+ if (this.netSize >= 0 && this.bytes < this.netSize && !this.encoding.equalsIgnoreCase("gzip") && !this.encoding.equalsIgnoreCase("deflate")) {
+ throw new InterruptedException("Network error, got " + this.bytes + " rather than " + this.netSize + " bytes.");
+ }
+
+ if (tries > 0) {
+ System.out.println("Second download attempt succeeded.");
+ }
+
+ Cache.cache.hasChanged++;
+ this.setState(7);
+ } catch (Exception var17) {
+ System.out.println("Download error for " + this.url);
+ System.out.println("\t" + var17.getMessage());
+ System.out.println("\t" + var17.toString());
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException var16) {
+ }
+
+ new File(this.localName).delete();
+ }
+
+ if (wasHttpNoSuchFile(var17, uc) || var17 instanceof FileNotFoundException) {
+ this.setState(6);
+ this.bytes = 0;
+ return;
+ } else {
+ if (this.state == 2) {
+ Cache.cache.hasChanged++;
+ this.setState(7);
+ } else {
+ this.bytes = 0;
+ this.setState(5);
+ }
+
+ return;
+ }
+ }
+ } finally {
+ Cache.cache.totalBytes = Cache.cache.totalBytes + this.bytes;
+ if (this.netSize <= 0) {
+ this.netSize = this.bytes;
+ }
+
+ this.finishedLoad();
+ }
+ }
+
+ private void finishedLoad() {
+ this.notifyObservers();
+ synchronized (threadQueue) {
+ numActiveThreads--;
+
+ while (numActiveThreads < MAX_THREADS && !threadQueue.isEmpty()) {
+ CacheEntry eNext = threadQueue.elementAt(0);
+ threadQueue.removeElementAt(0);
+ eNext.startThread();
+ }
+ }
+
+ if (numActiveThreads <= 0 && threadQueue.isEmpty()) {
+ Cache.cache.resyncIndex();
+ }
+ }
+}
diff --git a/NET/worlds/network/CacheFile.java b/NET/worlds/network/CacheFile.java
new file mode 100644
index 0000000..abafa53
--- /dev/null
+++ b/NET/worlds/network/CacheFile.java
@@ -0,0 +1,91 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Cursor;
+import java.util.Observer;
+
+public class CacheFile {
+ private URL url;
+ private CacheEntry entry;
+ private boolean active;
+
+ CacheFile(URL u, CacheEntry e) {
+ this.url = u;
+ this.active = true;
+ this.entry = e;
+ if (e != null) {
+ e.incRef();
+ }
+ }
+
+ @Override
+ public void finalize() {
+ if (this.active) {
+ this.active = false;
+ if (this.entry != null) {
+ this.entry.safeDecRef();
+ }
+ }
+ }
+
+ public synchronized void close() {
+ this.finalize();
+ }
+
+ public synchronized void markTemporary() {
+ if (this.entry != null) {
+ this.entry.remoteTime = 0L;
+ }
+ }
+
+ public boolean isActive() {
+ return this.active;
+ }
+
+ public void callWhenLoaded(Observer o) {
+ if (this.entry == null) {
+ o.update(null, this.url);
+ } else {
+ this.entry.addObserver(o);
+ }
+ }
+
+ public void waitUntilLoaded() {
+ if (this.entry != null) {
+ synchronized (this.entry) {
+ Cursor c = Cursor.getActive();
+ if (c == null) {
+ c = new Cursor(URL.make("system:WAIT_CURSOR"));
+ c.activate();
+ }
+
+ URL oldCursor = c.getURL();
+ c.setURL(URL.make("system:WAIT_CURSOR"));
+
+ while (this.active && !this.done()) {
+ try {
+ this.entry.wait();
+ } catch (InterruptedException var5) {
+ }
+ }
+
+ c.setURL(oldCursor);
+ }
+ }
+ }
+
+ public boolean error() {
+ return this.entry == null ? false : this.entry.state == 5 || this.entry.state == 6;
+ }
+
+ public boolean done() {
+ return this.entry == null ? true : this.entry.done();
+ }
+
+ public String getLocalName() {
+ return this.entry != null ? this.entry.localName : this.url.unalias();
+ }
+
+ public int bytesLoaded() {
+ return this.entry.bytes;
+ }
+}
diff --git a/NET/worlds/network/ChannelCmd.java b/NET/worlds/network/ChannelCmd.java
new file mode 100644
index 0000000..dd4ed51
--- /dev/null
+++ b/NET/worlds/network/ChannelCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class ChannelCmd extends netPacket {
+ public static final byte CHANNELCMD = 31;
+ protected String _channel;
+
+ public ChannelCmd(String channel) {
+ super(null, 31);
+ this._channel = channel;
+ }
+
+ @Override
+ int packetSize() {
+ return 1 + ServerOutputStream.utfLength(this._channel) + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeUTF(this._channel);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "CHANNEL " + this._channel;
+ }
+}
diff --git a/NET/worlds/network/ConnectionWaiter.java b/NET/worlds/network/ConnectionWaiter.java
new file mode 100644
index 0000000..d3c9419
--- /dev/null
+++ b/NET/worlds/network/ConnectionWaiter.java
@@ -0,0 +1,5 @@
+package NET.worlds.network;
+
+public interface ConnectionWaiter {
+ void connectionCallback(Object var1, boolean var2);
+}
diff --git a/NET/worlds/network/DDEMLClass.java b/NET/worlds/network/DDEMLClass.java
new file mode 100644
index 0000000..eaa0661
--- /dev/null
+++ b/NET/worlds/network/DDEMLClass.java
@@ -0,0 +1,23 @@
+package NET.worlds.network;
+
+public class DDEMLClass {
+ private int DDEMLptr = 0;
+
+ static {
+ nativeInit();
+ }
+
+ public static native void nativeInit();
+
+ public DDEMLClass(String service, String topic) {
+ this.create(service, topic);
+ }
+
+ private native boolean create(String var1, String var2);
+
+ public native void destroy();
+
+ public native boolean Request(String var1);
+
+ public native boolean Poke(String var1, String var2);
+}
diff --git a/NET/worlds/network/DNSLookup.java b/NET/worlds/network/DNSLookup.java
new file mode 100644
index 0000000..878c63d
--- /dev/null
+++ b/NET/worlds/network/DNSLookup.java
@@ -0,0 +1,132 @@
+package NET.worlds.network;
+
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+public class DNSLookup implements Runnable {
+ private static final int defaultTimeout = 30;
+ private static Hashtable<String, String[]> cache = new Hashtable<String, String[]>();
+ private String hostName;
+ private String[] dottedNames;
+ private int timeout;
+
+ public static java.net.URL lookup(java.net.URL url) throws MalformedURLException, UnknownHostException {
+ return lookup(url, 30);
+ }
+
+ public static java.net.URL lookupAll(java.net.URL url) throws MalformedURLException, UnknownHostException {
+ return lookupAll(url, 30);
+ }
+
+ public static java.net.URL lookup(java.net.URL url, int timeout) throws MalformedURLException, UnknownHostException {
+ String hostName = url.getHost();
+ return hostName == null ? url : new java.net.URL(url.getProtocol(), hostName, url.getPort(), url.getFile());
+ }
+
+ public static java.net.URL lookupAll(java.net.URL url, int timeout) throws MalformedURLException, UnknownHostException {
+ String hostName = url.getHost();
+ if (hostName == null) {
+ return url;
+ } else {
+ String[] addresses = lookupAll(hostName, timeout);
+ String hosts = "";
+
+ for (int i = 0; i < addresses.length; i++) {
+ if (i != 0) {
+ hosts = hosts + ";";
+ }
+
+ hosts = hosts + addresses[i];
+ }
+
+ return new java.net.URL(url.getProtocol(), hosts, url.getPort(), url.getFile());
+ }
+ }
+
+ public static String lookup(String hostName) throws UnknownHostException {
+ return lookup(hostName, 30);
+ }
+
+ public static String lookup(String hostName, int timeout) throws UnknownHostException {
+ return isDotted(hostName) ? hostName : lookupAllCommon(hostName, timeout)[0];
+ }
+
+ public static String[] lookupAll(String hostName) throws UnknownHostException {
+ return lookupAll(hostName, 30);
+ }
+
+ public static String[] lookupAll(String hostName, int timeout) throws UnknownHostException {
+ return isDotted(hostName) ? new String[]{hostName} : lookupAllCommon(hostName, timeout);
+ }
+
+ private static String[] lookupAllCommon(String hostName, int timeout) throws UnknownHostException {
+ String[] dotted = cache.get(hostName);
+ if (dotted == null) {
+ dotted = new DNSLookup(hostName, timeout).getDottedNames();
+ if (dotted == null) {
+ throw new UnknownHostException(hostName);
+ }
+
+ cache.put(hostName, dotted);
+ }
+
+ return dotted;
+ }
+
+ private DNSLookup(String hostName, int timeout) {
+ this.hostName = hostName;
+ this.timeout = timeout;
+ if (timeout != 0) {
+ Thread t = new Thread(this);
+ t.setDaemon(true);
+ t.start();
+ } else {
+ this.run();
+ }
+ }
+
+ @Override
+ public void run() {
+ this.dottedNames = gethostbyname(this.hostName);
+ if (this.timeout != 0) {
+ synchronized (this) {
+ this.notify();
+ }
+ }
+ }
+
+ private synchronized String[] getDottedNames() {
+ if (this.dottedNames == null && this.timeout != 0) {
+ try {
+ this.wait(this.timeout * 1000);
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ return this.dottedNames;
+ }
+
+ private static boolean isDotted(String name) {
+ StringTokenizer tok = new StringTokenizer(name, ".");
+ if (tok.countTokens() != 4) {
+ return false;
+ } else {
+ for (int i = 0; i < 4; i++) {
+ try {
+ int val = Integer.parseInt(tok.nextToken());
+ if (val < 0 || val > 255) {
+ return false;
+ }
+ } catch (NumberFormatException var4) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private static native String[] gethostbyname(String var0);
+}
diff --git a/NET/worlds/network/DirTimeStamp.java b/NET/worlds/network/DirTimeStamp.java
new file mode 100644
index 0000000..235a4b4
--- /dev/null
+++ b/NET/worlds/network/DirTimeStamp.java
@@ -0,0 +1,102 @@
+package NET.worlds.network;
+
+import NET.worlds.core.IniFile;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URLConnection;
+import java.util.Hashtable;
+
+public class DirTimeStamp {
+ private static Hashtable<URL, DirTimeStamp> _tsEntries = new Hashtable<URL, DirTimeStamp>();
+ private URL _name;
+ private long _mtime;
+ private boolean _loaded = false;
+
+ private DirTimeStamp(URL url) {
+ this._name = url;
+
+ assert url.isRemote();
+ }
+
+ private static synchronized DirTimeStamp lookup(URL url) {
+ DirTimeStamp t = _tsEntries.get(url);
+ if (t == null) {
+ t = new DirTimeStamp(url);
+ _tsEntries.put(url, t);
+ }
+
+ return t;
+ }
+
+ private void getMTime() {
+ this._mtime = 0L;
+
+ try {
+ int r = (int)(Math.random() * 1000000.0);
+ int retryCount = IniFile.gamma().getIniInt("NetCacheRetries", 1);
+ boolean offline = CacheEntry.getOffline();
+ if (offline) {
+ this._loaded = true;
+ return;
+ }
+
+ if (offline) {
+ retryCount = 1;
+ }
+
+ java.net.URL u = DNSLookup.lookup(new java.net.URL(this._name.unalias() + "?" + r));
+
+ while (true) {
+ try {
+ URLConnection uc = u.openConnection();
+ this._mtime = uc.getLastModified();
+ break;
+ } catch (IOException var7) {
+ if (--retryCount <= 0 || var7 instanceof FileNotFoundException) {
+ throw var7;
+ }
+
+ System.out.println("Exception " + var7 + " querying " + this._name + ", retrying...");
+ }
+ }
+
+ this._loaded = true;
+ } catch (FileNotFoundException var8) {
+ System.out.println("Warning: timestamp " + this._name + " not found.");
+ this._loaded = true;
+ } catch (Exception var9) {
+ System.out.println("Timestamp query error: " + var9 + " accessing " + this._name);
+ this._loaded = true;
+ }
+ }
+
+ public static long request(URL url) {
+ URL tsURL = URL.make(url, "timestamp.dir");
+ String u = url.getInternal();
+ int i = u.lastIndexOf(47);
+ if (i > 0) {
+ int j = u.lastIndexOf(47, i - 1) + 1;
+ if (j > 11) {
+ String par = u.substring(j, i);
+ if (url.endsWith("upgrades.lst")) {
+ if (!par.equals("gdkup") && !par.equals("newup") && !par.equals("3DCDup")) {
+ tsURL = URL.make(u.substring(0, j) + "timestamp.upgrades");
+ } else {
+ tsURL = URL.make(url, "timestamp.upgrades");
+ }
+ } else if (par.equals("cgi-bin")) {
+ return 0L;
+ }
+ }
+ }
+
+ DirTimeStamp t = lookup(tsURL);
+ synchronized (t) {
+ if (!t._loaded) {
+ t.getMTime();
+ }
+ }
+
+ return t._mtime;
+ }
+}
diff --git a/NET/worlds/network/ExceptionCmd.java b/NET/worlds/network/ExceptionCmd.java
new file mode 100644
index 0000000..2411569
--- /dev/null
+++ b/NET/worlds/network/ExceptionCmd.java
@@ -0,0 +1,26 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+class ExceptionCmd extends receivedNetPacket {
+ private Exception _exception;
+
+ public ExceptionCmd(Exception e) {
+ this._exception = e;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ assert false;
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ throw this._exception;
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "EXCEPT " + this._exception.getMessage();
+ }
+}
diff --git a/NET/worlds/network/FilthFilter.java b/NET/worlds/network/FilthFilter.java
new file mode 100644
index 0000000..d473bfc
--- /dev/null
+++ b/NET/worlds/network/FilthFilter.java
@@ -0,0 +1,210 @@
+package NET.worlds.network;
+
+import NET.worlds.core.IniFile;
+import java.io.RandomAccessFile;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class FilthFilter {
+ private static FilthFilter theFilthFilter = null;
+ private String filthFile = IniFile.gamma().getIniString("filthfile", "filter.dat");
+ private Hashtable<String, Vector<FilthyPhrase>> naughtyPhrases;
+ private Vector<String> naughtyWords;
+ private boolean allowObscenities;
+
+ public static FilthFilter get() {
+ if (theFilthFilter == null) {
+ theFilthFilter = new FilthFilter();
+ }
+
+ return theFilthFilter;
+ }
+
+ private FilthFilter() {
+ if (IniFile.gamma().getIniInt("encryptfilth", 0) == 1) {
+ this.encryptFilthFile();
+ }
+
+ this.allowObscenities = IniFile.gamma().getIniInt("allowObscenities", 0) == 1 || IniFile.override().getIniInt("allowObscentiies", 0) == 1;
+ this.loadFilth();
+ }
+
+ private void loadFilth() {
+ this.naughtyPhrases = new Hashtable<String, Vector<FilthyPhrase>>();
+ this.naughtyWords = new Vector<String>();
+
+ try {
+ RandomAccessFile fIn = new RandomAccessFile(this.filthFile, "r");
+ byte[] encrypted = new byte[fIn.readInt()];
+ fIn.readFully(encrypted);
+ fIn.close();
+ String decrypted = this.decrypt(encrypted);
+ StringTokenizer st = new StringTokenizer(decrypted, "\t\n\r.,;'\"!?*:/()[]{},「」『』《》?【】。!、;:", false);
+
+ while (st.hasMoreTokens()) {
+ String filth = st.nextToken();
+ FilthyPhrase phrase = new FilthyPhrase(filth);
+ String lookupValue = phrase.firstWord();
+ Vector<FilthyPhrase> phraseList = this.naughtyPhrases.get(lookupValue);
+ if (phraseList == null) {
+ phraseList = new Vector<FilthyPhrase>();
+ this.naughtyPhrases.put(lookupValue, phraseList);
+ }
+
+ phraseList.addElement(phrase);
+ if (phrase.size() == 1L) {
+ this.naughtyWords.addElement(phrase.firstWord());
+ }
+ }
+ } catch (Exception var9) {
+ System.out.println("Error in filth file: " + var9.toString());
+ }
+ }
+
+ private byte[] encrypt(String in) {
+ byte[] inBytes;
+ try {
+ inBytes = in.getBytes();
+ } catch (Exception var6) {
+ System.out.println("Error encoding to UTF8" + var6.toString());
+ return null;
+ }
+
+ byte[] outBytes = new byte[inBytes.length];
+ int len = inBytes.length;
+ outBytes[0] = inBytes[0];
+
+ for (int idx = 1; idx < len; idx++) {
+ outBytes[idx] = (byte)(inBytes[idx] ^ outBytes[idx - 1]);
+ }
+
+ return outBytes;
+ }
+
+ private String decrypt(byte[] in) {
+ byte[] outBytes = new byte[in.length];
+ int len = in.length;
+ outBytes[0] = in[0];
+
+ for (int idx = 1; idx < len; idx++) {
+ outBytes[idx] = (byte)(in[idx] ^ in[idx - 1]);
+ }
+
+ try {
+ return new String(outBytes, "UTF8");
+ } catch (Exception var6) {
+ System.out.println("Error encoding UTF8 " + var6.toString());
+ return null;
+ }
+ }
+
+ private void encryptFilthFile() {
+ try {
+ System.out.println("Encoding filth file...");
+ RandomAccessFile inFilth = new RandomAccessFile("filth.txt", "r");
+ String inStr = new String();
+
+ while (inFilth.getFilePointer() < inFilth.length()) {
+ String in = inFilth.readLine();
+ System.out.println(in);
+ inStr = inStr + in + "\r\n";
+ }
+
+ inFilth.close();
+ byte[] encrypted = this.encrypt(inStr);
+ RandomAccessFile outFilth = new RandomAccessFile(this.filthFile, "rw");
+ outFilth.writeInt(encrypted.length);
+ outFilth.write(encrypted);
+ outFilth.close();
+ System.out.println("Filth file " + this.filthFile + " successfully written.");
+ } catch (Exception var5) {
+ System.out.println("Error encoding filth file: " + var5.toString());
+ }
+ }
+
+ public String filter(String in) {
+ if (this.allowObscenities) {
+ return in;
+ } else {
+ String out = new String();
+
+ while (in.length() > 0) {
+ StringTokenizer st = new StringTokenizer(in, "\t\n\r.,;'\"!?*:/()[]{} ,「」『』《》?【】。!、;:", true);
+ String originalString = st.nextToken();
+ String toCheck = new String(originalString.toLowerCase());
+ Vector<FilthyPhrase> phraseList = this.naughtyPhrases.get(toCheck);
+ if (phraseList != null) {
+ int idx = 0;
+
+ boolean replaced;
+ for (replaced = false; idx < phraseList.size(); idx++) {
+ FilthyPhrase phrase = phraseList.elementAt(idx);
+ if (phrase.check(in)) {
+ String replaceWith = phrase.getReplacement();
+ out = out + replaceWith;
+ in = in.substring(replaceWith.length(), in.length());
+ replaced = true;
+ break;
+ }
+ }
+
+ if (!replaced) {
+ out = out + toCheck;
+ in = in.substring(toCheck.length(), in.length());
+ }
+ } else {
+ out = out + originalString;
+ in = in.substring(toCheck.length(), in.length());
+ }
+ }
+
+ return out;
+ }
+ }
+
+ public String filterName(String in) {
+ if (this.allowObscenities) {
+ return in;
+ } else {
+ String out = new String(in);
+
+ for (int idx = 0; idx < this.naughtyWords.size(); idx++) {
+ String toCompare = this.naughtyWords.elementAt(idx);
+ int location = out.indexOf(toCompare);
+ if (location > -1) {
+ String funnyChars = new String("$!@%#@&*!%#@%!@#$%@#@!@%!@#$%*&%$!");
+ new String();
+ String retVal = out.substring(0, location);
+ retVal = retVal + funnyChars.substring(0, toCompare.length());
+ retVal = retVal + out.substring(location + toCompare.length(), out.length());
+ out = retVal;
+ }
+ }
+
+ return out;
+ }
+ }
+
+ public boolean isFilthy(String in) {
+ if (this.allowObscenities) {
+ return false;
+ } else {
+ while (in.length() > 0) {
+ StringTokenizer st = new StringTokenizer(in, "\t\n\r.,;'\"!?*:/()[]{} ,「」『』《》?【】。!、;:", true);
+ String toCheck = st.nextToken().toLowerCase();
+ Vector<FilthyPhrase> phraseList = this.naughtyPhrases.get(toCheck);
+ if (phraseList != null) {
+ for (int idx = 0; idx < phraseList.size(); idx++) {
+ FilthyPhrase phrase = phraseList.elementAt(idx);
+ if (phrase.check(in)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/network/FilthyPhrase.java b/NET/worlds/network/FilthyPhrase.java
new file mode 100644
index 0000000..17c0d01
--- /dev/null
+++ b/NET/worlds/network/FilthyPhrase.java
@@ -0,0 +1,80 @@
+package NET.worlds.network;
+
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class FilthyPhrase {
+ private long compareValue;
+ private Vector<String> filthyWords;
+ private String rawData;
+
+ public FilthyPhrase(String phrase) {
+ this.rawData = new String(phrase);
+ this.filthyWords = new Vector<String>();
+ StringTokenizer st = new StringTokenizer(phrase, "\t\n\r.,;'\"!?*:/()[]{} ,「」『』《》?【】。!、;:", true);
+ if (st.hasMoreTokens()) {
+ String firstToken = st.nextToken().toLowerCase();
+ this.compareValue = firstToken.hashCode();
+ this.filthyWords.addElement(firstToken);
+ }
+
+ while (st.hasMoreTokens()) {
+ String nextWord = st.nextToken();
+ this.filthyWords.addElement(nextWord.toLowerCase());
+ }
+ }
+
+ public boolean check(String toCheck) {
+ StringTokenizer st = new StringTokenizer(toCheck, "\t\n\r.,;'\"!?*:/()[]{} ,「」『』《》?【】。!、;:", true);
+
+ for (int idx = 0; idx < this.filthyWords.size(); idx++) {
+ if (!st.hasMoreTokens()) {
+ return false;
+ }
+
+ String token = st.nextToken().toLowerCase();
+ String comparator = this.filthyWords.elementAt(idx);
+ if (comparator.compareTo(token) != 0) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public String getReplacement() {
+ String funnyChars = new String("$!@%#@&*!%#@%!@#$%@#@!@%!@#$%*&%$!");
+ String retVal = new String();
+
+ for (int idx = 0; idx < this.filthyWords.size(); idx++) {
+ int numChars = this.filthyWords.elementAt(idx).length();
+ new String();
+ String replacementWord;
+ if (numChars > 1) {
+ replacementWord = funnyChars.substring(0, numChars);
+ } else {
+ replacementWord = this.filthyWords.elementAt(idx);
+ }
+
+ retVal = retVal + replacementWord;
+ }
+
+ return retVal;
+ }
+
+ public long size() {
+ return this.filthyWords.size();
+ }
+
+ public long compareValue() {
+ return this.compareValue;
+ }
+
+ public String firstWord() {
+ return this.filthyWords.size() > 0 ? this.filthyWords.elementAt(0) : new String("");
+ }
+
+ public String asString() {
+ return this.rawData;
+ }
+}
diff --git a/NET/worlds/network/FingerReplyCmd.java b/NET/worlds/network/FingerReplyCmd.java
new file mode 100644
index 0000000..cf36d11
--- /dev/null
+++ b/NET/worlds/network/FingerReplyCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class FingerReplyCmd extends receivedNetPacket {
+ public static final byte FINGERREPLYCMD = 28;
+ private String _user;
+ private PropertyList _propList;
+
+ public FingerReplyCmd() {
+ this._commandType = 28;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._user = data.readUTF();
+ this._propList = new PropertyList();
+ this._propList.parseNetData(data);
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "FINGREP " + this._user + " " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/FingerReqCmd.java b/NET/worlds/network/FingerReqCmd.java
new file mode 100644
index 0000000..7b9e3c2
--- /dev/null
+++ b/NET/worlds/network/FingerReqCmd.java
@@ -0,0 +1,33 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class FingerReqCmd extends netPacket {
+ public static final byte FINGERREQCMD = 27;
+ private String _user;
+
+ public FingerReqCmd(String user) {
+ super(null, 27);
+ this._user = user;
+ }
+
+ @Override
+ int packetSize() {
+ int len = super.packetSize();
+
+ assert this._user != null;
+
+ return len + 1 + ServerOutputStream.utfLength(this._user);
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeUTF(this._user);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "FINGREQ " + this._user;
+ }
+}
diff --git a/NET/worlds/network/Galaxy.java b/NET/worlds/network/Galaxy.java
new file mode 100644
index 0000000..5d00115
--- /dev/null
+++ b/NET/worlds/network/Galaxy.java
@@ -0,0 +1,768 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.InternetConnectionDialog;
+import NET.worlds.console.LoginWizard;
+import NET.worlds.core.IniFile;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class Galaxy implements DialogReceiver {
+ private static Hashtable<String, Galaxy> _galaxyHash = new Hashtable<String, Galaxy>();
+ private static boolean _globalUserAllowsOnline = true;
+ private boolean _localUserAllowsOnline = true;
+ private ServerURL _serverURL;
+ private int _serverType;
+ private int _worldCount;
+ private Hashtable<String, NetworkObject> _nFlongID;
+ private ServerTracker _serverTracker;
+ private RoomMgr _roomTable;
+ private String _channel;
+ private String _username;
+ private String _usernameU;
+ private String _password;
+ private String _serial;
+ private String _newUsername;
+ private String _newPassword;
+ private int _mode;
+ private NetworkMulti _consoleList;
+ private int _retriesLeft = 2;
+ private InternetConnectionDialog _icd;
+ private LoginWizard _wizard;
+ private Object _wizardMutex = new Object();
+ private static int _debugLevel = IniFile.gamma().getIniInt("netdebug", 0);
+ private WaitList _waiters;
+ private boolean _relogin;
+ private boolean _onlineEnabled;
+ private boolean _online;
+ private boolean sentFriendsList;
+ private int protocolLevel;
+
+ static {
+ if (_debugLevel > 0) {
+ System.out.println("NETWORK DEBUGGING LEVEL = " + _debugLevel);
+ }
+ }
+
+ private Galaxy(ServerURL serverURL) {
+ this._serverURL = serverURL;
+ this._serverType = 0;
+ this._nFlongID = new Hashtable<String, NetworkObject>();
+ this._worldCount = 0;
+ this._channel = "";
+ this._serverTracker = new ServerTracker(this);
+ this._waiters = new WaitList(this);
+ this._username = "";
+ this._usernameU = "";
+ this._consoleList = new NetworkMulti(this._username, this);
+ this.regObject(this._username, this._consoleList);
+ if (serverURL == null) {
+ this._onlineEnabled = false;
+ this._online = false;
+ } else {
+ this._onlineEnabled = true;
+ this._online = false;
+ }
+
+ this.setOnlineState(this._onlineEnabled, this._online);
+ }
+
+ private synchronized void incWorldCount() {
+ this._worldCount++;
+ }
+
+ public synchronized void decWorldCount() {
+ this._worldCount--;
+
+ assert this._worldCount >= 0;
+
+ if (this._worldCount <= 0) {
+ if (this._serverURL != null) {
+ _galaxyHash.remove(this._serverURL.getHost());
+ }
+
+ this._waiters.clear();
+ this._serverTracker = new ServerTracker(this);
+ }
+ }
+
+ public static Galaxy getGalaxy(String strServerURL) throws InvalidServerURLException {
+ ServerURL serverURL = new ServerURL(strServerURL);
+ String serverHost = serverURL.getHost();
+ Galaxy reqGal = _galaxyHash.get(serverHost);
+ if (reqGal == null) {
+ reqGal = new Galaxy(serverURL);
+ _galaxyHash.put(serverHost, reqGal);
+ }
+
+ assert reqGal != null;
+
+ reqGal.incWorldCount();
+ return reqGal;
+ }
+
+ public static Galaxy getGalaxy(URL serverURL) throws InvalidServerURLException {
+ return getGalaxy(serverURL.unalias());
+ }
+
+ public static Galaxy getAnonGalaxy() {
+ Galaxy reqGal = new Galaxy(null);
+ reqGal.incWorldCount();
+ return reqGal;
+ }
+
+ public boolean isAnonymous() {
+ return this._serverURL == null;
+ }
+
+ public WorldServer getServer(String StrServerURL) throws InvalidServerURLException {
+ if (this._serverURL == null) {
+ return null;
+ } else if (!_globalUserAllowsOnline) {
+ return null;
+ } else if (!this._localUserAllowsOnline) {
+ return null;
+ } else if (this._icd != null) {
+ return null;
+ } else {
+ synchronized (this._wizardMutex) {
+ if (this._wizard != null && !this._wizard.waitingForConnection() && !this._wizard.safeToQueryServer()) {
+ return null;
+ }
+ }
+
+ return this._serverTracker.getServer(StrServerURL);
+ }
+ }
+
+ public WorldServer getServer(URL serverURL) throws InvalidServerURLException {
+ return this.getServer(serverURL.unalias());
+ }
+
+ public boolean isActive() {
+ return this._serverTracker.isActive();
+ }
+
+ protected boolean addPendingServer(WorldServer ws) {
+ assert ws != null;
+
+ boolean firstOnline = this._serverTracker.addPendingServer(ws);
+ if (firstOnline) {
+ this._retriesLeft = 2;
+ this.setOnlineState(true, true);
+ synchronized (this) {
+ this._roomTable = new RoomMgr();
+ }
+ }
+
+ return firstOnline;
+ }
+
+ void addActiveServer(WorldServer ws) {
+ boolean firstActive = this._serverTracker.addActiveServer(ws);
+ if (firstActive) {
+ this._waiters.notify(true);
+ if (this._wizard != null) {
+ System.out.println("LWDB: calling " + this._wizard + " setConnected");
+ this._wizard.setConnected();
+ }
+ }
+ }
+
+ boolean addClosingServer(WorldServer ws) {
+ assert this._nFlongID != null;
+
+ assert ws != null;
+
+ boolean lastActive = this._serverTracker.addClosingServer(ws);
+ if (lastActive) {
+ this.forceDisconnect();
+ }
+
+ return lastActive;
+ }
+
+ void markClosedServer(WorldServer ws) {
+ this._serverTracker.markClosedServer(ws);
+ }
+
+ void killServer(WorldServer serv) {
+ this._serverTracker.killServer(serv);
+ }
+
+ protected void noteServerDeath(VarErrorException lastError) {
+ synchronized (this._serverTracker) {
+ if (!this._serverTracker.isActive()) {
+ synchronized (this) {
+ this._roomTable = null;
+ }
+
+ this.setOnlineState(false, false);
+ if (this.getProtocol() == 0) {
+ this._icd = new InternetConnectionDialog(this, lastError);
+ } else {
+ if (lastError != null && (!lastError.getStatusFlag() || this._relogin)) {
+ _globalUserAllowsOnline = true;
+ boolean tryBackup = false;
+ synchronized (this._serverTracker) {
+ Enumeration<WorldServer> list = this._serverTracker.getAllServers();
+
+ while (list.hasMoreElements()) {
+ WorldServer ws = list.nextElement();
+ if (ws.useBackupServer()) {
+ tryBackup = true;
+ }
+ }
+ }
+
+ if (tryBackup) {
+ System.out.println("Server death noted, trying alternate.");
+ this.setChatname(this._username);
+ this.goOnline();
+ } else {
+ System.out.println("Server death noted, no more alternates. How sad.");
+ if (this._retriesLeft <= 0 || !this._relogin && !lastError.getRetryFlag()) {
+ this.setChatname("");
+ this.killZombies();
+ if (this._wizard == null) {
+ this._wizard = new LoginWizard(this, this.getIniSection(), lastError.getMsg());
+ System.out.println("LWDB: brought up " + this._wizard + " error " + lastError.getMsg());
+ } else {
+ System.out.println("LWDB: reporting error " + lastError.getMsg() + " to " + this._wizard);
+ this._wizard.loginError(lastError.getMsg());
+ }
+ } else {
+ System.out.println(this + ": doing retry on " + lastError);
+ this._retriesLeft = this._retriesLeft - lastError.getRetryCount();
+ this.setChatname(this._username);
+ this.goOnline();
+ }
+ }
+
+ this._relogin = false;
+ } else {
+ this.setOnlineState(true, false);
+ }
+ }
+ }
+ }
+ }
+
+ public void waitForConnection(ConnectionWaiter cw) {
+ this._waiters.addWaiter(cw);
+ }
+
+ public void goOffline(boolean relogin) {
+ this._relogin = relogin;
+ if (!this._serverTracker.isActive()) {
+ this._relogin = false;
+ }
+
+ synchronized (this._serverTracker) {
+ Enumeration<WorldServer> list = this._serverTracker.getAllServers();
+
+ while (list.hasMoreElements()) {
+ WorldServer ws = list.nextElement();
+ ws.forceOffline();
+ }
+ }
+ }
+
+ private void killZombies() {
+ synchronized (this._serverTracker) {
+ Enumeration<WorldServer> list = this._serverTracker.getAllServers();
+
+ while (list.hasMoreElements()) {
+ list.nextElement().killZombies();
+ }
+ }
+ }
+
+ void goOnline() {
+ synchronized (this._serverTracker) {
+ Enumeration<WorldServer> list = this._serverTracker.getAllServers();
+
+ while (list.hasMoreElements()) {
+ WorldServer ws = list.nextElement();
+ ws.goOnline();
+ }
+ }
+
+ this.reacquireServer(null);
+ }
+
+ public static synchronized void forceOffline(boolean relogin) {
+ if (_globalUserAllowsOnline) {
+ _globalUserAllowsOnline = false;
+ synchronized (_galaxyHash) {
+ Enumeration<Galaxy> list = _galaxyHash.elements();
+
+ while (list.hasMoreElements()) {
+ Galaxy g = list.nextElement();
+ g.goOffline(relogin);
+ }
+ }
+ }
+ }
+
+ public void localForceOnline() {
+ _globalUserAllowsOnline = true;
+ this._relogin = false;
+ if (!this.isActive()) {
+ this.setOnlineState(false, false);
+ this._localUserAllowsOnline = true;
+ if (this.getGalaxyType() != 0) {
+ this.setChatname("");
+ this._wizard = new LoginWizard(this, this.getIniSection());
+ System.out.println("LWDB: brought up " + this._wizard + " in localForceOnline");
+ } else {
+ this.reacquireServer(null);
+ }
+ }
+ }
+
+ public static int getDebugLevel() {
+ return _debugLevel;
+ }
+
+ public static void printDebugging() {
+ System.out.println("----GALAXY DEBUGGING-------");
+ Enumeration<Galaxy> e = _galaxyHash.elements();
+
+ while (e.hasMoreElements()) {
+ Galaxy g = e.nextElement();
+ System.out.println(g + " : ");
+ System.out.println(g._serverTracker);
+ }
+
+ System.out.println("---------------------------");
+ }
+
+ public String getChannel() {
+ return this._channel;
+ }
+
+ void setChannel(String channel) {
+ this.changeChannel(channel, false);
+ }
+
+ public void changeChannel(String channel) {
+ if (channel == null) {
+ channel = "";
+ }
+
+ channel = channel.replace(' ', '_');
+ channel = channel.replace('<', '{');
+ channel = channel.replace('>', '}');
+ this.changeChannel(channel, true);
+ }
+
+ private void changeChannel(String channel, boolean sendMsg) {
+ if (!channel.equals(this._channel)) {
+ String oldChannel = this._channel;
+ this._channel = channel;
+ Hashtable<String, NetworkObject> tmpIDtable = (Hashtable<String, NetworkObject>)this._nFlongID.clone();
+ Enumeration<NetworkObject> e = tmpIDtable.elements();
+
+ while (e.hasMoreElements()) {
+ NetworkObject no = e.nextElement();
+
+ assert no != null;
+
+ no.changeChannel(this, oldChannel, this._channel);
+ }
+
+ if (sendMsg) {
+ WorldServer ws = this._serverTracker.getActive(this);
+ if (ws != null) {
+ ws.tmpRefCnt(this);
+
+ try {
+ ws.sendNetworkMsg(new ChannelCmd(channel));
+ } catch (PacketTooLargeException var8) {
+ assert false;
+ } catch (InfiniteWaitException var9) {
+ }
+ }
+ }
+ }
+ }
+
+ public ServerURL getServerURL() {
+ return this._serverURL;
+ }
+
+ @Override
+ public String toString() {
+ return this._serverURL == null ? "AnonGalaxy=" + super.toString() : "Galaxy[" + this._serverURL + "]";
+ }
+
+ void swapServer(WorldServer oldServ, WorldServer newServ) {
+ if ((_debugLevel & 8192) > 0) {
+ System.out.println(this + ".swapServer(" + oldServ + ", " + newServ + ")");
+ }
+
+ this._serverTracker.swapServer(oldServ, newServ);
+ this.reacquireServer(oldServ);
+ }
+
+ void reacquireServer(WorldServer oldServ) {
+ if ((_debugLevel & 8192) > 0) {
+ System.out.println(this + ".reacquireServer(" + oldServ + ")");
+ }
+
+ Enumeration<NetworkObject> e = this._nFlongID.elements();
+
+ while (e.hasMoreElements()) {
+ e.nextElement().reacquireServer(oldServ);
+ }
+ }
+
+ public void regObject(String longID, NetworkObject obj) {
+ if ((_debugLevel & 8192) > 0) {
+ System.out.println(this + ".regObject(" + longID + ", " + obj + ")");
+ }
+
+ this._nFlongID.put(longID, obj);
+ }
+
+ public NetworkObject getObject(String longID) {
+ return this._nFlongID.get(longID);
+ }
+
+ public void delObject(String longID) {
+ if ((_debugLevel & 8192) > 0) {
+ System.out.println(this + ".delObject(" + longID + ")");
+ }
+
+ this._nFlongID.remove(longID);
+ }
+
+ public void forceObjectRereg() {
+ if ((_debugLevel & 8192) > 0) {
+ System.out.println(this + ".forceObjectRereg()");
+ }
+
+ Hashtable<String, NetworkObject> oldTable = this._nFlongID;
+ this._nFlongID = new Hashtable<String, NetworkObject>();
+ Enumeration<NetworkObject> e = oldTable.elements();
+
+ while (e.hasMoreElements()) {
+ e.nextElement().register();
+ }
+ }
+
+ private void forceDisconnect() {
+ if ((_debugLevel & 8192) > 0) {
+ System.out.println(this + ".forceDisconnect()");
+ }
+
+ Enumeration<NetworkObject> e = this._nFlongID.elements();
+
+ while (e.hasMoreElements()) {
+ NetworkObject no = e.nextElement();
+
+ assert no != null;
+
+ no.galaxyDisconnected();
+ }
+ }
+
+ void addRoomRequest(String roomName, NetworkRoom room) {
+ assert this._roomTable != null;
+
+ this._roomTable.addRequest(roomName, room);
+ }
+
+ void delRoomRequest(String roomName) {
+ if (this._roomTable != null) {
+ this._roomTable.delRequest(roomName);
+ }
+ }
+
+ NetworkRoom regRoomID(int roomID, String roomName) {
+ assert this._roomTable != null;
+
+ NetworkRoom room = this._roomTable.getRequest(roomName);
+ if (roomID != 0 && room != null) {
+ this._roomTable.regRoomID(roomID, room);
+ }
+
+ return room;
+ }
+
+ public void setRoomID(int roomID, NetworkRoom room) {
+ assert this._roomTable != null;
+
+ assert roomID != 0;
+
+ assert room != null;
+
+ this._roomTable.regRoomID(roomID, room);
+ }
+
+ void delRoomID(int roomID, NetworkRoom room) {
+ if (this._roomTable != null) {
+ this._roomTable.delRoomID(roomID, room);
+ }
+ }
+
+ NetworkRoom getRoom(int roomID) {
+ return this._roomTable == null ? null : this._roomTable.getRoom(roomID);
+ }
+
+ void setGalaxyType(int type) {
+ this._serverType = type;
+ if (_globalUserAllowsOnline) {
+ this.setOnlineState(false, this._online);
+ this.setChatname("");
+ this._wizard = new LoginWizard(this, this.getIniSection());
+ System.out.println("LWDB: brought up " + this._wizard + " in setGalaxyType");
+ }
+ }
+
+ public int getGalaxyType() {
+ return this._serverType;
+ }
+
+ public synchronized void setAuthInfo(String usernm, String newUsernm, String passwd, String newPasswd, String serial, int mode) {
+ _globalUserAllowsOnline = true;
+ this._localUserAllowsOnline = true;
+
+ assert this._serverType != 0;
+
+ this.setUsernameU(usernm);
+ this.setChatname(usernm);
+ this._newUsername = newUsernm;
+ this._password = passwd;
+ this._newPassword = newPasswd;
+ this._serial = serial;
+ this._mode = mode;
+ switch (this._serverType) {
+ case 1:
+ switch (this._mode) {
+ case 1:
+ default:
+ break;
+ case 2:
+ this._serial = null;
+ break;
+ case 3:
+ this._password = null;
+ this._serial = null;
+ }
+
+ assert this._mode != 4;
+ break;
+ case 3:
+ assert false;
+ break;
+ case 4:
+ assert this._mode == 2;
+ case 2:
+ assert this._mode != 1;
+
+ assert this._mode != 4;
+
+ if (this._password != null && this._password.length() != 0) {
+ System.out.println(this + ": Password shouldn't be specified.");
+ }
+
+ this._password = null;
+ if (this._serial != null && this._serial.length() != 0) {
+ System.out.println(this + ": Serial number shouldn't be specified.");
+ }
+
+ this._serial = null;
+ }
+
+ this.goOnline();
+ }
+
+ public String getSerialNum() {
+ return this._serial;
+ }
+
+ public String getPassword() {
+ return this._password;
+ }
+
+ String getNewPassword() {
+ return this._newPassword;
+ }
+
+ public String getChatname() {
+ return this._username;
+ }
+
+ String getNewChatname() {
+ return this._newUsername;
+ }
+
+ String getGuestExpiration() {
+ assert false;
+
+ return null;
+ }
+
+ public int getLoginMode() {
+ return this._mode;
+ }
+
+ void setOnlineState(boolean enabled, boolean online) {
+ synchronized (this) {
+ this._onlineEnabled = enabled;
+ this._online = online;
+ }
+
+ synchronized (this._consoleList) {
+ Enumeration<NetworkObject> cList = this.getConsoles();
+
+ while (cList.hasMoreElements()) {
+ Console c = (Console)cList.nextElement();
+ c.setOnlineState(enabled, online);
+ }
+ }
+ }
+
+ public boolean getOnlineEnabled() {
+ return this._onlineEnabled;
+ }
+
+ public boolean getOnline() {
+ return this._online;
+ }
+
+ void setPassword(String password) {
+ this._password = password;
+ }
+
+ void setNewPassword(String password) {
+ this._newPassword = password;
+ }
+
+ void setNewChatname(String chatname) {
+ this._newUsername = chatname;
+ }
+
+ void setSerialNum(String sn) {
+ this._serial = sn;
+ }
+
+ public void setUsernameU(String username) {
+ this._usernameU = username;
+ }
+
+ public String getUsernameU() {
+ return this._usernameU;
+ }
+
+ void setChatname(String newname) {
+ synchronized (this) {
+ this._consoleList = new NetworkMulti(newname, this._consoleList, this);
+ if (this._username != null) {
+ this.delObject(this._username);
+ }
+
+ this.regObject(newname, this._consoleList);
+ this._username = newname;
+ }
+
+ synchronized (this._consoleList) {
+ Enumeration<NetworkObject> cList = this.getConsoles();
+
+ while (cList.hasMoreElements()) {
+ Console c = (Console)cList.nextElement();
+ c.setChatname(this._username);
+ }
+ }
+
+ synchronized (this._serverTracker) {
+ Enumeration<WorldServer> list = this._serverTracker.getAllServers();
+
+ while (list.hasMoreElements()) {
+ WorldServer ws = list.nextElement();
+ ws.regShortID(1, this._username);
+ }
+ }
+ }
+
+ public IniFile getIniSection() {
+ if (this._serverURL == null) {
+ return new IniFile("UNSHARED");
+ } else {
+ if (this._serverURL.getHost().equals("www.3dcd.com:6650")) {
+ IniFile i = new IniFile("209.240.84.122:6650");
+ if (i.getIniString("User0", "").length() != 0) {
+ return i;
+ }
+ }
+
+ return new IniFile(this._serverURL.getHost());
+ }
+ }
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (who instanceof LoginWizard) {
+ synchronized (this._wizardMutex) {
+ System.out.println("LWDB: setting who " + who + " wiz " + this._wizard + " to null");
+ this._wizard = null;
+ }
+
+ if (!confirmed) {
+ this.setOnlineState(true, false);
+ this._localUserAllowsOnline = false;
+ } else {
+ this._localUserAllowsOnline = true;
+ _globalUserAllowsOnline = true;
+ }
+ } else if (who instanceof InternetConnectionDialog) {
+ this._icd = null;
+ if (!confirmed) {
+ this.setOnlineState(true, false);
+ this._localUserAllowsOnline = false;
+ } else {
+ this._localUserAllowsOnline = true;
+ _globalUserAllowsOnline = true;
+ this.reacquireServer(null);
+ }
+ } else {
+ assert false;
+ }
+ }
+
+ public void addConsole(Console c) {
+ assert this._consoleList != null;
+
+ this._consoleList.addObject(c);
+ this.setOnlineState(this._onlineEnabled, this._online);
+ }
+
+ public void delConsole(Console c) {
+ assert this._consoleList != null;
+
+ this._consoleList.delObject(c);
+ }
+
+ public Enumeration<NetworkObject> getConsoles() {
+ return this._consoleList.elements();
+ }
+
+ public void sentFriendsList(boolean state) {
+ this.sentFriendsList = state;
+ }
+
+ public boolean sentFriendsList() {
+ return this.sentFriendsList;
+ }
+
+ public int getProtocol() {
+ return this.protocolLevel;
+ }
+
+ void setProtocol(int level) {
+ this.protocolLevel = level;
+ }
+}
diff --git a/NET/worlds/network/IPhone.java b/NET/worlds/network/IPhone.java
new file mode 100644
index 0000000..56c12c0
--- /dev/null
+++ b/NET/worlds/network/IPhone.java
@@ -0,0 +1,121 @@
+package NET.worlds.network;
+
+import NET.worlds.console.ConfirmDialog;
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.core.RegKey;
+import NET.worlds.core.RegKeyNotFoundException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.MessageFormat;
+
+public class IPhone implements DialogReceiver {
+ private static String _IPhoneProgPath = null;
+ private static ConfirmDialog _dlg = null;
+ private String _name;
+ private String _ip;
+
+ private IPhone(String name, String ip) {
+ this._name = name;
+ this._ip = ip;
+ }
+
+ public static synchronized boolean placeCall(String name, String text) {
+ if (_dlg != null) {
+ return false;
+ } else {
+ String s = text.trim();
+ if (s.startsWith("[TALK:") && s.endsWith("]")) {
+ s = s.substring(6, s.length() - 1);
+ IPhone fone = new IPhone(name, s);
+ _dlg = new ConfirmDialog(
+ Console.getFrame(), fone, "Internet Phone Request", name + " has requested an Internet Phone call. " + "Do you want to call them?"
+ );
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static boolean isCall(String text) {
+ String s = text.trim().toUpperCase();
+ return s.startsWith("[TALK") && s.endsWith("]");
+ }
+
+ public static String initiateCall(String text) {
+ if (_IPhoneProgPath == null) {
+ getRegEntry();
+ }
+
+ if (_IPhoneProgPath.equals("")) {
+ return "Can't initiate call -- no Internet Telephone Application found.";
+ } else {
+ String ret = "[BAD REMOTE HOST ADDRESS]";
+
+ try {
+ String s = InetAddress.getLocalHost().toString();
+ s = s.substring(s.indexOf(47) + 1);
+ ret = "[TALK:" + s + "]";
+ Runtime.getRuntime().exec(_IPhoneProgPath);
+ } catch (SecurityException var3) {
+ ret = "Can't initiate call -- couldn't start Internet Telephone Application.";
+ } catch (UnknownHostException var4) {
+ var4.printStackTrace();
+ } catch (IOException var5) {
+ var5.printStackTrace();
+ }
+
+ return ret;
+ }
+ }
+
+ private static void getRegEntry() {
+ try {
+ RegKey root = RegKey.getRootKey(2);
+ RegKey key = new RegKey(root, "SOFTWARE\\Classes\\InternetPhoneUser\\shell\\open\\command", 0);
+ _IPhoneProgPath = key.getStringValue("");
+ key.close();
+ int idx = _IPhoneProgPath.indexOf(34);
+ if (idx == 0) {
+ _IPhoneProgPath = _IPhoneProgPath.substring(1, _IPhoneProgPath.indexOf(34, 1));
+ } else {
+ _IPhoneProgPath = _IPhoneProgPath.substring(0, idx);
+ }
+ } catch (RegKeyNotFoundException var3) {
+ _IPhoneProgPath = "";
+ }
+ }
+
+ private void talkToPhoneService() {
+ DDEMLClass ddeml = new DDEMLClass("InternetPhone", "CallIP");
+ ddeml.Request("," + this._ip);
+ ddeml.destroy();
+ ddeml = new DDEMLClass("InternetPhone", "Show");
+ ddeml.Request("2");
+ ddeml.destroy();
+ }
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (confirmed) {
+ Object[] arguments = new Object[]{new String(this._name), new String(this._ip)};
+ Console.println(MessageFormat.format(Console.message("Calling-IP"), arguments));
+ if (_IPhoneProgPath == null) {
+ getRegEntry();
+ }
+
+ try {
+ Runtime.getRuntime().exec(_IPhoneProgPath);
+ this.talkToPhoneService();
+ } catch (SecurityException var5) {
+ Console.println(Console.message("Call-failed"));
+ } catch (Exception var6) {
+ var6.printStackTrace();
+ }
+ }
+
+ _dlg = null;
+ }
+}
diff --git a/NET/worlds/network/InfiniteWaitException.java b/NET/worlds/network/InfiniteWaitException.java
new file mode 100644
index 0000000..4df657c
--- /dev/null
+++ b/NET/worlds/network/InfiniteWaitException.java
@@ -0,0 +1,12 @@
+package NET.worlds.network;
+
+public class InfiniteWaitException extends Exception {
+ private static final long serialVersionUID = -8872856399045515110L;
+
+ public InfiniteWaitException() {
+ }
+
+ public InfiniteWaitException(String msg) {
+ super(msg);
+ }
+}
diff --git a/NET/worlds/network/InvalidServerURLException.java b/NET/worlds/network/InvalidServerURLException.java
new file mode 100644
index 0000000..0e03814
--- /dev/null
+++ b/NET/worlds/network/InvalidServerURLException.java
@@ -0,0 +1,12 @@
+package NET.worlds.network;
+
+public class InvalidServerURLException extends Exception {
+ private static final long serialVersionUID = 5256010949259135827L;
+
+ public InvalidServerURLException() {
+ }
+
+ public InvalidServerURLException(String msg) {
+ super(msg);
+ }
+}
diff --git a/NET/worlds/network/LoginMode.java b/NET/worlds/network/LoginMode.java
new file mode 100644
index 0000000..8c2a022
--- /dev/null
+++ b/NET/worlds/network/LoginMode.java
@@ -0,0 +1,9 @@
+package NET.worlds.network;
+
+public interface LoginMode {
+ int UNKNOWN = 0;
+ int REGISTER = 1;
+ int AUTHENTICATE = 2;
+ int GUESTLOGIN = 3;
+ int ABORT = 4;
+}
diff --git a/NET/worlds/network/NetUpdate.java b/NET/worlds/network/NetUpdate.java
new file mode 100644
index 0000000..b55a774
--- /dev/null
+++ b/NET/worlds/network/NetUpdate.java
@@ -0,0 +1,919 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Gamma;
+import NET.worlds.console.InternetConnectionDialog;
+import NET.worlds.console.LoginWizard;
+import NET.worlds.console.Main;
+import NET.worlds.console.Window;
+import NET.worlds.console.WorldsMarkPart;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.RegKey;
+import NET.worlds.core.RegKeyNotFoundException;
+import NET.worlds.core.ServerTableManager;
+import NET.worlds.core.Std;
+import NET.worlds.scape.SendURLAction;
+import NET.worlds.scape.World;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class NetUpdate implements Runnable, RemoteFileConst {
+ static final String VERSIONS = "upgrades.lst";
+ static final String WORLDVERSIONS = "upgrades.lst";
+ static final String SERVER = "upgradeServer";
+ static final String RESTARTCMD = "WorldsPlayer.exe";
+ static final String WORLDCURVER = "\\ver.txt";
+ static final String UPGRADER = ".\\bin\\gdkup.exe";
+ static final String SCRIPTFILE = "updates.lst";
+ static final String LANGUAGES = "languages.lst";
+ static final int UPGRADETIMEOUT = IniFile.gamma().getIniInt("upgradeTimeout", 7);
+ static int TESTAUTOUPGRADE = IniFile.gamma().getIniInt("testautoupgrade", 0);
+ static final int TESTWORLDAUTOUPGRADE = IniFile.gamma().getIniInt("testworldautoupgrade", 0);
+ private static String uServer = getUpgradeServerIniEntry(IniFile.gamma());
+ private static String overrideServer;
+ public static String overrideWorldServer = null;
+ private static int _today;
+ private static boolean beenCalled;
+ static int gdkver;
+ private boolean _force;
+ private boolean forceWorldLoad;
+ private String worldToUpdate;
+ static int maxVers;
+ private static final String INTERNAL = "internal";
+ private static final String EXTERNAL = "external";
+ private static int maxworld;
+ private static Object updateLoadSyncer;
+
+ static {
+ IniFile oini = IniFile.override();
+ if (oini != null) {
+ overrideWorldServer = oini.getIniString("WorldServer", "");
+ if (overrideWorldServer.equals("")) {
+ if (Gamma.shaperEnabled()) {
+ overrideWorldServer = "worldserver://test.3dcd.com";
+ } else {
+ overrideWorldServer = null;
+ }
+ }
+ }
+
+ String s = getUpgradeServerIniEntry(oini);
+ if (!s.equals("")) {
+ overrideServer = s;
+ uServer = s;
+ }
+
+ URL.setHttpServer(uServer.substring(0, uServer.lastIndexOf(47) + 1));
+ beenCalled = false;
+ gdkver = 0;
+ maxVers = IniFile.gamma().getIniInt("maxupgradeversion", 999999999);
+ maxworld = -1;
+ updateLoadSyncer = new Object();
+ }
+
+ static String getUpgradeServerIniEntry(IniFile ini) {
+ return ini == null ? "" : ini.getIniString("upgradeServer", "");
+ }
+
+ public static void setUpgradeServerURL(String url) {
+ if (overrideServer == null) {
+ String upgradeDir = uServer;
+ int start = upgradeDir.length() - 1;
+ if (start != -1) {
+ if (upgradeDir.charAt(start) == '/') {
+ start--;
+ }
+
+ upgradeDir = upgradeDir.substring(upgradeDir.lastIndexOf(47, start));
+ uServer = url + upgradeDir;
+ URL.setHttpServer(url + "/");
+ }
+ }
+ }
+
+ public static boolean isInternalVersion() {
+ String chatName = null;
+ Console c = Console.getActive();
+ Galaxy g = null;
+ if (c != null) {
+ g = c.getGalaxy();
+ }
+
+ if (g != null && g.getOnline()) {
+ chatName = g.getChatname();
+ } else {
+ String entry = IniFile.gamma().getIniString("lastchatname", "Fred");
+ if (entry.startsWith("VIP ") || entry.startsWith("vip ")) {
+ chatName = entry.substring(4);
+ }
+ }
+
+ if (chatName != null) {
+ String[] employeeList = ServerTableManager.instance().getTable("employeeAccounts");
+ if (employeeList == null) {
+ return false;
+ }
+
+ for (int i = 0; i < employeeList.length; i++) {
+ if (employeeList[i].equals(chatName)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static String getInfoURL() {
+ return getInfoURL("");
+ }
+
+ public static String getInfoURL(String info) {
+ String url = getUpgradeServerURL();
+ if (url == null) {
+ return null;
+ } else {
+ String page = IniFile.override().getIniString("InfoPage", "index" + Console.message(".html"));
+ if (Console.wasHttpNoSuchFile(url + info + page)) {
+ page = IniFile.override().getIniString("InfoPage", "index.html");
+ }
+
+ return url + info + page;
+ }
+ }
+
+ public static String getUpgradeServerURL() {
+ if (uServer.equals("")) {
+ return null;
+ } else {
+ if (!uServer.endsWith("/")) {
+ uServer = uServer + "/";
+ }
+
+ return uServer;
+ }
+ }
+
+ public static void showInfo() {
+ showInfo("");
+ }
+
+ public static void showInfo(String info) {
+ new SendURLAction(getInfoURL(info)).startBrowser();
+ }
+
+ private static boolean openPage(String browser, String destination) {
+ DDEMLClass ddeml = new DDEMLClass(browser, "WWW_Activate");
+ boolean val = ddeml.Request("-1,0");
+ ddeml.destroy();
+ if (!val) {
+ return false;
+ } else {
+ ddeml = new DDEMLClass(browser, "WWW_OpenURL");
+ val = ddeml.Request("\"" + destination + "\",,-1,0,,,");
+ ddeml.destroy();
+ return val;
+ }
+ }
+
+ private NetUpdate(boolean force) {
+ this._force = force;
+ }
+
+ private NetUpdate(String w) {
+ this.worldToUpdate = w;
+ }
+
+ private NetUpdate(String w, boolean forceWorldLoad) {
+ this.worldToUpdate = w;
+ this.forceWorldLoad = forceWorldLoad;
+ }
+
+ static void notifyUser(String msg) {
+ Console.println(msg);
+ }
+
+ static void warnUser(String msg) {
+ IniFile.gamma().setIniString("RunUpgrade", "");
+ notifyUser(msg);
+ }
+
+ private static boolean timeToUpdate(boolean force) {
+ while (Window.getMainWindow() == null || !LoginWizard.isFirstTimeDone() && !InternetConnectionDialog.isFirstTimeDone()) {
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ if (!force) {
+ if (IniFile.gamma().getIniInt("lastUpgradeCheck", 0) + UPGRADETIMEOUT > _today) {
+ return false;
+ }
+
+ if (!LoginWizard.isFirstTimeDone() && InternetConnectionDialog.choseSingleUserMode()) {
+ return false;
+ }
+ }
+
+ if (getUpgradeServerURL() == null) {
+ Object[] arguments = new Object[]{new String("upgradeServer")};
+ notifyUser(MessageFormat.format(Console.message("upgrade-check"), arguments));
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private static int getNextVers(String line, int vers, int testLevel, int[] retSize) {
+ StringTokenizer st = null;
+
+ try {
+ st = new StringTokenizer(line);
+ if (!st.hasMoreTokens()) {
+ return -1;
+ } else {
+ int v = Integer.parseInt(st.nextToken());
+ if (st.hasMoreTokens() && (vers < 0 || v == vers) && (vers >= 0 || v <= 0 && v >= vers)) {
+ int best = -1;
+
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ int colon = s.indexOf(58);
+ if (colon != -1) {
+ int need = Integer.parseInt(s.substring(colon + 1));
+ if (need > 9999) {
+ need /= 10;
+ }
+
+ int fixedGdkVer = gdkver <= 9999 ? gdkver : gdkver / 10;
+ int curVer = Std.getVersion();
+ curVer = curVer <= 9999 ? curVer : curVer / 10;
+ if (need > curVer || gdkver != 0 && need > fixedGdkVer) {
+ continue;
+ }
+
+ s = s.substring(0, colon);
+ }
+
+ int size = 160000;
+ int pound = s.indexOf(35);
+ if (pound != -1) {
+ size = Integer.parseInt(s.substring(pound + 1));
+ s = s.substring(0, pound);
+ }
+
+ int t = Integer.parseInt(s);
+ int level = 0;
+ if (t >= 999000000) {
+ t -= 999000000;
+ level = t / 100000 + 1;
+ t %= 100000;
+ if (level > testLevel) {
+ continue;
+ }
+ }
+
+ if (t <= maxVers && t > best) {
+ best = t;
+ retSize[0] = size;
+ }
+ }
+
+ return best;
+ } else {
+ return -1;
+ }
+ }
+ } catch (NumberFormatException var13) {
+ return -1;
+ }
+ }
+
+ private static String getVersions(
+ URL remoteName, int vers, String patchRoot, Vector<Integer> numbers, Vector<String> patches, Vector<Integer> sizes, String readableName, int test
+ ) {
+ CacheFile cf = Cache.getFile(remoteName, true);
+ cf.waitUntilLoaded();
+ if (cf.error()) {
+ return "Network error retrieving " + remoteName;
+ } else {
+ String localName = cf.getLocalName();
+
+ try {
+ FileInputStream in = new FileInputStream(localName);
+ DataInputStream dis = new DataInputStream(in);
+ int[] size = new int[1];
+
+ String line;
+ while ((line = dis.readLine()) != null) {
+ int nextVersion = getNextVers(line, vers, test, size);
+ if (nextVersion >= 0) {
+ if (numbers != null) {
+ numbers.addElement(new Integer(nextVersion));
+ }
+
+ if (vers < 0) {
+ patches.addElement(patchRoot + nextVersion + ".exe");
+ } else {
+ patches.addElement(patchRoot + vers + "-" + nextVersion + ".exe");
+ }
+
+ sizes.addElement(new Integer(size[0]));
+ vers = nextVersion;
+ }
+ }
+
+ dis.close();
+ in.close();
+ return null;
+ } catch (FileNotFoundException var20) {
+ return "system error re-opening " + localName + ": " + var20;
+ } catch (IOException var21) {
+ } finally {
+ cf.close();
+ }
+
+ return "System I/O error during upgrade processing";
+ }
+ }
+
+ public static String getLanguages(URL remoteName, Vector<String> langIDs, Vector<String> subLangIDs, int[] lSizes) {
+ if (Gamma.loadProgress != null) {
+ Gamma.loadProgress.setMessage("Downloading language support information...");
+ Gamma.loadProgress.advance();
+ }
+
+ CacheFile cf = Cache.getFile(remoteName, true);
+ cf.waitUntilLoaded();
+ if (cf.error()) {
+ return "Network error retrieving " + remoteName;
+ } else {
+ String localName = cf.getLocalName();
+
+ try {
+ FileInputStream in = new FileInputStream(localName);
+ DataInputStream dis = new DataInputStream(in);
+ String lang = null;
+ String subLang = null;
+ int sz = 0;
+ int i = 0;
+
+ String line;
+ while ((line = dis.readLine()) != null) {
+ if (line.charAt(2) != '_' && line.charAt(2) != ' ') {
+ int lastSpace = line.lastIndexOf(32);
+ lang = line.substring(0, lastSpace);
+ subLang = null;
+ int lng = line.length();
+
+ try {
+ sz = Integer.parseInt(line.substring(lastSpace + 1, lng));
+ } catch (NumberFormatException var23) {
+ System.out.println(line.substring(lastSpace, lng) + " is not quite a number");
+ }
+
+ langIDs.addElement(lang);
+ subLangIDs.addElement(subLang);
+ lSizes[i++] = sz;
+ } else {
+ lang = line.substring(0, 2);
+ subLang = line.substring(3, 5);
+ int lng = line.length();
+
+ try {
+ sz = Integer.parseInt(line.substring(6, lng));
+ } catch (NumberFormatException var24) {
+ System.out.println(line.substring(6, lng) + " is not quite a number");
+ }
+
+ langIDs.addElement(lang);
+ subLangIDs.addElement(subLang);
+ lSizes[i++] = sz;
+ }
+ }
+
+ dis.close();
+ in.close();
+ return null;
+ } catch (FileNotFoundException var25) {
+ return "system error re-opening " + localName + ": " + var25;
+ } catch (IOException var26) {
+ } finally {
+ cf.close();
+ }
+
+ return "System I/O error during upgrade processing";
+ }
+ }
+
+ private static int wantUpdate(Vector<Integer> numbers, Vector<Integer> sizes, boolean first, String name, String info) {
+ name = WorldsMarkPart.getExternalName(name);
+ if (!Gamma.shaperEnabled()) {
+ return numbers.size();
+ } else {
+ Vector<String> names = new Vector<String>();
+
+ for (int i = 0; i < sizes.size(); i++) {
+ names.addElement("Rev " + numbers.elementAt(i));
+ }
+
+ return new UpgradeDialog(names, sizes, first, name, info, true).confirmUpgradeFromList();
+ }
+ }
+
+ private static Vector<String> needUpdate(int gdkTo, Vector<Integer> sizes, Vector<String> names) {
+ Vector<String> versionList = new Vector<String>();
+ Vector<Integer> versionNumList = new Vector<Integer>();
+ sizes.removeAllElements();
+ int curVersion = Std.getVersion();
+ String err = getVersions(
+ URL.make(uServer + "upgrades.lst"), curVersion, "gdkup", versionNumList, versionList, sizes, Std.getProductName(), TESTAUTOUPGRADE
+ );
+ if (err != null) {
+ System.out.println(err);
+ return versionList;
+ } else {
+ if (versionList.size() == 0 || gdkTo == 0 && (gdkTo = wantUpdate(versionNumList, sizes, false, Std.getProductName(), "")) <= 0) {
+ gdkTo = 0;
+ }
+
+ versionList.setSize(gdkTo);
+ sizes.setSize(gdkTo);
+
+ for (int i = 0; i < gdkTo; i++) {
+ names.addElement(i == gdkTo - 1 ? Std.getProductName() : null);
+ }
+
+ if (gdkTo > 0) {
+ gdkver = versionNumList.elementAt(gdkTo - 1);
+ }
+
+ return versionList;
+ }
+ }
+
+ public static int getCurrentVersionOfWorld(String worldDir, int curVersion) {
+ if (worldDir.equals("")) {
+ return curVersion;
+ } else {
+ try {
+ DataInputStream dis = new DataInputStream(new FileInputStream(worldDir + "\\ver.txt"));
+ String line = dis.readLine();
+ int lineStart = 0;
+ if (line.charAt(0) == '+') {
+ lineStart = line.indexOf(32) + 1;
+ }
+
+ if (line.regionMatches(true, lineStart, "internal", 0, "internal".length())) {
+ line = line.substring(lineStart + "internal".length());
+ } else if (line.regionMatches(true, lineStart, "external", 0, "external".length())) {
+ line = line.substring(lineStart + "external".length());
+ }
+
+ curVersion = Integer.parseInt(line.trim());
+ } catch (FileNotFoundException var5) {
+ } catch (IOException var6) {
+ } catch (NumberFormatException var7) {
+ System.out.println("Syntax error in " + worldDir + "\\ver.txt");
+ }
+
+ return curVersion;
+ }
+ }
+
+ private boolean listWorldUpgrades(String world, Vector<String> versionList, Vector<Integer> sizes, Vector<String> names) {
+ if (world.equals("")) {
+ return true;
+ } else {
+ int curVersion = getCurrentVersionOfWorld(world, !this.forceWorldLoad && World.isCloistered() ? -1 : -2);
+ Vector<Integer> vnumlist = new Vector<Integer>();
+ Vector<String> exelist = new Vector<String>();
+ Vector<Integer> sizelist = new Vector<Integer>();
+ String err = getVersions(
+ URL.make(getUpgradeServerURL() + world + "/" + "upgrades.lst"),
+ curVersion,
+ world + "\\" + world,
+ vnumlist,
+ exelist,
+ sizelist,
+ world,
+ TESTWORLDAUTOUPGRADE
+ );
+ if (err != null) {
+ System.out.println(err);
+ } else {
+ if (exelist.size() == 0) {
+ return false;
+ }
+
+ String name = WorldsMarkPart.getExternalName(world) + " world";
+ int verto = wantUpdate(vnumlist, sizelist, curVersion < 0, "the " + name, world + "/");
+ if (verto > 0) {
+ exelist.setSize(verto);
+ sizelist.setSize(verto);
+
+ for (int i = 0; i < verto; i++) {
+ versionList.addElement(exelist.elementAt(i));
+ sizes.addElement(sizelist.elementAt(i));
+ names.addElement(i == verto - 1 ? name : null);
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ public static int maxInstalledWorlds() {
+ if (maxworld == -1) {
+ IniFile ini = new IniFile("InstalledWorlds");
+ maxworld = ini.getIniInt("MaxInstalledWorlds", 0);
+ ini.setIniInt("MaxInstalledWorlds", maxworld);
+ }
+
+ return maxworld + 50;
+ }
+
+ public static void maxInstalledWorld(int n) {
+ if (maxworld == -1) {
+ maxInstalledWorlds();
+ }
+
+ if (n > maxworld) {
+ maxworld = n;
+ IniFile ini = new IniFile("InstalledWorlds");
+ ini.setIniInt("MaxInstalledWorlds", maxworld);
+ }
+ }
+
+ public static Vector<String> aboutWorlds() {
+ Vector<String> result = new Vector<String>();
+ IniFile ini = new IniFile("InstalledWorlds");
+
+ for (int worldNum = 0; worldNum < maxInstalledWorlds(); worldNum++) {
+ String name = ini.getIniString("InstalledWorld" + worldNum, "").trim();
+ int curVersion = getCurrentVersionOfWorld(name, -1);
+ name = WorldsMarkPart.getExternalName(name);
+ if (curVersion >= 0) {
+ result.addElement(name + " version " + curVersion);
+ maxInstalledWorld(worldNum);
+ }
+ }
+
+ return result;
+ }
+
+ private static String getRestartCmd() {
+ String restartCmd = "WorldsPlayer.exe";
+ return restartCmd + " world:restart";
+ }
+
+ private static boolean hasString(Vector<String> v, String s) {
+ int j = v.size();
+
+ do {
+ j--;
+ } while (j >= 0 && !s.equals(v.elementAt(j)));
+
+ return j >= 0;
+ }
+
+ private static Vector<String> getLinesFromScriptFile(String restartCmd) {
+ Vector<String> lines = new Vector<String>();
+ String scrFile = IniFile.gamma().getIniString("RunUpgrade", "");
+ if (!scrFile.equals("")) {
+ DataInputStream dis = null;
+
+ try {
+ dis = new DataInputStream(new FileInputStream(scrFile));
+
+ String line;
+ while ((line = dis.readLine()) != null) {
+ if (restartCmd == null || !line.equals(restartCmd)) {
+ lines.addElement(line.trim());
+ }
+ }
+ } catch (IOException var13) {
+ } finally {
+ if (dis != null) {
+ try {
+ dis.close();
+ } catch (IOException var12) {
+ }
+ }
+ }
+ }
+
+ return lines;
+ }
+
+ private static void writeScriptFile(Vector<String> lines, Vector<String> patches, String restartCmd) {
+ String scrFile = "updates.lst";
+ int count = patches.size();
+
+ for (int i = 0; i < count; i++) {
+ String line = patches.elementAt(i);
+ if (!hasString(lines, line)) {
+ FileInputStream in = null;
+ boolean needsPatch = false;
+
+ try {
+ in = new FileInputStream(line);
+ byte[] bytes = new byte[4];
+ int bytesRead = in.read(bytes);
+
+ assert bytesRead == bytes.length;
+
+ needsPatch = bytes[0] == 37 && bytes[1] == 88 && bytes[2] == 68 && bytes[3] == 90;
+ } catch (IOException var21) {
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException var19) {
+ }
+ }
+ }
+
+ if (needsPatch) {
+ String tempName = line + "-xdelta";
+ new File(line).renameTo(new File(tempName));
+ lines.addElement("./bin/xdelta patch " + tempName + " bin/xup.template " + line);
+ }
+
+ lines.addElement(line);
+ }
+ }
+
+ if (restartCmd != null) {
+ lines.addElement(restartCmd);
+ }
+
+ IniFile.gamma().setIniString("RunUpgrade", "");
+
+ try {
+ PrintStream ps = new PrintStream(new FileOutputStream(scrFile));
+ count = lines.size();
+
+ for (int ix = 0; ix < count; ix++) {
+ ps.println(lines.elementAt(ix));
+ }
+
+ ps.close();
+ IniFile.gamma().setIniString("RunUpgrade", "updates.lst");
+ } catch (IOException var20) {
+ Console.println(Console.message("No-write-upgrade"));
+ }
+ }
+
+ private static boolean loadPatchesAndUpdateScript(Vector<String> patches, String restartCmd, Vector<Integer> sizes, Vector<String> names, String worldDir) {
+ Vector<String> alreadyListed = getLinesFromScriptFile(restartCmd);
+ int i = patches.size();
+
+ while (--i >= 0) {
+ String p = patches.elementAt(i);
+ if (hasString(alreadyListed, p)) {
+ patches.removeElementAt(i);
+ sizes.removeElementAt(i);
+ names.removeElementAt(i);
+ }
+ }
+
+ Vector<URL> urls = new Vector<URL>();
+ Vector<Integer> bytes = new Vector<Integer>();
+ Vector<String> condensedNames = new Vector<String>();
+ int entrySize = 0;
+ int totalSize = 0;
+ boolean willNeedRegistry = false;
+
+ for (int ix = 0; ix < sizes.size(); ix++) {
+ String name = patches.elementAt(ix);
+ String dnld = (uServer + name).replace('\\', '/');
+ urls.addElement(URL.make(dnld));
+ if (name.indexOf(45) < 0) {
+ willNeedRegistry = true;
+ }
+
+ entrySize += sizes.elementAt(ix);
+ if (names.elementAt(ix) != null) {
+ totalSize += entrySize;
+ bytes.addElement(new Integer(entrySize));
+ entrySize = 0;
+ condensedNames.addElement(names.elementAt(ix));
+ }
+ }
+
+ assert entrySize == 0;
+
+ if (totalSize == 0) {
+ return true;
+ } else {
+ if (!Gamma.shaperEnabled()) {
+ String prodName = worldDir != null ? "the " + worldDir + " world" : Std.getProductName();
+ Vector<String> rjctdList = new UpgradeDialog(condensedNames, bytes, worldDir != null, prodName, "", false).rejectedList();
+ int ix = rjctdList.size();
+
+ while (--ix >= 0) {
+ String s = rjctdList.elementAt(ix);
+ int j = names.size();
+
+ while (--j >= 0) {
+ String t = names.elementAt(j);
+ if (t != null && s.equals(t)) {
+ break;
+ }
+ }
+
+ assert j >= 0;
+
+ do {
+ totalSize -= sizes.elementAt(j);
+ patches.removeElementAt(j);
+ urls.removeElementAt(j);
+ sizes.removeElementAt(j);
+ j--;
+ } while (j >= 0 && names.elementAt(j) == null);
+ }
+ }
+
+ if (totalSize == 0) {
+ return false;
+ } else {
+ try {
+ if (!new ProgressDialog(totalSize).loadFiles(patches, urls)) {
+ return false;
+ }
+ } catch (IOException var19) {
+ warnUser("Error creating upgrade script, upgrade failed");
+ System.out.println("error creating scriptfile " + var19);
+ return false;
+ }
+
+ writeScriptFile(alreadyListed, patches, restartCmd);
+ if (willNeedRegistry) {
+ try {
+ String intExt = isInternalVersion() ? "InternalGDK" : "3DCD";
+ RegKey root = RegKey.getRootKey(2);
+ RegKey key = new RegKey(root, "SOFTWARE\\Worlds, Inc.\\" + intExt, 0);
+ String here = URL.homeUnalias("x");
+ here = here.substring(0, here.length() - 2);
+ key.setStringValue("InstallDir", here, false);
+ key.close();
+ } catch (RegKeyNotFoundException var18) {
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+
+ private static boolean getUpdates(Vector<String> patches, Vector<Integer> sizes, Vector<String> names, String wd) {
+ String restartCmd = getRestartCmd();
+ if (restartCmd == null) {
+ notifyUser(Console.message("Automatic-restart"));
+ }
+
+ synchronized (updateLoadSyncer) {
+ if (!loadPatchesAndUpdateScript(patches, restartCmd, sizes, names, wd)) {
+ return false;
+ }
+ }
+
+ if (new NewVersionDialog().confirmRestart() && runUpdates("updates.lst")) {
+ Main.end();
+ }
+
+ return true;
+ }
+
+ private static native boolean CreateProcSpecial(String var0, String var1);
+
+ private static boolean runUpdates(String upgradeScript) {
+ IniFile.gamma().setIniString("RunUpgrade", "");
+ if (!CreateProcSpecial(".\\bin\\gdkup.exe", upgradeScript)) {
+ System.out.println("error running .\\bin\\gdkup.exe");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void run() {
+ if (this.worldToUpdate != null) {
+ this.asyncWorldCheck(this.worldToUpdate);
+ } else {
+ int gdkTo = 0;
+ if (TESTAUTOUPGRADE != 0 || TESTWORLDAUTOUPGRADE != 0) {
+ this._force = true;
+ }
+
+ if (timeToUpdate(this._force)) {
+ notifyUser(Console.message("Checking-network"));
+ Vector<Integer> sizes = new Vector<Integer>();
+ Vector<String> names = new Vector<String>();
+ Vector<String> updateList = needUpdate(gdkTo, sizes, names);
+ IniFile ini = new IniFile("InstalledWorlds");
+
+ for (int i = 0; i < maxInstalledWorlds(); i++) {
+ String name = ini.getIniString("InstalledWorld" + i, "").trim();
+ if (name.length() > 0) {
+ this.listWorldUpgrades(name, updateList, sizes, names);
+ maxInstalledWorld(i);
+ }
+ }
+
+ if (updateList.size() != 0 && getUpdates(updateList, sizes, names, null)) {
+ notifyUser(Console.message("finished-checking"));
+ } else {
+ notifyUser(Console.message("no-updates"));
+ }
+
+ IniFile.gamma().setIniInt("LastUpgradeCheck", _today);
+ }
+
+ beenCalled = false;
+ }
+ }
+
+ public static void loadWorld(String worldDir, boolean forceWorldLoad) {
+ if (worldDir.equals("chaos")) {
+ worldDir = "Chaos";
+ }
+
+ NetUpdate nu = new NetUpdate(worldDir, forceWorldLoad);
+ Thread t = new Thread(nu);
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public void asyncWorldCheck(String worldDir) {
+ if (getCurrentVersionOfWorld(worldDir, -1) < 0) {
+ Vector<Integer> sizes = new Vector<Integer>();
+ Vector<String> updateList = new Vector<String>();
+ Vector<String> names = new Vector<String>();
+ if (this.listWorldUpgrades(worldDir, updateList, sizes, names)) {
+ if (updateList.size() != 0 && getUpdates(updateList, sizes, names, worldDir)) {
+ notifyUser(worldDir + Console.message("download-finished"));
+ }
+ } else {
+ notifyUser(worldDir + Console.message("custom-world"));
+ }
+ }
+ }
+
+ private static synchronized boolean busy() {
+ if (beenCalled) {
+ return true;
+ } else {
+ beenCalled = true;
+ return false;
+ }
+ }
+
+ public static boolean doUpdate(boolean force) {
+ if (busy()) {
+ if (force) {
+ notifyUser(Console.message("Upgrade-progress"));
+ }
+
+ return false;
+ } else {
+ _today = (int)(new Date().getTime() / 86400000L);
+ String upgradeScript = IniFile.gamma().getIniString("RunUpgrade", "");
+ if (!force && !upgradeScript.equals("")) {
+ if (runUpdates(upgradeScript)) {
+ return true;
+ }
+
+ beenCalled = false;
+ } else {
+ if (InternetConnectionDialog.choseSingleUserMode() && !force) {
+ return false;
+ }
+
+ if (!force && IniFile.gamma().getIniInt("CheckUpgrades", 1) == 0) {
+ notifyUser(Console.message("Check-for-up-opt"));
+ beenCalled = false;
+ } else {
+ Thread t = new Thread(new NetUpdate(force));
+ t.setDaemon(true);
+ t.start();
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/network/NetworkMulti.java b/NET/worlds/network/NetworkMulti.java
new file mode 100644
index 0000000..0b587fa
--- /dev/null
+++ b/NET/worlds/network/NetworkMulti.java
@@ -0,0 +1,106 @@
+package NET.worlds.network;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class NetworkMulti implements NetworkObject {
+ String _longID;
+ Vector<NetworkObject> _list;
+ Galaxy _galaxy;
+
+ public NetworkMulti(String longID, Galaxy g) {
+ this._longID = longID;
+ this._list = new Vector<NetworkObject>();
+ this._galaxy = g;
+ this.register();
+ }
+
+ public NetworkMulti(String longID, NetworkMulti oldObj, Galaxy g) {
+ this._longID = longID;
+ this._list = oldObj.getList();
+ this._galaxy = g;
+ this.register();
+ }
+
+ Vector<NetworkObject> getList() {
+ return this._list;
+ }
+
+ @Override
+ public String getLongID() {
+ return this._longID;
+ }
+
+ @Override
+ public WorldServer getServer() {
+ assert false;
+
+ return null;
+ }
+
+ public Enumeration<NetworkObject> elements() {
+ return this._list.elements();
+ }
+
+ void addObject(NetworkObject obj) {
+ this._list.addElement(obj);
+ }
+
+ void delObject(NetworkObject obj) {
+ boolean exists = this._list.removeElement(obj);
+ if (!exists) {
+ System.out.println("Error - network object doesn't exist.");
+ System.out.println(" obj = " + obj);
+ System.out.println(" longID = " + this._longID);
+ System.out.println(" galaxy = " + this._galaxy);
+ System.out.println(" size(list) = " + this._list.size());
+ }
+
+ assert exists;
+ }
+
+ @Override
+ public void property(OldPropertyList propList) {
+ for (int i = this._list.size() - 1; i >= 0; i--) {
+ NetworkObject obj = this._list.elementAt(i);
+ obj.property(propList);
+ }
+ }
+
+ @Override
+ public void propertyUpdate(PropertyList propList) {
+ for (int i = this._list.size() - 1; i >= 0; i--) {
+ NetworkObject obj = this._list.elementAt(i);
+ obj.propertyUpdate(propList);
+ }
+ }
+
+ @Override
+ public void register() {
+ this._galaxy.regObject(this._longID, this);
+ }
+
+ @Override
+ public void galaxyDisconnected() {
+ for (int i = this._list.size() - 1; i >= 0; i--) {
+ NetworkObject obj = this._list.elementAt(i);
+ obj.galaxyDisconnected();
+ }
+ }
+
+ @Override
+ public void reacquireServer(WorldServer oldServ) {
+ for (int i = this._list.size() - 1; i >= 0; i--) {
+ NetworkObject obj = this._list.elementAt(i);
+ obj.reacquireServer(oldServ);
+ }
+ }
+
+ @Override
+ public void changeChannel(Galaxy g, String oldChannel, String newChannel) {
+ for (int i = this._list.size() - 1; i >= 0; i--) {
+ NetworkObject obj = this._list.elementAt(i);
+ obj.changeChannel(g, oldChannel, newChannel);
+ }
+ }
+}
diff --git a/NET/worlds/network/NetworkNobody.java b/NET/worlds/network/NetworkNobody.java
new file mode 100644
index 0000000..6f34512
--- /dev/null
+++ b/NET/worlds/network/NetworkNobody.java
@@ -0,0 +1,67 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Room;
+
+public class NetworkNobody {
+ String _longID;
+ WorldServer _server;
+
+ public NetworkNobody(String longID, WorldServer server) {
+ this._longID = longID;
+ this._server = server;
+ }
+
+ public WorldServer getServer() {
+ return this._server;
+ }
+
+ public String getLongID() {
+ return this._longID;
+ }
+
+ public void appear(Room rm, short x, short y, short z, short yaw) {
+ assert false;
+ }
+
+ public void disappear() {
+ assert false;
+ }
+
+ public void longLoc(short x, short y, short z, short yaw) {
+ assert false;
+ }
+
+ public void roomChange(Room newRoom, short x, short y, short z, short yaw) {
+ assert false;
+ }
+
+ public void shortLoc(byte dx, byte dy, byte dyaw) {
+ assert false;
+ }
+
+ public void teleport(WorldServer serv, byte exitType, byte entryType, Room newRoom, short x, short y, short z, short yaw) {
+ assert false;
+ }
+
+ public void property(OldPropertyList propList) {
+ }
+
+ public void propertyUpdate(PropertyList propList) {
+ }
+
+ public void register() {
+ assert false;
+ }
+
+ public void galaxyDisconnected() {
+ assert false;
+ }
+
+ public void reacquireServer(WorldServer oldServ) {
+ assert false;
+ }
+
+ public void changeChannel(Galaxy g, String oldChannel, String newChannel) {
+ assert false;
+ }
+}
diff --git a/NET/worlds/network/NetworkObject.java b/NET/worlds/network/NetworkObject.java
new file mode 100644
index 0000000..f52d497
--- /dev/null
+++ b/NET/worlds/network/NetworkObject.java
@@ -0,0 +1,19 @@
+package NET.worlds.network;
+
+public interface NetworkObject {
+ void property(OldPropertyList var1);
+
+ void propertyUpdate(PropertyList var1);
+
+ WorldServer getServer();
+
+ String getLongID();
+
+ void register();
+
+ void galaxyDisconnected();
+
+ void reacquireServer(WorldServer var1);
+
+ void changeChannel(Galaxy var1, String var2, String var3);
+}
diff --git a/NET/worlds/network/NetworkRoom.java b/NET/worlds/network/NetworkRoom.java
new file mode 100644
index 0000000..ec8d2bc
--- /dev/null
+++ b/NET/worlds/network/NetworkRoom.java
@@ -0,0 +1,483 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.Std;
+import NET.worlds.scape.Room;
+import NET.worlds.scape.RoomSubscribeInfo;
+import NET.worlds.scape.World;
+
+public class NetworkRoom implements NetworkObject, ConnectionWaiter {
+ private static final int STATE_DISCONNECTED = 0;
+ private static final int STATE_CONNECTING = 1;
+ private static final int STATE_GETTINGROOMID = 2;
+ private static final int STATE_CONNECTED = 3;
+ private static final int STATE_SUBSCRIBED = 4;
+ private static int _debugLevel = IniFile.gamma().getIniInt("roomdebug", 0);
+ Room _room;
+ String _worldName;
+ String _roomName;
+ String _longID;
+ Galaxy _galaxy;
+ String _debug1;
+ String _debug2;
+ private RoomSubscribeInfo _lastRSInfo = null;
+ private URL _serverURL = null;
+ private WorldServer _server = null;
+ private int _roomID = 0;
+ private boolean _wantsToBeSubscribed = false;
+ private int _serverState = 0;
+
+ static {
+ if (_debugLevel > 0) {
+ System.out.println("ROOM DEBUGGING LEVEL = " + _debugLevel);
+ }
+ }
+
+ public NetworkRoom(Room room) {
+ this._room = room;
+ this._debug1 = "";
+ this._debug2 = "";
+ this._galaxy = room.getGalaxy();
+ this.initNames();
+ this.register();
+ }
+
+ synchronized void initNames() {
+ this._roomName = this._room.getName();
+ World world = this._room.getWorld();
+ this._worldName = world.getName();
+ Galaxy galaxy = this._room.getGalaxy();
+ String channel = galaxy.getChannel();
+ if (channel.length() != 0) {
+ channel = "<" + channel + ">";
+ }
+
+ this._longID = this._worldName + "#" + this._roomName + channel;
+ }
+
+ public Room getRoom() {
+ return this._room;
+ }
+
+ public synchronized void setName(String newName) {
+ assert newName != this._roomName;
+
+ this.unregister();
+ this.initNames();
+ this.register();
+ }
+
+ void unregister() {
+ Galaxy tmpGalaxy = this._room.getGalaxy();
+
+ assert tmpGalaxy != null;
+
+ assert this._galaxy == tmpGalaxy;
+
+ tmpGalaxy.delObject(this._longID);
+ if (this._roomID != 0) {
+ tmpGalaxy.delRoomID(this._roomID, this);
+ }
+
+ this._debug2 = "";
+ this._roomID = 0;
+ }
+
+ public synchronized void detach() {
+ this.unregister();
+ this._galaxy = null;
+ this._room = null;
+ }
+
+ @Override
+ public String getLongID() {
+ return this._longID;
+ }
+
+ public int getRoomID() {
+ return this._roomID;
+ }
+
+ public boolean isServed() {
+ return this._serverState == 4;
+ }
+
+ public synchronized void serverRedirect(WorldServer serv, String roomName, ServerURL serverURL) {
+ if (this._server != null) {
+ if (serv.getGalaxy() == this._server.getGalaxy()) {
+ if (roomName.equals(this._longID)) {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": serverRedirect(" + serverURL + ")");
+ }
+
+ this._serverState = 3;
+ int tmpRoomID = this._roomID;
+ this.disconnect();
+
+ assert this._server == null;
+
+ this._roomID = tmpRoomID;
+ this._debug2 = this._debug2 + "; [" + Std.getRealTime() + "]: serverDirect(" + serv + ")";
+ this._serverURL = URL.make(serverURL.toString());
+ if (this._roomID != 0) {
+ this._room.getGalaxy().setRoomID(this._roomID, this);
+ }
+
+ if (this._wantsToBeSubscribed) {
+ this.acquireServer();
+ }
+ }
+ }
+ }
+ }
+
+ public synchronized void setRoomID(WorldServer serv, int roomID, String roomName, boolean willRedirect) {
+ assert serv != null;
+
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._longID + ": setRoomID(" + serv + ", " + roomID + ", " + roomName + ", " + willRedirect + ")");
+ System.out.println("last request made: " + this._debug1);
+ }
+
+ if (serv.getGalaxy() != this._server.getGalaxy()) {
+ System.out.println(this._longID + ": setRoomID(" + serv + ", " + roomID + ", " + roomName + ", " + willRedirect + ")");
+ System.out.println("\twas expecting server " + this._server);
+ System.out.println("last request made: " + this._debug1);
+ new Exception().printStackTrace(System.out);
+ }
+
+ if (serv.getGalaxy() == this._server.getGalaxy()) {
+ if (roomName.equals(this._longID)) {
+ if (roomID == 0) {
+ this._serverState = 0;
+ this.reacquireServer(serv);
+ } else {
+ if (this._roomID == 0) {
+ this._roomID = roomID;
+ this._debug2 = this._debug2 + "; [" + Std.getRealTime() + "]: setRoomID(" + serv + ", " + willRedirect + ")";
+ }
+
+ assert this._roomID == roomID;
+
+ this._serverState = 3;
+ if (!willRedirect) {
+ if (this._wantsToBeSubscribed) {
+ assert this._lastRSInfo != null;
+
+ this.subscribe();
+ } else {
+ this.disconnect();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public synchronized void subscribe(RoomSubscribeInfo info) {
+ assert this._galaxy == this._room.getGalaxy();
+
+ if ((_debugLevel & 1) > 0) {
+ System.out.println(this._room.getName() + ": subscribe(Info)");
+ }
+
+ assert this._room.getWorld() != null;
+
+ assert this._serverState != 4;
+
+ this._lastRSInfo = info;
+ this._wantsToBeSubscribed = true;
+ switch (this._serverState) {
+ case 0:
+ this.acquireServer();
+ case 1:
+ case 2:
+ default:
+ break;
+ case 3:
+ this.subscribe();
+ }
+ }
+
+ private void subscribe() {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println(this._room.getName() + ": subscribe()");
+ }
+
+ assert this._server != null;
+
+ assert this._wantsToBeSubscribed;
+
+ assert this._lastRSInfo != null;
+
+ assert this._roomID != 0;
+
+ assert this._serverState == 3;
+
+ assert this._room.getWorld() != null;
+
+ this._serverState = 4;
+ this.sendNetworkMsg(new SubscribeRoomCmd(this._lastRSInfo, this._roomID));
+ }
+
+ private void sendNetworkMsg(netPacket msg) {
+ assert this._server != null;
+
+ try {
+ this._server.sendNetworkMsg(msg);
+ } catch (InfiniteWaitException var3) {
+ this.disconnect();
+ } catch (PacketTooLargeException var4) {
+ assert false;
+ }
+ }
+
+ public synchronized void subscribeDist(RoomSubscribeInfo info) {
+ this._lastRSInfo = info;
+
+ assert this._wantsToBeSubscribed;
+
+ assert this._room.getWorld() != null;
+
+ if (this._serverState == 4) {
+ this.sendNetworkMsg(new SubscribeDistCmd(info.d, this._roomID));
+ }
+ }
+
+ public synchronized void unsubscribe() {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println(this._room.getName() + ": unsubscribe()");
+ }
+
+ assert this._wantsToBeSubscribed;
+
+ this._wantsToBeSubscribed = false;
+ this._lastRSInfo = null;
+ switch (this._serverState) {
+ case 0:
+ case 3:
+ default:
+ break;
+ case 1:
+ assert this._server != null;
+
+ this._server.abortWaitForConnection(this);
+ this.disconnect();
+ break;
+ case 2:
+ this.disconnect();
+ break;
+ case 4:
+ this.sendNetworkMsg(new UnsubscribeRoomCmd(this._roomID));
+ this.disconnect();
+ }
+ }
+
+ private synchronized void disconnect() {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": disconnect()");
+ }
+
+ switch (this._serverState) {
+ case 2:
+ this._server.delRoomRequest(this._longID);
+ if (this._debug1 == null) {
+ this._debug1 = "";
+ }
+
+ this._debug1 = this._debug1 + "; [" + Std.getRealTime() + "]: deleted request for " + this._longID;
+ default:
+ this._serverURL = null;
+ if (this._server != null && this._roomID != 0) {
+ this._server.delRoomID(this._roomID, this);
+ }
+
+ this._roomID = 0;
+ this._debug2 = "";
+ if (this._server != null) {
+ this._server.decRefCnt(this);
+ this._server = null;
+ this._serverState = 0;
+ }
+
+ assert this._serverState == 0;
+ }
+ }
+
+ private synchronized void acquireServer() {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": acquireServer() - " + this._serverURL);
+ }
+
+ assert this._serverState == 0;
+
+ if (this._server == null) {
+ World world = this._room.getWorld();
+
+ assert world != null;
+
+ Galaxy galaxy = world.getConsole().getGalaxy();
+
+ assert galaxy != null;
+
+ if (this._serverURL == null) {
+ this._serverURL = world.getConsole().getGalaxyURL();
+ if (this._serverURL == null) {
+ return;
+ }
+ }
+
+ try {
+ this._server = galaxy.getServer(this._serverURL);
+ } catch (InvalidServerURLException var4) {
+ Console.println(">> " + var4.getMessage());
+ this._serverURL = null;
+ return;
+ }
+
+ if (this._server == null) {
+ return;
+ }
+
+ this._server.incRefCnt(this);
+ }
+
+ this._serverState = 1;
+ this._server.waitForConnection(this);
+ }
+
+ @Override
+ public void connectionCallback(Object caller, boolean connected) {
+ if (caller instanceof WorldServer) {
+ WorldServer serv = (WorldServer)caller;
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": connectionCallback(" + serv + ", connected=" + connected + ") _server=" + this._server);
+ }
+
+ if (this._server == serv) {
+ if (!connected) {
+ this.disconnect();
+ } else {
+ if (this._roomID == 0) {
+ synchronized (this) {
+ this._serverState = 2;
+ serv.requestRoomID(this._longID, this);
+ this._debug1 = "[" + Std.getRealTime() + "] " + serv + ": requested roomID for " + this._longID;
+ }
+ } else {
+ this.setRoomID(serv, this._roomID, this._longID, false);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void property(OldPropertyList propList) {
+ for (int i = 0; i < propList.size(); i++) {
+ netProperty p = propList.elementAt(i);
+ byte[] data = new byte[p.value().length()];
+ p.value().getBytes(0, p.value().length(), data, 0);
+ this._room.getSharer().setFromNetData(p.property(), data);
+ }
+ }
+
+ @Override
+ public void propertyUpdate(PropertyList propList) {
+ for (int i = 0; i < propList.size(); i++) {
+ net2Property p = propList.elementAt(i);
+ this._room.getSharer().setFromNetData(p.property(), p.data());
+ }
+ }
+
+ @Override
+ public WorldServer getServer() {
+ return this._server;
+ }
+
+ @Override
+ public void register() {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": register()");
+ }
+
+ assert this._room.getWorld() != null;
+
+ Galaxy tmpGalaxy = this._room.getGalaxy();
+
+ assert tmpGalaxy != null;
+
+ tmpGalaxy.regObject(this._longID, this);
+ this._galaxy = tmpGalaxy;
+ if (this._serverState != 0) {
+ this.disconnect();
+ }
+
+ this._serverURL = null;
+ if (this._wantsToBeSubscribed) {
+ this.acquireServer();
+ }
+ }
+
+ @Override
+ public void galaxyDisconnected() {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": galaxyDisconnected()");
+ }
+
+ synchronized (this) {
+ if (this._server != null) {
+ this.reacquireServer(this._server);
+ }
+ }
+ }
+
+ @Override
+ public void reacquireServer(WorldServer oldServ) {
+ if (this._debug1 == null) {
+ this._debug1 = "";
+ }
+
+ this._debug1 = this._debug1 + "; [" + Std.getRealTime() + "]: reacquireServer(" + this._server + ", " + oldServ + ")";
+ if (this._server == oldServ) {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": reacquireServer()");
+ }
+
+ this.disconnect();
+ if (this._wantsToBeSubscribed) {
+ this.acquireServer();
+ }
+ }
+ }
+
+ @Override
+ public synchronized void changeChannel(Galaxy tmpGalaxy, String oldChannel, String newChannel) {
+ if ((_debugLevel & 2) > 0) {
+ System.out.println(this._room.getName() + ": changeChannel(" + oldChannel + " -> " + newChannel + ")");
+ }
+
+ boolean wantsToBeSubscribed = this._wantsToBeSubscribed;
+ RoomSubscribeInfo lastRSInfo = this._lastRSInfo;
+ if (wantsToBeSubscribed) {
+ this.unsubscribe();
+ }
+
+ tmpGalaxy.delObject(this._longID);
+ this.initNames();
+ this.register();
+ if (wantsToBeSubscribed) {
+ this.subscribe(lastRSInfo);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkRoom[" + this._room.getName() + "]";
+ }
+
+ public String debugStuff() {
+ return this + ": debug1 = " + this._debug1 + "\n\tdebug2 = " + this._debug2;
+ }
+}
diff --git a/NET/worlds/network/NewVersionDialog.java b/NET/worlds/network/NewVersionDialog.java
new file mode 100644
index 0000000..f651f4d
--- /dev/null
+++ b/NET/worlds/network/NewVersionDialog.java
@@ -0,0 +1,83 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.MultiLineLabel;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.Std;
+import java.awt.Button;
+import java.awt.Event;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.text.MessageFormat;
+
+public class NewVersionDialog extends PolledDialog {
+ private static final long serialVersionUID = -2091867202100838097L;
+ private Button yesButton = new Button(Console.message("Yes-Restart"));
+ private Button noButton = new Button(Console.message("No-Keep-Playing"));
+ private boolean confirmed;
+ Object[] arguments = new Object[]{new String(Std.getProductName())};
+ private String message = MessageFormat.format(Console.message("upgrade-is-now"), this.arguments);
+ private static String title = Console.message("Download-Complete");
+ private boolean done;
+
+ public NewVersionDialog() {
+ super(Console.getFrame(), null, title, false);
+ this.setAlignment(1);
+ this.readySetGo();
+ }
+
+ @Override
+ protected void build() {
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.anchor = 10;
+ c.fill = 0;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+ c.gridheight = 1;
+ this.add(gbag, new MultiLineLabel(this.message, 5, 5), c);
+ c.gridwidth = 2;
+ this.add(gbag, this.yesButton, c);
+ this.add(gbag, this.noButton, c);
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.yesButton.requestFocus();
+ }
+
+ public synchronized boolean confirmRestart() {
+ while (this.isActive()) {
+ try {
+ this.wait();
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ return this.getConfirmed();
+ }
+
+ @Override
+ protected synchronized boolean done(boolean confirmed) {
+ boolean retCode = super.done(confirmed);
+ this.notify();
+ return retCode;
+ }
+
+ @Override
+ public boolean action(Event event, Object what) {
+ if (event.target == this.yesButton) {
+ return this.done(true);
+ } else {
+ return event.target == this.noButton ? this.done(false) : false;
+ }
+ }
+
+ @Override
+ public boolean keyDown(Event event, int key) {
+ return key == 27 ? this.done(false) : super.keyDown(event, key);
+ }
+}
diff --git a/NET/worlds/network/ObjID.java b/NET/worlds/network/ObjID.java
new file mode 100644
index 0000000..d8ad62c
--- /dev/null
+++ b/NET/worlds/network/ObjID.java
@@ -0,0 +1,66 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class ObjID {
+ private int _shortObjID;
+ private String _longObjID;
+
+ public ObjID(int id) {
+ this._shortObjID = id;
+ this._longObjID = null;
+ }
+
+ public ObjID(String id) {
+ this._shortObjID = 0;
+ if (id.startsWith("!")) {
+ id = id.substring(1);
+ }
+
+ this._longObjID = id;
+ }
+
+ public ObjID() {
+ this._shortObjID = 0;
+ this._longObjID = null;
+ }
+
+ public int shortID() {
+ return this._shortObjID;
+ }
+
+ public String longID() {
+ return this._longObjID;
+ }
+
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._shortObjID = data.readUnsignedByte();
+ if (this._shortObjID == 0) {
+ this._longObjID = data.readUTF();
+ }
+ }
+
+ int packetSize() {
+ return this._longObjID != null ? 2 + ServerOutputStream.utfLength(this._longObjID) : 1;
+ }
+
+ void send(ServerOutputStream o) throws IOException {
+ if (this._longObjID != null) {
+ o.writeByte(0);
+ o.writeUTF(this._longObjID);
+ } else {
+ assert this._shortObjID == 1 || this._shortObjID >= 253;
+
+ o.writeByte(this._shortObjID);
+ }
+ }
+
+ public String toString(WorldServer serv) {
+ return this._longObjID != null ? this._longObjID : Integer.toString(this._shortObjID) + "[" + serv.getLongID(this) + "]";
+ }
+
+ @Override
+ public String toString() {
+ return this._longObjID != null ? this._longObjID : "[#" + Integer.toString(this._shortObjID) + "]";
+ }
+}
diff --git a/NET/worlds/network/ObjectMgr.java b/NET/worlds/network/ObjectMgr.java
new file mode 100644
index 0000000..31846c9
--- /dev/null
+++ b/NET/worlds/network/ObjectMgr.java
@@ -0,0 +1,70 @@
+package NET.worlds.network;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+class ObjectMgr {
+ private Hashtable<String, NetworkObject> nFlongID = new Hashtable<String, NetworkObject>();
+ private Hashtable<Integer, String> lFshortID = new Hashtable<Integer, String>();
+ private Galaxy _galaxy;
+
+ ObjectMgr(Galaxy galaxy) {
+ this._galaxy = galaxy;
+ }
+
+ void regShortID(int shortID, String longID) {
+ this.lFshortID.put(new Integer(shortID), longID);
+ }
+
+ void regObject(String longID, NetworkObject obj) {
+ this.nFlongID.put(longID, obj);
+ }
+
+ void regObject(ObjID objID, NetworkObject obj) {
+ String longID = this.getLongID(objID);
+ this.nFlongID.put(longID, obj);
+ }
+
+ NetworkObject getObject(ObjID objID) {
+ String longID = this.getLongID(objID);
+ NetworkObject obj = this.nFlongID.get(longID);
+ if (obj == null) {
+ assert this._galaxy != null;
+
+ obj = this._galaxy.getObject(longID);
+ }
+
+ return obj;
+ }
+
+ void delObject(ObjID objID) {
+ String longID = this.getLongID(objID);
+ NetworkObject obj = this.nFlongID.get(longID);
+
+ assert obj != null;
+
+ this.nFlongID.remove(longID);
+ }
+
+ Enumeration<NetworkObject> objects() {
+ return this.nFlongID.elements();
+ }
+
+ void clear() {
+ this.nFlongID.clear();
+ this.nFlongID = new Hashtable<String, NetworkObject>();
+ this.lFshortID.clear();
+ this.lFshortID = new Hashtable<Integer, String>();
+ }
+
+ final String getLongID(ObjID objID) {
+ String longID;
+ if (objID.shortID() != 0) {
+ longID = this.lFshortID.get(new Integer(objID.shortID()));
+ } else {
+ longID = objID.longID();
+ }
+
+ return longID;
+ }
+}
diff --git a/NET/worlds/network/OldPropertyList.java b/NET/worlds/network/OldPropertyList.java
new file mode 100644
index 0000000..5cb254e
--- /dev/null
+++ b/NET/worlds/network/OldPropertyList.java
@@ -0,0 +1,75 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+import java.util.Vector;
+
+public class OldPropertyList {
+ private Vector<netProperty> _propList = new Vector<netProperty>();
+
+ public void addProperty(netProperty prop) {
+ assert this.getProperty(prop.property()) == null;
+
+ this._propList.addElement(prop);
+ }
+
+ public int size() {
+ return this._propList.size();
+ }
+
+ public final netProperty elementAt(int i) {
+ return this._propList.elementAt(i);
+ }
+
+ public netProperty getProperty(int propID) {
+ for (int i = this._propList.size() - 1; i >= 0; i--) {
+ if (this.elementAt(i).property() == propID) {
+ return this.elementAt(i);
+ }
+ }
+
+ return null;
+ }
+
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._propList = new Vector<netProperty>();
+
+ while (!data.isEmpty()) {
+ netProperty tmpProp = new netProperty();
+ tmpProp.parseNetData(data);
+ this._propList.addElement(tmpProp);
+ }
+ }
+
+ int packetSize() {
+ int len = 0;
+
+ for (int i = this._propList.size() - 1; i >= 0; i--) {
+ netProperty tmpProp = this._propList.elementAt(i);
+ len += tmpProp.packetSize();
+ }
+
+ return len;
+ }
+
+ void send(ServerOutputStream o) throws IOException {
+ int maxidx = this._propList.size();
+
+ for (int i = 0; i < maxidx; i++) {
+ netProperty tmpProp = this._propList.elementAt(i);
+ tmpProp.send(o);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String out = "(";
+ int maxidx = this._propList.size();
+
+ for (int i = 0; i < maxidx; i++) {
+ netProperty tmpProp = this._propList.elementAt(i);
+ out = out + tmpProp + " ";
+ }
+
+ return out + ")";
+ }
+}
diff --git a/NET/worlds/network/P17UserServer.java b/NET/worlds/network/P17UserServer.java
new file mode 100644
index 0000000..1fa1cc2
--- /dev/null
+++ b/NET/worlds/network/P17UserServer.java
@@ -0,0 +1,12 @@
+package NET.worlds.network;
+
+public class P17UserServer extends UserServer {
+ protected P17UserServer() {
+ this._serverProtocolVersion = 17;
+ }
+
+ @Override
+ protected void state_XMIT_PROPREQ() {
+ this._state.setState(7);
+ }
+}
diff --git a/NET/worlds/network/PacketTooLargeException.java b/NET/worlds/network/PacketTooLargeException.java
new file mode 100644
index 0000000..89b928b
--- /dev/null
+++ b/NET/worlds/network/PacketTooLargeException.java
@@ -0,0 +1,14 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class PacketTooLargeException extends IOException {
+ private static final long serialVersionUID = 4415549519859917790L;
+
+ PacketTooLargeException() {
+ }
+
+ PacketTooLargeException(String msg) {
+ super(msg);
+ }
+}
diff --git a/NET/worlds/network/ProgressBar.java b/NET/worlds/network/ProgressBar.java
new file mode 100644
index 0000000..97d7d6d
--- /dev/null
+++ b/NET/worlds/network/ProgressBar.java
@@ -0,0 +1,78 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Event;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Toolkit;
+
+public class ProgressBar extends Canvas {
+ private static final long serialVersionUID = -4391762871660491011L;
+ private static final int borderThickness = 1;
+ private static final int heightPadding = 2;
+ private int barWidth;
+ private int barHeight;
+ private Font font;
+ private int fillWidth = -1;
+ private int percent;
+
+ public ProgressBar(int width) {
+ this.barWidth = width;
+ this.font = new Font(Console.message("DialogFont"), 1, 14);
+ FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(this.font);
+ this.barHeight = fm.getAscent() + 4 + 2;
+ }
+
+ public void setProgress(double amt) {
+ int visibleWidth = this.getSize().width;
+ if (visibleWidth == 0) {
+ visibleWidth = this.barWidth;
+ }
+
+ int width = (int)(amt * (visibleWidth - 2));
+ if (width != this.fillWidth) {
+ this.fillWidth = width;
+ this.percent = (int)Math.round(100.0 * amt);
+ this.repaint();
+ }
+ }
+
+ @Override
+ public Dimension preferredSize() {
+ return new Dimension(this.barWidth, this.barHeight);
+ }
+
+ @Override
+ public Dimension minimumSize() {
+ return this.preferredSize();
+ }
+
+ @Override
+ public boolean handleEvent(Event event) {
+ return event.id == 201 ? true : super.handleEvent(event);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ Dimension size = this.getSize();
+ int width = size.width;
+ int height = size.height;
+ g.setColor(Color.lightGray);
+ g.draw3DRect(0, 0, width - 1, height - 1, true);
+ if (this.fillWidth > 0) {
+ g.setColor(Color.blue);
+ g.fillRect(1, 1, this.fillWidth, height - 2);
+ }
+
+ String text = this.percent + "%";
+ g.setFont(this.font);
+ FontMetrics fm = g.getFontMetrics();
+ int textWidth = fm.stringWidth(text);
+ g.setColor(Color.black);
+ g.drawString(text, (width - textWidth) / 2, (height + fm.getAscent()) / 2 - 1);
+ }
+}
diff --git a/NET/worlds/network/ProgressDialog.java b/NET/worlds/network/ProgressDialog.java
new file mode 100644
index 0000000..85b4c20
--- /dev/null
+++ b/NET/worlds/network/ProgressDialog.java
@@ -0,0 +1,223 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.Std;
+import java.awt.Event;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Label;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+import java.util.Vector;
+
+public class ProgressDialog extends PolledDialog {
+ private static final long serialVersionUID = 7533646170494183110L;
+ private static final String bytesMsg = Console.message("Bytes-remaining");
+ private int bytesTotal;
+ private int bytesLoaded;
+ private ProgressBar progressBar;
+ private Label progressBytes;
+ private Label progressTime;
+ private int startTime = Std.getFastTime();
+ private CacheFile cf;
+ private boolean cancelled;
+ private int wholeFileBytes = 0;
+
+ public ProgressDialog(int totalSize) {
+ super(Console.getFrame(), null, Console.message("Download-Progress"), false);
+ this.bytesTotal = totalSize;
+ this.progressBar = new ProgressBar(240);
+ NumberFormat nF = NumberFormat.getNumberInstance(Locale.getDefault());
+ String strSize = nF.format((long)totalSize);
+ this.progressBytes = new Label(bytesMsg + strSize);
+ this.progressTime = new Label("");
+ this.setAlignment(1);
+ this.readySetGo();
+ }
+
+ public boolean loadFiles(Vector<String> names, Vector<URL> urls) throws IOException {
+ try {
+ int count = names.size();
+ int i = 0;
+
+ while (true) {
+ if (i >= count) {
+ return true;
+ }
+
+ synchronized (this) {
+ if (this.cancelled) {
+ NetUpdate.warnUser("Upgrade cancelled.");
+ break;
+ }
+
+ if (this.cf != null) {
+ this.wholeFileBytes = this.wholeFileBytes + this.cf.bytesLoaded();
+ }
+
+ this.cf = Cache.getFile(urls.elementAt(i));
+ }
+
+ this.cf.waitUntilLoaded();
+ if (!this.cf.isActive()) {
+ this.cf.markTemporary();
+ NetUpdate.warnUser("Upgrade cancelled.");
+ break;
+ }
+
+ if (this.cf.error()) {
+ this.cf.markTemporary();
+ NetUpdate.warnUser("Error getting upgrade info, try again later");
+ break;
+ }
+
+ copyFile(this.cf.getLocalName(), names.elementAt(i));
+ this.cf.markTemporary();
+ this.cf.close();
+ i++;
+ }
+ } finally {
+ this.done(true);
+ }
+
+ return false;
+ }
+
+ public static boolean copyFile(String from, String to) {
+ int lastSlash = to.lastIndexOf(47);
+ int lastBackslash = to.lastIndexOf(92);
+ if (lastBackslash > lastSlash) {
+ lastSlash = lastBackslash;
+ }
+
+ if (lastSlash >= 0) {
+ new File(to.substring(0, lastSlash)).mkdirs();
+ }
+
+ FileInputStream s = null;
+ FileOutputStream d = null;
+
+ try {
+ try {
+ s = new FileInputStream(from);
+ d = new FileOutputStream(to);
+ byte[] buffer = new byte[1024];
+
+ while (true) {
+ int got = s.read(buffer);
+ if (got == -1) {
+ return true;
+ }
+
+ d.write(buffer, 0, got);
+ }
+ } finally {
+ if (d != null) {
+ d.close();
+ }
+
+ if (s != null) {
+ s.close();
+ }
+ }
+ } catch (IOException var12) {
+ return false;
+ }
+ }
+
+ @Override
+ protected void build() {
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.anchor = 10;
+ c.gridwidth = 0;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ this.add(gbag, new Label(Console.message("Downloading-update")), c);
+ c.insets = new Insets(2, 2, 2, 2);
+ this.add(gbag, this.progressBar, c);
+ c.insets = new Insets(0, 2, 0, 2);
+ c.anchor = 17;
+ this.add(gbag, this.progressBytes, c);
+ c.fill = 2;
+ this.add(gbag, this.progressTime, c);
+ }
+
+ @Override
+ protected synchronized void activeCallback() {
+ int n;
+ synchronized (this) {
+ n = this.wholeFileBytes;
+ if (this.cf != null) {
+ n += this.cf.bytesLoaded();
+ }
+ }
+
+ if (n != this.bytesLoaded) {
+ this.bytesLoaded = n;
+ this.progressBar.setProgress((double)this.bytesLoaded / this.bytesTotal);
+ int bytesRemaining = this.bytesTotal - this.bytesLoaded;
+ NumberFormat nF = NumberFormat.getNumberInstance(Locale.getDefault());
+ String strRemain = nF.format((long)bytesRemaining);
+ this.progressBytes.setText(bytesMsg + strRemain);
+ int elapsed = (Std.getFastTime() - this.startTime) / 1000;
+ if (elapsed > 0) {
+ double bytesPerSec = (double)this.bytesLoaded / elapsed;
+ if (bytesPerSec > 0.0) {
+ String bps = formatTime((long)(bytesRemaining / bytesPerSec));
+ Object[] arguments = new Object[]{new String(bps)};
+ this.progressTime.setText(MessageFormat.format(Console.message("Time-remaining"), arguments));
+ }
+ }
+ }
+
+ this.notify();
+ }
+
+ @Override
+ protected boolean done(boolean confirmed) {
+ synchronized (this) {
+ this.cancelled = true;
+ if (this.cf != null) {
+ this.cf.close();
+ }
+ }
+
+ return super.done(confirmed);
+ }
+
+ private static String fmtTwoDigit(long val) {
+ return val < 10L ? "0" + val : "" + val;
+ }
+
+ private static String formatTime(long secs) {
+ String result = "";
+ long hrs = secs / 3600L;
+ secs -= hrs * 3600L;
+ long mins = secs / 60L;
+ secs -= mins * 60L;
+ if (hrs > 0L) {
+ result = result + hrs + ":";
+ }
+
+ return result + fmtTwoDigit(mins) + ":" + fmtTwoDigit(secs);
+ }
+
+ @Override
+ public boolean handleEvent(Event event) {
+ if (event.id == 1004) {
+ Console.getFrame().requestFocus();
+ return true;
+ } else {
+ return super.handleEvent(event);
+ }
+ }
+}
diff --git a/NET/worlds/network/PropertyList.java b/NET/worlds/network/PropertyList.java
new file mode 100644
index 0000000..8a83be8
--- /dev/null
+++ b/NET/worlds/network/PropertyList.java
@@ -0,0 +1,84 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+import java.io.UTFDataFormatException;
+import java.util.Vector;
+
+public class PropertyList {
+ private Vector<net2Property> _propList = new Vector<net2Property>();
+
+ public void addProperty(net2Property prop) {
+ this._propList.addElement(prop);
+ }
+
+ public int size() {
+ return this._propList.size();
+ }
+
+ public net2Property elementAt(int i) {
+ return this._propList.elementAt(i);
+ }
+
+ public net2Property getProperty(int propID) {
+ for (int i = this._propList.size() - 1; i >= 0; i--) {
+ if (this.elementAt(i).property() == propID) {
+ return this.elementAt(i);
+ }
+ }
+
+ return null;
+ }
+
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._propList = new Vector<net2Property>();
+
+ while (!data.isEmpty()) {
+ try {
+ net2Property tmpProp = new net2Property();
+ tmpProp.parseNetData(data);
+ this._propList.addElement(tmpProp);
+ } catch (UTFDataFormatException var4) {
+ System.out.println("Property list discarded; invalid UTF property.");
+ this._propList.removeAllElements();
+ data.skipBytes(data.bytesLeft());
+
+ assert data.isEmpty();
+
+ return;
+ }
+ }
+ }
+
+ int packetSize() {
+ int len = 0;
+
+ for (int i = this._propList.size() - 1; i >= 0; i--) {
+ net2Property tmpProp = this._propList.elementAt(i);
+ len += tmpProp.packetSize();
+ }
+
+ return len;
+ }
+
+ void send(ServerOutputStream o) throws IOException {
+ int maxidx = this._propList.size();
+
+ for (int i = 0; i < maxidx; i++) {
+ net2Property tmpProp = this._propList.elementAt(i);
+ tmpProp.send(o);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String out = "(";
+ int maxidx = this._propList.size();
+
+ for (int i = 0; i < maxidx; i++) {
+ net2Property tmpProp = this._propList.elementAt(i);
+ out = out + tmpProp + " ";
+ }
+
+ return out + ")";
+ }
+}
diff --git a/NET/worlds/network/PropertySetCmd.java b/NET/worlds/network/PropertySetCmd.java
new file mode 100644
index 0000000..50f7850
--- /dev/null
+++ b/NET/worlds/network/PropertySetCmd.java
@@ -0,0 +1,58 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class PropertySetCmd extends receivedNetPacket {
+ public static final byte PROPSETCMD = 15;
+ private PropertyList _propList;
+ private String _fromUser;
+
+ public PropertySetCmd() {
+ this._commandType = 15;
+ }
+
+ public PropertySetCmd(PropertyList propList) {
+ super(null, 15);
+ this._propList = propList;
+ this._fromUser = new String("");
+ }
+
+ public PropertySetCmd(ObjID objID, PropertyList propList) {
+ super(objID, 15);
+ this._propList = propList;
+ this._fromUser = new String("");
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._fromUser = data.readUTF();
+ this._propList = new PropertyList();
+ this._propList.parseNetData(data);
+ }
+
+ @Override
+ int packetSize() {
+ int len = super.packetSize();
+
+ assert this._fromUser != null;
+
+ len += 1 + ServerOutputStream.utfLength(this._fromUser);
+ return len + this._propList.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeUTF(this._fromUser);
+ this._propList.send(o);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "PROPSET \"" + this._fromUser + "\"->" + this._objID.toString(serv) + " " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/PropertyUpdateCmd.java b/NET/worlds/network/PropertyUpdateCmd.java
new file mode 100644
index 0000000..09d08f5
--- /dev/null
+++ b/NET/worlds/network/PropertyUpdateCmd.java
@@ -0,0 +1,33 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class PropertyUpdateCmd extends receivedNetPacket {
+ public static final byte PROPUPDCMD = 16;
+ protected PropertyList _propList;
+
+ public PropertyUpdateCmd() {
+ this._commandType = 16;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._propList = new PropertyList();
+ this._propList.parseNetData(data);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o != null) {
+ o.propertyUpdate(this._propList);
+ } else if ((Galaxy.getDebugLevel() & 32) != 0) {
+ System.err.println("PropertyUpdateCmd.process() status: message dropped because destination object is null");
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "PROPUPD " + this._objID.toString(serv) + " " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/RedirectCmd.java b/NET/worlds/network/RedirectCmd.java
new file mode 100644
index 0000000..21d2660
--- /dev/null
+++ b/NET/worlds/network/RedirectCmd.java
@@ -0,0 +1,40 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class RedirectCmd extends receivedNetPacket {
+ public static final byte REDIRECTCMD = 25;
+ protected int _roomNumber;
+ protected int _ip1;
+ protected int _ip2;
+ protected int _ip3;
+ protected int _ip4;
+ protected int _port;
+
+ public RedirectCmd() {
+ this._commandType = 25;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._roomNumber = data.readUnsignedShort();
+ this._ip1 = data.readUnsignedByte();
+ this._ip2 = data.readUnsignedByte();
+ this._ip3 = data.readUnsignedByte();
+ this._ip4 = data.readUnsignedByte();
+ this._port = data.readUnsignedShort();
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ }
+
+ String toStringHlpr() {
+ return this._roomNumber + " -> " + this._ip1 + "." + this._ip2 + "." + this._ip3 + "." + this._ip4 + ":" + this._port;
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "REDIRECT " + this.toStringHlpr();
+ }
+}
diff --git a/NET/worlds/network/RedirectIDCmd.java b/NET/worlds/network/RedirectIDCmd.java
new file mode 100644
index 0000000..b6fbbc8
--- /dev/null
+++ b/NET/worlds/network/RedirectIDCmd.java
@@ -0,0 +1,31 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class RedirectIDCmd extends RedirectCmd {
+ public static final byte REDIRECTIDCMD = 26;
+ protected String _roomName;
+
+ public RedirectIDCmd() {
+ this._commandType = 26;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._roomName = data.readUTF();
+ super.parseNetData(data);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ _serv.regRoomID(this._roomNumber, this._roomName, true);
+ String s = "worldserver://" + this._ip1 + "." + this._ip2 + "." + this._ip3 + "." + this._ip4 + ":" + this._port + "/RoomServer";
+ ServerURL url = new ServerURL(s);
+ _serv.redirectRoom(this._roomName, url);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "REDIRID " + this._roomName + "==" + super.toStringHlpr();
+ }
+}
diff --git a/NET/worlds/network/RemoteFileConst.java b/NET/worlds/network/RemoteFileConst.java
new file mode 100644
index 0000000..bb2100e
--- /dev/null
+++ b/NET/worlds/network/RemoteFileConst.java
@@ -0,0 +1,7 @@
+package NET.worlds.network;
+
+public interface RemoteFileConst {
+ String INI_WORLD_SECTION = "InstalledWorlds";
+ String INSTALLED_WORLD_TEMPLATE = "InstalledWorld";
+ String MAX_INSTALLED_WORLDS_TEMPLATE = "MaxInstalledWorlds";
+}
diff --git a/NET/worlds/network/RoomMgr.java b/NET/worlds/network/RoomMgr.java
new file mode 100644
index 0000000..24d366f
--- /dev/null
+++ b/NET/worlds/network/RoomMgr.java
@@ -0,0 +1,82 @@
+package NET.worlds.network;
+
+import NET.worlds.core.Std;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+class RoomMgr {
+ Hashtable<Integer, NetworkRoom> _roomFRoomID = new Hashtable<Integer, NetworkRoom>();
+ Hashtable<String, NetworkRoom> _requestList = null;
+ int _requestCount = 0;
+
+ public RoomMgr() {
+ }
+
+ public synchronized void addRequest(String roomName, NetworkRoom room) {
+ if (this._requestCount == 0) {
+ this._requestList = new Hashtable<String, NetworkRoom>();
+ }
+
+ assert this._requestList.get(roomName) == null;
+
+ this._requestList.put(roomName, room);
+ this._requestCount++;
+ }
+
+ public synchronized void delRequest(String roomName) {
+ if (this._requestList == null) {
+ System.out.println(this + ": delRequest() - " + roomName);
+ new Exception().printStackTrace(System.out);
+ } else {
+ this._requestCount--;
+ this._requestList.remove(roomName);
+ if (this._requestCount == 0) {
+ this._requestList = null;
+ }
+ }
+ }
+
+ public synchronized NetworkRoom getRequest(String roomName) {
+ if (this._requestList == null) {
+ return null;
+ } else {
+ NetworkRoom tmpRoom = this._requestList.get(roomName);
+ if (tmpRoom != null) {
+ this.delRequest(roomName);
+ }
+
+ return tmpRoom;
+ }
+ }
+
+ public void regRoomID(int roomID, NetworkRoom room) {
+ NetworkRoom noRoom = this._roomFRoomID.get(new Integer(roomID));
+ if (noRoom != null && noRoom != room) {
+ System.out.println("[" + Std.getRealTime() + "]: Weird - room is already registered.");
+ System.out.println("new roomID = " + roomID + ", new room = " + room);
+ System.out.println(room.debugStuff());
+ System.out.println("old room is " + noRoom);
+ System.out.println(noRoom.debugStuff());
+ new Exception().printStackTrace(System.out);
+ }
+
+ this._roomFRoomID.put(new Integer(roomID), room);
+ }
+
+ public void delRoomID(int roomID, NetworkRoom delRoom) {
+ NetworkRoom room = this._roomFRoomID.remove(new Integer(roomID));
+ if (room == null) {
+ System.out.println("Error - deleting a bad roomID: " + roomID);
+ System.out.println(delRoom.debugStuff());
+ new Exception().printStackTrace(System.out);
+ }
+ }
+
+ public NetworkRoom getRoom(int roomID) {
+ return roomID == 0 ? null : this._roomFRoomID.get(new Integer(roomID));
+ }
+
+ public Enumeration<NetworkRoom> rooms() {
+ return this._roomFRoomID.elements();
+ }
+}
diff --git a/NET/worlds/network/RoomServer.java b/NET/worlds/network/RoomServer.java
new file mode 100644
index 0000000..02f80ea
--- /dev/null
+++ b/NET/worlds/network/RoomServer.java
@@ -0,0 +1,68 @@
+package NET.worlds.network;
+
+import NET.worlds.core.IniFile;
+
+public class RoomServer extends AnonRoomServer {
+ @Override
+ public synchronized void incRefCnt(Object referrer) {
+ super.incRefCnt(referrer);
+ this.startConnect();
+ }
+
+ protected void state_Authprompt() {
+ this._state.setState(3);
+ }
+
+ @Override
+ protected sessionInitCmd buildSessionInitCmd() {
+ OldPropertyList props = new OldPropertyList();
+ String username = null;
+ props.addProperty(new netProperty(3, String.valueOf(this.getVersion())));
+ props.addProperty(new netProperty(9, String.valueOf(this._clientVersion)));
+ this._firstLogon = this._galaxy.addPendingServer(this);
+ if (this._firstLogon) {
+ return null;
+ } else {
+ int avatars = IniFile.gamma().getIniInt("avatars", 24);
+ props.addProperty(new netProperty(7, Integer.toString(avatars)));
+
+ assert this._galaxy.getChatname() != null;
+
+ username = this._galaxy.getChatname();
+ this.regShortID(1, username);
+ props.addProperty(new netProperty(2, username));
+ if (this._galaxy.getLoginMode() != 3 && this._galaxy.getPassword() != null) {
+ props.addProperty(new netProperty(6, this._galaxy.getPassword()));
+ }
+
+ if ((getDebugLevel() & 4) > 0) {
+ synchronized (System.out) {
+ System.out.println(this._serverURL.getHost() + ": sending sessionInit.");
+
+ assert username != null;
+
+ System.out.println(" username = \"" + username + "\"");
+ if (this._galaxy.getPassword() != null) {
+ System.out.println(" password = \"" + this._galaxy.getPassword() + "\"");
+ }
+ }
+ }
+
+ return new sessionInitCmd(props);
+ }
+ }
+
+ @Override
+ protected void state_Sleeping(int timeNow) {
+ if (this.getGalaxy().isActive()) {
+ super.state_Sleeping(timeNow);
+ } else {
+ this._state.setState(0);
+ }
+ }
+
+ @Override
+ void goOnline() {
+ this._requestOffline = false;
+ }
+}
diff --git a/NET/worlds/network/SMState.java b/NET/worlds/network/SMState.java
new file mode 100644
index 0000000..0138559
--- /dev/null
+++ b/NET/worlds/network/SMState.java
@@ -0,0 +1,59 @@
+package NET.worlds.network;
+
+import NET.worlds.core.IniFile;
+
+class SMState {
+ private int _state;
+ private WorldServer _ws;
+ private static int _debugLevel;
+
+ static {
+ try {
+ _debugLevel = Integer.parseInt(IniFile.gamma().getIniString("netdebug", "0"));
+ } catch (NumberFormatException var1) {
+ _debugLevel = 0;
+ }
+ }
+
+ public SMState(WorldServer ws, int state) {
+ this._state = state;
+ this._ws = ws;
+ }
+
+ public int getState() {
+ return this._state;
+ }
+
+ public synchronized void setState(int state) {
+ if ((_debugLevel & 8) > 0) {
+ synchronized (System.out) {
+ System.out.println(this._ws + ": *** new state: " + state);
+ if ((_debugLevel & 16) > 0) {
+ try {
+ throw new InterruptedException();
+ } catch (InterruptedException var4) {
+ var4.printStackTrace(System.out);
+ System.out.println("******************************");
+ }
+ }
+ }
+ }
+
+ this._state = state;
+ this.notifyAll();
+ }
+
+ public synchronized void waitForState(int state) throws InfiniteWaitException {
+ while (this._state != state) {
+ try {
+ this.wait();
+ } catch (InterruptedException var3) {
+ assert false;
+ }
+
+ if (this._state == -1) {
+ throw new InfiniteWaitException();
+ }
+ }
+ }
+}
diff --git a/NET/worlds/network/ServerInputStream.java b/NET/worlds/network/ServerInputStream.java
new file mode 100644
index 0000000..bfca04e
--- /dev/null
+++ b/NET/worlds/network/ServerInputStream.java
@@ -0,0 +1,248 @@
+package NET.worlds.network;
+
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UTFDataFormatException;
+
+public class ServerInputStream extends FilterInputStream {
+ private int _packetSize;
+ private int _version;
+
+ public ServerInputStream(InputStream in) {
+ super(in);
+
+ assert in != null;
+
+ this._packetSize = 0;
+ this._version = 24;
+ }
+
+ public ServerInputStream(InputStream in, int vers) {
+ super(in);
+
+ assert in != null;
+
+ this._packetSize = 0;
+ this._version = vers;
+ }
+
+ public void setVersion(int vers) {
+ this._version = vers;
+ }
+
+ public int getVersion() {
+ return this._version;
+ }
+
+ public void readPacketSize() throws IOException {
+ assert this._packetSize == 0;
+
+ this._packetSize = 1;
+ this._packetSize = this.readUnsignedByte() - 1;
+ if ((this._packetSize & 128) != 0 && this.getVersion() > 24) {
+ this._packetSize = (this._packetSize & 128) * 256 + this.readUnsignedByte() - 1;
+ }
+ }
+
+ public boolean isEmpty() {
+ return this._packetSize == 0;
+ }
+
+ public int bytesLeft() {
+ return this._packetSize;
+ }
+
+ @Override
+ public final int read(byte[] b) throws IOException {
+ assert this._packetSize >= b.length;
+
+ if (b.length == 0) {
+ return 0;
+ } else {
+ int bytesRead = this.in.read(b, 0, b.length);
+ if (bytesRead < 0) {
+ throw new EOFException();
+ } else {
+ this._packetSize -= bytesRead;
+ return bytesRead;
+ }
+ }
+ }
+
+ @Override
+ public final int read(byte[] b, int off, int len) throws IOException {
+ assert this._packetSize >= len;
+
+ int bytesRead = this.in.read(b, off, len);
+ if (bytesRead < 0) {
+ throw new EOFException();
+ } else {
+ this._packetSize -= bytesRead;
+ return bytesRead;
+ }
+ }
+
+ public final void readFully(byte[] b) throws IOException {
+ assert this._packetSize >= b.length;
+
+ this.readFully(b, 0, b.length);
+ }
+
+ public final void readFully(byte[] b, int off, int len) throws IOException {
+ assert this._packetSize >= len;
+
+ this._packetSize -= len;
+ InputStream in = this.in;
+
+ while (len > 0) {
+ int bytesRead = in.read(b, off, len);
+ if (bytesRead < 0) {
+ throw new EOFException();
+ }
+
+ len -= bytesRead;
+ off += bytesRead;
+ }
+ }
+
+ public void skipBytes(int n) throws IOException {
+ assert this._packetSize >= n;
+
+ this._packetSize -= n;
+ InputStream in = this.in;
+
+ while (n > 0) {
+ int bytesSkipped = (int)in.skip(n);
+ if (bytesSkipped < 0) {
+ throw new EOFException();
+ }
+
+ n -= bytesSkipped;
+ }
+ }
+
+ public final byte readByte() throws IOException {
+ if (this._packetSize < 1) {
+ throw new IOException();
+ } else {
+ int ch = this.in.read();
+ if (ch < 0) {
+ throw new EOFException();
+ } else {
+ this._packetSize--;
+ return (byte)ch;
+ }
+ }
+ }
+
+ public final int readUnsignedByte() throws IOException {
+ if (this._packetSize < 1) {
+ throw new IOException();
+ } else {
+ int ch = this.in.read();
+ if (ch < 0) {
+ throw new EOFException();
+ } else {
+ this._packetSize--;
+ return ch;
+ }
+ }
+ }
+
+ public final short readShort() throws IOException {
+ assert this._packetSize >= 2;
+
+ InputStream in = this.in;
+ int ch1 = in.read();
+ int ch2 = in.read();
+ if ((ch1 | ch2) < 0) {
+ throw new EOFException();
+ } else {
+ this._packetSize -= 2;
+ return (short)((ch1 << 8) + (ch2 << 0));
+ }
+ }
+
+ public final int readUnsignedShort() throws IOException {
+ assert this._packetSize >= 2;
+
+ InputStream in = this.in;
+ int ch1 = in.read();
+ int ch2 = in.read();
+ if ((ch1 | ch2) < 0) {
+ throw new EOFException();
+ } else {
+ this._packetSize -= 2;
+ return (ch1 << 8) + (ch2 << 0);
+ }
+ }
+
+ public String readUTF() throws IOException {
+ if (this._packetSize < 1) {
+ throw new IOException();
+ } else {
+ int utflen = this.readUnsignedByte();
+ if (this._packetSize < utflen) {
+ throw new UTFDataFormatException();
+ } else {
+ char[] str = new char[utflen];
+ int count = 0;
+ int strlen = 0;
+
+ while (count < utflen) {
+ int c = this.readUnsignedByte();
+ switch (c >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ count++;
+ str[strlen++] = (char)c;
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ default:
+ throw new UTFDataFormatException();
+ case 12:
+ case 13:
+ count += 2;
+ if (count > utflen) {
+ throw new UTFDataFormatException();
+ }
+
+ int char2 = this.readUnsignedByte();
+ if ((char2 & 192) != 128) {
+ throw new UTFDataFormatException();
+ }
+
+ str[strlen++] = (char)((c & 31) << 6 | char2 & 63);
+ break;
+ case 14:
+ count += 3;
+ if (count > utflen) {
+ throw new UTFDataFormatException();
+ }
+
+ int char2 = this.readUnsignedByte();
+ int char3 = this.readUnsignedByte();
+ if ((char2 & 192) != 128 || (char3 & 192) != 128) {
+ throw new UTFDataFormatException();
+ }
+
+ str[strlen++] = (char)((c & 15) << 12 | (char2 & 63) << 6 | (char3 & 63) << 0);
+ }
+ }
+
+ return new String(str, 0, strlen);
+ }
+ }
+ }
+}
diff --git a/NET/worlds/network/ServerOutputStream.java b/NET/worlds/network/ServerOutputStream.java
new file mode 100644
index 0000000..a95a0f1
--- /dev/null
+++ b/NET/worlds/network/ServerOutputStream.java
@@ -0,0 +1,97 @@
+package NET.worlds.network;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class ServerOutputStream extends FilterOutputStream {
+ private int _version;
+
+ public ServerOutputStream(OutputStream o) {
+ super(o);
+ this.setVersion(24);
+ }
+
+ public ServerOutputStream(OutputStream o, int vers) {
+ super(o);
+ this.setVersion(vers);
+ }
+
+ public void setVersion(int vers) {
+ this._version = vers;
+ }
+
+ public int getVersion() {
+ return this._version;
+ }
+
+ @Override
+ public final void write(int b) throws IOException {
+ this.out.write(b);
+ }
+
+ @Override
+ public final void write(byte[] b, int off, int len) throws IOException {
+ this.out.write(b, off, len);
+ }
+
+ public final void writeByte(int v) throws IOException {
+ this.out.write(v);
+ }
+
+ public final void writeShort(int v) throws IOException {
+ OutputStream out = this.out;
+ out.write(v >>> 8 & 0xFF);
+ out.write(v >>> 0 & 0xFF);
+ }
+
+ public final void writeInt(int v) throws IOException {
+ OutputStream out = this.out;
+ out.write(v >>> 24 & 0xFF);
+ out.write(v >>> 16 & 0xFF);
+ out.write(v >>> 8 & 0xFF);
+ out.write(v >>> 0 & 0xFF);
+ }
+
+ public static int utfLength(String str) {
+ int strlen = str.length();
+ int utflen = 0;
+
+ for (int i = 0; i < strlen; i++) {
+ int c = str.charAt(i);
+ if (c >= 1 && c <= 127) {
+ utflen++;
+ } else if (c > 2047) {
+ utflen += 3;
+ } else {
+ utflen += 2;
+ }
+ }
+
+ return utflen;
+ }
+
+ public void writeUTF(String str) throws IOException {
+ OutputStream out = this.out;
+ int strlen = str.length();
+ int utflen = utfLength(str);
+
+ assert utflen < 256;
+
+ out.write(utflen >>> 0 & 0xFF);
+
+ for (int i = 0; i < strlen; i++) {
+ int c = str.charAt(i);
+ if (c >= 1 && c <= 127) {
+ out.write(c);
+ } else if (c > 2047) {
+ out.write(224 | c >> 12 & 15);
+ out.write(128 | c >> 6 & 63);
+ out.write(128 | c >> 0 & 63);
+ } else {
+ out.write(192 | c >> 6 & 31);
+ out.write(128 | c >> 0 & 63);
+ }
+ }
+ }
+}
diff --git a/NET/worlds/network/ServerTracker.java b/NET/worlds/network/ServerTracker.java
new file mode 100644
index 0000000..7de2fbc
--- /dev/null
+++ b/NET/worlds/network/ServerTracker.java
@@ -0,0 +1,202 @@
+package NET.worlds.network;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+class ServerTracker {
+ private Hashtable<String, WorldServer> _serverHash = new Hashtable<String, WorldServer>();
+ private Vector<WorldServer> _pendingOpenServers = new Vector<WorldServer>();
+ private Vector<WorldServer> _activeServers = new Vector<WorldServer>();
+ private Vector<WorldServer> _pendingCloseServers = new Vector<WorldServer>();
+ private Galaxy _galaxy;
+ private ServerURL _serverURL;
+
+ protected ServerTracker(Galaxy parent) {
+ this._galaxy = parent;
+ this._serverURL = this._galaxy.getServerURL();
+ }
+
+ public synchronized WorldServer getServer(String StrServerURL) throws InvalidServerURLException {
+ if ((Galaxy.getDebugLevel() & 32) > 0) {
+ System.out.println("Galaxy.getServer(" + StrServerURL + ") from " + this._galaxy);
+ }
+
+ ServerURL serverURL = new ServerURL(StrServerURL);
+ WorldServer ws = null;
+ if (this._serverURL.getHost().equals(serverURL.getHost())) {
+ ws = this.getServer(this._activeServers, this);
+ if (ws == null) {
+ ws = this.getServer(this._pendingOpenServers, this);
+ }
+ }
+
+ if (ws == null) {
+ ws = this.findOrMake(serverURL, this);
+ }
+
+ ws.tmpRefCnt(this);
+ return ws;
+ }
+
+ protected WorldServer getActive(Object referrer) {
+ return this.getServer(this._activeServers, referrer);
+ }
+
+ protected synchronized WorldServer getServer(Vector<WorldServer> list, Object referrer) {
+ int lastServer = list.size() - 1;
+ if (lastServer >= 0) {
+ WorldServer ws = list.elementAt(lastServer);
+ ws.incRefCnt(referrer);
+ return ws;
+ } else {
+ return null;
+ }
+ }
+
+ private synchronized WorldServer findOrMake(ServerURL serverURL, Object referrer) throws InvalidServerURLException {
+ WorldServer ws = this._serverHash.get(serverURL.getHost());
+ if (ws == null) {
+ int _debugLevel = 0;
+ _debugLevel = Galaxy.getDebugLevel();
+ if ((_debugLevel & 32) > 0) {
+ System.out.println(" Creating new server of type=" + serverURL.getType() + ".");
+ }
+
+ try {
+ Class<?> wsClass = Class.forName("NET.worlds.network." + serverURL.getType());
+ ws = (WorldServer)wsClass.newInstance();
+ } catch (Exception var8) {
+ Exception e = var8;
+ if ((_debugLevel & 32) > 0) {
+ synchronized (System.out) {
+ System.out.println(" Exception during class creation.");
+ e.printStackTrace(System.out);
+ }
+ }
+
+ throw new InvalidServerURLException("Bad class: " + serverURL.getType());
+ }
+
+ this._serverHash.put(serverURL.getHost(), ws);
+ ws.initInstance(this._galaxy, serverURL);
+ } else if ((Galaxy.getDebugLevel() & 32) > 0) {
+ System.out.println(" Found old server.");
+ }
+
+ ws.incRefCnt(referrer);
+ return ws;
+ }
+
+ protected synchronized void swapServer(WorldServer oldServ, WorldServer newServ) {
+ String oldURL = oldServ.getServerURL().getHost();
+
+ assert oldURL.equals(newServ.getServerURL().getHost());
+
+ oldURL = oldServ.getServerURL().getHost();
+ this._serverHash.put(oldURL, newServ);
+
+ assert !this._activeServers.contains(oldServ);
+ }
+
+ protected synchronized boolean isActive() {
+ return this._activeServers.size() > 0 || this._pendingOpenServers.size() > 0 || this._pendingCloseServers.size() > 0;
+ }
+
+ protected synchronized boolean addPendingServer(WorldServer ws) {
+ if ((Galaxy.getDebugLevel() & 8) > 0) {
+ System.out.println(this._galaxy + ": addPendingServer(" + ws + ")");
+ System.out.println("\t_pendingOpen = " + this._pendingOpenServers);
+ System.out.println("\t_activeServers = " + this._activeServers);
+ System.out.println("\t_pendingClose = " + this._pendingCloseServers);
+ }
+
+ if (this._pendingOpenServers.indexOf(ws) < 0) {
+ this._pendingOpenServers.addElement(ws);
+ }
+
+ return this._pendingOpenServers.size() == 1 && this._activeServers.size() == 0 && this._pendingCloseServers.size() == 0;
+ }
+
+ protected synchronized boolean addActiveServer(WorldServer ws) {
+ if ((Galaxy.getDebugLevel() & 8) > 0) {
+ System.out.println(this._galaxy + ": addActiveServer(" + ws + ")");
+ System.out.println("\t_pendingOpen = " + this._pendingOpenServers);
+ System.out.println("\t_activeServers = " + this._activeServers);
+ System.out.println("\t_pendingClose = " + this._pendingCloseServers);
+ }
+
+ this._pendingOpenServers.removeElement(ws);
+ if (this._activeServers.indexOf(ws) < 0) {
+ this._activeServers.addElement(ws);
+ }
+
+ return this._activeServers.size() == 1 && this._pendingCloseServers.size() == 0;
+ }
+
+ protected synchronized boolean addClosingServer(WorldServer ws) {
+ if ((Galaxy.getDebugLevel() & 8) > 0) {
+ System.out.println(this._galaxy + ": addClosingServer(" + ws + ")");
+ System.out.println("\t_pendingOpen = " + this._pendingOpenServers);
+ System.out.println("\t_activeServers = " + this._activeServers);
+ System.out.println("\t_pendingClose = " + this._pendingCloseServers);
+ }
+
+ this._pendingOpenServers.removeElement(ws);
+ boolean wasActive = this._activeServers.removeElement(ws);
+ if (this._pendingCloseServers.indexOf(ws) < 0) {
+ this._pendingCloseServers.addElement(ws);
+ }
+
+ return wasActive && this._activeServers.size() == 0;
+ }
+
+ protected synchronized void markClosedServer(WorldServer ws) {
+ if ((Galaxy.getDebugLevel() & 8) > 0) {
+ System.out.println(this._galaxy + ": markClosedServer(" + ws + ")");
+ System.out.println("\t_pendingOpen = " + this._pendingOpenServers);
+ System.out.println("\t_activeServers = " + this._activeServers);
+ System.out.println("\t_pendingClose = " + this._pendingCloseServers);
+ }
+
+ this._pendingOpenServers.removeElement(ws);
+ this._pendingCloseServers.removeElement(ws);
+ this._activeServers.removeElement(ws);
+ }
+
+ protected synchronized void killServer(WorldServer ws) {
+ if ((Galaxy.getDebugLevel() & 8) > 0) {
+ System.out.println(this._galaxy + ": killServer(" + ws + ")");
+ System.out.println("\t_pendingOpen = " + this._pendingOpenServers);
+ System.out.println("\t_activeServers = " + this._activeServers);
+ System.out.println("\t_pendingClose = " + this._pendingCloseServers);
+ }
+
+ this._pendingOpenServers.removeElement(ws);
+ this._pendingCloseServers.removeElement(ws);
+ this._activeServers.removeElement(ws);
+ if (this._serverHash.get(ws.getServerURL().getHost()) == ws) {
+ this._serverHash.remove(ws.getServerURL().getHost());
+ } else {
+ System.out.println("DEBUG -- a server tried to murder another!");
+ System.out.println("Caller = " + ws);
+ System.out.println("Victim = " + this._serverHash.get(ws.getServerURL().getHost()));
+ new Exception().printStackTrace();
+ }
+ }
+
+ protected Enumeration<WorldServer> getAllServers() {
+ return this._serverHash.elements();
+ }
+
+ @Override
+ public String toString() {
+ return "ServerTracker[\n\t_pendingOpen = "
+ + this._pendingOpenServers
+ + "\n\t_activeServers = "
+ + this._activeServers
+ + "\n\t_pendingClose = "
+ + this._pendingCloseServers
+ + "\n]";
+ }
+}
diff --git a/NET/worlds/network/ServerURL.java b/NET/worlds/network/ServerURL.java
new file mode 100644
index 0000000..9461ee5
--- /dev/null
+++ b/NET/worlds/network/ServerURL.java
@@ -0,0 +1,59 @@
+package NET.worlds.network;
+
+public class ServerURL {
+ private String _serverType = null;
+ private String _serverHost = null;
+ private String _serverOptions = null;
+
+ public String getHost() {
+ return this._serverHost;
+ }
+
+ public String getType() {
+ return this._serverType;
+ }
+
+ public ServerURL(String serverURL) throws InvalidServerURLException {
+ String origServerURL = serverURL;
+ int txtPos = serverURL.indexOf("://");
+ if (txtPos >= 0) {
+ String protocol = serverURL.substring(0, txtPos);
+
+ assert protocol.equals("worldserver");
+
+ serverURL = serverURL.substring(txtPos + 3);
+ }
+
+ int typePos = serverURL.indexOf(47);
+ if (typePos >= 0) {
+ this._serverHost = serverURL.substring(0, typePos);
+ serverURL = serverURL.substring(typePos + 1);
+ } else {
+ this._serverHost = serverURL;
+ serverURL = "AutoServer";
+ }
+
+ int optPos = serverURL.indexOf(47);
+ if (optPos >= 0) {
+ this._serverType = serverURL.substring(0, optPos);
+ serverURL = serverURL.substring(optPos + 1);
+ } else {
+ this._serverType = serverURL;
+ serverURL = "";
+ }
+
+ this._serverOptions = serverURL;
+ if (this._serverHost.length() == 0) {
+ throw new InvalidServerURLException("Invalid server URL: " + origServerURL);
+ } else {
+ if (this._serverType.length() == 0) {
+ this._serverType = "AutoServer";
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "worldserver://" + this._serverHost + "/" + this._serverType + "/" + this._serverOptions;
+ }
+}
diff --git a/NET/worlds/network/SubscribeDistCmd.java b/NET/worlds/network/SubscribeDistCmd.java
new file mode 100644
index 0000000..33066a7
--- /dev/null
+++ b/NET/worlds/network/SubscribeDistCmd.java
@@ -0,0 +1,32 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class SubscribeDistCmd extends netPacket {
+ public static final byte SUBSCRIBEDISTCMD = 24;
+ protected short _distance;
+ protected short _roomNumber;
+
+ public SubscribeDistCmd(float dist, int room) {
+ super(null, 24);
+ this._distance = (short)(dist - 100.0F);
+ this._roomNumber = (short)room;
+ }
+
+ @Override
+ int packetSize() {
+ return 4 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeShort(this._roomNumber);
+ o.writeShort(this._distance);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "SUB-DIST " + this._roomNumber + ": " + this._distance + "cm";
+ }
+}
diff --git a/NET/worlds/network/SubscribeRoomCmd.java b/NET/worlds/network/SubscribeRoomCmd.java
new file mode 100644
index 0000000..9eef4fc
--- /dev/null
+++ b/NET/worlds/network/SubscribeRoomCmd.java
@@ -0,0 +1,42 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.RoomSubscribeInfo;
+import java.io.IOException;
+
+public class SubscribeRoomCmd extends netPacket {
+ public static final byte SUBSCRIBEROOMCMD = 22;
+ protected short _distance;
+ protected short _x;
+ protected short _y;
+ protected short _z;
+ protected short _roomNumber;
+
+ public SubscribeRoomCmd(RoomSubscribeInfo info, int room) {
+ super(null, 22);
+ this._roomNumber = (short)room;
+ this._distance = (short)(info.d - 100.0F);
+ this._x = (short)info.x;
+ this._y = (short)info.y;
+ this._z = (short)info.z;
+ }
+
+ @Override
+ int packetSize() {
+ return 10 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeShort(this._roomNumber);
+ o.writeShort(this._x);
+ o.writeShort(this._y);
+ o.writeShort(this._z);
+ o.writeShort(this._distance);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "SUBSCRIB " + this._roomNumber + ": " + this._distance + "cm @ " + this._x + "," + this._y + "," + this._z;
+ }
+}
diff --git a/NET/worlds/network/Timer.java b/NET/worlds/network/Timer.java
new file mode 100644
index 0000000..cf08204
--- /dev/null
+++ b/NET/worlds/network/Timer.java
@@ -0,0 +1,21 @@
+package NET.worlds.network;
+
+import NET.worlds.core.Std;
+
+public class Timer {
+ int _startTime;
+ String _msg;
+
+ public Timer(String msg) {
+ this._msg = msg;
+ this._startTime = Std.getRealTime();
+ }
+
+ public void stop(int minDur) {
+ int endTime = Std.getRealTime();
+ int duration = endTime - this._startTime;
+ if (duration > minDur) {
+ System.out.println(this._msg + ": " + duration + "ms");
+ }
+ }
+}
diff --git a/NET/worlds/network/URL.java b/NET/worlds/network/URL.java
new file mode 100644
index 0000000..eb45616
--- /dev/null
+++ b/NET/worlds/network/URL.java
@@ -0,0 +1,604 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Gamma;
+import NET.worlds.core.IniFile;
+import NET.worlds.scape.Restorer;
+import NET.worlds.scape.Saver;
+import NET.worlds.scape.SuperRoot;
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+public class URL implements Serializable {
+ static final long serialVersionUID = 1L;
+ private String _url;
+ private static Hashtable<String, Object> psConversion = new Hashtable<String, Object>();
+ private static IniFile protocols = new IniFile("Protocol");
+ private static String currentDir = System.getProperty("user.dir").replace('\\', '/');
+ private static URL home;
+ private static URL file;
+ private static boolean useCachedFiles;
+ private static URL avatar;
+
+ static {
+ assert currentDir.charAt(1) == ':' || currentDir.startsWith("//");
+
+ try {
+ currentDir = validateFile(currentDir);
+ } catch (MalformedURLException var2) {
+ var2.printStackTrace(System.out);
+
+ assert false;
+ }
+
+ if (!currentDir.endsWith("/")) {
+ currentDir = currentDir + "/";
+ }
+
+ home = make(Gamma.getHome());
+ file = make("file:");
+ psConversion.put("home", home);
+ useCachedFiles = true;
+ useCachedFiles = IniFile.gamma().getIniInt("useNetworkAvatars", 1) == 1;
+ int override = IniFile.override().getIniInt("useNetworkAvatars", -1);
+ if (override != -1) {
+ useCachedFiles = override == 1;
+ }
+
+ String avatarDir = IniFile.gamma().getIniString("avatarDir", "avatar/");
+ if (!avatarDir.endsWith("/")) {
+ avatarDir = avatarDir + "/";
+ }
+
+ if (useCachedFiles) {
+ setAvatarServer(NetUpdate.getUpgradeServerURL() + avatarDir);
+ } else {
+ setAvatarServer("home:avatars/");
+ }
+
+ avatar = make("avatar:");
+ }
+
+ public URL(SuperRoot reference, String urlstr) throws MalformedURLException {
+ this(getBestContainer(reference), urlstr);
+ }
+
+ public URL(URL reference, String urlstr) throws MalformedURLException {
+ if (isAbsolute(urlstr)) {
+ this._url = normalize(urlstr);
+ } else {
+ this._url = "rel:" + reference.getAbsolute(urlstr);
+ }
+ }
+
+ public URL(String urlstr) throws MalformedURLException {
+ this(null, urlstr);
+ }
+
+ public static URL make(String s) {
+ return make(getCurDir(), s);
+ }
+
+ public static URL make(URL url, String s) {
+ try {
+ return new URL(url, s);
+ } catch (MalformedURLException var3) {
+ var3.printStackTrace(System.out);
+ throw new Error("Can't make URL");
+ }
+ }
+
+ private String getAbsolute(String urlstr) throws MalformedURLException {
+ if (!isAbsolute(urlstr)) {
+ urlstr = this._url.substring(0, this.getBaseIndex()) + urlstr;
+ }
+
+ if (urlstr.startsWith("rel:")) {
+ urlstr = urlstr.substring(4);
+ }
+
+ return normalize(urlstr);
+ }
+
+ private int getBaseIndex() {
+ int i = this.getPackageIndex();
+ if (this._url.endsWith(".class")) {
+ int lastDot = this._url.lastIndexOf(46, this._url.length() - 7) + 1;
+ if (lastDot > i) {
+ i = lastDot;
+ }
+ }
+
+ return i;
+ }
+
+ public String getAbsolute() {
+ return this._url.startsWith("rel:") ? this._url.substring(4) : this._url;
+ }
+
+ @Override
+ public String toString() {
+ return this.getInternal();
+ }
+
+ public String getInternal() {
+ return this._url;
+ }
+
+ public String getBase() {
+ return this._url.substring(this.getBaseIndex());
+ }
+
+ public String getBaseWithoutExt() {
+ int start = this.getBaseIndex();
+ int end = this._url.lastIndexOf(46);
+ if (end < start) {
+ end = this._url.length();
+ }
+
+ return this._url.substring(start, end);
+ }
+
+ private static boolean isAbsolute(String urlstr) {
+ return urlstr != null && (urlstr.indexOf(58) >= 0 || urlstr.replace('\\', '/').startsWith("//"));
+ }
+
+ private static int getRelpathIndex(String s) {
+ int i = s.indexOf(58) + 1;
+ if (s.regionMatches(i, "//", 0, 2)) {
+ i = s.indexOf(47, i + 2) + 1;
+ } else if (s.startsWith("file:") && s.regionMatches(i + 1, ":/", 0, 2)) {
+ i += 3;
+ }
+
+ return i;
+ }
+
+ private static String normalize(String url) throws MalformedURLException {
+ if (url == null) {
+ throw new MalformedURLException("null URL string");
+ } else {
+ url = url.replace('\\', '/').trim();
+ int pathi = url.indexOf(58) + 1;
+ if (pathi == 1) {
+ throw new MalformedURLException("Missing protocol specifier");
+ } else {
+ boolean hasHost = url.regionMatches(pathi, "//", 0, 2);
+ if (pathi <= 2) {
+ if (pathi == 0 && !hasHost) {
+ throw new MalformedURLException("Missing protocol specifier");
+ }
+
+ url = "file:" + url;
+ pathi = 5;
+ }
+
+ if (url.lastIndexOf(47, pathi - 1) >= 0) {
+ throw new MalformedURLException("/ in protocol specifier of " + url);
+ } else {
+ url = url.substring(0, pathi).toLowerCase() + url.substring(pathi);
+ if (hasHost) {
+ pathi = url.indexOf(47, pathi + 2) + 1;
+ if (pathi == 0) {
+ url = url + '/';
+ pathi = url.length();
+ }
+ }
+
+ if (url.startsWith("rel:")) {
+ url = normalize(url.substring(4));
+ return url.startsWith("rel:") ? url : "rel:" + url;
+ } else {
+ if (url.startsWith("file:")) {
+ url = "file:" + validateFile(url.substring(5));
+ if (!hasHost) {
+ assert url.indexOf(58, 5) == 6;
+
+ assert url.charAt(7) == '/';
+
+ pathi += 3;
+ }
+ } else if (url.startsWith("http") && !hasHost) {
+ throw new MalformedURLException("http must have //host/");
+ }
+
+ return url.substring(0, pathi) + removeDots(url.substring(pathi));
+ }
+ }
+ }
+ }
+ }
+
+ private static String validateFile(String p) throws MalformedURLException {
+ if (p.startsWith("//")) {
+ int slash = p.indexOf(47, 2);
+ if (slash < 0) {
+ p = p + "/";
+ }
+
+ return p;
+ } else {
+ p = p.toLowerCase();
+ int colon = p.indexOf(58);
+ if (colon != 1) {
+ return p.indexOf(47) == 0 ? currentDir.substring(0, 2) + p : currentDir + p;
+ } else if (p.indexOf(47) != 2) {
+ throw new MalformedURLException("Slash must follow colon");
+ } else {
+ char drive = Character.toLowerCase(p.charAt(0));
+ if (!Character.isLowerCase(drive)) {
+ throw new MalformedURLException("Invalid drive letter");
+ } else {
+ return drive + p.substring(1);
+ }
+ }
+ }
+ }
+
+ public String getRelativeTo(URL reference) {
+ if (reference != null && this._url.startsWith("rel:")) {
+ String url = this.unalias();
+ String ref = reference.unalias();
+ int pathStart = ref.indexOf(58) + 1;
+ boolean isLocal = pathStart == 2;
+ if (!isLocal) {
+ String hasHost = null;
+ if (ref.regionMatches(pathStart, "//", 0, 2)) {
+ hasHost = ref;
+ } else if (url.regionMatches(pathStart, "//", 0, 2)) {
+ hasHost = url;
+ }
+
+ if (hasHost != null) {
+ pathStart = hasHost.indexOf(47, pathStart + 2) + 1;
+ if (pathStart == 0) {
+ return this._url;
+ }
+ }
+ }
+
+ if (!ref.regionMatches(isLocal, 0, url, 0, pathStart)) {
+ return this._url;
+ } else {
+ int noncommonStart = pathStart;
+ int len = Math.min(url.length(), ref.length());
+
+ for (int common = pathStart; common < len; common++) {
+ char c = url.charAt(common);
+ char d = ref.charAt(common);
+ if (c != d && (!isLocal || Character.toLowerCase(c) != Character.toLowerCase(d))) {
+ break;
+ }
+
+ if (c == '/') {
+ noncommonStart = common + 1;
+ }
+ }
+
+ url = url.substring(noncommonStart);
+ int pos = noncommonStart;
+
+ while ((pos = ref.indexOf(47, pos) + 1) != 0) {
+ url = "../" + url;
+ if (this._url.startsWith("rel:home:")) {
+ return this._url;
+ }
+ }
+
+ return url;
+ }
+ } else {
+ return this._url;
+ }
+ }
+
+ public String getRelativeTo(SuperRoot r) {
+ return this.getRelativeTo(getBestContainer(r));
+ }
+
+ public static URL getBestContainer(SuperRoot sr) {
+ URL url = null;
+ if (sr != null) {
+ url = sr.getContainingSourceURL();
+ }
+
+ return url == null ? getCurDir() : url;
+ }
+
+ public static String getRelativeTo(URL u, SuperRoot r) {
+ return u == null ? null : u.getRelativeTo(r);
+ }
+
+ public static URL getHome() {
+ return home;
+ }
+
+ public static String homeUnalias(String s) {
+ return make("home:" + s).unalias();
+ }
+
+ public static URL getContainingOrCurDir(SuperRoot t) {
+ URL dir = t.getContainingSourceURL();
+ return dir == null ? getCurDir() : make(dir._url.substring(0, dir.getBaseIndex()));
+ }
+
+ private static void setAvatarServer(String url) {
+ String avURL = protocols.getIniString("avatar", url);
+
+ try {
+ psConversion.put("avatar", new URL(new URL(avURL).unalias()));
+ } catch (MalformedURLException var3) {
+ System.out.println("Avatar protocol is invalid.");
+
+ assert false;
+ }
+ }
+
+ public static boolean usingCachedAvatars() {
+ return useCachedFiles;
+ }
+
+ public static void setHttpServer(String url) {
+ psConversion.put("worldshttp", make(url));
+ }
+
+ public static URL getCurDir() {
+ return file;
+ }
+
+ public static URL getAvatar() {
+ return avatar;
+ }
+
+ private int getPackageIndex() {
+ int i = this._url.lastIndexOf(47) + 1;
+ if (i == 0) {
+ i = this._url.indexOf(58) + 1;
+ if (i == 4 && this._url.startsWith("rel:")) {
+ i = this._url.indexOf(58, 4) + 1;
+ }
+ }
+
+ return i;
+ }
+
+ public String unalias() {
+ String url = this.getAbsolute();
+ if (url.endsWith(".class")) {
+ int base = this.getPackageIndex();
+ int len = url.length();
+ url = url.substring(0, base) + url.substring(base, len - 6).replace('.', '/') + ".class";
+ }
+
+ int protLen = url.indexOf(58);
+ String prot = url.substring(0, protLen);
+ Object alias = psConversion.get(prot);
+ if (alias == null) {
+ psConversion.put(prot, psConversion);
+ String s = protocols.getIniString(prot, "");
+ if (s != null && !s.equals("")) {
+ try {
+ alias = new URL(new URL(s).unalias());
+ psConversion.put(prot, alias);
+ } catch (MalformedURLException var8) {
+ System.out.println("Invalid inifile entry for " + prot);
+ }
+ }
+ } else if (prot.equals("avatar") && url.endsWith(".rwg")) {
+ alias = null;
+ }
+
+ if (alias instanceof URL) {
+ URL u = (URL)alias;
+
+ assert !u._url.startsWith("rel:");
+
+ if (u._url.startsWith("file:") && url.length() > protLen + 1 && url.charAt(protLen + 1) == '/') {
+ protLen++;
+ }
+
+ url = u._url.substring(0, u.getBaseIndex()) + url.substring(protLen + 1);
+ }
+
+ if (!url.startsWith("file:")) {
+ return url;
+ } else {
+ url = url.substring(5);
+
+ try {
+ url = normalize(validateFile(url));
+ } catch (MalformedURLException var7) {
+ return url;
+ }
+
+ assert url.startsWith("file:");
+
+ return url.substring(5);
+ }
+ }
+
+ public static String searchPath(String name, String path) {
+ StringTokenizer e = new StringTokenizer(path, File.pathSeparator);
+
+ while (e.hasMoreTokens()) {
+ String dir = e.nextToken();
+ String expandedName = name;
+ if (!dir.equals(".")) {
+ expandedName = dir + File.separator + name;
+ }
+
+ File f = new File(expandedName);
+ if (f.exists()) {
+ return expandedName;
+ }
+ }
+
+ return null;
+ }
+
+ public String getClassName() {
+ if (!this._url.endsWith(".class")) {
+ return null;
+ } else {
+ int base = this.getPackageIndex();
+ int len = this._url.length();
+ return this._url.substring(base, len - 6);
+ }
+ }
+
+ public URL getClassDir() {
+ return !this._url.endsWith(".class") ? null : make(this._url.substring(0, this.getPackageIndex()));
+ }
+
+ public boolean endsWith(String ext) {
+ return this._url.endsWith(ext);
+ }
+
+ public String getExt() {
+ int i = this._url.lastIndexOf(46);
+ return i != -1 && this._url.indexOf(47, i) < 0 && this._url.indexOf(58, i) < 0 ? this._url.substring(i) : "";
+ }
+
+ public static String maybeAddExt(String url, String ext) {
+ int dot = url.lastIndexOf(46);
+ return dot >= 0 && url.indexOf(47, dot) < 0 && url.indexOf(92, dot) < 0 ? url : url + ext;
+ }
+
+ public static URL restore(Restorer r, String defaultExt) throws IOException {
+ return restore(r, r.restoreString(), defaultExt);
+ }
+
+ public static URL restore(Restorer r, String url, String defaultExt) throws IOException {
+ if (url == null) {
+ return null;
+ } else {
+ if (defaultExt != null) {
+ url = maybeAddExt(url, defaultExt);
+ }
+
+ if (isAbsolute(url)) {
+ return new URL(url);
+ } else {
+ URL ref = r.getReferenceURL();
+ if (r.version() >= 6) {
+ if (ref == null) {
+ throw new IOException("No absolute base for relative URL " + url);
+ } else {
+ return new URL(ref, url);
+ }
+ } else if (url.endsWith(".class")) {
+ return make((url.indexOf(47) < 0 ? "system:" : "file:") + url);
+ } else {
+ String s = searchPath(url, ".;..");
+ if (s != null) {
+ if (ref == null) {
+ return new URL("file:" + s);
+ } else {
+ URL unaliasedRef = make(ref.unalias());
+ String rel = new URL("rel:file:" + s).getRelativeTo(unaliasedRef);
+ return new URL(ref, rel);
+ }
+ } else {
+ System.out.println(url + " doesn't exist in RWSHAPEPATH");
+ return make(ref, url);
+ }
+ }
+ }
+ }
+ }
+
+ public static URL restore(Restorer r) throws IOException {
+ return restore(r, null);
+ }
+
+ public void save(Saver s) throws IOException {
+ String r = this.getRelativeTo(s.getReferenceURL());
+ if (r.startsWith("../") || r.startsWith("rel:file:") || r.startsWith("file:")) {
+ Console.println(Console.message("path-to-outside") + r);
+ }
+
+ s.saveString(r);
+ }
+
+ public static void save(Saver s, URL url) throws IOException {
+ if (url == null) {
+ s.saveString(null);
+ } else {
+ url.save(s);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof URL) {
+ URL other = (URL)o;
+ return this._url.equals(other.getInternal()) ? true : this.unalias().equals(other.unalias());
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.unalias().hashCode();
+ }
+
+ public boolean isRemote() {
+ String s = this.unalias();
+ return s.startsWith("//") || s.indexOf(58) < 2 ? false : !s.startsWith("system:") && !s.startsWith("session:");
+ }
+
+ public static String removeDots(String url) {
+ url = "/" + url;
+ int firstSubdir = 1;
+ int nextSearch = firstSubdir - 1;
+
+ int firstDot;
+ while ((firstDot = url.indexOf("/.", nextSearch) + 1) > 0) {
+ int endSlash = url.indexOf(47, firstDot);
+ if (endSlash < 0) {
+ break;
+ }
+
+ int numDots = endSlash - firstDot;
+ int i = firstDot;
+
+ while (i < endSlash && url.charAt(i) == '.') {
+ i++;
+ }
+
+ if (i != endSlash) {
+ nextSearch = endSlash;
+ } else {
+ while (true) {
+ if (numDots == 1) {
+ endSlash++;
+ } else {
+ if (firstDot != firstSubdir) {
+ firstDot = url.lastIndexOf(47, firstDot - 2) + 1;
+ if (firstDot <= firstSubdir) {
+ firstDot = firstSubdir;
+ }
+
+ numDots--;
+ continue;
+ }
+
+ endSlash -= numDots;
+ firstSubdir += numDots + 1;
+ }
+
+ url = url.substring(0, firstDot) + url.substring(endSlash);
+ nextSearch = firstSubdir - 1;
+ break;
+ }
+ }
+ }
+
+ return url.substring(1);
+ }
+}
diff --git a/NET/worlds/network/UnsubscribeRoomCmd.java b/NET/worlds/network/UnsubscribeRoomCmd.java
new file mode 100644
index 0000000..5a56771
--- /dev/null
+++ b/NET/worlds/network/UnsubscribeRoomCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class UnsubscribeRoomCmd extends netPacket {
+ public static final byte UNSUBSCRIBEROOMCMD = 23;
+ protected int _roomNumber;
+
+ public UnsubscribeRoomCmd(int room) {
+ super(null, 23);
+ this._roomNumber = (short)room;
+ }
+
+ @Override
+ int packetSize() {
+ return 2 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeShort(this._roomNumber);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "UNSUBSCR " + this._roomNumber;
+ }
+}
diff --git a/NET/worlds/network/UpgradeDialog.java b/NET/worlds/network/UpgradeDialog.java
new file mode 100644
index 0000000..ee77ade
--- /dev/null
+++ b/NET/worlds/network/UpgradeDialog.java
@@ -0,0 +1,246 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.MultiLineLabel;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.IniFile;
+import java.awt.Button;
+import java.awt.Checkbox;
+import java.awt.Component;
+import java.awt.Event;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.Panel;
+import java.awt.ScrollPane;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+import java.util.Vector;
+
+public class UpgradeDialog extends PolledDialog {
+ private static final long serialVersionUID = -6015193016188781866L;
+ private Button yesButton = new Button(Console.message("Yes-now"));
+ private Button noButton = new Button(Console.message("No-later"));
+ private Button moreInfo = new Button(Console.message("Show-me-more"));
+ private Checkbox startupCheck;
+ private boolean forceUpgrades = IniFile.gamma().getIniInt("forceUpgrades", 1) == 1;
+ private static String instructions = Console.message("Please-uncheck") + " \n" + " \n";
+ private static String forcedInstructions = Console.message("you-can-continue") + " \n" + " \n";
+ private static String title = Console.message("Upgrade");
+ private Vector<Checkbox> checkboxes;
+ private String info;
+ private Vector<String> list;
+ private Vector<Integer> bytes;
+ private boolean first;
+ private boolean chooseOne;
+ private String name;
+ private Component getsFocus;
+ private MultiLineLabel msgLabel;
+
+ public UpgradeDialog(Vector<String> list, Vector<Integer> bytes, boolean first, String name, String info, boolean chooseOne) {
+ super(Console.getFrame(), null, title, false);
+ this.setAlignment(1);
+ this.list = list;
+ this.info = info;
+ this.name = name;
+ this.first = first;
+ this.bytes = bytes;
+ this.chooseOne = chooseOne;
+ this.readySetGo();
+ }
+
+ @Override
+ protected void build() {
+ this.startupCheck = new Checkbox(Console.message("Check-for-up-each"), IniFile.gamma().getIniInt("CheckUpgrades", 1) != 0);
+ int count = this.list.size();
+ this.checkboxes = new Vector<Checkbox>();
+ Panel p = new Panel(new GridLayout(count, 1));
+ Checkbox chk = null;
+
+ for (int i = 0; i < count; i++) {
+ int b = this.bytes.elementAt(i);
+ String kb = NumberFormat.getInstance().format((long)(b / 1000));
+ Object[] arguments = new Object[]{new String(this.list.elementAt(i).toString()), new String(kb)};
+ String msg = MessageFormat.format(Console.message("Kbytes"), arguments);
+ chk = new Checkbox(msg, true);
+ if (!this.forceUpgrades) {
+ p.add(chk);
+ } else {
+ p.add(new MultiLineLabel(msg));
+ }
+
+ this.checkboxes.addElement(chk);
+ }
+
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.anchor = 10;
+ c.fill = 0;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+ c.gridheight = 1;
+ c.insets = new Insets(0, 15, 0, 15);
+ Object[] arguments = new Object[]{new String(this.name)};
+ String msg = this.first
+ ? MessageFormat.format(Console.message("dont-have"), arguments)
+ : MessageFormat.format(Console.message("update-available"), arguments);
+ this.add(gbag, new MultiLineLabel(msg + "\n ", 5, 5), c);
+ if (count > 3) {
+ ScrollPane sp = new ScrollPane();
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.fill = 1;
+ c2.gridwidth = 0;
+ sp.setSize(280, 100);
+ sp.validate();
+ this.add(gbag, sp, c2);
+ sp.add(p);
+ } else {
+ this.add(gbag, p, c);
+ }
+
+ if (!this.forceUpgrades) {
+ this.add(gbag, this.startupCheck, c);
+ }
+
+ this.msgLabel = new MultiLineLabel(this.calcMsg(), 5, 5);
+ this.add(gbag, this.msgLabel, c);
+ c.gridwidth = 2;
+ this.add(gbag, this.getsFocus = this.yesButton, c);
+ if (!this.forceUpgrades || this.first) {
+ c.gridwidth = 0;
+ this.add(gbag, this.noButton, c);
+ c.insets.top = 5;
+ c.insets.bottom = 15;
+ this.add(gbag, this.moreInfo, c);
+ }
+ }
+
+ private String calcMsg() {
+ int totalBytes = 0;
+ if (this.bytes != null) {
+ for (int i = 0; i < this.bytes.size(); i++) {
+ if (this.checkboxes.elementAt(i).getState()) {
+ totalBytes += this.bytes.elementAt(i);
+ }
+ }
+ }
+
+ String msg = "";
+ String ins = this.forceUpgrades ? forcedInstructions : instructions;
+ if (totalBytes == 0) {
+ msg = Console.message("no-entries");
+ return "\n" + msg + " \n \n \n \n" + ins;
+ } else {
+ int modemMins = 10 * totalBytes / 288000 + 1;
+ String modemMinutes = modemMins / 10 + "." + modemMins % 10 + " " + (modemMins == 10 ? Console.message("minute") : Console.message("minutes"));
+ int cableMins = 10 * totalBytes / 1000000 + 1;
+ String cableMinutes = cableMins / 10 + "." + cableMins % 10 + " " + (cableMins == 10 ? Console.message("minute") : Console.message("minutes"));
+ NumberFormat nF = NumberFormat.getNumberInstance(Locale.getDefault());
+ String kb = nF.format((long)(totalBytes / 1000));
+ Object[] arguments = new Object[]{new String(kb), new String(cableMinutes), new String(modemMinutes)};
+ msg = MessageFormat.format(Console.message("entries-total"), arguments);
+ return msg + ins;
+ }
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.getsFocus.requestFocus();
+ }
+
+ public synchronized boolean confirmUpgrade() {
+ while (this.isActive()) {
+ try {
+ this.wait();
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ return this.getConfirmed();
+ }
+
+ public int confirmUpgradeFromList() {
+ if (!this.confirmUpgrade()) {
+ return 0;
+ } else {
+ int i = 0;
+
+ while (i < this.bytes.size() && this.checkboxes.elementAt(i).getState()) {
+ i++;
+ }
+
+ return i;
+ }
+ }
+
+ public Vector<String> rejectedList() {
+ if (!this.confirmUpgrade()) {
+ return this.list;
+ } else {
+ Vector<String> v = new Vector<String>();
+
+ for (int i = 0; i < this.bytes.size(); i++) {
+ if (!this.checkboxes.elementAt(i).getState()) {
+ v.addElement(this.list.elementAt(i));
+ }
+ }
+
+ return v;
+ }
+ }
+
+ @Override
+ protected synchronized boolean done(boolean confirmed) {
+ boolean retCode = super.done(confirmed);
+ this.notify();
+ return retCode;
+ }
+
+ @Override
+ public boolean action(Event event, Object what) {
+ if (event.target == this.yesButton) {
+ return this.done(true);
+ } else if (event.target == this.noButton) {
+ return this.done(false);
+ } else {
+ if (event.target == this.moreInfo) {
+ NetUpdate.showInfo(this.info);
+ } else if (event.target == this.startupCheck) {
+ IniFile.gamma().setIniInt("CheckUpgrades", this.startupCheck.getState() ? 1 : 0);
+ } else if (event.target instanceof Checkbox) {
+ if (this.chooseOne) {
+ int i = this.checkboxes.indexOf(event.target);
+ if (((Checkbox)event.target).getState()) {
+ while (--i >= 0) {
+ this.checkboxes.elementAt(i).setState(true);
+ }
+ } else {
+ while (++i < this.checkboxes.size()) {
+ this.checkboxes.elementAt(i).setState(false);
+ }
+ }
+ }
+
+ this.msgLabel.setLabel(this.calcMsg());
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public boolean handleEvent(Event event) {
+ return this.forceUpgrades && event.id == 201 ? this.done(true) : super.handleEvent(event);
+ }
+
+ @Override
+ public boolean keyDown(Event event, int key) {
+ return !this.forceUpgrades && key == 27 ? this.done(false) : super.keyDown(event, key);
+ }
+}
diff --git a/NET/worlds/network/UserServer.java b/NET/worlds/network/UserServer.java
new file mode 100644
index 0000000..c3112e6
--- /dev/null
+++ b/NET/worlds/network/UserServer.java
@@ -0,0 +1,73 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+
+public class UserServer extends AnonUserServer {
+ @Override
+ protected sessionInitCmd buildSessionInitCmd() {
+ OldPropertyList props = new OldPropertyList();
+ String name = this._galaxy.getChatname();
+ this._galaxy.setChatname(Console.parseUnicode(name));
+ props.addProperty(new netProperty(3, String.valueOf(this.getVersion())));
+ props.addProperty(new netProperty(9, String.valueOf(this._clientVersion)));
+ this._firstLogon = this._galaxy.addPendingServer(this);
+ switch (this.getGalaxy().getLoginMode()) {
+ case 1:
+ case 2:
+ assert this._galaxy.getChatname() != null;
+
+ this.regShortID(1, Console.parseUnicode(this._galaxy.getChatname()));
+ props.addProperty(new netProperty(2, Console.parseUnicode(this._galaxy.getChatname())));
+ if (this._galaxy.getNewChatname() != null) {
+ props.addProperty(new netProperty(28, this._galaxy.getNewChatname()));
+ }
+
+ if (this._galaxy.getPassword() != null) {
+ props.addProperty(new netProperty(6, this._galaxy.getPassword()));
+ }
+
+ if (this._galaxy.getNewPassword() != null) {
+ props.addProperty(new netProperty(20, this._galaxy.getNewPassword()));
+ }
+
+ if (this._galaxy.getLoginMode() == 1) {
+ if (this._galaxy.getSerialNum() != null) {
+ props.addProperty(new netProperty(10, this._galaxy.getSerialNum()));
+ }
+ } else if (this._firstLogon) {
+ props.addProperty(new netProperty(12, "1"));
+ }
+ break;
+ case 3:
+ assert this._galaxy.getGuestExpiration() != null;
+
+ props.addProperty(new netProperty(14, this._galaxy.getGuestExpiration()));
+ if (this._firstLogon) {
+ props.addProperty(new netProperty(12, "1"));
+ }
+ break;
+ default:
+ assert false;
+ }
+
+ if ((getDebugLevel() & 4) > 0) {
+ synchronized (System.out) {
+ System.out.println(this._serverURL.getHost() + ": sending sessionInit.");
+ System.out.println(" username = \"" + this._galaxy.getChatname() + "\"");
+ if (this._galaxy.getPassword() != null) {
+ System.out.println(" password = " + this._galaxy.getPassword());
+ }
+
+ if (this._galaxy.getLoginMode() == 1 && this._galaxy.getSerialNum() != null) {
+ System.out.println(" serial # = " + this._galaxy.getSerialNum());
+ }
+
+ if (this._galaxy.getLoginMode() == 3) {
+ System.out.println(" VAR_GUEST");
+ }
+ }
+ }
+
+ return new sessionInitCmd(props);
+ }
+}
diff --git a/NET/worlds/network/VarErrorException.java b/NET/worlds/network/VarErrorException.java
new file mode 100644
index 0000000..e2dd3b2
--- /dev/null
+++ b/NET/worlds/network/VarErrorException.java
@@ -0,0 +1,171 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.core.Std;
+import java.text.MessageFormat;
+
+public class VarErrorException extends Exception {
+ private static final long serialVersionUID = 4544550603845669010L;
+ String _msg;
+ String _altMsg;
+ int _varError;
+ int _RetryTimeout;
+ int _RetryCount;
+ boolean _retry;
+ boolean _isStatus;
+ Object[] arguments = new Object[]{new String(Std.getProductName())};
+
+ public boolean getRetryFlag() {
+ return this._retry;
+ }
+
+ public boolean getStatusFlag() {
+ return this._isStatus;
+ }
+
+ public int getRetryCount() {
+ return this._RetryCount;
+ }
+
+ public int getTimeout() {
+ return this._RetryTimeout;
+ }
+
+ public int getErrorNum() {
+ return this._varError;
+ }
+
+ public String getMsg() {
+ return this._msg;
+ }
+
+ public String getAltMsg() {
+ return this._altMsg != null ? this._altMsg : this._msg;
+ }
+
+ VarErrorException(int varError) {
+ this._varError = varError;
+ this._msg = "";
+ this._altMsg = null;
+ this._retry = false;
+ this._RetryCount = 1;
+ this._RetryTimeout = 60;
+ this._isStatus = false;
+
+ assert this._varError > 0;
+
+ switch (this._varError) {
+ case 1:
+ this._msg = Console.message("NAK_BAD_USER");
+ break;
+ case 2:
+ this._msg = Console.message("NAK_MAX_ORDINARY");
+ break;
+ case 3:
+ this._msg = Console.message("NAK_MAX_PRIORITY");
+ break;
+ case 4:
+ assert false;
+ break;
+ case 5:
+ this._msg = Console.message("NAK_FATAL");
+ this._retry = true;
+ this._RetryTimeout = 8 + (int)(Math.random() * 10.0);
+ break;
+ case 6:
+ this._msg = Console.message("NAK_BAD_PROTOCOL1") + Console.message("NAK_BAD_PROTOCOL2");
+ break;
+ case 7:
+ this._msg = Console.message("NAK_BAD_CLIENTSW");
+ break;
+ case 8:
+ assert false;
+ break;
+ case 9:
+ this._msg = Console.message("NAK_BAD_SERIAL");
+ break;
+ case 10:
+ this._msg = Console.message("NAK_TAKEN_SERIAL1") + Console.message("NAK_TAKEN_SERIAL2");
+ break;
+ case 11:
+ this._msg = Console.message("NAK_TAKEN_USER");
+ break;
+ case 12:
+ this._msg = Console.message("NAK_NO_SUCH_USER");
+ break;
+ case 13:
+ this._msg = Console.message("NAK_BAD_PASSWORD");
+ break;
+ case 14:
+ this._msg = Console.message("NAK_BAD_ACCOUNT");
+ break;
+ case 15:
+ this._msg = Console.message("NAK_NOT_LOGGEDON");
+ break;
+ case 16:
+ this._msg = Console.message("NAK_BAD_IPADDRESS");
+ break;
+ case 17:
+ this._msg = Console.message("NAK_LOGGEDON");
+ break;
+ case 21:
+ this._altMsg = "A room server is full. People might \nnot be visible nearby.";
+ this._msg = "The set of rooms you are in are quite full.\nPlease wait several minutes and try again.";
+ this._retry = true;
+ this._RetryTimeout = 15 + (int)(Math.random() * 15.0);
+ break;
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ this._msg = MessageFormat.format(Console.message("NAK_UNEXPECTED1"), this.arguments) + Console.message("NAK_UNEXPECTED2");
+ this._altMsg = MessageFormat.format(Console.message("NAK_UNEXPECTED3"), this.arguments);
+ this._retry = true;
+ this._RetryTimeout = 5 + (int)(Math.random() * 15.0);
+ break;
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ this._msg = MessageFormat.format(Console.message("NAK_UNREACHABLE1"), this.arguments)
+ + Console.message("NAK_UNREACHABLE2")
+ + Console.message("NAK_UNREACHABLE3")
+ + Console.message("NAK_UNREACHABLE4");
+ this._altMsg = MessageFormat.format(Console.message("NAK_UNREACHABLE5"), this.arguments);
+ this._retry = true;
+ this._RetryTimeout = 30 + (int)(Math.random() * 15.0);
+ break;
+ case 200:
+ this._msg = "Connected.";
+ this._isStatus = true;
+ break;
+ case 201:
+ this._msg = "Shutting down server.";
+ this._isStatus = true;
+ break;
+ case 202:
+ this._msg = "Automatically attempting to reconnect.";
+ this._isStatus = true;
+ break;
+ case 203:
+ this._msg = "Server has disconnected normally.";
+ this._isStatus = true;
+ break;
+ case 204:
+ this._msg = "Server has disconnected abnormally.";
+ this._isStatus = true;
+ break;
+ case 205:
+ this._msg = "Going into single user mode.";
+ this._isStatus = true;
+ break;
+ default:
+ this._msg = "Login error #" + this._varError;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "VarErrorException[#" + this._varError + " retry=" + this._retry + " retryCount=" + this._RetryCount + " isStatus=" + this._isStatus + "]";
+ }
+}
diff --git a/NET/worlds/network/WSConnecting.java b/NET/worlds/network/WSConnecting.java
new file mode 100644
index 0000000..5437a86
--- /dev/null
+++ b/NET/worlds/network/WSConnecting.java
@@ -0,0 +1,147 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+import java.net.NoRouteToHostException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+class WSConnecting implements Runnable {
+ private WorldServer _serv;
+ private String _host;
+ private Vector<String> _hosts;
+ private int _unresolvedHosts;
+ private int _port;
+ private int _timeout;
+ private int _error;
+ private boolean _calledBack;
+ private Vector<String> _resolvedHosts;
+
+ public WSConnecting(WorldServer serv, String host, int port, int timeout) {
+ this._serv = serv;
+ this._host = host;
+ this._hosts = new Vector<String>();
+ this._port = port;
+ this._timeout = timeout;
+ this._error = 0;
+ this.makeThread(-1);
+ StringTokenizer tok = new StringTokenizer(host, ";");
+
+ while (tok.hasMoreTokens()) {
+ this._hosts.addElement(tok.nextToken());
+ }
+
+ this._unresolvedHosts = this._hosts.size();
+
+ for (int i = 0; i < this._unresolvedHosts; i++) {
+ this.makeThread(i);
+ }
+ }
+
+ private void makeThread(int index) {
+ Thread t = new Thread(this, Integer.toString(index));
+ t.setDaemon(true);
+ t.start();
+ }
+
+ @Override
+ public void run() {
+ int index = Integer.parseInt(Thread.currentThread().getName());
+ if (index == -1) {
+ try {
+ Thread.sleep(this._timeout * 1000);
+ } catch (InterruptedException var10) {
+ }
+
+ synchronized (this) {
+ if (!this._calledBack) {
+ this._calledBack = true;
+ if (this._error == 0) {
+ this._error = 106;
+ }
+
+ this._serv.setSocket(null, new VarErrorException(this._error), null);
+ }
+ }
+ } else if (index < this._unresolvedHosts) {
+ try {
+ String host = this._hosts.elementAt(index);
+ String[] addresses = DNSLookup.lookupAll(host);
+ if (addresses.length > 1) {
+ for (int i = 0; i < addresses.length; i++) {
+ int newIndex;
+ synchronized (this._hosts) {
+ newIndex = this._hosts.size();
+ this._hosts.addElement(addresses[i]);
+ }
+
+ this.makeThread(newIndex);
+ }
+ } else {
+ this.connectTo(addresses[0], false);
+ }
+ } catch (UnknownHostException var11) {
+ synchronized (this) {
+ if (this._error == 0) {
+ this._error = 107;
+ }
+ }
+ }
+ } else {
+ this.connectTo(this._hosts.elementAt(index), false);
+ }
+ }
+
+ public Vector<String> getBackupHosts() {
+ this._resolvedHosts = new Vector<String>();
+
+ for (int i = this._unresolvedHosts; i < this._hosts.size(); i++) {
+ this._resolvedHosts.addElement(this._hosts.elementAt(i));
+ }
+
+ return this._resolvedHosts;
+ }
+
+ private void connectTo(String host, boolean delay) {
+ Socket sock = null;
+
+ try {
+ sock = new Socket(host, this._port);
+ synchronized (this) {
+ if (delay) {
+ try {
+ this.wait(this._timeout * 1000 * 2 / 3);
+ } catch (InterruptedException var7) {
+ }
+ }
+
+ System.out.println("Connected to " + host);
+ if (!this._calledBack) {
+ this._calledBack = true;
+ this._serv.setSocket(sock, null, host);
+ } else {
+ try {
+ sock.close();
+ } catch (IOException var6) {
+ }
+ }
+
+ this.notifyAll();
+ }
+ } catch (IOException var10) {
+ IOException e = var10;
+ synchronized (this) {
+ if (this._error == 0) {
+ if (!(e instanceof NoRouteToHostException) && !(e instanceof UnknownHostException)) {
+ this._error = 104;
+ } else {
+ this._error = 107;
+ }
+ }
+
+ this.notifyAll();
+ }
+ }
+ }
+}
diff --git a/NET/worlds/network/WaitList.java b/NET/worlds/network/WaitList.java
new file mode 100644
index 0000000..6fd3c00
--- /dev/null
+++ b/NET/worlds/network/WaitList.java
@@ -0,0 +1,48 @@
+package NET.worlds.network;
+
+import java.util.Vector;
+
+class WaitList {
+ private Vector<ConnectionWaiter> _waitList = new Vector<ConnectionWaiter>();
+ private Object _parent;
+
+ protected WaitList(Object parent) {
+ this._parent = parent;
+ }
+
+ protected synchronized void addWaiter(ConnectionWaiter cw) {
+ if ((Galaxy.getDebugLevel() & 16384) > 0) {
+ System.out.println(this._parent + ": waitForConnection(" + cw + ")");
+ }
+
+ if (this._waitList.indexOf(cw) < 0) {
+ this._waitList.addElement(cw);
+ }
+ }
+
+ protected synchronized void abortWait(ConnectionWaiter cw) {
+ assert this._waitList.indexOf(cw) != -1;
+
+ this._waitList.removeElement(cw);
+ }
+
+ protected synchronized void clear() {
+ this._waitList = new Vector<ConnectionWaiter>();
+ }
+
+ protected synchronized void notify(boolean connected) {
+ if ((Galaxy.getDebugLevel() & 16384) > 0 && this._waitList.size() > 0) {
+ System.out.println(this._parent + ": notify(" + connected + ")");
+ }
+
+ for (int i = this._waitList.size() - 1; i >= 0; i--) {
+ ConnectionWaiter cw = this._waitList.elementAt(i);
+ if ((Galaxy.getDebugLevel() & 16384) > 0) {
+ System.out.println("\tnotifying " + cw);
+ }
+
+ cw.connectionCallback(this._parent, connected);
+ this._waitList.removeElementAt(i);
+ }
+ }
+}
diff --git a/NET/worlds/network/WorldServer.java b/NET/worlds/network/WorldServer.java
new file mode 100644
index 0000000..e71e6d6
--- /dev/null
+++ b/NET/worlds/network/WorldServer.java
@@ -0,0 +1,1319 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import NET.worlds.core.Std;
+import NET.worlds.scape.Drone;
+import NET.worlds.scape.WObject;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class WorldServer implements MainCallback, MainTerminalCallback, NetworkObject {
+ protected int _serverProtocolVersion;
+ protected ServerURL _serverURL = null;
+ protected String _clientVersion = Std.getClientVersion();
+ protected WSConnecting _connectThread;
+ protected OutputStream _ostr = null;
+ protected Socket _sock = null;
+ protected netPacketReader _reader = null;
+ private WaitList _waiters;
+ protected int _refCnt = 0;
+ protected int _tmpRefCnt = 0;
+ protected boolean _isMainRegistered = false;
+ protected ObjectMgr _objTable = null;
+ protected Galaxy _galaxy = null;
+ protected SMState _state;
+ protected boolean _firstLogon = false;
+ protected boolean _requestOffline = false;
+ private int _lastAccessTime = 0;
+ protected int _retriesLeft = 5;
+ protected VarErrorException _lastError = null;
+ protected int _retryTimeout = 60000;
+ private int _lastMsgProcCnt = 5;
+ protected PropertyList _propList = null;
+ protected int _updateTime = 2000;
+ Vector<WorldServer.BackupServer> _backupServers;
+ String _currentBackupServer;
+ private static final int STATE_DEAD = -1;
+ protected static final int STATE_PRECONNECTED = 0;
+ private static final int STATE_AUTHPROMPT = 1;
+ private static final int STATE_AUTHREPLY = 2;
+ protected static final int STATE_INITIALIZING = 3;
+ private static final int STATE_CONNECTING = 4;
+ private static final int STATE_XMIT_PROPREQ = 5;
+ private static final int STATE_RCV_PROPS = 6;
+ protected static final int STATE_XMIT_SI = 7;
+ static final int STATE_RCV_SI_ACK = 8;
+ static final int STATE_XMIT_AI = 9;
+ static final int STATE_RCV_AI_ACK = 10;
+ static final int STATE_XMIT_PROPS = 11;
+ static final int STATE_MAINLOOP = 12;
+ private static final int STATE_XMIT_AE = 13;
+ private static final int STATE_RCV_AE_ACK = 14;
+ private static final int STATE_XMIT_SE = 15;
+ static final int STATE_RCV_SE_ACK = 16;
+ static final int STATE_DETACHING = 17;
+ static final int STATE_DISCONNECTED = 18;
+ static final int STATE_SLEEPING = 19;
+ private Vector<Object> _referrerList = new Vector<Object>();
+ private String _scriptServer;
+ private String _smtpServer;
+ private String _mailDomain;
+ private int _lastWhisperTick = 0;
+ private int _whisperCnt = 0;
+ private Vector<NetworkObject> zombies;
+
+ protected WorldServer() {
+ this._serverProtocolVersion = 24;
+ this._state = new SMState(this, 0);
+ this._currentBackupServer = null;
+ this._backupServers = new Vector<WorldServer.BackupServer>();
+ }
+
+ public void regShortID(int shortObjID, String longObjID) {
+ assert shortObjID < 253;
+
+ this._objTable.regShortID(shortObjID, longObjID);
+ }
+
+ public NetworkObject getObject(ObjID objID) {
+ return this._objTable.getObject(objID);
+ }
+
+ public void delObject(ObjID objID) {
+ this._objTable.delObject(objID);
+ }
+
+ public void regObject(ObjID objID, NetworkObject obj) {
+ this._objTable.regObject(objID, obj);
+ }
+
+ public void regObject(String longid, NetworkObject obj) {
+ this._objTable.regObject(new ObjID(longid), obj);
+ }
+
+ public String getLongID(ObjID objID) {
+ return this._objTable.getLongID(objID);
+ }
+
+ public InetAddress getLocalAddress() {
+ return this._sock != null ? this._sock.getLocalAddress() : null;
+ }
+
+ public Galaxy getGalaxy() {
+ return this._galaxy;
+ }
+
+ ServerURL getServerURL() {
+ return this._serverURL;
+ }
+
+ void initInstance(Galaxy galaxy, ServerURL serverURL) {
+ this._galaxy = galaxy;
+ this._serverURL = serverURL;
+ this._objTable = new ObjectMgr(this._galaxy);
+ this._waiters = new WaitList(this);
+ }
+
+ public net2Property getProperty(int propID) {
+ return this._propList.getProperty(propID);
+ }
+
+ public int getUpdateTime() {
+ return this._updateTime;
+ }
+
+ void setUsername(String newUsername) {
+ if ((getDebugLevel() & 4) > 0) {
+ System.out.println(this + ": Server requested username change to " + newUsername);
+ }
+
+ this._galaxy.setChatname(newUsername);
+ this.regShortID(1, newUsername);
+ }
+
+ public synchronized void printReferrers() {
+ System.out.println("[" + Std.getRealTime() + "] " + this + ": Referrer list -");
+
+ for (int i = this._referrerList.size() - 1; i >= 0; i--) {
+ Object ref = this._referrerList.elementAt(i);
+ System.out.println("\t" + ref);
+ }
+
+ System.out.println(this + ": Referrer list complete.");
+ }
+
+ public synchronized Vector<String> printDroneReferrers() {
+ Vector<String> list = new Vector<String>();
+
+ for (int i = this._referrerList.size() - 1; i >= 0; i--) {
+ Object ref = this._referrerList.elementAt(i);
+ if (ref.toString().startsWith("!")) {
+ list.addElement(ref.toString());
+ }
+ }
+
+ return list;
+ }
+
+ public synchronized void incRefCnt(Object referrer) {
+ if (this._refCnt == 0 && !this._isMainRegistered) {
+ Main.register(this);
+ this._isMainRegistered = true;
+ }
+
+ this._lastAccessTime = Std.getFastTime();
+ this._refCnt++;
+
+ assert !this._referrerList.removeElement(referrer);
+
+ this._referrerList.addElement(referrer);
+ if ((getDebugLevel() & 4096) > 0) {
+ System.out.println(this + ": incRefCnt to " + this._refCnt + " by " + referrer);
+ }
+ }
+
+ public synchronized void tmpRefCnt(Object referrer) {
+ this._tmpRefCnt++;
+ boolean existed = this._referrerList.removeElement(referrer);
+
+ assert existed;
+ }
+
+ public synchronized void decRefCnt(Object referrer) {
+ this._refCnt--;
+ boolean existed = this._referrerList.removeElement(referrer);
+
+ assert existed;
+
+ if ((getDebugLevel() & 4096) > 0) {
+ System.out.println(this + ": decRefCnt to " + this._refCnt + " by " + referrer);
+ }
+
+ assert this._refCnt >= 0;
+ }
+
+ int getRefCnt() {
+ return this._refCnt;
+ }
+
+ public int getVersion() {
+ return this._serverProtocolVersion;
+ }
+
+ public void setVersion(int ver) {
+ this._galaxy.setProtocol(ver);
+ this._serverProtocolVersion = ver;
+ if (this._reader != null) {
+ this._reader.setVersion(ver);
+ }
+
+ if (ver < 18) {
+ System.out.println(this + ": WARNING: Old server running protocol #17!");
+ }
+ }
+
+ public static int getDebugLevel() {
+ return Galaxy.getDebugLevel();
+ }
+
+ public void sendNetworkMsg(netPacket msg) throws InfiniteWaitException, PacketTooLargeException {
+ synchronized (this._state) {
+ assert this._refCnt != 0 || this._state.getState() != -1;
+
+ if (this._state.getState() != 12) {
+ throw new InfiniteWaitException();
+ } else {
+ this.sendNetMsg(msg);
+ }
+ }
+ }
+
+ public int getServerType() {
+ if (this._propList == null) {
+ return 1;
+ } else {
+ net2Property stProp = this._propList.getProperty(15);
+ int servType = 0;
+
+ try {
+ servType = Integer.parseInt(stProp.value());
+ } catch (NumberFormatException var4) {
+ assert false;
+ }
+
+ return servType;
+ }
+ }
+
+ private void setScriptServer(String server) {
+ if (!server.endsWith("/")) {
+ server = server + "/";
+ }
+
+ this._scriptServer = server;
+ }
+
+ public String getScriptServer() {
+ return this._scriptServer;
+ }
+
+ private void setSmtpServer(String server) {
+ this._smtpServer = server;
+ }
+
+ public String getSmtpServer() {
+ return this._smtpServer;
+ }
+
+ private void setMailDomain(String domain) {
+ this._mailDomain = domain;
+ }
+
+ public String getMailDomain() {
+ return this._mailDomain;
+ }
+
+ void sendNetMsg(netPacket msg) throws PacketTooLargeException {
+ assert msg != null;
+
+ if ((getDebugLevel() & 128) > 0) {
+ System.out.println("[" + Std.getRealTime() + "] " + this + ": send(" + msg.toString(this) + ")");
+ }
+
+ if (this._ostr != null) {
+ try {
+ ByteArrayOutputStream rostr = new ByteArrayOutputStream(256);
+ ServerOutputStream ostr = new ServerOutputStream(rostr, this.getVersion());
+ msg.send(ostr);
+ if ((getDebugLevel() & 1024) > 0) {
+ byte[] byteArray = rostr.toByteArray();
+ int size = byteArray[0] & 255;
+ synchronized (System.out) {
+ System.out.print(this + ": send[");
+
+ for (int i = 0; i < size; i++) {
+ System.out.print(Integer.toString(byteArray[i] & 255, 16) + " ");
+ }
+
+ System.out.println("]");
+ }
+ }
+
+ synchronized (this._ostr) {
+ rostr.writeTo(this._ostr);
+ }
+
+ this._lastAccessTime = Std.getFastTime();
+ } catch (PacketTooLargeException var10) {
+ throw var10;
+ } catch (IOException var11) {
+ VarErrorException ve = new VarErrorException(101);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ assert this._connectThread == null;
+
+ this._state.setState(17);
+ }
+ }
+ }
+
+ public void sendText(String input) {
+ this.sendText(null, input);
+ }
+
+ private void _sendText(String who, String msg) {
+ if (msg.length() > 200) {
+ Object[] arguments = new Object[]{new Integer(msg.length())};
+ Console.println(MessageFormat.format(Console.message("msg-too-long"), arguments));
+ msg = msg.substring(0, 199);
+ }
+
+ msg.trim();
+ if (msg.length() >= 1) {
+ if (who == null) {
+ try {
+ this.sendNetworkMsg(new textCmd(msg));
+ } catch (InfiniteWaitException var4) {
+ if (!msg.startsWith("&|+")) {
+ Console.println(Console.message("not-connected"));
+ }
+ } catch (PacketTooLargeException var5) {
+ assert false;
+ }
+ } else {
+ if (!msg.startsWith("&|+")) {
+ Console.printOwnWhisper(who, msg);
+ }
+
+ if (!msg.startsWith("&|+trade>") && !who.equalsIgnoreCase("trade")) {
+ int timeNow = Std.getRealTime();
+ if (timeNow - this._lastWhisperTick > 60000) {
+ this._whisperCnt = 0;
+ this._lastWhisperTick = timeNow;
+ }
+
+ this._whisperCnt++;
+ if (this._whisperCnt > 15) {
+ Console.println(Console.message("whisper-too-fast"));
+ return;
+ }
+ }
+
+ try {
+ this.sendNetworkMsg(new whisperCmd(who, msg));
+ } catch (PacketTooLargeException var6) {
+ assert false;
+ } catch (InfiniteWaitException var7) {
+ if (!msg.startsWith("&|+")) {
+ Console.println(Console.message("not-connected"));
+ }
+ }
+ }
+ }
+ }
+
+ public void sendText(String who, String msg) {
+ if ((getDebugLevel() & 1) > 0) {
+ System.out.println("[" + Std.getRealTime() + "] " + this + ": sendText(" + msg + ")");
+ }
+
+ msg = msg.trim();
+ if (msg.length() > 200) {
+ Console.println(Console.message("converting-long"));
+ int i1 = 0;
+ int i2 = 0;
+
+ while (msg.length() - i1 > 200) {
+ i2 = msg.lastIndexOf(32, i1 + 200);
+ if (i2 <= i1) {
+ i2 = i1 + 200;
+ }
+
+ this._sendText(who, msg.substring(i1, i2));
+ i1 = i2 + 1;
+ }
+
+ this._sendText(who, msg.substring(i1));
+ } else {
+ this._sendText(who, msg);
+ }
+ }
+
+ public int getState() {
+ return this._state.getState();
+ }
+
+ void setState(int state) {
+ this._state.setState(state);
+ }
+
+ public void waitForConnection() throws InfiniteWaitException {
+ this._state.waitForState(12);
+ }
+
+ public void requestRoomID(String roomName, NetworkRoom room) {
+ this._galaxy.addRoomRequest(roomName, room);
+ if (this._state.getState() == 12) {
+ try {
+ this.sendNetworkMsg(new roomIDReqCmd(roomName));
+ } catch (PacketTooLargeException var4) {
+ assert false;
+ } catch (InfiniteWaitException var5) {
+ }
+ }
+ }
+
+ public void delRoomRequest(String roomName) {
+ this._galaxy.delRoomRequest(roomName);
+ }
+
+ public void delRoomID(int roomID, NetworkRoom room) {
+ this._galaxy.delRoomID(roomID, room);
+ }
+
+ void regRoomID(int roomID, String roomName, boolean willRedirect) {
+ NetworkRoom room = this._galaxy.regRoomID(roomID, roomName);
+ if (room != null) {
+ room.setRoomID(this, roomID, roomName, willRedirect);
+ }
+ }
+
+ public void redirectRoom(String roomName, ServerURL serverURL) {
+ NetworkRoom room = (NetworkRoom)this._galaxy.getObject(roomName);
+ if (room != null) {
+ room.serverRedirect(this, roomName, serverURL);
+ }
+ }
+
+ NetworkRoom getNetworkRoom(int roomID) {
+ return this._galaxy.getRoom(roomID);
+ }
+
+ public final boolean isConnected() {
+ return this._state.getState() == 12;
+ }
+
+ void startConnect() {
+ synchronized (this._state) {
+ int state = this._state.getState();
+ switch (state) {
+ case 0:
+ assert this._connectThread == null;
+
+ this._state.setState(3);
+ break;
+ case 18:
+ this._retriesLeft = 5;
+
+ assert this._connectThread == null;
+
+ this._state.setState(3);
+ case 19:
+ }
+ }
+
+ this._lastAccessTime = Std.getFastTime();
+ }
+
+ void forceOffline() {
+ this._retriesLeft = 0;
+ this._lastError = new VarErrorException(205);
+ this._requestOffline = true;
+ }
+
+ void goOnline() {
+ this._requestOffline = false;
+ this.startConnect();
+ }
+
+ protected void perFrame(int timeNow) {
+ synchronized (this._state) {
+ int ServerState = this._state.getState();
+ switch (ServerState) {
+ case -1:
+ this.state_Dead(timeNow);
+ case 0:
+ case 4:
+ default:
+ break;
+ case 1:
+ case 2:
+ assert false;
+ break;
+ case 3:
+ this.state_Initializing();
+ break;
+ case 5:
+ this.state_XMIT_PROPREQ();
+ break;
+ case 6:
+ case 8:
+ case 16:
+ if (timeNow - this._lastAccessTime > 30000) {
+ if (getDebugLevel() > 0) {
+ System.out.println("[" + timeNow + "] " + this + ": Messaging timeout. (state=" + ServerState + ")");
+ }
+
+ if (this._lastError == null) {
+ this._lastError = new VarErrorException(106);
+ }
+
+ switch (ServerState) {
+ case 6:
+ case 16:
+ this._state.setState(17);
+ return;
+ case 8:
+ this._state.setState(15);
+ }
+ } else {
+ try {
+ this.processMsgs(ServerState, timeNow);
+ } catch (VarErrorException var10) {
+ if (getDebugLevel() > 0) {
+ System.out.println("[" + timeNow + "] " + this + ": VarError#" + var10.getErrorNum());
+ System.out.println(this + ": " + var10.getMsg());
+ }
+
+ if (this._lastError == null) {
+ this._lastError = var10;
+ }
+
+ this._state.setState(17);
+ } catch (EOFException var11) {
+ EOFException e = var11;
+ VarErrorException ve = new VarErrorException(100);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ if (getDebugLevel() > 0) {
+ synchronized (System.out) {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ this._state.setState(17);
+ } catch (IOException var12) {
+ IOException ex = var12;
+ VarErrorException vex = new VarErrorException(102);
+ if (this._lastError == null) {
+ this._lastError = vex;
+ }
+
+ synchronized (System.out) {
+ System.out.println("[" + timeNow + "] " + this + ": Read error:");
+ if (getDebugLevel() > 0) {
+ ex.printStackTrace(System.out);
+ }
+ }
+
+ this._state.setState(17);
+ } catch (Exception var13) {
+ Exception ex = var13;
+ VarErrorException vex = new VarErrorException(103);
+ if (this._lastError == null) {
+ this._lastError = vex;
+ }
+
+ synchronized (System.out) {
+ System.out.println("[" + timeNow + "] " + this + ": Unexpected error:");
+ ex.printStackTrace(System.out);
+ }
+
+ this._state.setState(17);
+ }
+ }
+ break;
+ case 7:
+ this.state_XMIT_SI();
+ break;
+ case 9:
+ this.state_XMIT_AI();
+ break;
+ case 10:
+ assert false;
+ break;
+ case 11:
+ this.state_XMIT_Props();
+ break;
+ case 12:
+ this.state_Mainloop(timeNow);
+ break;
+ case 13:
+ this.state_XMIT_AE();
+ break;
+ case 14:
+ assert false;
+ break;
+ case 15:
+ this.state_XMIT_SE();
+ break;
+ case 17:
+ this.state_Detaching();
+ break;
+ case 18:
+ this.state_Disconnected(timeNow);
+ break;
+ case 19:
+ this.state_Sleeping(timeNow);
+ }
+ }
+ }
+
+ private void processMsgs(int state, int timeNow) throws Exception {
+ int msgsInQueue = this._reader.count();
+ if (msgsInQueue > 0) {
+ int msgsToProcess = (int)Math.sqrt(this._lastMsgProcCnt * msgsInQueue);
+ if ((getDebugLevel() & 2) > 0 && msgsInQueue > 30) {
+ synchronized (System.out) {
+ System.out.println(this + ": msgs on incoming queue = " + msgsInQueue);
+ System.out.println(" processed approx " + this._lastMsgProcCnt + " messages on last round.");
+ System.out.println(" processing " + msgsToProcess + " messages.");
+ }
+ }
+
+ if (5 > msgsToProcess) {
+ this._lastMsgProcCnt = 5;
+ } else {
+ this._lastMsgProcCnt = msgsToProcess;
+ }
+
+ if (msgsInQueue < msgsToProcess) {
+ msgsToProcess = msgsInQueue;
+ }
+
+ msgsToProcess = Math.min(msgsToProcess, msgsInQueue);
+
+ while (this._state.getState() == state && msgsToProcess-- != 0) {
+ receivedNetPacket p = this._reader.get();
+
+ assert p != null;
+
+ if ((getDebugLevel() & 64) > 0) {
+ System.out.println(this + ": recv(" + p.toString(this) + ")");
+ }
+
+ p.process(this);
+ }
+
+ this._lastAccessTime = timeNow;
+ }
+ }
+
+ protected void state_Initializing() {
+ if (this._requestOffline) {
+ this._state.setState(-1);
+ } else if (this._serverURL.getHost().equals("0.0.0.0:0")) {
+ System.out.println(this + ": DOA");
+ this._state.setState(-1);
+ } else {
+ this._objTable.regShortID(255, this.getLongID());
+ this._objTable.regObject(this.getLongID(), this);
+ this._lastError = null;
+ this._firstLogon = false;
+ String host = this._serverURL.getHost();
+ int port = 5100;
+
+ assert host != null;
+
+ int cindx = this._serverURL.getHost().lastIndexOf(58);
+ if (cindx >= 0) {
+ try {
+ port = Integer.parseInt(this._serverURL.getHost().substring(cindx + 1));
+ } catch (NumberFormatException var8) {
+ NumberFormatException e = var8;
+ synchronized (System.out) {
+ System.out.println("######DEBUGGING######");
+ System.out.println(" server: " + this._serverURL.getHost());
+ System.out.println(" message: " + e.getMessage());
+ e.printStackTrace(System.out);
+ System.out.println("#####################");
+ }
+
+ VarErrorException ve = new VarErrorException(103);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ System.out.println("Error in server URL format: " + this._serverURL.getHost());
+ this._state.setState(17);
+ return;
+ }
+
+ host = this._serverURL.getHost().substring(0, cindx);
+ }
+
+ this._lastAccessTime = Std.getFastTime();
+ if (this._currentBackupServer != null) {
+ if (this._sock != null) {
+ try {
+ this._sock.close();
+ } catch (Exception var7) {
+ }
+
+ this._sock = null;
+ }
+
+ host = this._currentBackupServer;
+ }
+
+ if (this._sock == null) {
+ this._state.setState(4);
+
+ assert this._connectThread == null;
+
+ this._connectThread = new WSConnecting(this, host, port, 15);
+ } else if (this._propList == null) {
+ this._state.setState(5);
+ } else {
+ this._state.setState(7);
+ }
+ }
+ }
+
+ protected void setSocket(Socket sock, VarErrorException ve, String host) {
+ Vector<String> resolvedHosts = this._connectThread.getBackupHosts();
+ Enumeration<String> en = resolvedHosts.elements();
+
+ while (en.hasMoreElements()) {
+ WorldServer.BackupServer bs = new WorldServer.BackupServer(en.nextElement());
+ Enumeration<WorldServer.BackupServer> en2 = this._backupServers.elements();
+ boolean unique = true;
+
+ while (en2.hasMoreElements()) {
+ if (en2.nextElement().GetHost().equals(bs.GetHost())) {
+ unique = false;
+ break;
+ }
+ }
+
+ if (unique) {
+ this._backupServers.addElement(bs);
+ }
+
+ if (host != null && host.equals(bs.GetHost())) {
+ bs.IncTries();
+ }
+ }
+
+ this._connectThread = null;
+ if (this._state.getState() == 4) {
+ if (sock != null) {
+ this._sock = sock;
+
+ try {
+ this._ostr = this._sock.getOutputStream();
+ this._reader = new netPacketReader(this, new ServerInputStream(this._sock.getInputStream()));
+ this._reader.setVersion(this.getVersion());
+ } catch (Exception var9) {
+ ve = new VarErrorException(105);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ System.out.println(this + ": Error opening I/O streams.");
+ this._state.setState(17);
+ return;
+ }
+
+ this._reader.setDaemon(true);
+ this._reader.start();
+ this._state.setState(5);
+ } else {
+ assert ve != null;
+
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ this._state.setState(17);
+ }
+ }
+ }
+
+ protected void state_XMIT_PROPREQ() {
+ if (this._requestOffline) {
+ this._state.setState(17);
+ } else {
+ propReqCmd propReq = new propReqCmd(new ObjID(255));
+ if (NetUpdate.isInternalVersion()) {
+ propReq.addProp(1);
+ propReq.addProp(3);
+ propReq.addProp(15);
+ propReq.addProp(29);
+ propReq.addProp(25);
+ propReq.addProp(26);
+ propReq.addProp(27);
+ }
+
+ try {
+ this.sendNetMsg(propReq);
+ } catch (PacketTooLargeException var3) {
+ assert false;
+ }
+
+ this._state.setState(6);
+ }
+ }
+
+ protected void state_XMIT_SI() {
+ assert false;
+
+ if (this._requestOffline) {
+ this._state.setState(17);
+ } else {
+ this._galaxy.addPendingServer(this);
+ this._state.setState(8);
+ }
+ }
+
+ protected void state_XMIT_AI() {
+ assert false;
+
+ if (this._requestOffline) {
+ this._state.setState(17);
+ } else {
+ this._state.setState(11);
+ }
+ }
+
+ protected void state_XMIT_Props() {
+ if (this._requestOffline) {
+ this._state.setState(15);
+ } else {
+ this._state.setState(12);
+ this._galaxy.addActiveServer(this);
+ }
+ }
+
+ protected void state_Mainloop(int timeNow) {
+ this.killZombies();
+ if (this._requestOffline) {
+ this._state.setState(15);
+ } else if (timeNow - this._lastAccessTime > 120000) {
+ if (getDebugLevel() > 0) {
+ System.out.println(this + ": Timeout during connection.");
+ }
+
+ System.out.println("[" + timeNow + "] " + this + ": Timeout during connection.");
+ System.out.println("\t_lastAccessTime = " + this._lastAccessTime);
+ System.out.println("\t timeNow = " + timeNow);
+ this._retriesLeft = 0;
+ this._state.setState(15);
+ } else {
+ this._waiters.notify(true);
+
+ try {
+ this.processMsgs(12, timeNow);
+ } catch (VarErrorException var8) {
+ assert false;
+
+ this._state.setState(17);
+ } catch (EOFException var9) {
+ EOFException e = var9;
+ VarErrorException ve = new VarErrorException(100);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ synchronized (System.out) {
+ System.out.println("[" + timeNow + "] " + this + ": Server has shut down connection.");
+ if (getDebugLevel() > 0) {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ this._state.setState(17);
+ } catch (IOException var10) {
+ IOException e = var10;
+ VarErrorException ve = new VarErrorException(100);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ synchronized (System.out) {
+ System.out.println("[" + timeNow + "] " + this + ": Error reading from network.");
+ if (getDebugLevel() > 0) {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ this._state.setState(17);
+ } catch (Exception var11) {
+ Exception e = var11;
+ VarErrorException ve = new VarErrorException(103);
+ if (this._lastError == null) {
+ this._lastError = ve;
+ }
+
+ synchronized (System.out) {
+ System.out.println("[" + timeNow + "] " + this + ": Unexpected error.");
+ e.printStackTrace(System.out);
+ }
+
+ this._state.setState(17);
+ }
+ }
+ }
+
+ protected void state_XMIT_AE() {
+ assert false;
+
+ this._state.setState(14);
+ this._state.setState(15);
+ }
+
+ protected void state_XMIT_SE() {
+ boolean sendVAR_LOGONOFF = this._galaxy.addClosingServer(this);
+ OldPropertyList propList = new OldPropertyList();
+ if (sendVAR_LOGONOFF) {
+ propList.addProperty(new netProperty(12, "1"));
+ }
+
+ try {
+ this.sendNetMsg(new sessionExitCmd(propList));
+ } catch (PacketTooLargeException var4) {
+ assert false;
+ }
+
+ this._state.setState(16);
+ }
+
+ protected void reuseConnection(WorldServer src) {
+ this._reader = src._reader;
+ src._reader = null;
+ this._ostr = src._ostr;
+ src._ostr = null;
+ this._sock = src._sock;
+ src._sock = null;
+ this._backupServers = (Vector<WorldServer.BackupServer>)src._backupServers.clone();
+ }
+
+ public boolean useBackupServer() {
+ Enumeration<WorldServer.BackupServer> enums = this._backupServers.elements();
+
+ while (enums.hasMoreElements()) {
+ WorldServer.BackupServer bs = enums.nextElement();
+ if (bs.tries == 0) {
+ bs.IncTries();
+ this._currentBackupServer = bs.GetHost();
+ return true;
+ }
+ }
+
+ this._currentBackupServer = null;
+ return false;
+ }
+
+ private void addZombies() {
+ Enumeration<NetworkObject> enums = this._objTable.objects();
+
+ while (enums.hasMoreElements()) {
+ NetworkObject no = enums.nextElement();
+ if (no instanceof WObject) {
+ if (this.zombies == null) {
+ this.zombies = new Vector<NetworkObject>();
+ }
+
+ this.zombies.addElement(no);
+ } else if (no instanceof Drone) {
+ ((Drone)no).disappear();
+ }
+ }
+
+ this._objTable.clear();
+ }
+
+ public void killZombies() {
+ if (this.zombies != null) {
+ int i = this.zombies.size();
+
+ while (--i >= 0) {
+ NetworkObject no = this.zombies.elementAt(i);
+ this._objTable.regObject(no.getLongID(), no);
+ if (no instanceof Drone) {
+ ((Drone)no).disappear();
+ }
+ }
+
+ this.zombies = null;
+ }
+ }
+
+ private void cleanup() {
+ assert this._objTable != null;
+
+ if (this._lastError != null && !this._lastError.getStatusFlag()) {
+ this.addZombies();
+ } else {
+ this.killZombies();
+ Enumeration<NetworkObject> enums = this._objTable.objects();
+
+ while (enums.hasMoreElements()) {
+ NetworkObject no = enums.nextElement();
+ if (no instanceof Drone) {
+ ((Drone)no).disappear();
+ }
+ }
+
+ this._objTable.clear();
+ }
+
+ if (this._reader != null) {
+ if (this._reader.isAlive()) {
+ this._reader.stop();
+ }
+
+ this._reader = null;
+ }
+
+ if (this._ostr != null) {
+ try {
+ this._ostr.close();
+ } catch (Exception var4) {
+ }
+
+ this._ostr = null;
+ }
+
+ if (this._sock != null) {
+ try {
+ this._sock.close();
+ } catch (Exception var3) {
+ }
+
+ this._sock = null;
+ }
+
+ assert this._connectThread == null;
+ }
+
+ protected void state_Detaching_helper() {
+ if (this._galaxy != null) {
+ this._galaxy.addClosingServer(this);
+ this._galaxy.markClosedServer(this);
+ }
+
+ this.cleanup();
+ this._retryTimeout = 60000;
+ if (this._galaxy != null) {
+ this._galaxy.noteServerDeath(this._lastError);
+ }
+ }
+
+ protected void state_Detaching() {
+ this._state.setState(18);
+ this.state_Detaching_helper();
+ if (this._lastError != null) {
+ System.out.println("[" + Std.getRealTime() + "] " + this + ": lastError=" + this._lastError);
+ this._lastError = null;
+ this._galaxy.reacquireServer(this);
+ } else if (this._refCnt - this._tmpRefCnt > 0) {
+ this.startConnect();
+ }
+ }
+
+ protected void state_Sleeping(int timeNow) {
+ if (this._requestOffline) {
+ this._state.setState(-1);
+ } else {
+ if (timeNow - this._lastAccessTime > this._retryTimeout) {
+ if (this._refCnt == 0) {
+ this._state.setState(18);
+ } else {
+ this._state.setState(3);
+ }
+ }
+ }
+ }
+
+ protected void state_Disconnected(int timeNow) {
+ this._waiters.notify(false);
+ if (timeNow - this._lastAccessTime > 1800000) {
+ synchronized (this) {
+ if (this._refCnt == 0) {
+ assert this._isMainRegistered;
+
+ Main.unregister(this);
+ this._isMainRegistered = false;
+ if (this._galaxy != null) {
+ this._galaxy.killServer(this);
+ }
+ }
+ }
+ } else {
+ this._lastAccessTime = timeNow;
+ }
+ }
+
+ protected void state_Dead(int timeNow) {
+ this.killZombies();
+ this.state_Disconnected(timeNow);
+ }
+
+ @Override
+ public void mainCallback() {
+ int t = Std.getRealTime();
+ this.perFrame(t);
+ if ((getDebugLevel() & 4096) > 0 && this._tmpRefCnt > 0) {
+ System.out.println(this + ": tmpRefCnt cleanup of " + this._tmpRefCnt + " refs.");
+ }
+
+ synchronized (this) {
+ this._refCnt = this._refCnt - this._tmpRefCnt;
+ this._tmpRefCnt = 0;
+ }
+
+ assert this._refCnt >= 0;
+ }
+
+ @Override
+ public void terminalCallback() {
+ synchronized (this) {
+ if (this._isMainRegistered) {
+ Main.unregister(this);
+ }
+
+ Galaxy.forceOffline(false);
+ if (this._lastError == null) {
+ this._lastError = new VarErrorException(201);
+ }
+
+ this._retriesLeft = 0;
+ int state = this._state.getState();
+ this._state.setState(-1);
+ switch (state) {
+ case 4:
+ this._connectThread = null;
+ case 7:
+ case 16:
+ case 17:
+ if ((getDebugLevel() & 512) > 0) {
+ System.out.println(this + ": terminalCallback(): Detach");
+ }
+
+ this.state_Detaching();
+ break;
+ case 5:
+ case 6:
+ case 13:
+ case 14:
+ default:
+ if ((getDebugLevel() & 512) > 0) {
+ System.out.println(this + ": terminalCallback(): no operation");
+ }
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ if ((getDebugLevel() & 512) > 0) {
+ System.out.println(this + ": terminalCallback(): XMIT_SE, Detach");
+ }
+
+ this.state_XMIT_SE();
+ this.state_Detaching();
+ }
+ }
+ }
+
+ public void waitForConnection(ConnectionWaiter cw) {
+ this._waiters.addWaiter(cw);
+ }
+
+ public void abortWaitForConnection(ConnectionWaiter cw) {
+ this._waiters.abortWait(cw);
+ }
+
+ @Override
+ public String toString() {
+ return this.getLongID();
+ }
+
+ @Override
+ public void property(OldPropertyList propList) {
+ assert false;
+ }
+
+ @Override
+ public void propertyUpdate(PropertyList propList) {
+ this._propList = propList;
+ net2Property protocol = this._propList.getProperty(3);
+ if (protocol != null) {
+ int ver;
+ try {
+ ver = Integer.parseInt(protocol.value());
+ } catch (NumberFormatException var9) {
+ System.err.println(this + ": Error converting protocol value: " + protocol.value());
+ ver = 18;
+ }
+
+ int oldVer = this.getVersion();
+ this.setVersion(ver < oldVer ? ver : oldVer);
+ }
+
+ net2Property update = this._propList.getProperty(8);
+ if (update != null) {
+ try {
+ this._updateTime = Integer.parseInt(update.value());
+ this._updateTime /= 1000;
+ } catch (NumberFormatException var8) {
+ System.err.println(this + ": Error converting update value: " + update.value());
+ }
+ }
+
+ net2Property http = this._propList.getProperty(24);
+ if (http == null) {
+ http = this._propList.getProperty(29);
+ }
+
+ if (http != null) {
+ NetUpdate.setUpgradeServerURL(http.value());
+ }
+
+ net2Property script = this._propList.getProperty(25);
+ if (script != null) {
+ this.setScriptServer(script.value());
+ }
+
+ net2Property smtp = this._propList.getProperty(26);
+ if (smtp != null) {
+ this.setSmtpServer(smtp.value());
+ }
+
+ net2Property domain = this._propList.getProperty(27);
+ if (domain != null) {
+ this.setMailDomain(domain.value());
+ }
+
+ if (this._state.getState() == 6) {
+ this._state.setState(7);
+ }
+ }
+
+ @Override
+ public WorldServer getServer() {
+ return this;
+ }
+
+ @Override
+ public String getLongID() {
+ return this._serverURL.getHost();
+ }
+
+ @Override
+ public void register() {
+ assert false;
+ }
+
+ @Override
+ public void galaxyDisconnected() {
+ assert false;
+ }
+
+ @Override
+ public void reacquireServer(WorldServer oldServer) {
+ }
+
+ @Override
+ public void changeChannel(Galaxy g, String oldChannel, String newChannel) {
+ }
+
+ protected class BackupServer {
+ protected String hostName;
+ protected int tries;
+
+ public BackupServer() {
+ this.hostName = "";
+ this.tries = 0;
+ }
+
+ public BackupServer(String host) {
+ this.hostName = host;
+ this.tries = 0;
+ }
+
+ public String GetHost() {
+ return this.hostName;
+ }
+
+ public void IncTries() {
+ this.tries++;
+ }
+ }
+}
diff --git a/NET/worlds/network/appInitCmd.java b/NET/worlds/network/appInitCmd.java
new file mode 100644
index 0000000..0b8f50b
--- /dev/null
+++ b/NET/worlds/network/appInitCmd.java
@@ -0,0 +1,37 @@
+package NET.worlds.network;
+
+public class appInitCmd extends propCmd {
+ public static final byte APPINITCMD = 8;
+
+ public appInitCmd() {
+ this._commandType = 8;
+ }
+
+ public appInitCmd(String s) {
+ this._commandType = 8;
+ this._propList.addProperty(new netProperty(1, s));
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ assert serv.getState() == 10;
+
+ netProperty _error = this._propList.elementAt(0);
+
+ try {
+ int errorval = Integer.parseInt(_error.value());
+ if (errorval != 0) {
+ throw new VarErrorException(errorval);
+ }
+ } catch (NumberFormatException var4) {
+ System.err.println("appInitCmd: couldn't parse VAR_ERROR = " + _error.value());
+ }
+
+ serv.setState(11);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "APPINIT " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/appearActorCmd.java b/NET/worlds/network/appearActorCmd.java
new file mode 100644
index 0000000..7960f1e
--- /dev/null
+++ b/NET/worlds/network/appearActorCmd.java
@@ -0,0 +1,42 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Drone;
+import java.io.IOException;
+
+public class appearActorCmd extends receivedNetPacket {
+ public static final byte APPEARACTORCMD = 12;
+ protected int _roomID;
+ protected short _x;
+ protected short _y;
+ protected short _z;
+ protected short _direction;
+
+ public appearActorCmd() {
+ this._commandType = 12;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._roomID = data.readUnsignedShort();
+ this._x = data.readShort();
+ this._y = data.readShort();
+ this._z = data.readShort();
+ this._direction = data.readShort();
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ Drone d = Drone.make(this._objID, _serv);
+ this._direction = (short)(90 - this._direction);
+ this._direction = (short)(360 - this._direction);
+ NetworkRoom netroom = _serv.getNetworkRoom(this._roomID);
+ if (netroom != null) {
+ d.appear(netroom.getRoom(), this._x, this._y, this._z, this._direction);
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "APPRACTR " + this._objID.toString(serv) + " in " + this._roomID + " @ " + this._x + "," + this._y + "," + this._z + "," + this._direction;
+ }
+}
diff --git a/NET/worlds/network/disappearActorCmd.java b/NET/worlds/network/disappearActorCmd.java
new file mode 100644
index 0000000..72a4808
--- /dev/null
+++ b/NET/worlds/network/disappearActorCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Drone;
+import java.io.IOException;
+
+public class disappearActorCmd extends receivedNetPacket {
+ public static final byte DISAPPEARACTORCMD = 11;
+
+ public disappearActorCmd() {
+ this._commandType = 11;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o instanceof Drone) {
+ ((Drone)o).disappear();
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "DISAPPR " + this._objID.toString(serv);
+ }
+}
diff --git a/NET/worlds/network/longLocCmd.java b/NET/worlds/network/longLocCmd.java
new file mode 100644
index 0000000..0f9afd4
--- /dev/null
+++ b/NET/worlds/network/longLocCmd.java
@@ -0,0 +1,65 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Drone;
+import java.io.IOException;
+
+public class longLocCmd extends receivedNetPacket {
+ public static final byte LONGLOCCMD = 1;
+ protected short _x;
+ protected short _y;
+ protected short _z;
+ protected short _dir;
+
+ public longLocCmd() {
+ this._commandType = 1;
+ }
+
+ public longLocCmd(short x, short y, short z, short dir) {
+ super(null, 1);
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._dir = dir;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._x = data.readShort();
+ this._y = data.readShort();
+ this._z = data.readShort();
+ this._dir = data.readShort();
+ }
+
+ @Override
+ int packetSize() {
+ return 8 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeShort(this._x);
+ o.writeShort(this._y);
+ o.writeShort(this._z);
+ o.writeShort(this._dir);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o instanceof Drone) {
+ this._dir = (short)(90 - this._dir);
+ this._dir = (short)(360 - this._dir);
+ if (o == null) {
+ System.out.println("error in message: " + this.toString(_serv));
+ }
+
+ ((Drone)o).longLoc(this._x, this._y, this._z, this._dir);
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "LONGLOC " + this._objID.toString(serv) + " @ " + this._x + "," + this._y + "," + this._z + "," + this._dir;
+ }
+}
diff --git a/NET/worlds/network/net2Property.java b/NET/worlds/network/net2Property.java
new file mode 100644
index 0000000..eb88175
--- /dev/null
+++ b/NET/worlds/network/net2Property.java
@@ -0,0 +1,171 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+import java.io.UTFDataFormatException;
+
+public class net2Property {
+ private int _propID;
+ protected int _flags;
+ protected int _access;
+ protected String _stringValue;
+ protected byte[] _binValue;
+
+ public net2Property(int p, int flags, int access, byte[] data) {
+ this._propID = p;
+ this._flags = flags;
+ this._access = access;
+
+ assert (flags & 16) > 0;
+
+ this._binValue = data;
+ this._stringValue = null;
+ }
+
+ public net2Property(int p, int flags, int access, String data) {
+ this._propID = p;
+ this._flags = flags;
+ this._access = access;
+
+ assert (flags & 16) == 0;
+
+ this._stringValue = data;
+ this._binValue = null;
+ }
+
+ public net2Property() {
+ this._propID = 0;
+ this._flags = 0;
+ this._access = 0;
+ this._stringValue = null;
+ this._binValue = null;
+ }
+
+ public int property() {
+ return this._propID;
+ }
+
+ public int flags() {
+ return this._flags;
+ }
+
+ public int access() {
+ return this._access;
+ }
+
+ public byte[] data() {
+ if ((this._flags & 16) > 0) {
+ return this._binValue;
+ } else {
+ byte[] data = new byte[this._stringValue.length()];
+ this._stringValue.getBytes(0, this._stringValue.length(), data, 0);
+ return data;
+ }
+ }
+
+ public String value() {
+ return (this._flags & 16) == 0 ? this._stringValue : new String(this._binValue);
+ }
+
+ int packetSize() {
+ if ((this._flags & 16) > 0) {
+ assert this._binValue != null;
+
+ return 4 + this._binValue.length;
+ } else {
+ assert this._stringValue != null;
+
+ return 4 + ServerOutputStream.utfLength(this._stringValue);
+ }
+ }
+
+ void parseNetData(ServerInputStream data) throws IOException, UTFDataFormatException {
+ this._propID = data.readUnsignedByte();
+ this._flags = data.readUnsignedByte();
+ this._access = data.readUnsignedByte();
+ if ((this._flags & 16) > 0) {
+ int size = data.readUnsignedByte();
+ this._binValue = new byte[size];
+ data.readFully(this._binValue);
+ this._stringValue = null;
+ } else {
+ try {
+ this._stringValue = data.readUTF();
+ } catch (UTFDataFormatException var3) {
+ this._stringValue = "";
+ throw var3;
+ }
+
+ this._binValue = null;
+ }
+ }
+
+ void send(ServerOutputStream o) throws IOException {
+ o.writeByte(this._propID);
+ o.writeByte(this._flags);
+ o.writeByte(this._access);
+ if ((this._flags & 16) > 0) {
+ o.writeByte(this._binValue.length);
+ o.write(this._binValue);
+ } else {
+ o.writeUTF(this._stringValue);
+ }
+ }
+
+ private String flagString() {
+ String out = "";
+ if ((this._flags & 128) > 0) {
+ out = out + "DBSTORE ";
+ }
+
+ if ((this._flags & 64) > 0) {
+ out = out + "AUTOUPDATE ";
+ }
+
+ if ((this._flags & 32) > 0) {
+ out = out + "FINGER ";
+ }
+
+ if ((this._flags & 16) > 0) {
+ out = out + "BINARY ";
+ }
+
+ if (out.length() == 0) {
+ out = "NONE";
+ }
+
+ return out;
+ }
+
+ private String accessString() {
+ String out = "";
+ if ((this._access & 1) > 0) {
+ out = out + "POSSESS ";
+ }
+
+ if ((this._access & 2) > 0) {
+ out = out + "PRIVATE ";
+ }
+
+ if (out.length() == 0) {
+ out = "NONE";
+ }
+
+ return out;
+ }
+
+ @Override
+ public String toString() {
+ String tmp = "#" + this._propID + " [" + this.flagString() + "/" + this.accessString() + "] ";
+ if ((this._flags & 16) == 0) {
+ return tmp + this._stringValue;
+ } else {
+ tmp = tmp + "val=[";
+
+ for (int i = 0; i < this._binValue.length; i++) {
+ tmp = tmp + Integer.toString(this._binValue[i], 16) + " ";
+ }
+
+ return tmp + "] (" + this._binValue + ")";
+ }
+ }
+}
diff --git a/NET/worlds/network/netCmds.java b/NET/worlds/network/netCmds.java
new file mode 100644
index 0000000..ef3cdbb
--- /dev/null
+++ b/NET/worlds/network/netCmds.java
@@ -0,0 +1,68 @@
+package NET.worlds.network;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+class netCmds {
+ private Vector<String> _recvNetPacket = new Vector<String>();
+ private static Hashtable<Integer, String> _propList = new Hashtable<Integer, String>();
+
+ static {
+ _propList.put(new Integer(1), "VAR_APPNAME");
+ _propList.put(new Integer(2), "VAR_USERNAME");
+ _propList.put(new Integer(3), "VAR_PROTOCOL");
+ _propList.put(new Integer(4), "VAR_ERROR");
+ _propList.put(new Integer(5), "VAR_CHANNEL");
+ _propList.put(new Integer(6), "VAR_PASSWORD");
+ _propList.put(new Integer(7), "VAR_AVATARS");
+ _propList.put(new Integer(8), "VAR_UPDATETIME");
+ _propList.put(new Integer(9), "VAR_CLIENT");
+ _propList.put(new Integer(10), "VAR_SERIAL");
+ _propList.put(new Integer(11), "VAR_EMAIL");
+ _propList.put(new Integer(12), "VAR_LOGONOFF");
+ _propList.put(new Integer(13), "VAR_DURATION");
+ _propList.put(new Integer(14), "VAR_GUEST");
+ _propList.put(new Integer(15), "VAR_SERVERTYPE");
+ _propList.put(new Integer(16), "VAR_BIZCARD");
+ _propList.put(new Integer(22), "VAR_PRIV");
+ _propList.put(new Integer(20), "VAR_NEW_PASSWD");
+ _propList.put(new Integer(23), "VAR_ASLEEP");
+ _propList.put(new Integer(24), "VAR_EXTERNAL_HTTP_SERVER");
+ _propList.put(new Integer(25), "VAR_SCRIPT_SERVER");
+ _propList.put(new Integer(26), "VAR_SMTP_SERVER");
+ _propList.put(new Integer(27), "VAR_MAIL_DOMAIN");
+ _propList.put(new Integer(28), "VAR_NEW_USERNAME");
+ _propList.put(new Integer(29), "VAR_INTERNAL_HTTP_SERVER");
+ }
+
+ public netCmds() {
+ this._recvNetPacket.addElement("appInitCmd");
+ this._recvNetPacket.addElement("appearActorCmd");
+ this._recvNetPacket.addElement("disappearActorCmd");
+ this._recvNetPacket.addElement("longLocCmd");
+ this._recvNetPacket.addElement("propCmd");
+ this._recvNetPacket.addElement("regObjIDCmd");
+ this._recvNetPacket.addElement("roomChangeCmd");
+ this._recvNetPacket.addElement("sessionExitCmd");
+ this._recvNetPacket.addElement("sessionInitCmd");
+ this._recvNetPacket.addElement("shortLocCmd");
+ this._recvNetPacket.addElement("teleportCmd");
+ this._recvNetPacket.addElement("textCmd");
+ this._recvNetPacket.addElement("whisperCmd");
+ this._recvNetPacket.addElement("roomIDCmd");
+ this._recvNetPacket.addElement("PropertySetCmd");
+ this._recvNetPacket.addElement("PropertyUpdateCmd");
+ this._recvNetPacket.addElement("FingerReplyCmd");
+ this._recvNetPacket.addElement("RedirectCmd");
+ this._recvNetPacket.addElement("RedirectIDCmd");
+ this._recvNetPacket.addElement("BuddyListNotifyCmd");
+ }
+
+ Vector<String> recvCmdList() {
+ return this._recvNetPacket;
+ }
+
+ static String getPropName(int id) {
+ return _propList.get(new Integer(id));
+ }
+}
diff --git a/NET/worlds/network/netConst.java b/NET/worlds/network/netConst.java
new file mode 100644
index 0000000..b15ee4c
--- /dev/null
+++ b/NET/worlds/network/netConst.java
@@ -0,0 +1,94 @@
+package NET.worlds.network;
+
+public interface netConst {
+ byte PROTOCOL_VERSION = 24;
+ byte STATECMD = 2;
+ int MAXCMD = 255;
+ int CURRENT_ROOM = 253;
+ int CLIENT = 1;
+ int CO = 254;
+ int PO = 255;
+ byte VAR_APPNAME = 1;
+ byte VAR_USERNAME = 2;
+ byte VAR_PROTOCOL = 3;
+ byte VAR_ERROR = 4;
+ byte VAR_CHANNEL = 5;
+ byte VAR_BITMAP = 5;
+ byte VAR_PASSWORD = 6;
+ byte VAR_AVATARS = 7;
+ byte VAR_UPDATETIME = 8;
+ byte VAR_CLIENT = 9;
+ int VAR_SERIAL = 10;
+ int VAR_EMAIL = 11;
+ int VAR_LOGONOFF = 12;
+ int VAR_DURATION = 13;
+ int VAR_GUEST = 14;
+ int VAR_SERVERTYPE = 15;
+ int VAR_BIZCARD = 16;
+ int VAR_NEW_PASSWD = 20;
+ int VAR_PRIV = 22;
+ byte VAR_ASLEEP = 23;
+ byte VAR_EXTERNAL_HTTP_SERVER = 24;
+ byte VAR_SCRIPT_SERVER = 25;
+ byte VAR_SMTP_SERVER = 26;
+ byte VAR_MAIL_DOMAIN = 27;
+ byte VAR_NEW_USERNAME = 28;
+ byte VAR_INTERNAL_HTTP_SERVER = 29;
+ byte VAR_INVENTORY = 32;
+ int ACK = 0;
+ int NAK_BAD_USER = 1;
+ int NAK_MAX_ORDINARY = 2;
+ int NAK_MAX_PRIORITY = 3;
+ int NAK_BAD_WORLD = 4;
+ int NAK_FATAL = 5;
+ int NAK_BAD_PROTOCOL = 6;
+ int NAK_BAD_CLIENTSW = 7;
+ int NAK_BAD_ROOM = 8;
+ int NAK_BAD_SERIAL = 9;
+ int NAK_TAKEN_SERIAL = 10;
+ int NAK_TAKEN_USER = 11;
+ int NAK_NO_SUCH_USER = 12;
+ int NAK_BAD_PASSWORD = 13;
+ int NAK_BAD_ACCOUNT = 14;
+ int NAK_NOT_LOGGEDON = 15;
+ int NAK_BAD_IPADDRESS = 16;
+ int NAK_LOGGEDON = 17;
+ int NAK_CRYPT_METHOD = 18;
+ int NAK_CRYPT_ERROR = 19;
+ int NAK_SESSIONINIT = 20;
+ int NAK_ROOM_FULL = 21;
+ int NAK_SHUTDOWN = 100;
+ int NAK_WRITE_ERROR = 101;
+ int NAK_READ_ERROR = 102;
+ int NAK_UNEXPECTED = 103;
+ int NAK_CONNECTION = 104;
+ int NAK_IOSTREAMS = 105;
+ int NAK_TIMEOUT = 106;
+ int NAK_UNREACHABLE = 107;
+ int STATUS_CONNECTED = 200;
+ int STATUS_DETACHING = 201;
+ int STATUS_WILLRETRY = 202;
+ int STATUS_DISCONNECTED = 203;
+ int STATUS_DEAD = 204;
+ int STATUS_OFFLINE = 205;
+ int STATUS_GALAXY_ONLINE = 206;
+ int STATUS_GALAXY_OFFLINE = 206;
+ int PROPFLAG_BINARY = 16;
+ int PROPFLAG_FINGER = 32;
+ int PROPFLAG_AUTOUPDATE = 64;
+ int PROPFLAG_DBSTORE = 128;
+ int PROPACCESS_POSSESS = 1;
+ int PROPACCESS_PRIVATE = 2;
+ int SERVER_UNKNOWN = 0;
+ int USER_SERVER_DB = 1;
+ int USER_SERVER_ANON = 2;
+ int ROOM_SERVER_US = 3;
+ int ROOM_SERVER_ANON = 4;
+ int PRIV_NONE = 0;
+ int PRIV_BUILD = 1;
+ int PRIV_BROADCAST = 2;
+ int PRIV_PROPERTY = 4;
+ int PRIV_VIP = 8;
+ int PRIV_VIP2 = 16;
+ int PRIV_SPECIALGUEST = 64;
+}
diff --git a/NET/worlds/network/netData.java b/NET/worlds/network/netData.java
new file mode 100644
index 0000000..c3375a3
--- /dev/null
+++ b/NET/worlds/network/netData.java
@@ -0,0 +1,114 @@
+package NET.worlds.network;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.UTFDataFormatException;
+
+class netData {
+ private byte[] _data;
+ private int _packetSize;
+ private int _offset;
+
+ public netData(DataInputStream in) {
+ try {
+ this._packetSize = in.readUnsignedByte();
+ this._data = new byte[256];
+ in.readFully(this._data, 1, this._packetSize - 1);
+ this._data[0] = (byte)this._packetSize;
+ } catch (Exception var3) {
+ this._data = null;
+ this._packetSize = 0;
+ }
+
+ this._offset = 1;
+ }
+
+ public final int packetSize() {
+ return this._packetSize;
+ }
+
+ public final boolean isEmpty() {
+ return this._offset >= this._packetSize;
+ }
+
+ public final byte getByte() {
+ assert this._offset < this._packetSize;
+
+ return this._data[this._offset++];
+ }
+
+ public final short getShort() {
+ assert this._offset < this._packetSize;
+
+ assert this._offset + 1 < this._packetSize;
+
+ short retVal = (short)(this._data[this._offset] << 8 | this._data[this._offset + 1] & 255);
+ this._offset += 2;
+ return retVal;
+ }
+
+ public String getUTFString(int utflen) {
+ char[] str = new char[utflen];
+ int count = 0;
+ int strlen = 0;
+
+ try {
+ while (count < utflen) {
+ int c = this.getByte() & 255;
+ switch (c >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ count++;
+ str[strlen++] = (char)c;
+ break;
+ case 12:
+ case 13:
+ count += 2;
+ if (count > utflen) {
+ throw new UTFDataFormatException();
+ }
+
+ int char2 = this.getByte() & 255;
+ if ((char2 & 192) != 128) {
+ throw new UTFDataFormatException();
+ }
+
+ str[strlen++] = (char)((c & 31) << 6 | char2 & 63);
+ break;
+ case 14:
+ count += 3;
+ if (count > utflen) {
+ throw new UTFDataFormatException();
+ }
+
+ int char2 = this.getByte() & 255;
+ int char3 = this.getByte() & 255;
+ if ((char2 & 192) != 128 || (char3 & 192) != 128) {
+ throw new UTFDataFormatException();
+ }
+
+ str[strlen++] = (char)((c & 15) << 12 | (char2 & 63) << 6 | (char3 & 63) << 0);
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ default:
+ throw new UTFDataFormatException();
+ }
+ }
+ } catch (IOException var8) {
+ System.err.println("Exception: " + var8.getMessage());
+ var8.printStackTrace();
+
+ assert false;
+ }
+
+ return new String(str, 0, strlen);
+ }
+}
diff --git a/NET/worlds/network/netPacket.java b/NET/worlds/network/netPacket.java
new file mode 100644
index 0000000..bc430a3
--- /dev/null
+++ b/NET/worlds/network/netPacket.java
@@ -0,0 +1,58 @@
+package NET.worlds.network;
+
+import NET.worlds.console.StatNetMUNode;
+import java.io.IOException;
+
+public abstract class netPacket {
+ protected ObjID _objID;
+ protected int _commandType;
+
+ public netPacket(ObjID id, int cmd) {
+ if (id != null) {
+ this._objID = id;
+ } else {
+ this._objID = new ObjID(1);
+ }
+
+ this._commandType = cmd;
+ }
+
+ public netPacket() {
+ this._objID = new ObjID(1);
+ }
+
+ public int msgID() {
+ return this._commandType;
+ }
+
+ int packetSize() {
+ return 2 + this._objID.packetSize();
+ }
+
+ public String toString(WorldServer serv) {
+ return new Integer(this._commandType).toString();
+ }
+
+ void send(ServerOutputStream o) throws IOException {
+ int packetsize = this.packetSize();
+ if (packetsize >= 256 && o.getVersion() <= 24) {
+ throw new PacketTooLargeException();
+ } else {
+ StatNetMUNode netStat = StatNetMUNode.getNode();
+ netStat.addBytesSent(packetsize);
+ netStat.addPacketsSent(1);
+
+ assert this._commandType > 0;
+
+ if (packetsize >= 128 && o.getVersion() > 24) {
+ o.writeByte(128 + packetsize / 256);
+ o.writeByte(packetsize & 0xFF);
+ } else {
+ o.writeByte(packetsize);
+ }
+
+ this._objID.send(o);
+ o.writeByte(this._commandType);
+ }
+ }
+}
diff --git a/NET/worlds/network/netPacketReader.java b/NET/worlds/network/netPacketReader.java
new file mode 100644
index 0000000..b42f357
--- /dev/null
+++ b/NET/worlds/network/netPacketReader.java
@@ -0,0 +1,160 @@
+package NET.worlds.network;
+
+import NET.worlds.console.StatNetMUNode;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Vector;
+
+public class netPacketReader extends Thread {
+ private Vector<receivedNetPacket> _msgQ;
+ private ServerInputStream _in;
+ private WorldServer _serv;
+ private static Class<receivedNetPacket>[] msgTable = new Class[255];
+
+ static {
+ String basePath = "NET.worlds.network.";
+ Vector<String> cmdList = new netCmds().recvCmdList();
+
+ for (int i = 0; i < cmdList.size(); i++) {
+ String cmdName = basePath + cmdList.elementAt(i);
+
+ try {
+ Class<receivedNetPacket> tmpCmdClass = (Class<receivedNetPacket>)Class.forName(cmdName);
+ receivedNetPacket tmpInstance = tmpCmdClass.newInstance();
+ int indx = tmpInstance.msgID();
+
+ assert indx > -1;
+
+ assert msgTable[indx] == null;
+
+ msgTable[indx] = tmpCmdClass;
+ } catch (NoSuchMethodError var11) {
+ NoSuchMethodError e = var11;
+ synchronized (System.out) {
+ System.out.println("netPacketReader:: " + e.getClass().getName() + " creating " + cmdName);
+ System.out.println("netPacketReader:: Exception: " + e.getMessage());
+ e.printStackTrace(System.out);
+ }
+
+ assert false;
+ } catch (Exception var12) {
+ Exception e = var12;
+ synchronized (System.out) {
+ System.out.println("netPacketReader:: " + e.getClass().getName() + " creating " + cmdName);
+ System.out.println("netPacketReader:: Exception: " + e.getMessage());
+ e.printStackTrace(System.out);
+ }
+
+ assert false;
+ }
+ }
+ }
+
+ public netPacketReader(ServerInputStream in) {
+ this._in = in;
+ this._msgQ = new Vector<receivedNetPacket>();
+ }
+
+ public netPacketReader(WorldServer serv, ServerInputStream in) {
+ this._serv = serv;
+ this._in = in;
+ this._msgQ = new Vector<receivedNetPacket>();
+ this._in.setVersion(this.getVersion());
+ }
+
+ public void setVersion(int vers) {
+ this._in.setVersion(vers);
+ }
+
+ public int getVersion() {
+ return this._serv.getVersion();
+ }
+
+ public void put(receivedNetPacket pkt) {
+ this._msgQ.addElement(pkt);
+ }
+
+ public receivedNetPacket get() {
+ assert this._msgQ != null;
+
+ if (this._msgQ.isEmpty()) {
+ return null;
+ } else {
+ receivedNetPacket packet = this._msgQ.firstElement();
+ this._msgQ.removeElement(packet);
+ return packet;
+ }
+ }
+
+ public int count() {
+ return this._msgQ.size();
+ }
+
+ private final void buildMsg() throws IOException {
+ this._in.readPacketSize();
+ byte[] packetData = new byte[this._in.bytesLeft() + 1];
+ packetData[0] = (byte)(this._in.bytesLeft() + 1);
+ this._in.readFully(packetData, 1, this._in.bytesLeft());
+ StatNetMUNode netStat = StatNetMUNode.getNode();
+ netStat.addBytesRcvd(packetData.length);
+ netStat.addPacketsRcvd(1);
+ ServerInputStream in = new ServerInputStream(new ByteArrayInputStream(packetData));
+ in.readPacketSize();
+ if ((WorldServer.getDebugLevel() & 2048) > 0) {
+ synchronized (System.out) {
+ System.out.print(this._serv + ": recv[");
+
+ for (int i = 0; i < packetData.length; i++) {
+ System.out.print(Integer.toString(packetData[i] & 255, 16) + " ");
+ }
+
+ System.out.println("]");
+ }
+ }
+
+ receivedNetPacket packet = null;
+ ObjID objID = new ObjID();
+ objID.parseNetData(in);
+ boolean isCO = objID.shortID() == 254;
+ int cmdType = in.readUnsignedByte();
+ if (cmdType < msgTable.length && msgTable[cmdType] != null) {
+ do {
+ if (isCO) {
+ objID = new ObjID();
+ objID.parseNetData(in);
+ }
+
+ try {
+ packet = msgTable[cmdType].newInstance();
+ } catch (Exception var8) {
+ System.out.println(var8 + ": " + var8.getMessage());
+
+ assert false;
+ }
+
+ packet.init(objID);
+ packet.parseNetData(in);
+ this._msgQ.addElement(packet);
+ yield();
+ } while (!in.isEmpty() && isCO);
+
+ assert in.isEmpty();
+ } else {
+ System.out.println("UNKNOWN SERVER MSG#" + String.valueOf(cmdType));
+ in.skipBytes(in.bytesLeft());
+
+ assert in.isEmpty();
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ this.buildMsg();
+ }
+ } catch (IOException var2) {
+ this._msgQ.addElement(new ExceptionCmd(var2));
+ }
+ }
+}
diff --git a/NET/worlds/network/netProperty.java b/NET/worlds/network/netProperty.java
new file mode 100644
index 0000000..c2f8e4b
--- /dev/null
+++ b/NET/worlds/network/netProperty.java
@@ -0,0 +1,50 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class netProperty {
+ protected int _propID;
+ protected String _value;
+
+ public netProperty() {
+ this._propID = 0;
+ }
+
+ public netProperty(int p) {
+ this._propID = p;
+ }
+
+ public netProperty(int p, String val) {
+ assert val != null;
+
+ this._propID = p;
+ this._value = val;
+ }
+
+ public int property() {
+ return this._propID;
+ }
+
+ public String value() {
+ return this._value;
+ }
+
+ int packetSize() {
+ return this._value != null ? 2 + ServerOutputStream.utfLength(this._value) : 0;
+ }
+
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._propID = data.readUnsignedByte();
+ this._value = data.readUTF();
+ }
+
+ void send(ServerOutputStream o) throws IOException {
+ o.writeByte(this._propID);
+ o.writeUTF(this._value);
+ }
+
+ @Override
+ public String toString() {
+ return netCmds.getPropName(this._propID) + "=" + this._value;
+ }
+}
diff --git a/NET/worlds/network/propCmd.java b/NET/worlds/network/propCmd.java
new file mode 100644
index 0000000..6d7386e
--- /dev/null
+++ b/NET/worlds/network/propCmd.java
@@ -0,0 +1,58 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class propCmd extends receivedNetPacket {
+ public static final byte PROPCMD = 3;
+ protected OldPropertyList _propList;
+
+ public propCmd() {
+ this._commandType = 3;
+ this._propList = new OldPropertyList();
+ }
+
+ public propCmd(OldPropertyList propList) {
+ super(null, 3);
+ this._propList = propList;
+ }
+
+ public propCmd(ObjID objID, OldPropertyList propList) {
+ super(objID, 3);
+ this._propList = propList;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._propList = new OldPropertyList();
+ this._propList.parseNetData(data);
+ }
+
+ @Override
+ int packetSize() {
+ return super.packetSize() + this._propList.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+
+ assert this._propList != null;
+
+ this._propList.send(o);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o == null) {
+ System.err.println("propCmd::process() error: cannot find object with name " + this._objID);
+ } else {
+ o.property(this._propList);
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "PROP " + this._objID.toString(serv) + " " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/propReqCmd.java b/NET/worlds/network/propReqCmd.java
new file mode 100644
index 0000000..0c6c043
--- /dev/null
+++ b/NET/worlds/network/propReqCmd.java
@@ -0,0 +1,50 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+import java.util.Vector;
+
+public class propReqCmd extends netPacket {
+ public static final byte PROPREQCMD = 10;
+ protected Vector<Integer> _varids = new Vector<Integer>();
+
+ public propReqCmd(ObjID id, int varid) {
+ super(id, 10);
+ this.addProp(varid);
+ }
+
+ public propReqCmd(ObjID id) {
+ super(id, 10);
+ }
+
+ public void addProp(int varid) {
+ this._varids.addElement(new Integer(varid));
+ }
+
+ @Override
+ int packetSize() {
+ return this._varids.size() + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ int maxidx = this._varids.size();
+
+ for (int i = 0; i < maxidx; i++) {
+ Integer tmpInt = this._varids.elementAt(i);
+ o.writeByte(tmpInt);
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ String out = "PROPREQ " + this._objID.toString(serv) + " ";
+ int maxidx = this._varids.size();
+
+ for (int i = 0; i < maxidx; i++) {
+ out = out + " #" + this._varids.elementAt(i);
+ }
+
+ return out;
+ }
+}
diff --git a/NET/worlds/network/receivedNetPacket.java b/NET/worlds/network/receivedNetPacket.java
new file mode 100644
index 0000000..a2f6622
--- /dev/null
+++ b/NET/worlds/network/receivedNetPacket.java
@@ -0,0 +1,20 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public abstract class receivedNetPacket extends netPacket {
+ public receivedNetPacket(ObjID id, int cmd) {
+ super(id, cmd);
+ }
+
+ public receivedNetPacket() {
+ }
+
+ public final void init(ObjID objID) {
+ this._objID = objID;
+ }
+
+ abstract void parseNetData(ServerInputStream var1) throws IOException;
+
+ abstract void process(WorldServer var1) throws Exception;
+}
diff --git a/NET/worlds/network/regObjIDCmd.java b/NET/worlds/network/regObjIDCmd.java
new file mode 100644
index 0000000..32cd921
--- /dev/null
+++ b/NET/worlds/network/regObjIDCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class regObjIDCmd extends receivedNetPacket {
+ public static final byte REGOBJIDCMD = 13;
+ private String _longObjID;
+ private int _shortObjID;
+
+ public regObjIDCmd() {
+ this._commandType = 13;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._longObjID = data.readUTF();
+ this._shortObjID = data.readByte();
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ _serv.regShortID(this._shortObjID, this._longObjID);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "REGOBJID " + this._shortObjID + " --> " + this._longObjID;
+ }
+}
diff --git a/NET/worlds/network/roomChangeCmd.java b/NET/worlds/network/roomChangeCmd.java
new file mode 100644
index 0000000..fa2d58c
--- /dev/null
+++ b/NET/worlds/network/roomChangeCmd.java
@@ -0,0 +1,77 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Drone;
+import NET.worlds.scape.Room;
+import java.io.IOException;
+
+public class roomChangeCmd extends receivedNetPacket {
+ public static final byte ROOMCHNGCMD = 5;
+ protected int _roomID;
+ protected short _x;
+ protected short _y;
+ protected short _z;
+ protected short _direction;
+
+ public roomChangeCmd() {
+ this._commandType = 5;
+ }
+
+ public roomChangeCmd(Room room, short x, short y, short z, short direction) {
+ super(null, 5);
+ this._roomID = room.getNetworkRoom().getRoomID();
+
+ assert this._roomID != 0;
+
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._direction = direction;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._roomID = data.readUnsignedShort();
+ this._x = data.readShort();
+ this._y = data.readShort();
+ this._z = data.readShort();
+ this._direction = data.readShort();
+ }
+
+ @Override
+ int packetSize() {
+ return 10 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeShort(this._roomID);
+ o.writeShort(this._x);
+ o.writeShort(this._y);
+ o.writeShort(this._z);
+ o.writeShort(this._direction);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o instanceof Drone) {
+ assert this._roomID != 0;
+
+ Room newroom = null;
+ NetworkRoom netroom = _serv.getNetworkRoom(this._roomID);
+ if (netroom != null) {
+ newroom = netroom.getRoom();
+ }
+
+ this._direction = (short)(90 - this._direction);
+ this._direction = (short)(360 - this._direction);
+ ((Drone)o).roomChange(newroom, this._x, this._y, this._z, this._direction);
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "ROOMCHNG " + this._objID.toString(serv) + " in " + this._roomID + " @ " + this._x + "," + this._y + "," + this._z + "," + this._direction;
+ }
+}
diff --git a/NET/worlds/network/roomIDCmd.java b/NET/worlds/network/roomIDCmd.java
new file mode 100644
index 0000000..dcfd9bd
--- /dev/null
+++ b/NET/worlds/network/roomIDCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class roomIDCmd extends receivedNetPacket {
+ public static final byte ROOMIDCMD = 21;
+ protected String _roomName;
+ protected int _roomNumber;
+
+ public roomIDCmd() {
+ this._commandType = 21;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._roomName = data.readUTF();
+ this._roomNumber = data.readUnsignedShort();
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ serv.regRoomID(this._roomNumber, this._roomName, false);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "ROOMID " + this._roomName + " <--> " + this._roomNumber;
+ }
+}
diff --git a/NET/worlds/network/roomIDReqCmd.java b/NET/worlds/network/roomIDReqCmd.java
new file mode 100644
index 0000000..a3d5e19
--- /dev/null
+++ b/NET/worlds/network/roomIDReqCmd.java
@@ -0,0 +1,29 @@
+package NET.worlds.network;
+
+import java.io.IOException;
+
+public class roomIDReqCmd extends netPacket {
+ public static final byte ROOMIDREQCMD = 20;
+ protected String _roomName;
+
+ public roomIDReqCmd(String name) {
+ super(null, 20);
+ this._roomName = name;
+ }
+
+ @Override
+ int packetSize() {
+ return ServerOutputStream.utfLength(this._roomName) + 1 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeUTF(this._roomName);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "ROOMIDRQ " + this._roomName;
+ }
+}
diff --git a/NET/worlds/network/sessionExitCmd.java b/NET/worlds/network/sessionExitCmd.java
new file mode 100644
index 0000000..0caf036
--- /dev/null
+++ b/NET/worlds/network/sessionExitCmd.java
@@ -0,0 +1,37 @@
+package NET.worlds.network;
+
+public class sessionExitCmd extends propCmd {
+ public static final byte SESSIONEXITCMD = 7;
+
+ public sessionExitCmd() {
+ this._commandType = 7;
+ }
+
+ public sessionExitCmd(OldPropertyList propList) {
+ this._commandType = 7;
+ this._propList = propList;
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ assert serv.getState() == 16;
+
+ netProperty _error = this._propList.elementAt(0);
+
+ try {
+ int errorval = Integer.parseInt(_error.value());
+ if (errorval != 0) {
+ throw new VarErrorException(errorval);
+ }
+ } catch (NumberFormatException var4) {
+ System.err.println("appInitCmd: couldn't parse VAR_ERROR = " + _error.value());
+ }
+
+ serv.setState(17);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "SESSEXIT " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/sessionInitCmd.java b/NET/worlds/network/sessionInitCmd.java
new file mode 100644
index 0000000..32b6b77
--- /dev/null
+++ b/NET/worlds/network/sessionInitCmd.java
@@ -0,0 +1,120 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import java.util.Enumeration;
+
+public class sessionInitCmd extends propCmd {
+ public static final byte SESSIONINITCMD = 6;
+
+ public sessionInitCmd() {
+ this._commandType = 6;
+ }
+
+ public sessionInitCmd(String user, String pass, String proto, String avatars, String ver) {
+ this._commandType = 6;
+
+ assert user != null;
+
+ this._propList.addProperty(new netProperty(2, user));
+ if (pass != null) {
+ this._propList.addProperty(new netProperty(6, pass));
+ }
+
+ this._propList.addProperty(new netProperty(3, proto));
+ this._propList.addProperty(new netProperty(7, avatars));
+ this._propList.addProperty(new netProperty(9, ver));
+ }
+
+ public sessionInitCmd(OldPropertyList props) {
+ this._commandType = 6;
+ this._propList = props;
+ }
+
+ @Override
+ void process(WorldServer serv) throws Exception {
+ if (serv.getState() == 8) {
+ for (int i = 0; i < this._propList.size(); i++) {
+ netProperty tmpProp = this._propList.elementAt(i);
+ switch (tmpProp.property()) {
+ case 1:
+ case 3:
+ case 8:
+ case 13:
+ case 15:
+ break;
+ case 2:
+ serv.setUsername(tmpProp.value());
+ serv.getGalaxy().setNewChatname(null);
+ break;
+ case 4:
+ try {
+ int errorval = Integer.parseInt(tmpProp.value());
+ if (errorval != 0) {
+ throw new VarErrorException(errorval);
+ }
+ } catch (NumberFormatException var7) {
+ System.err.println("sessionInitCmd: couldn't parse VAR_ERROR = " + tmpProp.value());
+ }
+ break;
+ case 5:
+ serv.getGalaxy().setChannel(tmpProp.value());
+ break;
+ case 6:
+ serv.getGalaxy().setPassword(tmpProp.value());
+ serv.getGalaxy().setNewPassword(null);
+ break;
+ case 7:
+ case 9:
+ case 11:
+ case 12:
+ case 14:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ default:
+ System.out.println("sessionInitCmd: received unknown property: " + tmpProp.property());
+
+ assert false;
+ break;
+ case 10:
+ serv.getGalaxy().setSerialNum(tmpProp.value());
+ break;
+ case 22:
+ try {
+ int priv = Integer.parseInt(tmpProp.value());
+ Enumeration<NetworkObject> list = serv.getGalaxy().getConsoles();
+
+ while (list.hasMoreElements()) {
+ Console c = (Console)list.nextElement();
+ c.setVIP((priv & 8) != 0);
+ c.setFullVIP((priv & 16) != 0);
+ c.setSpecialGuest((priv & 64) != 0);
+ }
+
+ list = serv.getGalaxy().getConsoles();
+
+ while (list.hasMoreElements()) {
+ Console c = (Console)list.nextElement();
+ c.enableBroadcast((priv & 2) != 0);
+ }
+ } catch (NumberFormatException var8) {
+ }
+ }
+ }
+
+ if (serv.getVersion() < 18) {
+ serv.setState(9);
+ } else {
+ serv.setState(11);
+ }
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "SESSINIT " + this._propList;
+ }
+}
diff --git a/NET/worlds/network/shortLocCmd.java b/NET/worlds/network/shortLocCmd.java
new file mode 100644
index 0000000..80463a8
--- /dev/null
+++ b/NET/worlds/network/shortLocCmd.java
@@ -0,0 +1,45 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Drone;
+import java.io.IOException;
+
+public class shortLocCmd extends receivedNetPacket {
+ public static final byte SHORTLOCCMD = 4;
+ protected byte _dx;
+ protected byte _dy;
+ protected byte _ddirection;
+
+ public shortLocCmd() {
+ this._commandType = 4;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._dx = data.readByte();
+ this._dy = data.readByte();
+ this._ddirection = data.readByte();
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o == null) {
+ System.out.println("Unknown short id: " + this.toString(_serv));
+ new Exception().printStackTrace(System.out);
+ } else {
+ if (o instanceof Drone) {
+ ((Drone)o).shortLoc(this._dx, this._dy, this._ddirection);
+ }
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "SHORTLOC " + this._objID.toString(serv) + " delta=" + this._dx + "," + this._dy + "," + this._ddirection;
+ }
+
+ @Override
+ public String toString() {
+ return "SHORTLOC " + this._objID + " delta=" + this._dx + "," + this._dy + "," + this._ddirection;
+ }
+}
diff --git a/NET/worlds/network/teleportCmd.java b/NET/worlds/network/teleportCmd.java
new file mode 100644
index 0000000..7c8c9ff
--- /dev/null
+++ b/NET/worlds/network/teleportCmd.java
@@ -0,0 +1,103 @@
+package NET.worlds.network;
+
+import NET.worlds.scape.Drone;
+import NET.worlds.scape.Room;
+import java.io.IOException;
+
+public class teleportCmd extends receivedNetPacket {
+ public static final byte TELEPORTCMD = 18;
+ protected int _roomID;
+ protected byte _exittype;
+ protected byte _entrytype;
+ protected short _x;
+ protected short _y;
+ protected short _z;
+ protected short _direction;
+
+ public teleportCmd() {
+ this._commandType = 18;
+ }
+
+ public teleportCmd(Room room, byte exittype, byte entrytype, short x, short y, short z, short direction) {
+ super(null, 18);
+ this._roomID = 0;
+ if (room != null) {
+ this._roomID = room.getNetworkRoom().getRoomID();
+ }
+
+ this._exittype = exittype;
+ this._entrytype = entrytype;
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._direction = direction;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._roomID = data.readUnsignedShort();
+ this._exittype = data.readByte();
+ this._entrytype = data.readByte();
+ this._x = data.readShort();
+ this._y = data.readShort();
+ this._z = data.readShort();
+ this._direction = data.readShort();
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ NetworkObject o = _serv.getObject(this._objID);
+ if (o == null) {
+ o = Drone.make(this._objID, _serv);
+ }
+
+ NetworkRoom netroom = _serv.getNetworkRoom(this._roomID);
+ Room newroom = null;
+ if (netroom != null) {
+ newroom = netroom.getRoom();
+ }
+
+ this._direction = (short)(90 - this._direction);
+ this._direction = (short)(360 - this._direction);
+ if (o instanceof Drone) {
+ ((Drone)o).teleport(_serv, this._exittype, this._entrytype, newroom, this._x, this._y, this._z, this._direction);
+ }
+ }
+
+ @Override
+ int packetSize() {
+ return 12 + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ o.writeShort(this._roomID);
+ o.writeByte(this._exittype);
+ o.writeByte(this._entrytype);
+ o.writeShort(this._x);
+ o.writeShort(this._y);
+ o.writeShort(this._z);
+ o.writeShort(this._direction);
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "TELEPORT "
+ + this._objID.toString(serv)
+ + " <"
+ + this._exittype
+ + " >"
+ + this._entrytype
+ + " in "
+ + this._roomID
+ + " @ "
+ + this._x
+ + ","
+ + this._y
+ + ","
+ + this._z
+ + ","
+ + this._direction;
+ }
+}
diff --git a/NET/worlds/network/textCmd.java b/NET/worlds/network/textCmd.java
new file mode 100644
index 0000000..f5ba287
--- /dev/null
+++ b/NET/worlds/network/textCmd.java
@@ -0,0 +1,141 @@
+package NET.worlds.network;
+
+import NET.worlds.console.BBChatCommand;
+import NET.worlds.console.BlackBox;
+import NET.worlds.console.Console;
+import NET.worlds.console.GammaTextArea;
+import NET.worlds.console.MuteListPart;
+import NET.worlds.core.IniFile;
+import NET.worlds.scape.Drone;
+import NET.worlds.scape.Pilot;
+import NET.worlds.scape.PosableDrone;
+import java.io.IOException;
+
+public class textCmd extends receivedNetPacket {
+ public static final byte TEXTCMD = 14;
+ protected ObjID _senderID;
+ protected String _text;
+
+ public textCmd() {
+ this._commandType = 14;
+ }
+
+ public textCmd(String text) {
+ super(null, 14);
+ this._senderID = new ObjID("");
+ this._text = text;
+ }
+
+ @Override
+ void parseNetData(ServerInputStream data) throws IOException {
+ this._senderID = new ObjID();
+ this._senderID.parseNetData(data);
+ this._text = data.readUTF();
+ }
+
+ @Override
+ int packetSize() {
+ return ServerOutputStream.utfLength(this._text) + 1 + this._senderID.packetSize() + super.packetSize();
+ }
+
+ @Override
+ void send(ServerOutputStream o) throws IOException {
+ super.send(o);
+ this._senderID.send(o);
+ o.writeUTF(this._text);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ String name;
+ if (this._senderID.longID() == null) {
+ name = "[Unknown Name (#" + String.valueOf(this._senderID.shortID()) + ")]";
+ } else {
+ name = this._senderID.longID();
+ if (MuteListPart.isMuted(_serv, name)) {
+ return;
+ }
+ }
+
+ handleActionText(_serv, this._text, name, this._senderID);
+ if (!this._text.startsWith("&|+")) {
+ this.displayText(name, this._text);
+ }
+ }
+
+ protected void displayText(String name, String text) {
+ String filteredName = FilthFilter.get().filterName(name);
+ String line = "";
+ if (IniFile.gamma().getIniInt("classicChatBox", 1) == 1) {
+ line = filteredName + "> ";
+ line = line + FilthFilter.get().filter(text);
+ BlackBox.getInstance().submitEvent(new BBChatCommand(line));
+ Console.println(line);
+ } else {
+ boolean colored = false;
+ if (Drone.isEmployeeAccount(name)) {
+ line = GammaTextArea.colorStartBlueTag + " ";
+ colored = true;
+ } else if (name.toLowerCase().startsWith(Console.message("host"))) {
+ line = GammaTextArea.colorStartRedTag + " ";
+ colored = true;
+ } else if (name.toLowerCase().startsWith(Console.message("guest-"))) {
+ line = GammaTextArea.colorStartMagentaTag + " ";
+ colored = true;
+ }
+
+ line = line + "<b> " + filteredName + "> </b> ";
+ if (colored) {
+ line = line + " " + GammaTextArea.colorEndTag + " ";
+ }
+
+ line = line + FilthFilter.get().filter(text);
+ BlackBox.getInstance().submitEvent(new BBChatCommand(line));
+ Console.println(line);
+ }
+ }
+
+ public static void handleActionText(WorldServer _serv, String msg, String name, ObjID senderID) {
+ if (msg.startsWith("&|+action>")) {
+ NetworkObject o = _serv.getObject(senderID);
+ if (o == null) {
+ return;
+ }
+
+ String act = msg.substring(10);
+ if (!(o instanceof PosableDrone)) {
+ return;
+ }
+
+ ((PosableDrone)o).animate(act);
+ }
+
+ if (msg.startsWith("&|+action2>")) {
+ int idx = msg.indexOf("|sender|");
+ String senderAction = null;
+ String receiverAction = null;
+ if (idx != -1) {
+ senderAction = msg.substring(idx);
+ receiverAction = msg.substring(11, idx);
+ NetworkObject ox = _serv.getObject(senderID);
+ if (ox != null && ox instanceof PosableDrone) {
+ ((PosableDrone)ox).animate(senderAction);
+ Pilot.sendText("&|+action>" + senderAction);
+ }
+ } else {
+ receiverAction = msg.substring(11);
+ }
+
+ try {
+ Console.getActive().getPilot().animate(receiverAction);
+ } catch (Exception var8) {
+ System.out.println("Error animating pilot " + var8.toString());
+ }
+ }
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return "TEXT " + this._senderID.toString(serv) + ": " + this._text;
+ }
+}
diff --git a/NET/worlds/network/whisperCmd.java b/NET/worlds/network/whisperCmd.java
new file mode 100644
index 0000000..dc0a862
--- /dev/null
+++ b/NET/worlds/network/whisperCmd.java
@@ -0,0 +1,66 @@
+package NET.worlds.network;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.FriendsListPart;
+import NET.worlds.console.MuteListPart;
+import NET.worlds.scape.WorldScriptManager;
+import java.text.MessageFormat;
+
+public class whisperCmd extends textCmd {
+ public static final byte WHISPERCMD = 17;
+ private static String rejectMsg = Console.message("not-whispers");
+
+ public whisperCmd() {
+ this._commandType = 17;
+ }
+
+ public whisperCmd(String who, String text) {
+ super(text);
+ WorldScriptManager.getInstance().onConversation(who, text);
+ this._commandType = 17;
+ this._objID = new ObjID(who);
+ }
+
+ @Override
+ void process(WorldServer _serv) throws Exception {
+ String name;
+ if (this._senderID.longID() == null) {
+ Object[] arguments = new Object[]{new String(String.valueOf(this._senderID.shortID()))};
+ name = MessageFormat.format(Console.message("Unknown-Name"), arguments);
+ } else {
+ name = this._senderID.longID();
+ if (MuteListPart.isMuted(_serv, name)) {
+ try {
+ _serv.sendNetworkMsg(new whisperCmd(name, Console.message("have-you-muted")));
+ } catch (InfiniteWaitException var4) {
+ } catch (PacketTooLargeException var5) {
+ }
+
+ return;
+ }
+
+ if (!this._text.startsWith("&|+") && MuteListPart.isRejecting(_serv)) {
+ try {
+ if (!this._text.equals(rejectMsg)) {
+ Object[] arguments = new Object[]{new String(name)};
+ Console.println(MessageFormat.format(Console.message("You-rejected"), arguments));
+ _serv.sendNetworkMsg(new whisperCmd(name, rejectMsg));
+ }
+ } catch (InfiniteWaitException var6) {
+ } catch (PacketTooLargeException var7) {
+ }
+
+ return;
+ }
+ }
+
+ FriendsListPart.processWhisper(_serv, name, this._text);
+ handleActionText(_serv, this._text, name, this._senderID);
+ Console.printWhisper(name, FilthFilter.get().filter(this._text));
+ }
+
+ @Override
+ public String toString(WorldServer serv) {
+ return Console.message("WHISPER") + " " + this._senderID.toString(serv) + " --> " + this._objID.toString(serv) + ": " + this._text;
+ }
+}