diff options
Diffstat (limited to 'NET/worlds/network')
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; + } +} |