Logo Search packages:      
Sourcecode: castle-combat version File versions  Download package

server.py

from twisted.spread import pb
from twisted.cred.portal import IRealm
from twisted.internet import reactor
from widget import WidgetState
import common

class WaitForPlayersState(WidgetState):
      def __init__(self):
            from widget import Label
            WidgetState.__init__(self)
            Label("Waiting for Players to join", (None, None))

00013 class GamePerspectiveForClient(pb.Referenceable):
      '''Contains all methods related to the Game class, which can be called from the clients
      '''

      def __init__(self, server):
            self.server = server

      def remote_pause(self):
            self.server.call('pause')

      def remote_unpause(self):
            self.server.call('unpause')

00026 class ClientAvatar(pb.Avatar):
      '''This class contains all functions which can be called by the client.

         There is exacty one instance of this class per connected client.
      '''

      def __init__(self, server, mind):
            self.server = server
            self.mind = mind
            self.ready = False
            print "One client connected. Total: %d" % len(self.server.clients)
            
      ##### callbacks

      def logout_callback(self):
            print self, "logged out"
            self.server.clients.remove(self)

            # quit game_state if it didn't quit already
            game_state = self.server.game.game_state
            if game_state in game_state.stack:
                  game_state.quit()
            
      ##### remote functions
      
      def perspective_claim_player_as_local(self):
            return self.server.claim_player_as_local()
      
      def perspective_get_server_info(self):
            game = self.server.game
            from player import PlayerCacheable
            info = {
                  'players': game.players,
                  'map': game.field.map,
                  'server_game': GamePerspectiveForClient(self.server)
            }
            return info

00064       def perspective_client_ready(self):
            '''Gets called when the client has been fully initialised'''
            
            def get_client_info_callback(info):
                  '''Finishes integration of this client into the game'''
                  self.remote_game = info['game']
                  #self.remote_players = info['players']
                  self.ready = True
                  self.server.start_game_if_ready()

            d = self.mind.callRemote('get_client_info')
            d.addCallback(get_client_info_callback)
            

class RequestClientRealm:
      __implements__ = IRealm
      
      def __init__(self, server):
            self.server = server

      def requestAvatar(self, avatarId, mind, *interfaces):
            if pb.IPerspective in interfaces:
                  avatar = ClientAvatar(self.server, mind)
                  self.server.clients.append(avatar)
                  return pb.IPerspective, avatar, avatar.logout_callback 
            else:
                  raise NotImplementedError("no interface")

class Server:

      clients = []

      def __init__(self, map_class, total_players):
            import player
            players = [player.PlayerCacheable(i) for i in range(total_players)]
            import game
            self.game = game.Game(players=players, server=self)
            self.game.set_map(map_class())
            self.ai_players = []

            from twisted.cred.portal import Portal
            from twisted.cred.checkers import AllowAnonymousAccess, InMemoryUsernamePasswordDatabaseDontUse
            portal = Portal(RequestClientRealm(self))
            checker = InMemoryUsernamePasswordDatabaseDontUse()
            checker.addUser("guest", "guest")
      #     checker = AllowAnonymousAccess()
            portal.registerChecker(checker)
            self.listening_port = reactor.listenTCP(pb.portno, pb.PBServerFactory(portal))

      def call(self, command, *args):
            try:
                  eval('self.game.remote_'+command)(*args)
                  for client in self.clients:
                        client.remote_game.callRemote(command, *args)
                  for ai in self.ai_players:
                        ai.act_on_game_event(command)
                  print command, 'successful'
            except common.ActionNotPossible:
                  print command, 'failed'
                  return
            

      def claim_player_as_local(self):
            for player in self.game.players:
                  if not player.connected:
                        player.connected = True
                        self.start_game_if_ready()
                        #return player.player_id, player
                        return player
            assert False, "All player slots are already occupied"

      def start_game_if_ready(self):
            all_clients_ready = False not in [client.ready for client in self.clients]
            all_players_connected = False not in [player.connected for player in self.game.players]
            if all_players_connected and all_clients_ready:
                  print "Stopping to listen"
                  self.listening_port.stopListening()
                  reactor.callLater(0, lambda: self.game.server_call("run"))
            
      
      def run(self, local_players, ai_players):
            self.wait_for_players_state = WaitForPlayersState()
            self.game.run_callback = self.wait_for_players_state.quit

            for i in range(local_players):
                  #(player_id, avatar) = self.get_player()
                  #self.game.players[player_id].local = True
                  player = self.claim_player_as_local()
                  player.local = True

            for i in range(ai_players):
                  import ai
                  (player_id, avatar) = self.get_player()
                  self.game.players[player_id].local = True
                  newai = ai.DefaultAI(player_id)
                  self.game.players[player_id].ai = newai
                  self.ai_players.append(newai)

      def quit(self):
            print "Disconnecting all clients"
            for client in self.clients:
                  client.mind.broker.transport.loseConnection()
            self.listening_port.stopListening()
      

Generated by  Doxygen 1.6.0   Back to index