"Java-MOO" Project Planning Document The broad outlines of the project are to write an initial specification document for the reimplemention of the LambdaMOO environment under the following constraints: 1. Must be implemented in Java 2. MOO server - backward compatible to earlier LambdaMOO databases - online extensibility - distributed (synchronized) 3. Code Control, version tracking 4. Development environment - robust API - tools for content engineers - server-side interface specification capability 5. Instructor Support 6. A local-area network solution (authentication) There are five units in the MUD specification: Client: A Java applet which connects to the server and graphically represents the user's view of the simulated world. Server: A Java application which is the engine that runs the simulated world, and communicates with the clients. Object Library: An archive (JAR) of Java class definitions for all possible objects in the simulation. This is the "Physics" of the simulated universe. The JavaMOO package would come with a standard set of objects (Room, Exit, Player, etc.), which the developer would then extend. Object Database: A database of all the objects that exist in the simulation. This is the "Matter" of the universe. Resource Directory: A directory of media (art, music, movies, etc.) for use by the objects in the universe. The client and resource directory should be made accessible to the general public via an http or ftp server, or some equivalent. Development Procedure One of the consequences of this design is that the MOO developer will no longer be able to define objects or change their definitions within a running MOO simulation. This is a limitation (feature) of the Java language, which doesn't allow classes to be redefined once they have been loaded. This consequence, though, is only a problem if the simulation requires the creation or modification of classes while running the simulation, as we would probably want to disallow global changes like class modification on a MOO server that is on line and in production. The development procedure would then be broken up into two parts. First, a Java programmer would create whatever object classes were needed in the world to be simulated. He or she would do this by adding to or extending the standard object set that comes with JavaMOO. This object library would then be put onto the server host where the server can have access to it. Second, content producers would log into the running server and start building the world using the object types that the programmer has created. These objects would get stored in the Object Database, and would define the starting state of the simulated world. Obviously, these two steps can overlap quite a bit, but care must be taken to plan ahead and maintain compatibility from one version of the Object Library to the next, lest the Object Database be rendered obsolete. For example, if a programmer changes all the fields of an object, the server won’t know how to match the object in the database with the new class definition. What's missing, though, is a way to convert existing objects to their new class types when they are modified. This needs to be specified. It would be possible, then, to upgrade the Object Library of a running, online server. The procedure would be the following: 1. The developer creates and debugs a new version of the Object Library. 2. The developer then places the new version of the library on the server host. 3. The administrator then tells the server that a new version of the Object Library is to be used. 4. The server then launches a new server, one which loads the new library. 5. The old server then migrates the currently connected clients to the new server on a different port. 6. Once all the connections have been migrated, the old server shuts down. 7. Once the old server shuts down, the new server then migrates its clients to the original port. If all goes well, this procedure should go entirely unnoticed by the clients. Of course, maintaining compatibility between versions of the Object Library is paramount. Object Database There is a question as to how to store all the simulations objects and their states. One approach would be to use an out-of-the-box database solution, such as mySQL. Another is to simply store each object in its own file in some directory structure. Since we are talking about Java objects, we can use Serialization to stream the object information to any storage facility, whether it is a file or a SQL BLOB. The out-of-the-box approach has the advantage of already solving many of our issues for us. Plus the database would be directly accessible from the JavaMOO server using the Java Database Connection protocol (JDBC). Client-Server Communication One idea for effecting server changes from the client is to use Java's Remote Method Invocation (RMI). What this allows you to do is have the client request a proxy to an object that exists on the server. The client would then have what appears to be a real reference to a server object, as if that object were local to the client. The client could then call methods on the object, just as it would a local object. However, these method calls would get translated into messages that are transmitted to the server, and the server would then call those methods on the server object. This approach is very exciting and seems like it would be highly attractive to the client developer. There are some drawbacks and some unknowns. First, it does not appear like this mechanism could be used to pass notification from the server to the client. This might have to happen via a traditional message passing method. Second, getting this system all up and running would require the learning of a good chunk of new technology. The benefits seem really great, though, so this should be further explored. Distributed Servers It seems very desirable to have more than one JavaMOO server running simultaneously to handle very large numbers of client connections. There is a problem, though, of synchronizing the servers so that we don't have branching versions of the Object Database. One (bad) approach to this problem is to have a master server and several slave servers, where all slave servers would need to get permission from the master server before any changes to objects are made. This is a classic bottleneck scenario, and would make things worse than the single server approach. A second approach would be to have peer servers, but only allow any given object to be modified by a single server. If a user connected to server A wanted to change object X, and object X was assigned to server A, then the change would just happen and all other servers would receive notification of the change. If, however, object X was assigned to server B, then server A would pass the change request to server B. Server B would then be responsible for notifying the other servers. There is a serious concern with this or any other distributed scenario, which is the problem of distributed object locking. As with any multi-threaded system, object locking will be required to maintain object sanity. On distributed servers, where different objects are being maintained on different servers, this locking must be done over the network. This is certainly doable, but some serious care must be taken. Client Details Another consequence of having a binary connection between the client and the server is that there will be no "text mode" like there is today. For clients to log in to the JavaMOO server, they will need to use a Java Applet client. This does not preclude the creation of a text-based client, and indeed there will be many users of JavaMOO who will want such a client. There was also discussion about player-based security. MOO has a player-based security system that limits which players can manipulate which objects. It is possible to simply re-implement the existing MOO security system. But also bear in mind that a certain level of security can be established simply by limiting the capabilities of the client. In other words, if you don't want players deleting any rooms, you wouldn't put a "Delete Room" button in the client. There is always the possibility that a "Wizard" client could fall into the wrong hands, though, and so some level of player authentication and security are required. Also, it is unknown what kind of security measures are provided for by RMI. Distributed Servers, Part II There are now two possibilities for distributing the server load. One, which was discussed previously, would allow multiple servers to run as peers, with each server being in charge of some mutually exclusive subset of database objects. Another twist is to allow the JavaMOO clients to be these peer servers, with the subset of objects for which they are responsible consisting of the player and his or her possessions. It's unclear how useful this would be, considering that the client would really only be responsible for a small subset of objects, while the server would still be in charge of the vast bulk of objects. Still, it seems to be the case that some client-to-client communication would be very useful for distributing server load. Any client-to-client scenario calls for the client to establish connections with servers other than the applet host. This is an applet security violation, which requires a certificate to be overridden. We already know how to do this. Multicasting was also discussed as a potentially desirable technology to employ for the server. Currently, multicasting relies on UDP, which does not guarantee delivery of messages, which does not make it useful for our purposes. However, there is currently under development a Reliable Multicasting Transport Protocol (RMTP) that might well suit our needs. Backward Compatability Issues Currently, backward compatibility with currently existing MOOs is envisioned as a conversion process that will read in LambdaMOO source and produce a translation into the new JavaMOO scheme. As the day went on, it became increasingly clear that translated JavaMOO games will be a lot uglier than games written in JavaMOO from start to finish. Plus, there seem to be a number of thorny issues associated with this translation. The primary source of trouble with translation is the fundamental differences in handling objects and classes between LambdaMOO and Java. Some of these are defined below. LambdaMOO Class objects are also instances of the defined class. Both classes and instances can be subclasses. A property which is "clear" will reflect the value of that property in the superclass. Java Class objects are distinct from instances of that class. Only classes can be subclassed. There is no "clear" value, and it doesn't make sense to reflect values in the parent, since the parent is a class and has no instance values. Another issue: task scheduling. This is a complicated problem, but a solution is highly desirable if not mandatory. I recommend that this be studied, explored and tested thoroughly, and that a plan be written up which would describe the exact process for performing the translation from LambdaMOO to JavaMOO. Core Object Library Architecture There was general agreement about the design of the Core Object Library. There would be a MOObject root object that would look something like this: public class MOObject { protected String protected Container protected Point protected Dimension protected Vector protected Player protected String name; location; position; size; contents; owner; imageURL; public void action( Player p ) {}; [...] } The idea is that all MOObjects have a name, owner, location, position, size, and image URL. Also, all objects would be capable of being containers, but there would be language support for enforcing which objects would be containers and which wouldn't. The could be done through the use of an empty interface, like so: public interface Container {} All methods dealing with containers would take Containers as arguments. Then, only those classes which implement Container would be accepted in those argument positions. This could serve as a model for other types of objects as well. The primary goal of the Core Object Library is to provide a basic model of multiplayer database access and communication and simulation building and running. It is also important that these capabilities are replaceable by the programmer. For example, the Room metaphor will define the scope of a player: players will only see those objects which are in the player’s current room. However, one can imagine different models of scope, which can be dependent on objects of interest or Euclidian distance. While providing basic functionality for the room metaphor of player scope, the library should allow for the implementation of any of these other scope metaphors. One can imagine an online object library that holds class definitions (or collections of classes) which add new functionality to the core object library. These objects can then be downloaded and incorporated into the MOO by the game programmer to provide whatever functionality he or she deems necessary. We might want to include an alternative scope metaphor, such as Brad’s VCell scope implementation, in the Core Library. Note that, like containing objects, even though the root object has certain capabilities, programmers need not use them if they don't want to. For example, all MOObjects may have a Point location, but programmers are welcome to subclass this class and provide a more sophisticated location representation for, say, 3-dimentional presentations. The interface and implementation spec should be completed before implementation starts. Initial Client Design The JavaMOO package should come with three basic clients (or one client with three modes). All three clients will provide a graphical user interface to support their functionality. These clients are: Wizard Client. This client allows for the administration of the MOO as a whole. This would include interfaces for account management, database management, etc. This is a very powerful client and should only be made accessible to the most trusted users. Builder Client: This client would be used for world building. It would have an interface for the creation of rooms, objects, and NPCs. It would have an interface for connection rooms to each other. It would also allow for the application of art to objects, including rooms, objects, NPCs, etc. This client should be built to support any content provision. User Client: This is a very basic user client for the testing of the MOO. The user client should be thought of as the equivalent of text mode for non-privileged users. Users would be able to use this client to move around the MOO, talk to other players, etc. Clearly, most game builders will want to build their own specific interface, and the client library will be provided and documented to allow such a customization. The game builders could then create their own client with their own interface and provide this client on an http server. One such custom client could be the much-talked-about text-based client. This client would include a text parser like the one that exists in the current MOO, which would translate between English and the client/server communication protocol which all clients would use. Client/Server Communication For the purposes of clarity, a message sent from the client to the server will be called a “command,” while a message sent from the server to the client will be called an “event.” Commands inform the server when the client has performed an action, and servers will keep the clients updated as to the state of the world by issuing events. As previously stated, there is a desire to use RMI for sending commands. But we don’t know enough about RMI to create a spec that uses it, and it is currently under study. Without RMI, there would be a simple client/server communication protocol based on serialized objects. When the user performs an action on a client that changes the state of an object, the client issues a command to the server by creating a Command object and sending it to the server via an open TCP/IP connection. The command that is issued will be defined on the object in the server, and will be transmitted to the client along with all of the other information about the object (position, owner, image, etc.). Once the server receives the command, it will look up the command in a Master Command Table (MCT). This table will contain the ID of the command, the method to be invoked by the command on the server, and a privilege description. The privilege description will be checked against the user to see if the user has authorization to issue the command. If the command is authorized, the appropriate method is invoked. This simple command-based security scheme (thanks to John Bauer) will be a first level security check to make sure that nobody using a pirated client can issue destructive commands. When the server determines that a player should receive an update, it creates an Event object and sends it to the client via the open TCP/IP connection. The client will then receive the event and invoke the appropriate method as determined by a lookup table on the server. Event reception should be handled asynchronously, so that extensive client operations will not block the reception of events. Security Issues In our discussion, the use of a security system in the JavaMOO has been talked about as serving two purposes: protection from the malicious, and protection from programmer error. This document refers to the second purpose as “sanity checking.” We feel that some degree of sanity checking is important, and must be implemented to avoid the inevitable occurrence of a buggy client or server creating a database inconsistency. While sanity checking can be a great tool in creating MOO games, the programmer is fully capable of obviating any sanity checking scheme we could implement, and that’s ok. Sanity checking should be a safety net, not a straight jacket. The details of this sanity checking, though, are currently unspecified, and will be part of the MOO Database Access Spec. But on to security. Security issues are meant to protect the MOO, specifically the MOO Database contents, from malicious people. These people can be MOO users or MOO programmers. In the world of LambdaMOO, programmers, content providers and players all occupy the same interface. As a consequence, LambdaMOO has a complicated protection scheme to give the right people access to the right things. However, JavaMOO has a much different architecture, which gives programmers absolute power and clients (including users and content providers) virtually no power (or as much power as the programmers give them). While this simplifies the problem of malicious clients (see the simple command security system described above), it severely complicates the problem of protecting the MOO from malicious programmers. It is our belief that under most circumstances, this will not be a problem, since the programming team will usually be working together and under each other’s supervision. This system was designed to give programmers as much power over the MOO as possible, including the power to mess things up royally. But in the current LambdaMOO implementation, there is also the provision for having multiple, uncoordinated and untrusted programmers working on the MOO. Without a security provision on the programmer side of things, this kind of community programming system is untenable. The trick here is to keep programmers from writing code that could screw up the database, while still allowing for the absolute power to trusted programmers. While the previously described methods (command authentication, sanity checking) will go some way in protecting the database, all these are designed to be obviated by the knowing programmer, and will not suffice as a security system for community programming. This is very complicated issue and must be specified fully before implementation can begin. There are many tools that have been suggested to aid in the implementation of a community programming security scheme, including the use of the Java Security Manager, host file protections, etc. While I am fully confident that this problem is solvable, I want to strongly urge that we make sure the cure does not kill the patient. It would be very easy for a security implementation to render the JavaMOO so complicated and unwieldy as to be nearly unusable. At the very least, whatever security scheme is decided upon should be optional, so that developers who are using the trusted programmer team model of development will not be unduly burdened. In addition, the benefits of such a security scheme must be weighed against the costs of implementing the scheme in terms of time, resources, technology and usability. It may be the case that the number of people who would need a community development security scheme would be small compared to the number of man-hours it takes to implement the scheme. Implementation Implementation will take place in four phases (0-3). Phase 0 will be the completion of the design specs. Phase 1 will be creating a reliable core. Phase 2 will be building on this core and fleshing out all the features. Phase 3 will be the implementation of a game, which will iron out all the wrinkles. Phase 0: MOO Database Access Spec Distributed Server Spec Legacy Server Translation Spec Community Development Security Spec Client Interface and Design Spec Phase 1: Start with server Mini-core library Loading library is trivial Work out details with database access This includes the local caching scheme. Whatever security system will be used for the first pass, will likely overlap somewhat with database implementation. Minimal client that can issue commands and accept events. Implement client/server communication on server side. Maybe a little load testing at this point to check for bottlenecks. Phase 2: At this point, progress can be made on all fronts simultaneously. The server should be fleshed out and stabilized. The basic clients should be created and beautified. The core object library should be designed and implemented. Simultaneous with all this is the implementation of the legacy server translator. Phase 3: Once most of the details have been pounded out, phase 3 would be the implementation of a game on the new system. This will bring out all of the flaws in the entire system, and make the architecture solid and robust.