ProjectDarkStar服务器端开发文档(九)
附录A:SwordWorld例子代码
Sword World
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* * 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 Sword... */ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | /* * 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | /* * 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> items = new HashSet>(); /** The set of players in this room. */ private final Set> players = new HashSet>(); /** * 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | /* * 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); } } } |


翻译的很好 ^_^
最近正在学习sgs,也看了您翻译的客户端开发指南以及属性文件配置的pdf文件,受益匪浅。
感谢您辛苦的翻译,为了我们这些英语不过关的人带来了福音。
哈哈 再次感谢,好人一生平安!
里面有不少生涩的地方,但也就这水平了,呵呵
I want to quote your post in my blog. It can?
And you et an account on Twitter?
Yes,of cause you can.
But,I don’t have an account on Twitter.
Very nice site!
很好,很厉害,谢谢, 希望能够把qq发到我邮箱