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);
}
}
}

本文下载地址:http://d.namipan.com/sd/1311061

6 Comments

袁冰十一月 25th, 2009 at 4:14 下午

翻译的很好 ^_^
最近正在学习sgs,也看了您翻译的客户端开发指南以及属性文件配置的pdf文件,受益匪浅。
感谢您辛苦的翻译,为了我们这些英语不过关的人带来了福音。
哈哈 再次感谢,好人一生平安!

David十一月 26th, 2009 at 11:36 下午

里面有不少生涩的地方,但也就这水平了,呵呵

arttemka十二月 25th, 2009 at 5:19 下午

I want to quote your post in my blog. It can?
And you et an account on Twitter?

David一月 4th, 2010 at 11:12 下午

Yes,of cause you can.
But,I don’t have an account on Twitter.

Pharme479一月 26th, 2010 at 4:00 下午

Very nice site!

闵大双四月 8th, 2010 at 5:36 下午

很好,很厉害,谢谢, 希望能够把qq发到我邮箱

请留下评论

您的评论