📄 mudplace.java
字号:
} // Let everyone know of the demise of this thing. tellEveryone(name + " had destroyed the " + thing); } /** * Create a new place in this MUD, with the specified name an description. * The new place is accessible from this place through * the specified exit, and this place is accessible from the new place * through the specified entrance. The creator must be in this place * in order to create a exit from this place. **/ public void createPlace(RemoteMudPerson creator, String exit, String entrance, String name, String description) throws RemoteException,NotThere,ExitAlreadyExists,PlaceAlreadyExists { // Verify that the creator is actually here in this place String creatorname = verifyPresence(creator); synchronized(exits) { // Only one client may change exits at a time // Check that the exit doesn't already exist. if (exits.indexOf(exit) != -1) throw new ExitAlreadyExists(); // Create the new place, registering its name with the server MudPlace destination = new MudPlace(server, name, description); // Link from there back to here destination.exits.addElement(entrance); destination.destinations.addElement(this); // And link from here to there exits.addElement(exit); destinations.addElement(destination); } // Let everyone know about the new exit, and the new place beyond tellEveryone(creatorname + " has created a new place: " + exit); } /** * Create a new exit from this mud, linked to a named place in a named * MUD on a named host (this can also be used to link to a named place in * the current MUD, of course). Because of the possibilities of deadlock, * this method only links from here to there; it does not create a return * exit from there to here. That must be done with a separate call. **/ public void linkTo(RemoteMudPerson linker, String exit, String hostname, String mudname, String placename) throws RemoteException, NotThere, ExitAlreadyExists, NoSuchPlace { // Verify that the linker is actually here String name = verifyPresence(linker); // Check that the link target actually exists. Throw NoSuchPlace if // not. Note that NoSuchPlace may also mean "NoSuchMud" or // "MudNotResponding". String url = "rmi://" + hostname + '/' + Mud.mudPrefix + mudname; try { RemoteMudServer s = (RemoteMudServer) Naming.lookup(url); RemoteMudPlace destination = s.getNamedPlace(placename); } catch (Exception e) { throw new NoSuchPlace(); } synchronized(exits) { // Check that the exit doesn't already exist. if (exits.indexOf(exit) != -1) throw new ExitAlreadyExists(); // Add the exit, to the list of exit names exits.addElement(exit); // And add the destination to the list of destinations. Note that // the destination is stored as a string rather than as a // RemoteMudPlace. This is because if the remote server goes down // then comes back up again, a RemoteMudPlace is not valid, but the // string still is. destinations.addElement(url + '@' + placename); } // Let everyone know about the new exit and where it leads tellEveryone(name + " has linked " + exit + " to " + "'" + placename + "' in MUD '" + mudname + "' on host " + hostname); } /** * Close an exit that leads out of this place. * It does not close the return exit from there back to here. * Note that this method does not destroy the place that the exit leads to. * In the current implementation, there is no way to destroy a place. **/ public void close(RemoteMudPerson who, String exit) throws RemoteException, NotThere, NoSuchExit { // check that the person closing the exit is actually here String name = verifyPresence(who); synchronized(exits) { // Check that the exit exists int i = exits.indexOf(exit); if (i == -1) throw new NoSuchExit(); // Remove it and its destination from the lists exits.removeElementAt(i); destinations.removeElementAt(i); } // Let everyone know that the exit doesn't exist anymore tellEveryone(name + " has closed exit " + exit); } /** * Remove a person from this place. If there is a message, send it to * everyone who is left in this place. If the specified person is not here * this method does nothing and does not throw an exception. This method * is called by go(), and the client should call it when the user quits. * The client should not allow the user to invoke it directly, however. **/ public void exit(RemoteMudPerson who, String message) throws RemoteException { String name; synchronized(names) { int i = people.indexOf(who); if (i == -1) return; names.removeElementAt(i); people.removeElementAt(i); } if (message != null) tellEveryone(message); } /** * This method puts a person into this place, assigning them the * specified name, and displaying a message to anyone else who is in * that place. This method is called by go(), and the client should * call it to initially place a person into the MUD. Once the person * is in the MUD, however, the client should restrict them to using go() * and should not allow them to call this method directly. * If there have been networking problems, a client might call this method * to restore a person to this place, in case they've been bumped out. * (A person will be bumped out of a place if the server tries to send * a message to them and gets a RemoteException.) **/ public void enter(RemoteMudPerson who, String name, String message) throws RemoteException, AlreadyThere { // Send the message to everyone who is already here. if (message != null) tellEveryone(message); // Add the person to this place. synchronized (names) { if (people.indexOf(who) != -1) throw new AlreadyThere(); names.addElement(name); people.addElement(who); } } /** * This final remote method returns the server object for the MUD in which * this place exists. The client should not allow the user to invoke this * method. **/ public RemoteMudServer getServer() throws RemoteException { return server; } /** * Create and start a thread that sends out a message everyone in this * place. If it gets a RemoteException talking to a person, it silently * removes that person from this place. This is not a remote method, but * is used internally by a number of remote methods. **/ protected void tellEveryone(final String message) { // If there is no-one here, don't bother sending the message! if (people.size() == 0) return; // Make a copy of the people here now. The message is sent // asynchronously and the list of people in the room may change before // the message is sent to everyone. final Vector recipients = (Vector) people.clone(); // Create and start a thread to send the message, using an anonymous // class. We do this because sending the message to everyone in this // place might take some time, (particularly on a slow or flaky // network) and we don't want to wait. new Thread() { public void run() { // Loop through the recipients for(int i = 0; i < recipients.size(); i++) { RemoteMudPerson person = (RemoteMudPerson)recipients.elementAt(i); // Try to send the message to each one. try { person.tell(message); } // If it fails, assume that that person's client or // network has failed, and silently remove them from // this place. catch (RemoteException e) { try { MudPlace.this.exit(person, null); } catch (Exception ex) {} } } } }.start(); } /** * This convenience method checks whether the specified person is here. * If so, it returns their name. If not it throws a NotThere exception **/ protected String verifyPresence(RemoteMudPerson who) throws NotThere { int i = people.indexOf(who); if (i == -1) throw new NotThere(); else return (String) names.elementAt(i); } /** * This method is used for custom de-serialization. Since the vectors of * people and of their names are transient, they are not serialized with * the rest of this place. Therefore, when the place is de-serialized, * those vectors have to be recreated (empty). **/ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); // Read most of the object as normal names = new Vector(); // Then recreate the names vector people = new Vector(); // and recreate the people vector } /** This constant is a version number for serialization */ static final long serialVersionUID = 5090967989223703026L;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -