ProjectDarkStar服务器端开发文档(九)

附录A:SwordWorld例子代码

Sword World

/*
 * Copyright 2007-2009 Sun Microsystems, Inc.
 *
 * This file is part of Project Darkstar Server.
 *
 * Project Darkstar Server is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation and
 * distributed hereunder to you.
 *
 * Project Darkstar Server is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see .
 
*/
package  com.sun.sgs.tutorial.server.swordworld;

import  java.io.Serializable;
import  java.util.Properties;
import  java.util.logging.Level;
import  java.util.logging.Logger;
import  com.sun.sgs.app.AppContext;
import  com.sun.sgs.app.AppListener;
import  com.sun.sgs.app.ClientSession;
import  com.sun.sgs.app.ClientSessionListener;
import  com.sun.sgs.app.DataManager;
import  com.sun.sgs.app.ManagedReference;

/**
 * A tiny sample MUD application for the Project Darkstar Server.
 * 
 * 
 * There is a Room. In the Room there is a SwordProjectDarkStar服务器端开发文档(九)
 
*/
public   class  SwordWorld  implements  Serializable, AppListener {
    
/**  The version of the serialized form of this class.  */
    
private   static   final   long  serialVersionUID  =   1L ;

    
/**  The { @link  Logger} for this class.  */
    
private   static   final  Logger logger  =  Logger.getLogger(SwordWorld. class
            .getName());

    
/**  A reference to the one-and-only { @linkplain  SwordWorldRoom room}.  */
    
private  ManagedReference roomRef  =   null ;

    
/**
     * {
@inheritDoc }
     * 
     * 
     * Creates the world within the MUD.
     
*/
    
public   void  initialize(Properties props) {
        logger.info(
" Initializing SwordWorld " );
        
//  Create the Room
        SwordWorldRoom room  =   new  SwordWorldRoom( " Plain Room " ,
                
" a nondescript room " );

        
//  Create the Sword
        SwordWorldObject sword  =   new  SwordWorldObject( " Shiny Sword " ,
                
" a shiny sword. " );

        
//  Put the Sword to the Room
        room.addItem(sword);

        
//  Keep a reference to the Room
        setRoom(room);
        logger.info(
" SwordWorld Initialized " );
    }

    
/**
     * Gets the SwordWorld's One True Room.
     * 
     * 
     * 
@return  the room for this { @code  SwordWorld}
     
*/
    
public  SwordWorldRoom getRoom() {
        
if  (roomRef  ==   null )
            
return   null ;
        
return  roomRef.get();
    }

    
/**
     * Sets the SwordWorld's One True Room to the given room.
     * 
     * 
     * 
@param  room
     *            the room to set
     
*/
    
public   void  setRoom(SwordWorldRoom room) {
        DataManager dataManager 
=  AppContext.getDataManager();
        
if  (room  ==   null ) {
            roomRef 
=   null ;
            
return ;
        }
        roomRef 
=  dataManager.createReference(room);
    }

    
/**
     * {
@inheritDoc }
     * 
     * 
     * Obtains the {
@linkplain  SwordWorldPlayer player} for this
     * {
@linkplain  ClientSession session}'s user, and puts the player into the
     * One True Room for this {
@code  SwordWorld}.
     
*/
    
public  ClientSessionListener loggedIn(ClientSession session) {
        logger.log(Level.INFO, 
" SwordWorld Client login: {0} " , session
                .getName());

        
//  Delegate to a factory method on SwordWorldPlayer,
        
//  since player management really belongs in that class.
        SwordWorldPlayer player  =  SwordWorldPlayer.loggedIn(session);

        
//  Put player in room
        player.enter(getRoom());

        
//  return player object as listener to this client session
         return  player;
    }
}

 

SwordWorldObject

/*
 * Copyright 2007-2009 Sun Microsystems, Inc.
 *
 * This file is part of Project Darkstar Server.
 *
 * Project Darkstar Server is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation and
 * distributed hereunder to you.
 *
 * Project Darkstar Server is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see .
 
*/
package  com.sun.sgs.tutorial.server.swordworld;

import  java.io.Serializable;
import  com.sun.sgs.app.AppContext;
import  com.sun.sgs.app.ManagedObject;

/**
 * A {
@code  ManagedObject} that has a name and a description.
 
*/
public   class  SwordWorldObject  implements  Serializable, ManagedObject {
    
/**  The version of the serialized form of this class.  */
    
private   static   final   long  serialVersionUID  =   1L ;

    
/**  The name of this object.  */
    
private  String name;

    
/**  The description of this object.  */
    
private  String description;

    
/**
     * Creates a new {
@code  SwordWorldObject} with the given { @code  name} and
     * {
@code  description}.
     * 
     * 
@param  name
     *            the name of this object
     * 
@param  description
     *            the description of this object
     
*/
    
public  SwordWorldObject(String name, String description) {
        
this .name  =  name;
        
this .description  =  description;
    }

    
/**
     * Sets the name of this object.
     * 
     * 
@param  name
     *            the name of this object
     
*/
    
public   void  setName(String name) {
        AppContext.getDataManager().markForUpdate(
this );
        
this .name  =  name;
    }

    
/**
     * Returns the name of this object.
     * 
     * 
@return  the name of this object
     
*/
    
public  String getName() {
        
return  name;
    }

    
/**
     * Sets the description of this object.
     * 
     * 
@param  description
     *            the description of this object
     
*/
    
public   void  setDescription(String description) {
        AppContext.getDataManager().markForUpdate(
this );
        
this .description  =  description;
    }

    
/**
     * Returns the description of this object.
     * 
     * 
@return  the description of this object
     
*/
    
public  String getDescription() {
        
return  description;
    }

    
/**  { @inheritDoc */
    @Override
    
public  String toString() {
        
return  getName();
    }
}

SwordWorldRoom

/*
* Copyright 2007-2009 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package  com.sun.sgs.tutorial.server.swordworld;
import  java.util.ArrayList;
import  java.util.Collections;
import  java.util.HashSet;
import  java.util.Iterator;
import  java.util.List;
import  java.util.Set;
import  java.util.logging.Level;
import  java.util.logging.Logger;
import  com.sun.sgs.app.AppContext;
import  com.sun.sgs.app.DataManager;
import  com.sun.sgs.app.ManagedReference;
/**
 * Represents a room in the {
@link  SwordWorld} example MUD.
 
*/
public   class  SwordWorldRoom  extends  SwordWorldObject
{
    
/**  The version of the serialized form of this class.  */
    
private   static   final   long  serialVersionUID  =   1L ;
     
    
/**  The { @link  Logger} for this class.  */
    
private   static   final  Logger logger  =
        Logger.getLogger(SwordWorldRoom.
class .getName());
     
    
/**  The set of items in this room.  */
    
private   final  Set & gt; items  =
        
new  HashSet & gt;();
     
    
/**  The set of players in this room.  */
    
private   final  Set & gt; players  =
        
new  HashSet & gt;();
    
/**
     * Creates a new room with the given name and description, initially empty of
     * items and players.
     * 
     * 
@param  name
     *            the name of this room
     * 
@param  description
     *            a description of this room
     * 
     
*/
    
public  SwordWorldRoom(String name, String description) {
        
super (name, description);
    }
    
/**
     * Adds an item to this room.
     * 
     * 
@param  item
     *            the item to add to this room.
     * 
@return  { @code  true} if the item was added to the room
     
*/
    
public   boolean  addItem(SwordWorldObject item) {
        logger.log(Level.INFO, 
" {0} placed in {1} " ,
                
new  Object[] { item,  this  });
     
        
//  NOTE: we can't directly save the item in the list, or
        
//  we'll end up with a local copy of the item. Instead, we
        
//  must save a ManagedReference to the item.
        DataManager dataManager  =  AppContext.getDataManager();
        dataManager.markForUpdate(
this );
        
return  items.add(dataManager.createReference(item));
    }
    
/**
     * Adds a player to this room.
     * 
     * 
@param  player
     *            the player to add
     * 
@return  { @code  true} if the player was added to the room
     
*/
    
public   boolean  addPlayer(SwordWorldPlayer player) {
        logger.log(Level.INFO, 
" {0} enters {1} " ,
        
new  Object[] { player,  this  });
        DataManager dataManager 
=  AppContext.getDataManager();
        dataManager.markForUpdate(
this );
        
return  players.add(dataManager.createReference(player));
    }
    
/**
     * Removes a player from this room.
     * 
     * 
@param  player
     *            the player to remove
     * 
@return  { @code  true} if the player was in the room
     
*/
    
public   boolean  removePlayer(SwordWorldPlayer player) {
        logger.log(Level.INFO, 
" {0} leaves {1} " ,
        
new  Object[] { player,  this  });
        DataManager dataManager 
=  AppContext.getDataManager();
        dataManager.markForUpdate(
this );
        
return  players.remove(dataManager.createReference(player));
    }
    
/**
     * Returns a description of what the given player sees in this room.
     * 
     * 
@param  looker
     *            the player looking in this room
     * 
@return  a description of what the given player sees in this room
     
*/
    
public  String look(SwordWorldPlayer looker) {
        logger.log(Level.INFO, 
" {0} looks at {1} " ,
        
new  Object[] { looker,  this  });
        StringBuilder output 
=   new  StringBuilder();
        output.append(
" You are in  " ).append(getDescription()).append( " .\n " );
        List otherPlayers 
=  getPlayersExcluding(looker);
        
if  ( !  otherPlayers.isEmpty()) {
            output.append(
" Also in here are  " );
            appendPrettyList(output, otherPlayers);
            output.append(
" .\n " );
        }
        
if  ( !  items.isEmpty()) {
            output.append(
" On the floor you see:\n " );
            
for  (ManagedReference itemRef : items) {
                SwordWorldObject item 
=  itemRef.get();
                output.append(item.getDescription()).append(
' \n ' );
            }
        }
        
return  output.toString();
    }
    
/**
     * Appends the names of the {
@code  SwordWorldObject}s in the list to the
     * builder, separated by commas, with an "and" before the final item.
     * 
     * 
@param  builder
     *            the {
@code  StringBuilder} to append to
     * 
@param  list
     *            the list of items to format
     
*/
    
private   void  appendPrettyList(StringBuilder builder,
        List
<!-- xtends SwordWorldObje -->  list)
        {
            
if  (list.isEmpty()) {
                
return ;
        }
        
int  lastIndex  =  list.size()  -   1 ;
        SwordWorldObject last 
=  list.get(lastIndex);
        Iterator
<!-- xtends SwordWorldObje -->  it  =
        list.subList(
0 , lastIndex).iterator();
        
if  (it.hasNext()) {
            SwordWorldObject other 
=  it.next();
            builder.append(other.getName());
            
while  (it.hasNext()) {
                other 
=  it.next();
                builder.append(
"  , " );
                builder.append(other.getName());
            }
            builder.append(
"  and  " );
        }
        builder.append(last.getName());
    }
    
/**
     * Returns a list of players in this room excluding the given player.
     * 
     * 
@param  player
     *            the player to exclude
     * 
@return  the list of players
     
*/
    
private  ListgetPlayersExcluding(SwordWorldPlayer player)
    {
        
if  (players.isEmpty()) {
            
return  Collections.emptyList();
        }
        ArrayList otherPlayers 
=
            
new  ArrayList(players.size());
        
for  (ManagedReference playerRef : players) {
            SwordWorldPlayer other 
=  playerRef.get();
            
if  ( ! player.equals(other)) {
                otherPlayers.add(other);
            }
        }
        
return  Collections.unmodifiableList(otherPlayers);
    }
}

