Module bzServer
[frames] | no frames]

Source Code for Module bzServer

   1  ##bzServer.py Server class for BZoo world hosting. 
   2  ##Copyright (C) 2006  Jean-Baptiste PERIN 
   3  ## 
   4  ##This program is free software; you can redistribute it and/or 
   5  ##modify it under the terms of the GNU General Public License 
   6  ##as published by the Free Software Foundation; either version 2 
   7  ##of the License, or (at your option) any later version. 
   8  ## 
   9  ##This program is distributed in the hope that it will be useful, 
  10  ##but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11  ##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  12  ##GNU General Public License for more details. 
  13  ## 
  14  ##You should have received a copy of the GNU General Public License 
  15  ##along with this program; if not, write to the Free Software 
  16  ##Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. 
  17  """ 
  18   This module contains Bzoo Server side objects. 
  19   
  20   Each message is an object providing encoding and decoding convenience for network transportation. 
  21   
  22   Client Messages 
  23   =============== 
  24     This is a paragraph in section 1. 
  25   
  26     Periodic messages 
  27     ----------------- 
  28     such as Postion and Oriention Report 
  29   
  30     Asynchronous messages 
  31     --------------------- 
  32     such as message broadcasting, objetct activation,  
  33   
  34   
  35   Server Messages 
  36   =============== 
  37     Use numerical constant instead of string for indexing received message. 
  38   
  39     Periodic messages 
  40     ----------------- 
  41     such as players'positions and orientions Report 
  42   
  43     Asynchronous messages 
  44     --------------------- 
  45     such as message broadcasting, objetct activation. 
  46      
  47  """ 
  48   
  49  import socket 
  50   
  51  import bzProtocol 
  52  from bzProtocol import bzProtocol 
  53   
  54  import bzPicture 
  55  from bzPicture import bzPicture 
  56   
  57  import bzMessage 
  58  import bzTools 
  59  import time 
  60  import bzInventory 
  61  import bzException 
  62  import sys 
  63   
