|
|||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
World.java | 0% | 0% | 0% | 0% |
|
1 |
/*
|
|
2 |
|
|
3 |
VRMoo Server - Virtual Reality Object Oriented MUD Server
|
|
4 |
Copyright (C) 2001 - 2003 VRMoo Development Team
|
|
5 |
|
|
6 |
|
|
7 |
This program is free software; you can redistribute it and/or modify
|
|
8 |
it under the terms of the GNU General Public License as published by
|
|
9 |
the Free Software Foundation; either version 2 of the License, or
|
|
10 |
(at your option) any later version.
|
|
11 |
|
|
12 |
This program is distributed in the hope that it will be useful,
|
|
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 |
GNU General Public License for more details.
|
|
16 |
|
|
17 |
You should have received a copy of the GNU General Public License
|
|
18 |
along with this program; if not, write to the Free Software
|
|
19 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
20 |
|
|
21 |
|
|
22 |
For information about VRMoo and its authors, please visit the website:
|
|
23 |
http://www.vrmoo.org/
|
|
24 |
|
|
25 |
*/
|
|
26 |
|
|
27 |
package org.vrmoo.server.world;
|
|
28 |
|
|
29 |
import java.io.BufferedReader;
|
|
30 |
import java.io.File;
|
|
31 |
import java.io.PrintWriter;
|
|
32 |
import java.util.ArrayList;
|
|
33 |
import java.util.HashMap;
|
|
34 |
import java.util.List;
|
|
35 |
import java.util.Map;
|
|
36 |
|
|
37 |
import org.vrmoo.common.data.AppearanceData;
|
|
38 |
import org.vrmoo.common.data.ObjectData;
|
|
39 |
import org.vrmoo.common.data.VisibleObject;
|
|
40 |
import org.vrmoo.common.exception.VRMooException;
|
|
41 |
import org.vrmoo.common.exception.VRMooParseException;
|
|
42 |
import org.vrmoo.common.objectbroker.AppearanceDataBroker;
|
|
43 |
import org.vrmoo.common.objectbroker.ObjectDataBroker;
|
|
44 |
import org.vrmoo.common.objectbroker.VisibleObjectBroker;
|
|
45 |
import org.vrmoo.common.util.CommandHandler;
|
|
46 |
import org.vrmoo.common.util.CommandProcessor;
|
|
47 |
import org.vrmoo.common.util.FileUtility;
|
|
48 |
import org.vrmoo.common.util.ParserUtility;
|
|
49 |
import org.vrmoo.common.util.Base64Utility;
|
|
50 |
|
|
51 |
import org.vrmoo.server.client.AllClients;
|
|
52 |
import org.vrmoo.server.client.ClientHandler;
|
|
53 |
import org.vrmoo.server.data.TextureManager;
|
|
54 |
|
|
55 |
/**
|
|
56 |
* This class contains the functionality for dealing with an interactive 3D
|
|
57 |
* world that can be explored and altered by VRMoo Clients.
|
|
58 |
*
|
|
59 |
*@author Jeff Weston
|
|
60 |
*/
|
|
61 |
public class World extends CommandHandler implements CommandProcessor { |
|
62 |
/**
|
|
63 |
* The root directory where all world data is saved.
|
|
64 |
*/
|
|
65 |
private static final String WORLD_DATA_DIR = "data/worlds"; |
|
66 |
|
|
67 |
/**
|
|
68 |
* The prefix used for world commands.
|
|
69 |
*/
|
|
70 |
private static final String WORLD_COMMAND_PREFIX = "world:"; |
|
71 |
|
|
72 |
/**
|
|
73 |
* Holds the name of the world.
|
|
74 |
*/
|
|
75 |
private String name;
|
|
76 |
|
|
77 |
/**
|
|
78 |
* Holds the directory location of the world data.
|
|
79 |
*/
|
|
80 |
private String worldDataDirectory;
|
|
81 |
|
|
82 |
/**
|
|
83 |
* The directory where avatar data is stored
|
|
84 |
*/
|
|
85 |
private String avatarDirectory;
|
|
86 |
|
|
87 |
/**
|
|
88 |
* Holds the list of clients currently connected to this world.
|
|
89 |
*/
|
|
90 |
private List clients;
|
|
91 |
|
|
92 |
/**
|
|
93 |
* Holds the map of clients that are currently connecting to this world
|
|
94 |
* paired up with the state information for those connecting clients.
|
|
95 |
*/
|
|
96 |
private Map connectingClients;
|
|
97 |
|
|
98 |
/**
|
|
99 |
* The texture manager for this world.
|
|
100 |
*/
|
|
101 |
private TextureManager textureManager;
|
|
102 |
|
|
103 |
/**
|
|
104 |
* The appearance data broker for this world.
|
|
105 |
*/
|
|
106 |
private AppearanceDataBroker appearanceBroker;
|
|
107 |
|
|
108 |
/**
|
|
109 |
* The object data broker for this world.
|
|
110 |
*/
|
|
111 |
private ObjectDataBroker objectBroker;
|
|
112 |
|
|
113 |
/**
|
|
114 |
* The visible object broker for this world.
|
|
115 |
*/
|
|
116 |
private VisibleObjectBroker visibleObjectBroker;
|
|
117 |
|
|
118 |
|
|
119 |
/**
|
|
120 |
* This default constructor creates a minimal 3D world.
|
|
121 |
*
|
|
122 |
*@param name the name for the world
|
|
123 |
*@exception VRMooException Description of the Exception
|
|
124 |
*@throws VRMooException for any errors while creating the world
|
|
125 |
*/
|
|
126 | 0 |
public World( String name )
|
127 |
throws VRMooException {
|
|
128 | 0 |
this.name = name;
|
129 | 0 |
worldDataDirectory = WORLD_DATA_DIR + "/" + name;
|
130 | 0 |
avatarDirectory = worldDataDirectory + "/avatars";
|
131 | 0 |
File dataDir = new File( worldDataDirectory );
|
132 | 0 |
FileUtility.ensureDirectoryExists( dataDir ); |
133 |
|
|
134 | 0 |
textureManager = new TextureManager( this ); |
135 |
|
|
136 | 0 |
appearanceBroker = new AppearanceDataBroker();
|
137 | 0 |
appearanceBroker.addCommandHandler( this );
|
138 | 0 |
addCommandProcessor( appearanceBroker ); |
139 |
|
|
140 | 0 |
objectBroker = new ObjectDataBroker();
|
141 | 0 |
objectBroker.addCommandHandler( this );
|
142 | 0 |
addCommandProcessor( objectBroker ); |
143 |
|
|
144 | 0 |
visibleObjectBroker = new VisibleObjectBroker();
|
145 | 0 |
visibleObjectBroker.addCommandHandler( this );
|
146 | 0 |
addCommandProcessor( visibleObjectBroker ); |
147 |
|
|
148 | 0 |
addCommandProcessor( new NewLocationCommandProcessor() );
|
149 | 0 |
addCommandProcessor( new SendCommandCommandProcessor() );
|
150 | 0 |
addCommandProcessor( new AvatarCommandProcessor() );
|
151 |
|
|
152 | 0 |
clients = new ArrayList();
|
153 | 0 |
connectingClients = new HashMap();
|
154 |
|
|
155 | 0 |
loadWorldData(); |
156 |
} |
|
157 |
|
|
158 |
|
|
159 |
/**
|
|
160 |
* Returns the command prefix used to recognize commands that this processor
|
|
161 |
* can handle.
|
|
162 |
*
|
|
163 |
*@return the command prefix
|
|
164 |
*/
|
|
165 | 0 |
public String getCommandPrefix() {
|
166 | 0 |
return WORLD_COMMAND_PREFIX;
|
167 |
} |
|
168 |
|
|
169 |
|
|
170 |
/**
|
|
171 |
* Process a command matching the command prefix established by the
|
|
172 |
* <code>getCommandPrefix()</code> method.
|
|
173 |
*
|
|
174 |
*@param command the command to process
|
|
175 |
*@param extraData extra data that isn't part of the command but may
|
|
176 |
* be needed for dealing with the command (such as the ID of the client
|
|
177 |
* that sent the command)
|
|
178 |
*@throws VRMooException for any errors while processing the command
|
|
179 |
*/
|
|
180 | 0 |
public synchronized void processCommand( String command, String extraData ) |
181 |
throws VRMooException {
|
|
182 | 0 |
String worldCommand = command.substring( |
183 |
WORLD_COMMAND_PREFIX.length() ).trim(); |
|
184 |
|
|
185 | 0 |
handleCommand( worldCommand, extraData ); |
186 |
} |
|
187 |
|
|
188 |
|
|
189 |
/**
|
|
190 |
* Get the name of the world.
|
|
191 |
*
|
|
192 |
*@return the name of the world
|
|
193 |
*/
|
|
194 | 0 |
public String getName() {
|
195 | 0 |
return name;
|
196 |
} |
|
197 |
|
|
198 |
|
|
199 |
/**
|
|
200 |
* Get the data directory of the world.
|
|
201 |
*
|
|
202 |
*@return the data directory of the world
|
|
203 |
*/
|
|
204 | 0 |
public String getWorldDataDirectory() {
|
205 | 0 |
return worldDataDirectory;
|
206 |
} |
|
207 |
|
|
208 |
|
|
209 |
/**
|
|
210 |
* Connect a client to this world.
|
|
211 |
*
|
|
212 |
*@param client the <code>ClientHandler</code> to connect
|
|
213 |
*/
|
|
214 | 0 |
public synchronized void connectClient( ClientHandler client ) { |
215 | 0 |
if ( ( !clients.contains( client ) ) &&
|
216 |
( !connectingClients.containsKey( client ) ) ) { |
|
217 |
// Register this world to receive world commands from the client.
|
|
218 | 0 |
client.addCommandProcessor( this );
|
219 |
|
|
220 |
// Add the client to the list of connecting clients.
|
|
221 | 0 |
connectingClients.put( client, new ConnectingClientState() );
|
222 |
|
|
223 |
// Start the texture initialization procedure.
|
|
224 | 0 |
textureManager.newClientConnected( client ); |
225 |
} |
|
226 |
} |
|
227 |
|
|
228 |
|
|
229 |
/**
|
|
230 |
* Indicate that the specified client has finished the texture
|
|
231 |
* initialization procedure. If this is the final step for connecting the
|
|
232 |
* client to the world, then connect the client to the world.
|
|
233 |
*
|
|
234 |
*@param client the <code>ClientHandler</code> that has finished
|
|
235 |
* the texture initialization procedure
|
|
236 |
*@throws VRMooException for any errors while processing the command
|
|
237 |
*/
|
|
238 | 0 |
public synchronized void clientFinishedTextures( ClientHandler client ) |
239 |
throws VRMooException {
|
|
240 | 0 |
if ( connectingClients.containsKey( client ) ) {
|
241 | 0 |
ConnectingClientState clientState = |
242 |
( ConnectingClientState ) connectingClients.get( client ); |
|
243 | 0 |
clientState.texturesFinished(); |
244 | 0 |
if ( clientState.clientReady() ) {
|
245 | 0 |
clientConnected( client ); |
246 |
} |
|
247 |
} |
|
248 |
} |
|
249 |
|
|
250 |
|
|
251 |
/**
|
|
252 |
* Disconnect a client from this world.
|
|
253 |
*
|
|
254 |
*@param client the <code>ClientHandler</code> to disconnect
|
|
255 |
*/
|
|
256 | 0 |
public synchronized void disconnectClient( ClientHandler client ) { |
257 | 0 |
if ( clients.contains( client ) ) {
|
258 | 0 |
client.removeCommandProcessor( this );
|
259 | 0 |
clients.remove( client ); |
260 | 0 |
broadcast( "disconnect: " + client.getClientID() );
|
261 |
} |
|
262 |
|
|
263 | 0 |
if ( connectingClients.containsKey( client ) ) {
|
264 | 0 |
client.removeCommandProcessor( this );
|
265 | 0 |
connectingClients.remove( client ); |
266 |
} |
|
267 |
//Remove avatar data for this client
|
|
268 | 0 |
File f = FileUtility.getImageFile(avatarDirectory + "/client" +
|
269 |
client.getClientID()); |
|
270 | 0 |
if (f != null) { |
271 | 0 |
f.delete(); |
272 |
} |
|
273 |
} |
|
274 |
|
|
275 |
|
|
276 |
/**
|
|
277 |
* Sends a line of text to all connected clients.
|
|
278 |
*
|
|
279 |
*@param line the line of text
|
|
280 |
*/
|
|
281 | 0 |
public synchronized void broadcast( String line ) { |
282 | 0 |
for ( int i = 0; i < clients.size(); i++ ) { |
283 | 0 |
ClientHandler client = ( ClientHandler ) clients.get( i ); |
284 | 0 |
client.writeLine( line ); |
285 |
} |
|
286 |
} |
|
287 |
|
|
288 |
|
|
289 |
/**
|
|
290 |
* Save all of the data used by this world out to disk.
|
|
291 |
*/
|
|
292 | 0 |
public synchronized void saveWorldData() { |
293 | 0 |
System.out.println( "Saving world data..." + name );
|
294 | 0 |
saveAppearanceData(); |
295 | 0 |
saveObjectData(); |
296 | 0 |
saveVisibleObjects(); |
297 |
} |
|
298 |
|
|
299 |
|
|
300 |
/**
|
|
301 |
* Load all of the data used by this world from disk.
|
|
302 |
*/
|
|
303 | 0 |
private void loadWorldData() { |
304 | 0 |
System.out.println( "Loading world data..." + name );
|
305 | 0 |
loadAppearanceData(); |
306 | 0 |
loadObjectData(); |
307 | 0 |
loadVisibleObjects(); |
308 |
} |
|
309 |
|
|
310 |
|
|
311 |
/**
|
|
312 |
* Save all of the appearances used by this world out to disk.
|
|
313 |
*/
|
|
314 | 0 |
private void saveAppearanceData( ) |
315 |
{ |
|
316 | 0 |
try
|
317 |
{ |
|
318 | 0 |
PrintWriter writer = FileUtility.getPrintWriter( |
319 |
worldDataDirectory + "/appearances.dat" );
|
|
320 | 0 |
String[] appearanceNames = |
321 |
appearanceBroker.getAppearanceDataNames(); |
|
322 |
|
|
323 | 0 |
for ( int i = 0; i < appearanceNames.length; i++ ) { |
324 | 0 |
AppearanceData appearance = appearanceBroker.getAppearanceData( |
325 |
appearanceNames[i] ); |
|
326 | 0 |
writer.println( appearance.toEncodedString() ); |
327 |
} |
|
328 | 0 |
writer.close(); |
329 |
} catch ( Exception e ) {
|
|
330 | 0 |
e.printStackTrace(); |
331 |
} |
|
332 |
} |
|
333 |
|
|
334 |
|
|
335 |
/**
|
|
336 |
* Load all of the appearances used by this world from disk.
|
|
337 |
*/
|
|
338 | 0 |
private void loadAppearanceData( ) |
339 |
{ |
|
340 | 0 |
try
|
341 |
{ |
|
342 | 0 |
BufferedReader reader = FileUtility.getBufferedReader( |
343 |
worldDataDirectory + "/appearances.dat" );
|
|
344 |
|
|
345 | 0 |
String line = reader.readLine(); |
346 |
|
|
347 | 0 |
while ( line != null ) { |
348 | 0 |
AppearanceData appearance = new AppearanceData( line );
|
349 | 0 |
appearanceBroker.setAppearanceData( appearance ); |
350 | 0 |
line = reader.readLine(); |
351 |
} |
|
352 | 0 |
reader.close(); |
353 |
} catch ( Exception e ) {
|
|
354 | 0 |
e.printStackTrace(); |
355 |
} |
|
356 |
} |
|
357 |
|
|
358 |
|
|
359 |
/**
|
|
360 |
* Save all of the object definitions used by this world out to disk.
|
|
361 |
*/
|
|
362 | 0 |
private void saveObjectData( ) |
363 |
{ |
|
364 | 0 |
try
|
365 |
{ |
|
366 | 0 |
PrintWriter writer = FileUtility.getPrintWriter( |
367 |
worldDataDirectory + "/objects.dat" );
|
|
368 | 0 |
String[] objectNames = objectBroker.getObjectDataNames(); |
369 |
|
|
370 | 0 |
for ( int i = 0; i < objectNames.length; i++ ) { |
371 | 0 |
ObjectData object = objectBroker.getObjectData( |
372 |
objectNames[i] ); |
|
373 | 0 |
writer.println( object.toEncodedString() ); |
374 |
} |
|
375 | 0 |
writer.close(); |
376 |
} catch ( Exception e ) {
|
|
377 | 0 |
e.printStackTrace(); |
378 |
} |
|
379 |
} |
|
380 |
|
|
381 |
|
|
382 |
/**
|
|
383 |
* Load all of the object definitions used by this world from disk.
|
|
384 |
*/
|
|
385 | 0 |
private void loadObjectData( ) |
386 |
{ |
|
387 | 0 |
try
|
388 |
{ |
|
389 | 0 |
BufferedReader reader = FileUtility.getBufferedReader( |
390 |
worldDataDirectory + "/objects.dat" );
|
|
391 |
|
|
392 | 0 |
String line = reader.readLine(); |
393 |
|
|
394 | 0 |
while ( line != null ) { |
395 | 0 |
ObjectData object = new ObjectData( line );
|
396 | 0 |
objectBroker.setObjectData( object ); |
397 | 0 |
line = reader.readLine(); |
398 |
} |
|
399 | 0 |
reader.close(); |
400 |
} catch ( Exception e ) {
|
|
401 | 0 |
e.printStackTrace(); |
402 |
} |
|
403 |
} |
|
404 |
|
|
405 |
|
|
406 |
/**
|
|
407 |
* Save all of the visible objects used by this world out to disk.
|
|
408 |
*/
|
|
409 | 0 |
private void saveVisibleObjects( ) |
410 |
{ |
|
411 | 0 |
try
|
412 |
{ |
|
413 | 0 |
PrintWriter writer = FileUtility.getPrintWriter( |
414 |
worldDataDirectory + "/visibleObjects.dat" );
|
|
415 | 0 |
int[] visibleObjectNames =
|
416 |
visibleObjectBroker.getVisibleObjectNames(); |
|
417 |
|
|
418 | 0 |
for ( int i = 0; i < visibleObjectNames.length; i++ ) { |
419 | 0 |
VisibleObject visibleObject = |
420 |
visibleObjectBroker.getVisibleObject( |
|
421 |
visibleObjectNames[i] ); |
|
422 | 0 |
writer.println( visibleObject.toEncodedString() ); |
423 |
} |
|
424 | 0 |
writer.close(); |
425 |
} catch ( Exception e ) {
|
|
426 | 0 |
e.printStackTrace(); |
427 |
} |
|
428 |
} |
|
429 |
|
|
430 |
|
|
431 |
/**
|
|
432 |
* Load all of the visible objects used by this world from disk.
|
|
433 |
*/
|
|
434 | 0 |
private void loadVisibleObjects( ) |
435 |
{ |
|
436 | 0 |
try
|
437 |
{ |
|
438 | 0 |
BufferedReader reader = FileUtility.getBufferedReader( |
439 |
worldDataDirectory + "/visibleObjects.dat" );
|
|
440 |
|
|
441 | 0 |
String line = reader.readLine(); |
442 |
|
|
443 | 0 |
while ( line != null ) { |
444 | 0 |
VisibleObject visibleObject = new VisibleObject( line );
|
445 | 0 |
visibleObjectBroker.addVisibleObject( visibleObject ); |
446 | 0 |
line = reader.readLine(); |
447 |
} |
|
448 | 0 |
reader.close(); |
449 |
} catch ( Exception e ) {
|
|
450 | 0 |
e.printStackTrace(); |
451 |
} |
|
452 |
} |
|
453 |
|
|
454 |
/**
|
|
455 |
* Indicates that the specified client is now actually connected.
|
|
456 |
* Move the client from the "connecting" state to the "connected"
|
|
457 |
* state.
|
|
458 |
*
|
|
459 |
* @param client the <code>ClientHandler</code> that is now connected
|
|
460 |
*
|
|
461 |
*@throws VRMooException for any errors while processing the command
|
|
462 |
*/
|
|
463 | 0 |
private void clientConnected( ClientHandler client ) |
464 |
throws VRMooException {
|
|
465 | 0 |
if ( ( connectingClients.containsKey( client ) ) &&
|
466 |
( !clients.contains( client ) ) ) { |
|
467 |
// Add the client to the object brokers.
|
|
468 | 0 |
appearanceBroker.clientConnected( client.getClientID() ); |
469 | 0 |
objectBroker.clientConnected( client.getClientID() ); |
470 | 0 |
visibleObjectBroker.clientConnected( client.getClientID() ); |
471 |
|
|
472 |
// Tell all of the clients that a new client has connected.
|
|
473 | 0 |
broadcast( "connect: " + client.getClientID() );
|
474 |
|
|
475 |
// Remove the client from the list of connecting clients.
|
|
476 | 0 |
connectingClients.remove( client ); |
477 |
|
|
478 |
// Add the client to the list of connected clients.
|
|
479 | 0 |
clients.add( client ); |
480 |
|
|
481 |
// Send the new client a list of all the connected clients.
|
|
482 | 0 |
sendClientList( client ); |
483 |
} |
|
484 |
} |
|
485 |
|
|
486 |
|
|
487 |
/**
|
|
488 |
* Send a list of all the connected clients to the specified client.
|
|
489 |
*
|
|
490 |
*@param clientHandler the client to send the list to
|
|
491 |
*/
|
|
492 | 0 |
private void sendClientList( ClientHandler clientHandler ) { |
493 | 0 |
for ( int i = 0; i < clients.size(); i++ ) { |
494 | 0 |
ClientHandler client = ( ClientHandler ) clients.get( i ); |
495 | 0 |
clientHandler.writeLine( "connect: " + client.getClientID() );
|
496 |
} |
|
497 |
} |
|
498 |
|
|
499 |
|
|
500 |
/**
|
|
501 |
* Private inner class for tracking the state of a connecting client.
|
|
502 |
*
|
|
503 |
*@author dusty
|
|
504 |
*/
|
|
505 |
private class ConnectingClientState { |
|
506 |
/**
|
|
507 |
* This flag determines if the client has finished the texture
|
|
508 |
* initialization procedure. This flag must be set to true in order for
|
|
509 |
* the client to finish connecting to the world.
|
|
510 |
*/
|
|
511 |
private boolean texturesComplete = false; |
|
512 |
|
|
513 |
|
|
514 |
/**
|
|
515 |
* This method indicates that the client has finished the texture
|
|
516 |
* initialization procedure.
|
|
517 |
*/
|
|
518 | 0 |
public void texturesFinished() { |
519 | 0 |
texturesComplete = true;
|
520 |
} |
|
521 |
|
|
522 |
|
|
523 |
/**
|
|
524 |
* This method determines if the client is ready to be connected. It
|
|
525 |
* will only return true if all of the flags determining client
|
|
526 |
* readiness have also been set to true.
|
|
527 |
*
|
|
528 |
*@return true if the client is ready to connect, false otherwise
|
|
529 |
*/
|
|
530 | 0 |
public boolean clientReady() { |
531 | 0 |
return texturesComplete;
|
532 |
} |
|
533 |
} |
|
534 |
|
|
535 |
|
|
536 |
/**
|
|
537 |
* Private inner class implementing the <code>CommandProcessor</code>
|
|
538 |
* interface for dealing with the "newLocation" command sent from the
|
|
539 |
* client.
|
|
540 |
*
|
|
541 |
*@author dusty
|
|
542 |
*/
|
|
543 |
private class NewLocationCommandProcessor implements CommandProcessor { |
|
544 |
/**
|
|
545 |
* The prefix for the command handled by this processor.
|
|
546 |
*/
|
|
547 |
private static final String PREFIX = "newLocation:"; |
|
548 |
|
|
549 |
|
|
550 |
/**
|
|
551 |
* Returns the command prefix used to recognize commands that this
|
|
552 |
* processor can handle.
|
|
553 |
*
|
|
554 |
*@return the command prefix
|
|
555 |
*/
|
|
556 | 0 |
public String getCommandPrefix() {
|
557 | 0 |
return PREFIX;
|
558 |
} |
|
559 |
|
|
560 |
|
|
561 |
/**
|
|
562 |
* Process a command matching the command prefix established by the
|
|
563 |
* <code>getCommandPrefix()</code> method.
|
|
564 |
*
|
|
565 |
*@param command the command to process
|
|
566 |
*@param extraData extra data that isn't part of the command
|
|
567 |
* but may be needed for dealing with the command (such as the ID
|
|
568 |
* of the client that sent the command)
|
|
569 |
*@throws VRMooParseException for any parsing errors while processing
|
|
570 |
* the command
|
|
571 |
*/
|
|
572 | 0 |
public void processCommand( String command, String extraData ) |
573 |
throws VRMooParseException {
|
|
574 | 0 |
int clientId = ParserUtility.parseInt( extraData );
|
575 | 0 |
ClientHandler client = AllClients.getClientByID( clientId ); |
576 |
|
|
577 | 0 |
if ( clients.contains( client ) ) {
|
578 | 0 |
String location = |
579 |
command.substring( PREFIX.length() ).trim(); |
|
580 | 0 |
broadcast( "newClientLocation: [" +
|
581 |
clientId + "] " + location );
|
|
582 |
} |
|
583 |
} |
|
584 |
} |
|
585 |
|
|
586 |
|
|
587 |
/**
|
|
588 |
* Private inner class implementing the <code>CommandProcessor</code>
|
|
589 |
* interface for dealing with the "avatar" command sent from the client.
|
|
590 |
*
|
|
591 |
*@author dusty
|
|
592 |
*/
|
|
593 |
private class AvatarCommandProcessor implements CommandProcessor { |
|
594 |
/**
|
|
595 |
* The prefix for the command handled by this processor.
|
|
596 |
*/
|
|
597 |
private static final String PREFIX = "avatar:"; |
|
598 |
|
|
599 |
|
|
600 |
/**
|
|
601 |
* Returns the command prefix used to recognize commands that this
|
|
602 |
* processor can handle.
|
|
603 |
*
|
|
604 |
*@return the command prefix
|
|
605 |
*/
|
|
606 | 0 |
public String getCommandPrefix() {
|
607 | 0 |
return PREFIX;
|
608 |
} |
|
609 |
|
|
610 |
|
|
611 |
/**
|
|
612 |
* Process a command matching the command prefix established by the
|
|
613 |
* <code>getCommandPrefix()</code> method.
|
|
614 |
*
|
|
615 |
*@param command the command to process
|
|
616 |
*@param extraData extra data that isn't part of the command
|
|
617 |
* but may be needed for dealing with the command (such as the ID
|
|
618 |
* of the client that sent the command)
|
|
619 |
*@throws VRMooParseException for any parsing errors while processing
|
|
620 |
* the command
|
|
621 |
*/
|
|
622 | 0 |
public void processCommand( String command, String extraData ) |
623 |
throws VRMooParseException {
|
|
624 | 0 |
int clientId = ParserUtility.parseInt( extraData );
|
625 | 0 |
ClientHandler client = AllClients.getClientByID( clientId ); |
626 | 0 |
String avatarData = |
627 |
command.substring( PREFIX.length() ).trim(); |
|
628 |
|
|
629 | 0 |
if ( clients.contains( client ) ||
|
630 |
( connectingClients.containsKey( client ) ) ) { |
|
631 |
//Ensure that no files for this client exist
|
|
632 | 0 |
File oldAv = FileUtility.getImageFile(avatarDirectory + |
633 |
"/client" + clientId);
|
|
634 | 0 |
if (oldAv != null) { |
635 | 0 |
oldAv.delete(); |
636 |
} |
|
637 | 0 |
int delimiter = avatarData.indexOf( "," ); |
638 |
//ext is the extension (png, jpg, gif) sent from client
|
|
639 | 0 |
String ext = avatarData.substring( 0, delimiter ).trim( ); |
640 | 0 |
String base64Data = |
641 |
avatarData.substring( delimiter + 1 ).trim( ); |
|
642 | 0 |
File avFile = new File(
|
643 |
avatarDirectory + "/client" + clientId + "." + ext); |
|
644 |
//Save client avatar
|
|
645 | 0 |
byte[ ] data = Base64Utility.toBinary( base64Data );
|
646 | 0 |
try
|
647 |
{ |
|
648 | 0 |
FileUtility.ensureDirectoryExists( |
649 |
new File(avatarDirectory));
|
|
650 | 0 |
avFile.createNewFile(); |
651 | 0 |
FileUtility.writeFile( avFile, data ); |
652 |
} |
|
653 |
catch ( Exception e )
|
|
654 |
{ |
|
655 | 0 |
e.printStackTrace( ); |
656 |
} |
|
657 | 0 |
broadcast( "world: newAvatar: [" +
|
658 |
clientId + "] " + avatarData );
|
|
659 |
} |
|
660 |
} |
|
661 |
} |
|
662 |
|
|
663 |
|
|
664 |
/**
|
|
665 |
* Private inner class implementing the <code>CommandProcessor</code>
|
|
666 |
* interface for dealing with the "sendCommand" command sent from the
|
|
667 |
* <code>AppearanceDataBroker</code>.
|
|
668 |
*
|
|
669 |
*@author dusty
|
|
670 |
*/
|
|
671 |
private class SendCommandCommandProcessor implements CommandProcessor { |
|
672 |
/**
|
|
673 |
* The prefix for the command handled by this processor.
|
|
674 |
*/
|
|
675 |
private static final String PREFIX = "sendCommand:"; |
|
676 |
|
|
677 |
|
|
678 |
/**
|
|
679 |
* Returns the command prefix used to recognize commands that this
|
|
680 |
* processor can handle.
|
|
681 |
*
|
|
682 |
*@return the command prefix
|
|
683 |
*/
|
|
684 | 0 |
public String getCommandPrefix() {
|
685 | 0 |
return PREFIX;
|
686 |
} |
|
687 |
|
|
688 |
|
|
689 |
/**
|
|
690 |
* Process a command matching the command prefix established by the
|
|
691 |
* <code>getCommandPrefix()</code> method.
|
|
692 |
*
|
|
693 |
*@param command the command to process
|
|
694 |
*@param extraData extra data that isn't part of the command but
|
|
695 |
* may be needed for dealing with the command (such as the ID of
|
|
696 |
* the client that sent the command)
|
|
697 |
*@throws VRMooException for any errors while processing the command
|
|
698 |
*/
|
|
699 | 0 |
public void processCommand( String command, String extraData ) |
700 |
throws VRMooException {
|
|
701 | 0 |
String sendCommand = command.substring( PREFIX.length() ).trim(); |
702 |
|
|
703 | 0 |
if ( extraData == null ) { |
704 | 0 |
broadcast( sendCommand ); |
705 |
} |
|
706 |
else {
|
|
707 | 0 |
int[] clients = ParserUtility.parseIntArray( extraData );
|
708 |
|
|
709 | 0 |
for ( int i = 0; i < clients.length; i++ ) { |
710 | 0 |
ClientHandler clientHandler = |
711 |
AllClients.getClientByID( clients[i] ); |
|
712 | 0 |
clientHandler.writeLine( sendCommand ); |
713 |
} |
|
714 |
} |
|
715 |
} |
|
716 |
} |
|
717 |
} |
|
718 |
|
|