SwordWorldPlayer

/*
 * Copyright 2007-2009 Sun Microsystems, Inc.
 *
 * This file is part of Project Darkstar Server.
 *
 * Project Darkstar Server is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation and
 * distributed hereunder to you.
 *
 * Project Darkstar Server is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see .
 
*/
package  com.sun.sgs.tutorial.server.swordworld;

import  java.io.UnsupportedEncodingException;
import  java.nio.ByteBuffer;
import  java.util.logging.Level;
import  java.util.logging.Logger;
import  com.sun.sgs.app.AppContext;
import  com.sun.sgs.app.ClientSession;
import  com.sun.sgs.app.ClientSessionListener;
import  com.sun.sgs.app.DataManager;
import  com.sun.sgs.app.ManagedReference;
import  com.sun.sgs.app.NameNotBoundException;

/**
 * Represents a player in the {
@link  SwordWorld} example MUD.
 
*/
public   class  SwordWorldPlayer  extends  SwordWorldObject  implements
        ClientSessionListener {
    
/**  The version of the serialized form of this class.  */
    
private   static   final   long  serialVersionUID  =   1L ;

    
/**  The { @link  Logger} for this class.  */
    
private   static   final  Logger logger  =  Logger
            .getLogger(SwordWorldPlayer.
class .getName());

    
/**  The message encoding.  */
    
public   static   final  String MESSAGE_CHARSET  =   " UTF-8 " ;

    
/**  The prefix for player bindings in the { @code  DataManager}.  */
    
protected   static   final  String PLAYER_BIND_PREFIX  =   " Player. " ;

    
/**  The { @code  ClientSession} for this player, or null if logged out.  */
    
private  ManagedReference currentSessionRef  =   null ;

    
/**  The { @link  SwordWorldRoom} this player is in, or null if none.  */
    
private  ManagedReference currentRoomRef  =   null ;

    
/**
     * Find or create the player object for the given session, and mark the
     * player as logged in on that session.
     * 
     * 
@param  session
     *            which session to find or create a player for
     * 
@return  a player for the given session
     
*/
    
public   static  SwordWorldPlayer loggedIn(ClientSession session) {
        String playerBinding 
=  PLAYER_BIND_PREFIX  +  session.getName();
        
//  try to find player object, if non existent then create
        DataManager dataMgr  =  AppContext.getDataManager();
        SwordWorldPlayer player;
        
try  {
            player 
=  (SwordWorldPlayer) dataMgr.getBinding(playerBinding);
        } 
catch  (NameNotBoundException ex) {
            
//  this is a new player
            player  =   new  SwordWorldPlayer(playerBinding);
            logger.log(Level.INFO, 
" New player created: {0} " , player);
            dataMgr.setBinding(playerBinding, player);
        }
        player.setSession(session);
        
return  player;
    }

    
/**
     * Creates a new {
@code  SwordWorldPlayer} with the given name.
     * 
     * 
@param  name
     *            the name of this player
     
*/
    
protected  SwordWorldPlayer(String name) {
        
super (name,  " Seeker of the Sword " );
    }

    
/**
     * Returns the session for this listener.
     * 
     * 
@return  the session for this listener
     
*/
    
protected  ClientSession getSession() {
        
if  (currentSessionRef  ==   null ) {
            
return   null ;
        }
        
return  currentSessionRef.get();
    }

    
/**
     * Mark this player as logged in on the given session.
     * 
     * 
@param  session
     *            the session this player is logged in on
     
*/
    
protected   void  setSession(ClientSession session) {
        DataManager dataMgr 
=  AppContext.getDataManager();
        dataMgr.markForUpdate(
this );
        currentSessionRef 
=  dataMgr.createReference(session);
        logger.log(Level.INFO, 
" Set session for {0} to {1} " new  Object[] {
                
this , session });
    }

    
/**
     * Handles a player entering a room.
     * 
     * 
@param  room
     *            the room for this player to enter
     
*/
    
public   void  enter(SwordWorldRoom room) {
        logger.log(Level.INFO, 
" {0} enters {1} " new  Object[] {  this , room });
        room.addPlayer(
this );
        setRoom(room);
    }

    
/**  { @inheritDoc */
    
public   void  receivedMessage(ByteBuffer message) {
        String command 
=  decodeString(message);
        logger.log(Level.INFO, 
" {0} received command: {1} " new  Object[] {
                
this , command });
        
if  (command.equalsIgnoreCase( " look " )) {
            String reply 
=  getRoom().look( this );
            getSession().send(encodeString(reply));
        } 
else  {
            logger.log(Level.WARNING, 
" {0} unknown command: {1} " new  Object[] {
                    
this , command });
            
//  We could disconnect the rogue player at this point.
            
//  currentSession.disconnect();
        }
    }

    
/**  { @inheritDoc */
    
public   void  disconnected( boolean  graceful) {
        setSession(
null );
        logger.log(Level.INFO, 
" Disconnected: {0} " this );
        getRoom().removePlayer(
this );
        setRoom(
null );
    }

    
/**
     * Returns the room this player is currently in, or {
@code  null} if this
     * player is not in a room.
     * 
     * 
     * 
@return  the room this player is currently in, or { @code  null}
     
*/
    
protected  SwordWorldRoom getRoom() {
        
if  (currentRoomRef  ==   null ) {
            
return   null ;
        }
        
return  currentRoomRef.get();
    }

    
/**
     * Sets the room this player is currently in. If the room given is null,
     * marks the player as not in any room.
     * 
     * 
     * 
@param  room
     *            the room this player should be in, or {
@code  null}
     
*/
    
protected   void  setRoom(SwordWorldRoom room) {
        DataManager dataManager 
=  AppContext.getDataManager();
        dataManager.markForUpdate(
this );
        
if  (room  ==   null ) {
            currentRoomRef 
=   null ;
            
return ;
        }
        currentRoomRef 
=  dataManager.createReference(room);
    }

    
/**  { @inheritDoc */
    @Override
    
public  String toString() {
        StringBuilder buf 
=   new  StringBuilder(getName());
        buf.append(
' @ ' );
        
if  (getSession()  ==   null ) {
            buf.append(
" null " );
        } 
else  {
            buf.append(currentSessionRef.getId());
        }
        
return  buf.toString();
    }

    
/**
     * Encodes a {
@code  String} into a { @link  ByteBuffer}.
     * 
     * 
@param  s
     *            the string to encode
     * 
@return  the { @code  ByteBuffer} which encodes the given string
     
*/
    
protected   static  ByteBuffer encodeString(String s) {
        
try  {
            
return  ByteBuffer.wrap(s.getBytes(MESSAGE_CHARSET));
        } 
catch  (UnsupportedEncodingException e) {
            
throw   new  Error( " Required character set  "   +  MESSAGE_CHARSET
                    
+   "  not found " , e);
        }
    }

    
/**
     * Decodes a message into a {
@code  String}.
     * 
     * 
@param  message
     *            the message to decode
     * 
@return  the decoded string
     
*/
    
protected   static  String decodeString(ByteBuffer message) {
        
try  {
            
byte [] bytes  =   new   byte [message.remaining()];
            message.get(bytes);
            
return   new  String(bytes, MESSAGE_CHARSET);
        } 
catch  (UnsupportedEncodingException e) {
            
throw   new  Error( " Required character set  "   +  MESSAGE_CHARSET
                    
+   "  not found " , e);
        }
    }
}

 

你可能感兴趣的:(project)