Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: marauroa/game/GameServerManager.java


1   /* $Id: GameServerManager.java,v 1.23 2003/12/12 16:33:30 arianne_rpg Exp $ */
2   /***************************************************************************
3    *                      (C) Copyright 2003 - Marauroa                      *
4    ***************************************************************************
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   ***************************************************************************/
13  package marauroa.game;
14  
15  import java.util.*;
16  import java.io.*;
17  
18  import marauroa.net.*;
19  import marauroa.*;
20  
21  /** The GameServerManager is a active entity of the marauroa.game package,
22   *  it is in charge of processing all the messages and modify PlayerEntry Container accordingly. */
23  public class GameServerManager extends Thread
24    {
25    private NetworkServerManager netMan;  
26    private RPServerManager rpMan;
27    private PlayerEntryContainer playerContainer;
28    
29    /** The thread will be running while keepRunning is true */
30    private boolean keepRunning;
31    /** isFinished is true when the thread has really exited. */
32    private boolean isfinished;
33    
34    /** Constructor that initialize also the RPManager 
35     *  @param netMan a NetworkServerManager instance. */
36    public GameServerManager(NetworkServerManager netMan)
37      {
38      super("GameServerManager");
39      marauroad.trace("GameServerManager",">");    
40      
41      keepRunning=true;    
42      this.netMan=netMan;
43      playerContainer=PlayerEntryContainer.getContainer();    
44      rpMan=new RPServerManager(netMan);
45      
46      start();
47          
48      marauroad.trace("GameServerManager","<");
49      }
50  
51    /** Constructor that initialize also the RPManager 
52     *  @param netMan a NetworkServerManager instance.
53     *  @param rpMan a RPManager instance */
54    public GameServerManager(NetworkServerManager netMan, RPServerManager rpMan)
55      {
56      super("GameServerManager");
57      marauroad.trace("GameServerManager",">");    
58      
59      keepRunning=true;    
60      this.netMan=netMan;
61      this.rpMan=rpMan;
62      playerContainer=PlayerEntryContainer.getContainer();    
63      
64      start();
65          
66      marauroad.trace("GameServerManager","<");
67      }
68  
69    public void finish()
70      {
71      marauroad.trace("GameServerManager::finish",">");
72      
73      rpMan.finish();
74      keepRunning=false;
75  
76      while(isfinished==false)
77        {
78        try
79          {
80          Thread.sleep(1000);
81          }
82        catch(java.lang.InterruptedException e)
83          {
84          }
85        }
86      
87      marauroad.trace("GameServerManager::finish","<");
88      }
89      
90    public void run()
91      {
92      marauroad.trace("GameServerManager::run",">");
93  
94      try
95        {
96        while(keepRunning)
97          {
98          Message msg=netMan.getMessage(TimeoutConf.GAMESERVER_MESSAGE_GET_TIMEOUT);
99         
100         if(msg!=null)
101           {
102           playerContainer.getLock().requestWriteLock();
103               
104           switch(msg.getType()) 
105             {
106             case Message.TYPE_C2S_LOGIN:
107               marauroad.trace("GameServerManager::run","D","Processing C2S Login Message");
108               processLoginEvent((MessageC2SLogin)msg);
109               break;
110             case Message.TYPE_C2S_CHOOSECHARACTER:
111               marauroad.trace("GameServerManager::run","D","Processing C2S Choose Character Message");
112               processChooseCharacterEvent((MessageC2SChooseCharacter)msg);
113               break;
114             case Message.TYPE_C2S_LOGOUT:
115               marauroad.trace("GameServerManager::run","D","Processing C2S Logout Message");
116               processLogoutEvent((MessageC2SLogout)msg);
117               break;
118             case Message.TYPE_C2S_ACTION:
119               marauroad.trace("GameServerManager::run","D","Processing C2S Action Message");
120               processActionEvent((MessageC2SAction)msg);
121               break;
122             case Message.TYPE_C2S_PERCEPTION_ACK:
123               marauroad.trace("GameServerManager::run","D","Processing C2S Perception ACK Message");
124               processPerceptionACKEvent((MessageC2SPerceptionACK)msg);
125               break;
126             default:
127               marauroad.trace("GameServerManager::run","W","Unknown Message["+msg.getType()+"]");
128               break;
129             }
130             
131           playerContainer.getLock().releaseLock();
132           }
133         }
134       }
135     finally
136       {
137       isfinished=true;
138       marauroad.trace("GameServerManager::run","<");
139       }
140     }
141   
142   private static class ServerInfo
143     {
144     static private String typeGame;
145     static private String name;
146     static private String version;
147     static private String contact;
148     
149     static
150       {
151       marauroad.trace("GameServerManager::ServerInfo::(static)",">");
152       
153       try
154         {
155       Configuration conf=Configuration.getConfiguration();
156       
157       typeGame=conf.get("server_typeGame");
158       name=conf.get("server_name");
159       version=conf.get("server_version");
160       contact=conf.get("server_contact");
161       }
162     catch(Exception e)
163       {
164         marauroad.trace("GameServerManager::ServerInfo::(static)","X",e.getMessage());
165         marauroad.trace("GameServerManager::ServerInfo::(static)","!","ABORT: Unable to load Server info");
166         System.exit(-1);
167       }    
168     finally
169       {
170         marauroad.trace("GameServerManager::ServerInfo::(static)","<");
171       }
172       }
173     
174     public static String[] get()
175       {
176       String[] result=new String[4];
177       
178       result[0]=typeGame;
179       result[1]=name;
180       result[2]=version;
181       result[3]=contact;      
182       
183       return result;
184       }
185     }  
186     
187   private void processLoginEvent(MessageC2SLogin msg)
188     {
189     marauroad.trace("GameServerManager::processLoginEvent",">");
190     try
191       {
192       if(playerContainer.hasRuntimePlayer(msg.getClientID()) || playerContainer.hasPlayer(msg.getUsername()))
193         {
194         /* Error: Player is already logged. */
195         marauroad.trace("GameServerManager::processLoginEvent","W","Client("+msg.getAddress().toString()+") trying to login twice");
196 
197         /* Notify player of the event. */
198         MessageS2CLoginNACK msgLoginNACK=new MessageS2CLoginNACK(msg.getAddress(),MessageS2CLoginNACK.UNKNOWN_REASON);
199         netMan.addMessage(msgLoginNACK);
200         return;
201         }
202             
203       if(playerContainer.size()==GameConst.MAX_NUMBER_PLAYERS)
204         {
205         /* Error: Too many clients logged on the server. */
206         marauroad.trace("GameServerManager::processLoginEvent","W","Server is full, Client("+msg.getAddress().toString()+") can't login");
207       
208         /* Notify player of the event. */
209         MessageS2CLoginNACK msgLoginNACK=new MessageS2CLoginNACK(msg.getAddress(),MessageS2CLoginNACK.SERVER_IS_FULL);
210         netMan.addMessage(msgLoginNACK);
211         return;
212         }
213       
214     if(playerContainer.verifyAccount(msg.getUsername(),msg.getPassword()))
215       {
216         marauroad.trace("GameServerManager::processLoginEvent","D","Correct username/password");
217 
218       /* Correct: The login is correct */
219       int clientid=playerContainer.addRuntimePlayer(msg.getUsername(),msg.getAddress());
220       playerContainer.addLoginEvent(msg.getUsername(),msg.getAddress(),true);
221         
222       /* Send player the Login ACK message */
223       MessageS2CLoginACK msgLoginACK=new MessageS2CLoginACK(msg.getAddress());
224       msgLoginACK.setClientID(clientid);
225       netMan.addMessage(msgLoginACK);
226 
227     /* Send player the ServerInfo */
228       MessageS2CServerInfo msgServerInfo=new MessageS2CServerInfo(msg.getAddress(),ServerInfo.get());
229       msgServerInfo.setClientID(clientid);
230       netMan.addMessage(msgServerInfo);
231         
232       /* Build player character list and send it to client */
233       String[] characters=playerContainer.getCharacterList(clientid);
234       MessageS2CCharacterList msgCharacters=new MessageS2CCharacterList(msg.getAddress(),characters);
235       msgCharacters.setClientID(clientid);
236       netMan.addMessage(msgCharacters);
237 
238       playerContainer.changeRuntimeState(clientid,PlayerEntryContainer.STATE_LOGIN_COMPLETE);
239       }
240     else
241       {
242         marauroad.trace("GameServerManager::processLoginEvent","W","Incorrect username/password");
243         if(playerContainer.hasPlayer(msg.getUsername()))
244           {
245         playerContainer.addLoginEvent(msg.getUsername(),msg.getAddress(),false);
246         }
247       else
248         {
249           marauroad.trace("GameServerManager::processLoginEvent","W","Incorrect username: Can't add login event.");
250         }
251 
252       /* Send player the Login NACK message */
253       MessageS2CLoginNACK msgLoginNACK=new MessageS2CLoginNACK(msg.getAddress(),MessageS2CLoginNACK.USERNAME_WRONG);
254       netMan.addMessage(msgLoginNACK);
255       }
256     }
257     catch(Exception e)      
258       {
259       marauroad.trace("GameServerManager::processLoginEvent","X",e.getMessage());
260       }
261     finally
262       {
263       marauroad.trace("GameServerManager::processLoginEvent","<");      
264       }
265     }
266 
267   private void processChooseCharacterEvent(MessageC2SChooseCharacter msg)
268     {
269     marauroad.trace("GameServerManager::processChooseCharacterEvent",">");
270    
271     try
272       {
273       int clientid=msg.getClientID();
274       
275     if(!playerContainer.hasRuntimePlayer(clientid))
276       {
277       /* Error: Player didn't login. */
278         marauroad.trace("GameServerManager::processChooseCharacterEvent","W","Client("+msg.getAddress().toString()+") has not login yet");
279       return;
280       }
281       
282     if(playerContainer.getRuntimeState(clientid)!=playerContainer.STATE_LOGIN_COMPLETE)
283       {
284       /* Error: Player has not completed login yet, or he/she has logout already. */
285         marauroad.trace("GameServerManager::processChooseCharacterEvent","W","Client("+msg.getAddress().toString()+") has not login yet");
286       return;
287       }
288       
289     if(!playerContainer.verifyRuntimePlayer(clientid,msg.getAddress()))
290       {
291       /* Error: Player has not correct IP<->clientid relation */
292         marauroad.trace("GameServerManager::processChooseCharacterEvent","E","Client("+msg.getAddress().toString()+") has not correct IP<->clientid relation");
293       return;      
294       }
295         
296     if(playerContainer.hasCharacter(clientid,msg.getCharacter()))
297       {
298         marauroad.trace("GameServerManager::processChooseCharacterEvent","D","Client("+msg.getAddress().toString()+") has character("+msg.getCharacter()+")");
299         
300         /* We set the character in the runtime info */
301         playerContainer.setChoosenCharacter(clientid,msg.getCharacter());
302 
303       /* We restore back the character to the world */
304       RPObject object=playerContainer.getRPObject(clientid,msg.getCharacter());
305       rpMan.addRPObject(object);      
306       
307       playerContainer.changeRuntimeState(clientid,playerContainer.STATE_GAME_BEGIN);
308 
309       /* Correct: Character exist */
310       MessageS2CChooseCharacterACK msgChooseCharacterACK=new MessageS2CChooseCharacterACK(msg.getAddress(),new RPObject.ID(object));
311       msgChooseCharacterACK.setClientID(clientid);
312       netMan.addMessage(msgChooseCharacterACK);
313       }
314     else
315       {
316         marauroad.trace("GameServerManager::processChooseCharacterEvent","W","Client("+msg.getAddress().toString()+") hasn't character("+msg.getCharacter()+")");
317 
318       playerContainer.changeRuntimeState(clientid,playerContainer.STATE_LOGIN_COMPLETE);
319 
320       /* Error: There is no such character */
321       MessageS2CChooseCharacterNACK msgChooseCharacterNACK=new MessageS2CChooseCharacterNACK(msg.getAddress());
322       msgChooseCharacterNACK.setClientID(clientid);
323       netMan.addMessage(msgChooseCharacterNACK);
324       }
325       }
326     catch(Exception e)      
327       {
328       marauroad.trace("GameServerManager::processChooseCharacterEvent","X",e.getMessage());
329       }
330     finally
331       {    
332       marauroad.trace("GameServerManager::processChooseCharacterEvent","<");
333       }
334     }
335 
336   private void processLogoutEvent(MessageC2SLogout msg)
337     {
338     marauroad.trace("GameServerManager::processLogoutEvent",">");
339     
340     try
341       {
342       int clientid=msg.getClientID();
343       
344     if(!playerContainer.hasRuntimePlayer(clientid))
345       {
346       /* Error: Player didn't login. */
347         marauroad.trace("GameServerManager::processLogoutEvent","W","Client("+msg.getAddress().toString()+") has not login yet");
348       return;
349       }
350       
351     if(!playerContainer.verifyRuntimePlayer(clientid,msg.getAddress()))
352       {
353       /* Error: Player has not correct IP<->clientid relation */
354         marauroad.trace("GameServerManager::processLogoutEvent","E","Client("+msg.getAddress().toString()+") has not correct IP<->clientid relation");
355       return;      
356       }
357     
358     if(playerContainer.getRuntimeState(clientid)==PlayerEntryContainer.STATE_GAME_BEGIN)
359       {
360       RPObject.ID id=playerContainer.getRPObjectID(clientid);    
361         RPObject object=rpMan.getRPObject(id);      
362       rpMan.removeRPObject(id);
363       
364         /* NOTE: Set the Object so that it is stored in Database */
365         playerContainer.setRPObject(clientid,object);  
366         }
367       else
368         {
369         marauroad.trace("GameServerManager::processLogoutEvent","D","Player trying to logout without choosing character");
370         }
371           
372     playerContainer.removeRuntimePlayer(clientid);
373     
374     /* Send Logout ACK message */
375     MessageS2CLogoutACK msgLogout=new MessageS2CLogoutACK(msg.getAddress());
376       msgLogout.setClientID(clientid);
377     netMan.addMessage(msgLogout);
378       }
379     catch(Exception e)      
380       {
381       marauroad.trace("GameServerManager::processLogoutEvent","X",e.getMessage());
382       }
383     finally
384       {
385       marauroad.trace("GameServerManager::processLogoutEvent","<");
386       }
387     }
388     
389   static int lastActionIdGenerated=0;
390     
391   private void processActionEvent(MessageC2SAction msg)
392     {
393     marauroad.trace("GameServerManager::processActionEvent",">");
394     
395     try
396       {
397       int clientid=msg.getClientID();
398       
399     if(!playerContainer.hasRuntimePlayer(clientid))
400       {
401       /* Error: Player didn't login. */
402         marauroad.trace("GameServerManager::processActionEvent","W","Client("+msg.getAddress().toString()+") has not login yet");
403       return;
404       }
405         
406     if(playerContainer.getRuntimeState(clientid)!=playerContainer.STATE_GAME_BEGIN)
407       {
408       /* Error: Player has not choose a character yey. */
409         marauroad.trace("GameServerManager::processActionEvent","W","Client("+msg.getAddress().toString()+") has not chose a character yet");
410       return;
411       }
412 
413     if(!playerContainer.verifyRuntimePlayer(clientid,msg.getAddress()))
414       {
415       /* Error: Player has not correct IP<->clientid relation */
416         marauroad.trace("GameServerManager::processActionEvent","E","Client("+msg.getAddress().toString()+") has not correct IP<->clientid relation");
417       return;      
418       }
419     
420     /* Send the action to RP Manager */
421     RPAction action=msg.getRPAction();
422     
423     /* Enforce source_id and action_id*/
424     RPObject.ID id=playerContainer.getRPObjectID(clientid);
425     action.put("source_id",id.getObjectID());
426     action.put("action_id",lastActionIdGenerated);
427     
428     rpMan.addRPAction(action);
429 
430     /* Notify client that we recieved the action */
431     MessageS2CActionACK msgAction=new MessageS2CActionACK(msg.getAddress(),lastActionIdGenerated);
432       msgAction.setClientID(clientid);
433     netMan.addMessage(msgAction);    
434     
435     ++lastActionIdGenerated;
436       }
437     catch(Exception e)      
438       {
439       marauroad.trace("GameServerManager::processActionEvent","X",e.getMessage());
440       }
441     finally
442       {
443       marauroad.trace("GameServerManager::processActionEvent","<");
444       }
445     }       
446 
447   private void processPerceptionACKEvent(MessageC2SPerceptionACK msg)
448     {
449     marauroad.trace("GameServerManager::processPerceptionACKEvent",">");
450     
451     try
452       {
453       int clientid=msg.getClientID();
454       
455     if(!playerContainer.hasRuntimePlayer(clientid))
456       {
457       /* Error: Player didn't login. */
458         marauroad.trace("GameServerManager::processPerceptionACKEvent","W","Client("+msg.getAddress().toString()+") has not login yet");
459       return;
460       }
461         
462     if(playerContainer.getRuntimeState(clientid)!=playerContainer.STATE_GAME_BEGIN)
463       {
464       /* Error: Player has not choose a character yey. */
465         marauroad.trace("GameServerManager::processPerceptionACKEvent","W","Client("+msg.getAddress().toString()+") has not chose a character yet");
466       return;
467       }
468 
469     if(!playerContainer.verifyRuntimePlayer(clientid,msg.getAddress()))
470       {
471       /* Error: Player has not correct IP<->clientid relation */
472         marauroad.trace("GameServerManager::processPerceptionACKEvent","E","Client("+msg.getAddress().toString()+") has not correct IP<->clientid relation");
473       return;      
474       }
475 
476     playerContainer.updateTimestamp(clientid);
477       }
478     catch(Exception e)      
479       {
480       marauroad.trace("GameServerManager::processPerceptionACKEvent","X",e.getMessage());
481       }
482     finally
483       {
484       marauroad.trace("GameServerManager::processPerceptionACKEvent","<");
485       }
486     }         
487   }