示例#1
0
文件: temp.py 项目: zimmed/project200
def server_main():
    print "Starting server..."
    EventServer.start()
    try:
        while True:
            if EventServer.has_events:
                event = EventServer.get_event()
                print str(event)
                if event.type is 'exit':
                    break
    except Exception as e:
        print e
    EventServer.stop()
    sys.exit(0)
示例#2
0
文件: temp.py 项目: zimmed/project200
def server_main():
    print "Starting server..."
    EventServer.start()
    try:
        while True:
            if EventServer.has_events:
                event = EventServer.get_event()
                print str(event)
                if event.type is "exit":
                    break
    except Exception as e:
        print e
    EventServer.stop()
    sys.exit(0)
    def start(self):
        self._socket_server = EventServer(self._server_address)
        self._socket_server.heartbeat_rate = 35
        self._socket_server._message_protocol = PacketProtocol()

        # set up handlers
        self._socket_server.on('connected', self.client_connected)
        self._socket_server.on('disconnected', self.client_disconnected)
        self._socket_server.on(PacketId.JOIN, self.player_join)
        self._socket_server.on(PacketId.PLAYER_INPUT, self.player_movement)
        self._socket_server.on(PacketId.ACK, self.received_ack)
        self._socket_server.on(PacketId.PLAYER_FIRE, self.player_fire)
        self._socket_server.on(PacketId.HEARTBEAT, self.received_heartbeat)

        self._server_thread = threading.Thread(target=self._socket_server.serve_forever)
        self._server_thread.daemon = True
        self._server_thread.start()

        print("Serving on {}".format(self._socket_server.socket.getsockname()))

        # for a fixed update tick
        last_time = time.time()
        loop_time = 1.0 / self._tick_rate
        loop_timer = 0

        while True:
            time_now = time.time()
            delta = time_now - last_time
            last_time = time_now            

            loop_timer += delta
            if loop_timer >= loop_time:
                if loop_timer >= loop_time * 1.5:
                    print("----------------------")
                    print("FRAMERATE DROPPED TO {}fps".format((1.0 / loop_timer)))
                    print("----------------------")

                self.game_loop(loop_timer)
                loop_timer = 0

        self._socket_server.shutdown()
示例#4
0
 def __init__(self, event_port, client_port):
     self.event_manager = EventManager()
     self.client_server = ClientServer.create(('', client_port), self.event_manager)
     self.event_server = EventServer.create(('', event_port), self.event_manager)