64 -class bzUser:
65 """ 66 This object deals with socket connection and low level data exchanges 67 68 @ivar pseudo: the pseudo of the player. 69 @type pseudo: string. 70 @ivar password: the password of the player 71 @type password: string. 72 @ivar current_id: the current identifier of the player 73 @type current_id: integer 74 @ivar connected: indicates if the player is currently connected. 75 @type connected: boolean 76 @ivar avatar: the avatar id choosen by the player. 77 @type avatar: integer. 78 @ivar last_connection_date: 79 @type last_connection_date: 80 @ivar last_disconnection_date: 81 @type last_disconnection_date: 82 @ivar last_saved_position: the position of the player when saved for the last time. 83 @type last_saved_position: 1*3 vector. 84 @ivar last_saved_orientation: 85 @type last_saved_orientation: 3*3 matrix. 86 @ivar last_saved_heading: 87 @type last_saved_heading: 3*3 matrix 88 @ivar last_saved_state: 89 @type last_saved_state: integer. 90 @ivar last_saved_action: 91 @type last_saved_action: integer. 92 @ivar last_saved_scene: 93 @type last_saved_scene: integer. 94 @ivar current_inventory: 95 @type current_inventory: L{bzInventory.bzInventory} 96 @ivar last_saved_inventory: 97 @type last_saved_inventory: L{bzInventory.bzInventory} 98 """ 99
100 - def __init__(self, pseudo, password):
101 """ 102 @param pseudo: the pseudo of the user 103 @type pseudo: string. 104 @param password: password of the user 105 @type password: string. 106 @return: N/A 107 @rtype: L{bzUser} 108 """ 109 self.pseudo = pseudo 110 self.password = password 111 self.current_id = -1 112 self.connected = False 113 self.avatar = None 114 self.last_connection_date = time.localtime() 115 self.last_disconnection_date = 0 116 self.last_saved_position = [0.0, 0.0, 4.0] 117 self.last_saved_orientation = [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]] 118 self.last_saved_heading = [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]] 119 self.last_saved_state = 0 120 self.last_saved_action = 0 121 self.last_saved_scene = 0 122 123 self.current_inventory = bzInventory.bzInventory() 124 self.last_saved_inventory = bzInventory.bzInventory()
125 #print "bzUserInit self.last_saved_inventory = ", self.last_saved_inventory.getContent() 126 127 128
129 - def __str__(self):
130 s= '' 131 s = s + "pseudo = %s, password = %s, cur_id = %d, last_connection = %s\n"%(self.pseudo, self.password, self.current_id, self.last_connection_date ) 132 s = s + "pos = %s,\n ori = %s,\n heading = %s,\n state = %d,\n action = %d,\n scene = %d\n"%(self.last_saved_position, self.last_saved_orientation, self.last_saved_heading, self.last_saved_state, self.last_saved_action, self.last_saved_scene) 133 s = s + "inventory = %s\n"%(self.current_inventory.getContent()) 134 return s
135
136 - def __repr__(self):
137 return ''
138
139 - def getPseudo(self):
140 """ 141 returns the pseudo of the player 142 @return: the pseudo of the player. 143 @rtype: string. 144 """ 145 return (self.pseudo)
146
147 - def getInventory(self):
148 """ 149 returns the inventory of the user 150 @return: the inventory of the user. 151 @rtype: L{bzInventory.bzInventory}. 152 """ 153 return (self.current_inventory)
154
155 - def hasAvatar(self):
156 """ 157 indicates if the user has already choosen an avatar 158 @return: True if user has selected an avatar, False otherwise 159 @rtype: boolean. 160 """ 161 return (self.avatar != None)
162
163 - def getAvatar(self):
164 """ 165 returns the identifier of the avatar choosen by user. 166 @return: the identifier of the avatar choosen by user. 167 @rtype: integer. 168 """ 169 return(self.avatar)
170
171 - def getPassword(self):
172 """ 173 returns the password of user. 174 @return: the password used to authenticate the user. 175 @rtype: string. 176 """ 177 return (self.password)
178
179 - def setConnected(self, current_id):
180 """ 181 Changes the connection status of user to 'Connected'. 182 This function is called when user log in. 183 @param current_id: the id the player was given at connection. 184 @type current_id: string. 185 """ 186 self.current_id = current_id 187 self.connected = True 188 self.last_connection_date = time.localtime()
189
190 - def setDisconnected(self):
191 """ 192 Changes the connection status of user to 'Disconnected'. 193 This function is called when user log off. 194 """ 195 self.current_id = -1 196 self.connected = False 197 self.last_disconnection_date = time.localtime()
198
199 - def getCurrentId(self):
200 """ 201 returns the user current id (-1 if user is not connected). 202 @return: the user current id. 203 @rtype: integer. 204 """ 205 return (self.current_id)
206
207 - def isConnected (self):
208 """ 209 Indicates whether the player is connected or not. 210 @return: True if the user is connected, False otherwise. 211 @rtype: boolean. 212 """ 213 if self.current_id == -1: 214 return (False) 215 else: 216 return (True)
217
218 - def setAvatar (self, avatar):
219 """ 220 Set the avatar id choosen by the user. 221 This function is typically called when user choose his avatar. 222 """ 223 self.avatar = avatar
224
225 - def save(self, position = [0.0, 0.0, 0.0], 226 orientation = [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 227 heading = [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 228 scene = 0, 229 inventory = None):
230 """ 231 Save information of user (position, orientation, scene number, inventory content). 232 User information that was saved can than be retrieved next time user connects. 233 @param position: the current position of the user. 234 @param position: 1*3 vector. 235 @param orientation: the current orientation of the user. 236 @param orientation: 3*3 matrix. 237 @param heading: the current heading of the user. 238 @param heading: 3*3 matrix. 239 @param scene: the scene id the user is currently in. 240 @param scene: integer. 241 @param inventory: the inventory of the user. 242 @param inventory: L{bzInventory.bzInventory} 243 """ 244 self.last_saved_position = position 245 self.last_saved_orientation = orientation 246 self.last_saved_heading = heading 247 self.last_saved_scene = scene 248 self.last_saved_inventory = bzInventory.bzInventory() #self.current_inventory 249 inv = inventory.getContent() 250 for ii in inv: 251 self.last_saved_inventory.add(ii[0], ii[1])
252 #print "save player.last_saved_inventory = ", self.last_saved_inventory.getContent() 253
254 - def saveInventory(self):
255 """ 256 Save player inventory with current known content. 257 """ 258 self.last_saved_inventory = bzInventory.bzInventory() #self.current_inventory 259 inv = self.current_inventory.getContent() 260 for ii in inv: 261 self.last_saved_inventory.add(ii[0], ii[1])
262 #self.last_saved_inventory = bzInventory.bzInventory(self.current_inventory.getContent()) #self.current_inventory 263 #print "saveInventory player.last_saved_inventory = ", self.last_saved_inventory.getContent() 264
265 - def getSavedPosition (self):
266 """ 267 Returns the last known position of user. 268 @return: the saved user position. 269 @rtype: integer. 270 """ 271 return self.last_saved_position
272
273 - def getSavedInventory (self):
274 """ 275 Returns the inventory the user had the last time he saved game. 276 @return: the last saved inventory. 277 @rtype: L{bzInventory.bzInventory}. 278 """ 279 #print "getSavedInventory player.last_saved_inventory = ", self.last_saved_inventory.getContent() 280 return self.last_saved_inventory
281
282 - def getSavedOrientation (self):
283 """ 284 Returns the last known orientation of user. 285 @return: the user orientation. 286 @rtype: 3*3 matrix. 287 """ 288 return self.last_saved_orientation
289
290 - def getSavedHeading (self):
291 """ 292 Returns the last known heading of user. 293 @return: the user heading. 294 @rtype: 3*3 matrix. 295 """ 296 return self.last_saved_heading
297
298 - def getSavedScene (self):
299 """ 300 Returns the id of the last scene the user saved in. 301 @return: the user scene id. 302 @rtype: integer. 303 """ 304 return self.last_saved_scene
305
306 -class bzMemory:
307 """ 308 This object deals server memory 309 310 @ivar users: the pseudo of the player. 311 @type users: List of L{bzUser}. 312 """
313 - def __init__(self):
314 self.users = {} 315 pass
316
317 - def __str__(self):
318 return ''
319
320 - def RegisterUser(self, user_name, password):
321 self.users[user_name] = bzUser(user_name,password) 322 self.users[user_name].setDisconnected() 323 return self.users[user_name]
324
325 - def GetUser(self, usr_pseudo):
326 usr = None 327 if usr_pseudo in self.users.keys(): 328 usr = self.users[usr_pseudo] 329 return (usr)
330
331 - def GetUserPassword(self, usr_pseudo):
332 return self.GetUser(usr_pseudo).getPassword()
333
334 -class bzServerSocket:
335 """ 336 A socket 337 338 @ivar hostname: the socket. 339 @type hostname: string. 340 @ivar port: the port number on which the server accept connection from. 341 @type port: integer. 342 @ivar socket: the socket. 343 @type socket: socket.socket. 344 @ivar sa: socket address. 345 @type sa: sockaddr. 346 """ 347
348 - def __init__ (self, hostname, port):
349 self.hostname, self.port = hostname, port 350 351 self.socket = None 352 self.sa = None 353 354 355 for res in socket.getaddrinfo(self.hostname, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): 356 af, socktype, proto, canonname, self.sa = res 357 try: 358 self.socket = socket.socket(af, socktype, proto) 359 except socket.error, msg: 360 print "socket error" 361 self.socket = None 362 continue 363 try: 364 self.socket.bind(self.sa) 365 self.socket.listen(1) 366 except socket.error, msg: 367 print "bind error" 368 self.socket.close() 369 self.socket = None 370 continue 371 break 372 if self.socket is None: 373 print 'could not open socket' 374 self.socket.setblocking(0)
375 376
377 - def __repr__ (self, ):
378 return ""
379 380 381
382 -class bzServerConnection:
383 """ 384 A connection with a client 385 386 @ivar connected: . 387 @type connected: boolean. 388 @ivar connection: . 389 @type connection: socket. 390 @ivar address: . 391 @type address: sockaddr. 392 @ivar receive_status: . 393 @type receive_status: boolean. 394 @ivar serversocket: . 395 @type serversocket: socket. 396 """
397 - def __init__ (self, serversocket):
398 self.connected = False 399 self.connection = None 400 self.address = None 401 self.receive_status = False 402 self.serversocket = serversocket
403
404 - def NewConnection(self):
405 """ 406 Check for connection request. 407 Socket is supposed not to be in blocking mode. 408 @return: True if a new connection was received 409 @rtype: Boolean 410 """ 411 try: 412 [self.connection, self.address] = self.serversocket.accept() 413 print "connection from ", self.address 414 except: 415 [self.connection, self.address] = [None, None] 416 pass 417 418 if self.connection != None: 419 self.connected = True 420 else: 421 self.connected = False 422 return (self.connected)
423 424
425 - def ReceiveData (self):
426 """ 427 Attempts to receive a data packet from a client. 428 Socket is supposed not to be in blocking mode. 429 @return: received data if attempt succeed.. None otherwise 430 @rtype: Byte array or None 431 """ 432 data = None 433 try: 434 self.receive_status = False 435 data = self.connection.recv(1024) 436 self.receive_status = True 437 except socket.error, (errno, msg): 438 #print "Exception %s %s while receiving "%(errno,msg) 439 if (errno == 10054) or (errno == 10053): # TODO: find the corresponding symbolic constant ? 440 self.receive_status = False 441 self.connected=False 442 return data
443
444 - def SendData (self, data):
445 """ 446 Send a raw data packet to client. 447 @param data: the data to send to the client. 448 @type data: Byte Array. 449 """ 450 try: 451 self.connection.send(data) 452 except socket.error, (errno, msg): 453 #print "Exception %s %s while sending"%(errno,msg) 454 if (errno == 10054) or (errno == 10053): # TODO: find the corresponding symbolic constant ? 455 self.connected=False
456 457
458 - def CloseConnection (self):
459 """ 460 Close connection with client. 461 """ 462 self.connection.close() 463 self.connected = False
464 465
466 - def Connected (self):
467 """ 468 Gives the connection status of the socket. 469 @return: a boolean indicating whether socket is connected or not 470 @rtype: Boolean 471 """ 472 return self.connected
473 474
475 -class bzServer(bzProtocol, bzServerSocket,bzPicture):
476 """ 477 A Bzoo server. 478 479 @ivar nb_max_client: The maximum number of accepted client. 480 @type nb_max_client: integer. 481 @ivar nb_client: The current number of connected client. 482 @type nb_client: integer. 483 @ivar connections: . 484 @type connections: list of L{bzServerConnection}. 485 @ivar pseudos: . 486 @type pseudos: list of string. 487 @ivar logged: . 488 @type logged: list of boolean. 489 @ivar positions: . 490 @type positions: list of 1*3 vector. 491 @ivar orientations: . 492 @type orientations: list of 3*3 matrix. 493 @ivar headings: . 494 @type headings: list of 3*3 matrix. 495 @ivar states: . 496 @type states: list of integer. 497 @ivar actions: . 498 @type actions: list of integer. 499 @ivar avatars: . 500 @type avatars: list of integer. 501 @ivar message_queue: . 502 @type message_queue: socket. 503 @ivar inventories: . 504 @type inventories: list of L{bzInventory.bzInventory}. 505 @ivar visible_client: . 506 @type visible_client: socket. 507 """ 508
509 - def __init__ (self, hostname='127.0.0.1', port=50000, nb_max_client=5):
510 """ 511 @param hostname: The server hostname or IP adress ("" for internet hosting, "127.0.0.1" for local hosting) 512 @type hostname: Character string. 513 @param port: The port the server will listen and accept connection on. 514 @type port: Integer 515 @param nb_max_client: The max number of player. 516 @type nb_max_client: Integer. 517 @return: N/A 518 @rtype: L{bzServer} 519 """ 520 self.nb_max_client = nb_max_client 521 self.nb_client = 0 522 self.current_client_id = 0 523 524 self.connections=[] 525 self.pseudos=[] 526 #self.passwords=[] 527 self.logged=[] 528 self.positions=[] 529 self.orientations=[] 530 self.headings=[] 531 self.states=[] 532 self.actions=[] 533 self.scenes=[] 534 self.avatars=[] 535 self.message_queue=[] 536 self.inventories=[] 537 538 self.visible_client=[[]] # indexed by scene number, contains list of client ids 539 540 bzServerSocket.__init__(self,hostname, port) 541 bzProtocol.__init__(self,) 542 bzPicture.__init__(self,) 543 544 self.ServerMemory = bzMemory() 545 546 self.addHandler(bzMessage.POSITION_REPORT_MESSAGE,self.PositionReportEvent) 547 self.addHandler(bzMessage.SAY_MESSAGE,self.SayMessageEvent) 548 self.addHandler(bzMessage.PRIVATE_SAY_MESSAGE,self.PrivateSayMessageEvent) 549 self.addHandler(bzMessage.GRAB_OBJECT_MESSAGE,self.GrabObjectEvent) 550 self.addHandler(bzMessage.ACTIVATE_OBJECT_MESSAGE,self.ActivateObjectEvent) 551 self.addHandler(bzMessage.RELEASE_OBJECT_MESSAGE, self.ReleaseObjectEvent) 552 self.addHandler(bzMessage.STORE_AVATAR_MESSAGE, self.StoreAvatarEvent) 553 self.addHandler(bzMessage.DECLARE_VAR_MESSAGE, self.DeclareVarEvent) 554 555 556 self.connections.append(bzServerConnection (self.socket))
557 558
559 - def __repr__ (self, ):
560 return ""
561
562 - def __rebuildVisibleClients__ (self):
563 self.visible_client=[[]] 564 if self.nb_client != 0: 565 self.visible_client=[[]] * (max(self.scenes)+1) 566 for i in range(max(self.scenes)+1): 567 self.visible_client[i]=[x for x in range(len(self.scenes)) if self.scenes[x]==i]
568 569 570
571 - def CloseConnection(self):
572 """ 573 Close connection with all client. 574 """ 575 idx_cnx =0 576 for co in self.connections: 577 if co.connected == True: 578 clt_pseudo = self.pseudos[idx_cnx] 579 self.ServerMemory.GetUser(clt_pseudo).setDisconnected() 580 # TODO: ajouter la sauvegarde des positions et inventaire 581 co.CloseConnection() 582 idx_cnx = idx_cnx + 1
583
584 - def SaveUser(self, client_id):
585 """ 586 Saves user information into server memory for retrieval at next connection. 587 @param client_id: the current user id 588 @type client_id: Character string. 589 """ 590 #print "Save User" 591 clt_pseudo = self.pseudos[client_id] 592 self.ServerMemory.GetUser(clt_pseudo).save ( 593 self.positions[client_id] , 594 self.orientations[client_id], 595 self.headings[client_id], 596 self.scenes[client_id] , 597 self.inventories[client_id])
598 599 ## def computeNewPseudo(self, pseudo): 600 ## """ 601 ## Compute a pseudo beginning by "pseudo" that is not yet in use on the Server. 602 ## @param pseudo: The radical of the pseudo. 603 ## @type pseudo: String. 604 ## @return: An unused pseudo. 605 ## @rtype: String. 606 ## """ 607 ## effpseudo = pseudo 608 ## idx = 0 609 ## while effpseudo in self.pseudos: 610 ## effpseudo = pseudo + ".%03d"%idx 611 ## idx = idx+1 612 ## return effpseudo 613
614 - def registerPseudo (self, pseudo):
615 """ 616 Create an entry into server's tables for a new user. 617 If the given pseudo is already in use on current Server, a new one is computed. 618 The given pseudo is used as a radical to which is added an index .Ex:: 619 Nick will become Nick.001 is Nick is already used. 620 @param pseudo: The asked pseudo of the new user. 621 @type pseudo: String. 622 @return: The effective pseudo of the player. 623 @rtype: String. 624 """ 625 effpseudo = pseudo 626 self.pseudos.append (effpseudo) 627 #self.passwords.append (effpseudo) 628 self.logged.append (False) 629 self.positions.append([0.0, 0.0, 4.0]) 630 self.orientations.append([[0.0, 1.0, 0.0],[-1.0, 0.0, 0.0],[0.0, 0.0, 1.0]]) 631 self.headings.append([[0.0, 1.0, 0.0],[-1.0, 0.0, 0.0],[0.0, 0.0, 1.0]]) 632 self.states.append(0) 633 self.actions.append(0) 634 self.scenes.append(0) 635 self.inventories.append(bzInventory.bzInventory()) 636 # TODO: recuperer l'avatar depuis la memoire 637 self.avatars.append(0) 638 self.message_queue.append([]) 639 return (effpseudo)
640
641 - def removeClient(self, idClient):
642 """ 643 Remove a player from server's tables. 644 @param idClient: The id in Server tables of the player to remove. 645 @type idClient: Integer. 646 """ 647 del self.connections[idClient] 648 del self.pseudos[idClient] 649 #del self.passwords[idClient] 650 del self.logged[idClient] 651 del self.positions[idClient] 652 del self.orientations[idClient] 653 del self.headings[idClient] 654 del self.states[idClient] 655 del self.actions[idClient] 656 del self.inventories[idClient] 657 del self.scenes[idClient] 658 del self.avatars[idClient] 659 del self.message_queue[idClient]
660 661
662 - def fct (self, idClient, part):
663 if self.connections[idClient].Connected(): 664 data = self.connections[idClient].ReceiveData() 665 if (self.connections[idClient].receive_status == True) and (data is not None): 666 667 effpseudo = self.registerPseudo(data.split (':')[1]) 668 669 pseudo = data.split (':')[1] 670 given_password = data.split (':')[2] 671 672 player = self.ServerMemory.GetUser(pseudo) 673 result = 0 674 reason = 0 675 if (player == None): 676 player = self.ServerMemory.RegisterUser(pseudo, given_password) 677 678 679 if (player.hasAvatar() == False): 680 reason = 1 # New user or doesn't have an avatar yet 681 else: 682 self.avatars[idClient]=self.ServerMemory.GetUser(effpseudo).getAvatar() 683 684 if part == 1: 685 reg_password = player.getPassword() 686 else: 687 reg_password = self.ServerMemory.GetUserPassword(pseudo) 688 689 if (reg_password == given_password) and (player.isConnected() == False): 690 self.pseudos[idClient]=pseudo 691 #self.passwords[idClient]=data.split (':')[2] 692 player.setConnected(idClient) 693 print "%s : connection from %s at %s"%(bzTools.getDateTime(), self.pseudos[idClient], self.connections[idClient].address) 694 # TODO: Recuperer les positions, orientations, scene et etat depuis la memoire 695 #print "Saved Scene = ",self.ServerMemory.GetUser(effpseudo).getSavedScene() 696 responsedata = bzMessage.WelcomeMessage ().Encode(idClient, result, reason, effpseudo, 697 self.ServerMemory.GetUser(effpseudo).getSavedPosition(), 698 self.ServerMemory.GetUser(effpseudo).getSavedOrientation(), 699 self.ServerMemory.GetUser(effpseudo).getSavedHeading(), 700 0, 701 0, 702 self.ServerMemory.GetUser(effpseudo).getSavedScene()) 703 ## responsedata = bzMessage.WelcomeMessage ().Encode(idClient, result, reason, effpseudo, 704 ## [1.0, 0.0, 4.0], 705 ## [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 706 ## [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 707 ## 0, 708 ## 0, 709 ## 0) 710 711 self.connections[idClient].SendData(responsedata) 712 #print "fct ", self.ServerMemory.GetUser(effpseudo).getSavedInventory().getContent() 713 # Don't know why I have to copy element by element .. So weird ???? 714 inv=self.ServerMemory.GetUser(effpseudo).getSavedInventory().getContent() 715 self.inventories[idClient] = bzInventory.bzInventory() 716 for inp in inv: 717 self.inventories[idClient].add(inp[0], inp[1]) 718 719 #print "memo " , self.ServerMemory.GetUser(effpseudo).getSavedInventory().getContent() 720 #print "Inventaire actuel: ",player.getInventory().getContent() 721 self.message_queue[idClient].append(bzMessage.InitInventory(self.inventories[idClient].getContent())) 722 #self.inventories[idClient] = bzInventory.bzInventory(player.getInventory().getContent()) 723 #print "Inventaire nouveau: ",self.inventories[idClient].getContent() 724 725 self.logged[idClient] = True 726 if part == 2: 727 self.nb_client = self.nb_client+1 728 print "nb_client = ", self.nb_client 729 self.connections.append(bzServerConnection (self.socket)) 730 ## self.inventories[idClient] = player.getInventory() 731 ## print self.inventories[idClient] 732 733 else: 734 result = 1 735 if (reg_password != given_password): 736 reason = 2 # Wrong Password 737 elif (player.isConnected() == True): 738 reason = 3 # Player Already Connected 739 responsedata = bzMessage.WelcomeMessage ().Encode(idClient, result, reason, "DENIED", 740 [1.0, 0.0, 4.0], 741 [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 742 [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 743 0, 744 0, 745 0) 746 self.connections[idClient].SendData(responsedata) 747 print "Already connected player or wrong password 1" 748 #player.setDisconnected() 749 self.connections[idClient].CloseConnection() 750 if part == 1: 751 self.logged[idClient] = False 752 lostClients.append(idClient) 753 else: 754 self.removeClient(idClient) 755 self.connections.append(bzServerConnection (self.socket)) 756 757 else: 758 if part == 1: 759 print "Client %d still not connected .."%idClient 760 self.logged[idClient] = False 761 else: 762 effpseudo = self.registerPseudo("Unlogged")
763 764 765
766 - def handleConnection(self):
767 """ 768 Check for login and new connection. 769 """ 770 # TODO: A simplifier !!! 771 lostClients = [] 772 773 # 774 # check for pending loggin connection 775 # 776 for idClient in range (self.nb_client): 777 if self.logged[idClient] == False: 778 self.fct(idClient, 1) 779 # 780 # remove lost clients from lists 781 # 782 783 ii = 0; 784 for idClient in lostClients: 785 self.connections[idClient-ii].CloseConnection() 786 print "%s: disconnection from %s"%(bzTools.getDateTime(),self.pseudos[idClient-ii]) 787 788 theuser = self.ServerMemory.GetUser(self.pseudos[idClient]) 789 theuser.setDisconnected() 790 791 self.removeClient(idClient -ii) 792 ii = ii+1 793 self.nb_client = self.nb_client -1 794 print "nb_client = ", self.nb_client 795 796 # 797 # check for new connection 798 # 799 nb_client = self.nb_client 800 #if we get a connection 801 if self.connections[nb_client].NewConnection() == True: 802 #if we're not full 803 if nb_client < self.nb_max_client: 804 # we register the connection 805 self.fct(nb_client,2) 806 else: 807 # we refuse connection 808 data = self.connections[nb_client].ReceiveData() 809 if (self.connections[nb_client].receive_status == True) and (data is not None): 810 print "%s: Refused connection from %s at %s "%(bzTools.getDateTime(),self.effpseudo, self.connections[nb_client].address) 811 reason = 4 # server full 812 response = bzMessage.WelcomeMessage ().Encode(nb_client, 1, reason, "DENIED", 813 [1.0, 0.0, 4.0], 814 [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 815 [[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]], 816 0, 817 0, 818 0) 819 self.connections[nb_client].SendData(response) 820 print "4.0" 821 # prepare for next connection 822 self.connections[nb_client].CloseConnection() 823 del self.connections[nb_client] 824 self.connections.append(bzServerConnection (self.socket))
825 826 827 828
829 - def PositionReportEvent(self, values):
830 """ 831 Handles reception of a Position Report Message 832 @param values: [position, orientation, heading, state, action, scene] 833 @type values: [3*1 vector, 3*3 matrix, 3*3matrix, integer, integer, integer]. 834 """ 835 #print "PositionReportEvent, ", values 836 [position, orientation, heading, state, action, scene] = values 837 self.positions[self.current_client_id] = position 838 self.orientations[self.current_client_id] = orientation 839 self.headings[self.current_client_id] = heading 840 self.actions[self.current_client_id] = action 841 self.states[self.current_client_id] = state 842 self.scenes[self.current_client_id] = scene
843 844
845 - def SayMessageEvent(self, values):
846 """ 847 Handles reception of a Say Message 848 @param values: [message] 849 @type values: [string]. 850 """ 851 #print "SayMessageEvent, ", values 852 [message] = values 853 if message.startswith("$"): 854 if message.startswith("$SAVEME"): 855 self.SaveUser(self.current_client_id) 856 else: 857 pass 858 else: 859 for cltid in range(self.nb_client): 860 self.message_queue[cltid].append(bzMessage.ClientsMessages([self.current_client_id, message]))
861
862 - def PrivateSayMessageEvent(self, values):
863 """ 864 Handles reception of a Private Say Message 865 @param values: [topseudo, message] 866 @type values: [string, string]. 867 """ 868 #print "PrivateSayMessageEvent, ", values 869 [topseudo, message] = values 870 if topseudo in self.pseudos: 871 cltid = self.pseudos.index(topseudo) 872 self.message_queue[cltid].append(bzMessage.ClientsMessages([self.current_client_id, message]))
873
874 - def GrabObjectEvent(self, values):
875 """ 876 Handles reception of a Grab Object Message 877 @param values: [quantity, objname] 878 @type values: [integer, string]. 879 """ 880 #print "GrabObjectEvent, ", values 881 [quantity, objname] = values 882 for cltid in range(self.nb_client): 883 self.message_queue[cltid].append(bzMessage.VanishObject(objname)) 884 self.message_queue[self.current_client_id].append(bzMessage.InventoryAdd(quantity, objname)) 885 self.inventories[self.current_client_id].add(quantity, objname)
886 #player = self.ServerMemory.GetUser(self.pseudos[self.current_client_id]) 887 #player.getInventory().add(quantity, objname) 888
889 - def DeclareVarEvent(self, values):
890 """ 891 Handles reception of a Declare Var Message 892 @param values: [quantity, varname] 893 @type values: [integer, string]. 894 """ 895 #print "DeclareVarEvent, ", values 896 [quantity, varname] = values 897 self.message_queue[self.current_client_id].append(bzMessage.InventoryAdd(quantity, varname)) 898 self.inventories[self.current_client_id].add(quantity, varname) 899 player = self.ServerMemory.GetUser(self.pseudos[self.current_client_id]) 900 player.getInventory().add(quantity, varname) 901 player.saveInventory()
902
903 - def ActivateObjectEvent(self, values):
904 """ 905 Handles reception of an Activate Object Message 906 @param values: [objname, activation type] 907 @type values: [string, integer]. 908 """ 909 #print "ActivateObjectEvent, ", values 910 [objname, value] = values 911 for cltid in range(self.nb_client): 912 self.message_queue[cltid].append(bzMessage.ActivateObject(objname, value))
913
914 - def ReleaseObjectEvent(self, values):
915 """ 916 Handles reception of a Realease Object Message 917 @param values: [objname, position] 918 @type values: [string, 3*1 vector]. 919 """ 920 #print "ReleaseObjectEvent, ", values 921 [objname, position] = values 922 for cltid in range(self.nb_client): 923 self.message_queue[cltid].append(bzMessage.InstanciateObject(objname, position)) 924 self.message_queue[self.current_client_id].append(bzMessage.InventoryAdd(-1, objname)) 925 #player = self.ServerMemory.GetUser(self.pseudos[self.current_client_id]) 926 #player.getInventory().add(-1, objname) 927 inventories[self.current_client_id].add(quantity, objname)
928
929 - def StoreAvatarEvent(self, values):
930 """ 931 Handles reception of a Store Avatar Message 932 @param values: [id_avatar] 933 @type values: [integer]. 934 """ 935 [id_avatar] = values 936 self.ServerMemory.GetUser(self.pseudos[self.current_client_id]).setAvatar(id_avatar) 937 self.avatars[self.current_client_id] = id_avatar
938 939
940 - def Pulse (self):
941 """ 942 Performs an exchange with each client. 943 """ 944 945 self.handleConnection() 946 947 948 # 949 # perform an exchange with clients and build a list of lost clients (connection ended) 950 # 951 952 lostClients = [] 953 self.current_client_id = 0 954 955 self.__rebuildVisibleClients__() 956 957 958 for self.current_client_id in range (self.nb_client): 959 if (self.logged[self.current_client_id] == True): 960 if (self.connections[self.current_client_id].Connected() == True) : 961 962 data = self.connections[self.current_client_id].ReceiveData() 963 if (self.connections[self.current_client_id].receive_status == True) and (data is not None): 964 self.processDataMessage(data) 965 966 #TODO: n'envoyez que les infos des joueurs present adans la meme scene 967 self.__rebuildVisibleClients__() 968 #print self.visible_client 969 client_scene = self.scenes[self.current_client_id] 970 # If there are client in the scene of the current player 971 #if len(self.visible_client[client_scene]) != 0: 972 ids = self.visible_client[client_scene] 973 pseudos = [self.pseudos[x] for x in self.visible_client[client_scene]] 974 positions = [self.positions[x] for x in self.visible_client[client_scene]] 975 orientations= [self.orientations[x] for x in self.visible_client[client_scene]] 976 headings= [self.headings[x] for x in self.visible_client[client_scene]] 977 states= [self.states[x] for x in self.visible_client[client_scene]] 978 actions= [self.actions[x] for x in self.visible_client[client_scene]] 979 scenes= [self.scenes[x] for x in self.visible_client[client_scene]] 980 avatars= [self.avatars[x] for x in self.visible_client[client_scene]] 981 #self.message_queue[self.current_client_id].append(bzMessage.ClientsSituationReport(ids, self.pseudos, self.positions, self.orientations, self.headings, self.states, self.actions, self.scenes, self.avatars)) 982 self.message_queue[self.current_client_id].append(bzMessage.ClientsSituationReport(ids,pseudos, positions,orientations,headings, states, actions, scenes, avatars)) 983 #else: 984 # self.message_queue[self.current_client_id].append(bzMessage.ClientsSituationReport([self.current_client_id],pseudos, positions,orientations,headings, states, actions, scenes, avatars)) 985 986 packet = self.getNextDataMessage(self.message_queue[self.current_client_id], 1024) 987 self.connections[self.current_client_id].SendData(packet) 988 else: 989 lostClients.append(self.current_client_id) 990 991 # 992 # remove lost clients from lists 993 # 994 995 ii = 0; 996 for idClient in lostClients: 997 self.connections[idClient-ii].CloseConnection() 998 print "disconnection from %s"%self.pseudos[idClient-ii] 999 theuser = self.ServerMemory.GetUser(self.pseudos[idClient]) 1000 theuser.setDisconnected() 1001 self.removeClient(idClient -ii) 1002 ii = ii+1 1003 self.nb_client = self.nb_client -1 1004 print "nb_client = ", self.nb_client
1005