class GameServer:
    def __init__(self, settings):
        self._clients = {}
        self._socket_to_player = {}
        self._clients_to_remove = []
        self._player_id_number = 0

        # Binding Address
        self._server_address = (settings.host, int(settings.port))

        self._socket_server = None
        self._server_thread = None

        self._sequence_number = 0
        self._max_sequence_number = 10000
        self._ack_needed = []

        self.protocol = PacketProtocol()

        # game state stuff
        self._world = World()
        self._bullets = []

        # game tick rate, in frames per second.
        self._tick_rate = int(settings.tickRate)

        # stats
        self._stat_timer = 5
        self._stat_time = 5
        self._stat_sent = 0
        self._stat_sent_bandwidth = 0

    def start(self):
        self._socket_server = EventServer(self._server_address)
        self._socket_server.heartbeat_rate = 35
        self._socket_server._message_protocol = PacketProtocol()

        # set up handlers
        self._socket_server.on('connected', self.client_connected)
        self._socket_server.on('disconnected', self.client_disconnected)
        self._socket_server.on(PacketId.JOIN, self.player_join)
        self._socket_server.on(PacketId.PLAYER_INPUT, self.player_movement)
        self._socket_server.on(PacketId.ACK, self.received_ack)
        self._socket_server.on(PacketId.PLAYER_FIRE, self.player_fire)
        self._socket_server.on(PacketId.HEARTBEAT, self.received_heartbeat)

        self._server_thread = threading.Thread(target=self._socket_server.serve_forever)
        self._server_thread.daemon = True
        self._server_thread.start()

        print("Serving on {}".format(self._socket_server.socket.getsockname()))

        # for a fixed update tick
        last_time = time.time()
        loop_time = 1.0 / self._tick_rate
        loop_timer = 0

        while True:
            time_now = time.time()
            delta = time_now - last_time
            last_time = time_now            

            loop_timer += delta
            if loop_timer >= loop_time:
                if loop_timer >= loop_time * 1.5:
                    print("----------------------")
                    print("FRAMERATE DROPPED TO {}fps".format((1.0 / loop_timer)))
                    print("----------------------")

                self.game_loop(loop_timer)
                loop_timer = 0

        self._socket_server.shutdown()

    def next_player_id(self):
        self._player_id_number += 1
        return self._player_id_number

    def next_sequence_number(self):
        this_seq = self._sequence_number
        if self._sequence_number < self._max_sequence_number:
            self._sequence_number += 1
        else:
            print("SEQUENCE NUMBER LOOPED")
            self._sequence_number = 0
        return this_seq

    def send(self, player_id, event, payload, needs_ack=False, seq_num=None):
        if player_id not in self._clients:
            return

        if not seq_num:
            seq_num = self.next_sequence_number()

        self._stat_sent += 1

        player = self._clients[player_id]
        player_addr = player.address
                
        msg_bytes = self.protocol.create(event, payload, seq_num, needs_ack)

        if needs_ack:
            info = PacketInfo(seq_num, time.time(), player_id, event, payload)
            # print("new ACK for {} at time: {}".format(seq_num, info.sent_ticks))
            self._ack_needed.append(info)

        self._stat_sent_bandwidth += sys.getsizeof(msg_bytes)

        self._socket_server.sendto(player_addr, msg_bytes)

    def send_all(self, event, payload, needs_ack=False):
        """Sends the message to all active players."""
        for player_id, player in self._clients.items():
            self.send(player_id, event, payload, needs_ack)

    def game_loop(self, dt):
        updated_players = []

        self._stat_timer -= dt
        if self._stat_timer <= 0:
            self._stat_timer = self._stat_time
            with lock:
                sent = self._stat_sent
                self._stat_sent = 0
                avg = sent / self._stat_time
                print("AVG MESSAGES SENT PER SECOND: {}".format(avg))
                band = self._stat_sent_bandwidth
                self._stat_sent_bandwidth = 0
                avg = band / self._stat_time
                amnt = "bytes"
                if avg > 1000000:
                    avg /= 1000
                    avg /= 1000
                    amnt = "megabytes"
                elif avg > 10000:
                    avg /= 1000
                    amnt = "kilobytes"
                print("AVG BANDWIDTH SENT PER SECOND: {} {}".format(avg, amnt))
                if len(self._clients) > 0:
                    avg = (sent / self._stat_time) / len(self._clients)
                    print("AVG MESSAGES PER PLAYER: {}".format(avg))

        with lock:
            # remove disconnected players
            for player_id in self._clients_to_remove:
                if player_id not in self._clients:
                    continue
                player = self._clients[player_id]

                # send player_left message to everyone else
                self.send_all(PacketId.PLAYER_LEFT, self.protocol.pack_data(player.uuid))

                del self._clients[player_id]

            self._clients_to_remove.clear()

            # loop through players and handle updates
            for player_id, player in self._clients.items():
                if player.movement[0] != 0 or player.movement[1] != 0:
                    player.position[0] += player.movement[0] * player.speed * dt
                    player.position[1] += player.movement[1] * player.speed * dt                    
                    if player.position[0] <= -self._world.width + 1:
                        player.position[0] = -self._world.width + 1
                    elif player.position[0] >= self._world.width - 1:
                        player.position[0] = self._world.width - 1 
                    if player.position[1] < -self._world.height + 1:
                        player.position[1] = -self._world.height + 1
                    elif player.position[1] >= self._world.height - 1:
                        player.position[1] = self._world.height - 1
                    updated_players.append(player.as_dict())

            if len(updated_players) > 0:
                # print("sending player updates for {} players".format(len(updated_players)))
                self.send_all(PacketId.PLAYER_UPDATES, self.protocol.pack_data(updated_players))

            # update bullets
            dead_bullets = []
            bullet_update = []
            for bullet in self._bullets:
                bullet.lifetime -= dt
                if bullet.lifetime <= 0:
                    dead_bullets.append(bullet)
                    continue
                bullet.position[0] += bullet.direction[0] * bullet.speed * dt
                bullet.position[1] += bullet.direction[1] * bullet.speed * dt
                bullet_update.append(bullet.as_dict())

            # remove dead bullets
            for bullet in dead_bullets:
                self._bullets.remove(bullet)

            # send bullet updates if some were updated or removed
            if len(bullet_update) > 0 or len(dead_bullets) > 0:
                self.send_all(PacketId.BULLETS, self.protocol.pack_data(bullet_update))

            # loop through the Acks queue to see if we need to send more acks
            if len(self._ack_needed):
                resend_acks = []
                while len(self._ack_needed) > 0:
                    ack = self._ack_needed[0]
                    since = time.time() - ack.sent_ticks
                    if since >= 2:
                        # resend and requeue
                        # print("ACK needed for {}".format(ack.sequence_number))
                        resend_acks.append(self._ack_needed.pop())
                    else:
                        # hit a young pack, quit for now
                        # oldest packs will be at the front
                        break

                for ack in resend_acks:
                    self.send(ack.target, ack.event, ack.payload, True, ack.sequence_number)
    
    def sequence_more_recent(self, s1, s2):
        return (s1 > s2 and s1 - s2 <= self._max_sequence_number / 2) or (s2 > s1 and s2 - s1 > self._max_sequence_number/2)

    def player_join(self, msg, socket):
        pass

    def client_connected(self, msg, socket):
        """ Both 'connected' and 'disconnected' are events
            reserved by the server. It will call them automatically.
        """
        with lock:            
            player = PlayerClient(self.next_player_id(), socket)
            print("New client: {} is now player {}".format(socket, player.uuid))
            self._clients[player.uuid] = player
            self._socket_to_player[socket] = player.uuid

            # send welcome
            # print(player.as_dict())
            self.send(player.uuid, PacketId.WELCOME, self.protocol.pack_data(player.as_dict()), True)

            # send world, require acknowledge
            self.send(player.uuid, PacketId.WORLD_INFO, self.protocol.pack_data(self._world.as_dict()), True)
    
    def client_disconnected(self, msg, socket):
        player = self._clients[self._socket_to_player[socket]]
        print("Player {} has disconnected.".format(player.uuid))
        if player.uuid in self._clients and player.uuid not in self._clients_to_remove:
            self._clients_to_remove.append(player.uuid)

    def player_movement(self, msg, socket):
        if socket not in self._socket_to_player:
            return        

        player = self._clients[self._socket_to_player[socket]]
        movement = self.protocol.unpack_data(msg)
        # print("Got player input for {}: {}".format(player.uuid, movement))
        player.set_movement(movement)

    def player_fire(self, msg, socket):
        if socket not in self._socket_to_player:
            return

        player = self._clients[self._socket_to_player[socket]]
        
        # create bullet
        bullet = Bullet(player.position, player.facing, player.uuid)
        self._bullets.append(bullet)

    def received_heartbeat(self, msg, socket):
        pass

    def received_ack(self, msg, socket):
        if socket not in self._socket_to_player:
            return
        acks = self.protocol.unpack_data(msg)
        with lock:
            for ack in acks:
                ackInfo = next((a for a in self._ack_needed if a.sequence_number == ack), None)
                if ackInfo and ackInfo:
                    # print("ack received: {}".format(ackInfo.sequence_number))
                    self._ack_needed.remove(ackInfo)