Ejemplo n.º 1
0
    def startProtocol(self):
        self.transport.connect(self.host, self.port)

        cds = CubeDataStream()
        cds.putint(1)

        self.transport.write(str(cds))
Ejemplo n.º 2
0
    def __init__(self) -> None:
        self.game_clock: Optional[GameClock] = None
        self.messages = CubeDataStream()
        self.state: int = -1

        self.lifesequence = 0
        self.frags = 0
        self.deaths = 0
        self.suicides = 0
        self.teamkills = 0
        self.damage_dealt = 0
        self.damage_spent = 0
        self.flags = 0
        self.flag_returns = 0
        self.health = 100
        self.maxhealth = 100
        self.armour = 0
        self.armourtype = armor_types.A_BLUE
        self.gunselect = weapon_types.GUN_PISTOL
        self.ammo = [0] * weapon_types.NUMGUNS
        self.death_timer = None
        self.pos = vec(0, 0, 0)
        self._quadexpiry: Optional[Expiry] = None
        self.shotwait: Optional[Expiry] = None
        self.spawnwait: Optional[Expiry] = None
        self._pending_spawn = False
        self.rockets: Dict = {}
        self.grenades: Dict = {}
        self.position = b''

        self.reset()
Ejemplo n.º 3
0
    def write_state(self, room_positions: CubeDataStream,
                    room_messages: CubeDataStream) -> None:
        if self.state.position is not None:
            room_positions.write(self.state.position)

        if not self.state.messages.empty():
            swh.put_clientdata(room_messages, self, self.state.messages)
Ejemplo n.º 4
0
    def info_request(self, address, millis):
        cds = CubeDataStream()
        cds.putint(millis)

        swh.put_info_reply(cds, self.room.lan_info_name,
                           self.room.player_count, self.room.maxplayers,
                           self.room.mode_num, self.room.map_name,
                           self.room.timeleft, self.room.mastermask,
                           self.room.is_paused, 100)

        self.respond(bytes(cds), address)
Ejemplo n.º 5
0
    def process(self, channel, data):
        if len(data) == 0: return []

        if channel == 0:
            messages = self._parse_channel_0_data(data)
        elif channel == 1:
            messages = sauerbraten_stream_spec.read(data, {'aiclientnum': -1})
        else:
            return []
            print(channel)
            # ...  <cube int: port><cube str: domain><cube int: mode num><cube str: map name>
            cds = CubeDataStream(data)
            print((cds.getint()))
            print((cds.getint()))
            print((cds.getint()))
            print((cds.getint()))
            print((cds.getint()))

            print((cds.getstring()))

            print((cds.getbyte()))

            print((cds.getstring()))

            print((repr(data)))
            sys.exit(0)

        return messages
Ejemplo n.º 6
0
def get_ext_info_reply_cds(rcds):
    cds = CubeDataStream()

    cds.write(rcds.data)

    cds.putint(EXT_ACK)
    cds.putint(EXT_VERSION)

    return cds
Ejemplo n.º 7
0
    def info_request(self, address, millis):
        cds = CubeDataStream()
        cds.putint(millis)

        swh.put_info_reply(
            cds,
            self.room.lan_info_name,
            self.room.player_count,
            self.room.maxplayers,
            self.room.mode_num,
            self.room.map_name,
            self.room.timeleft,
            self.room.mastermask,
            self.room.is_paused,
            100)

        self.respond(str(cds), address)
Ejemplo n.º 8
0
 def broadcastbuffer(
         self,
         channel: int,
         reliable: bool = False,
         exclude: Optional[Union[List[Client], Tuple, List[Player]]] = None,
         clients: Optional[List[Client]] = None
 ) -> Iterator[CubeDataStream]:
     cds = CubeDataStream()
     yield cds
     self.broadcast(channel, cds, reliable, exclude, clients)
Ejemplo n.º 9
0
def get_ext_info_reply_cds(rcds):
    cds = CubeDataStream()

    cds.write(rcds.data)

    cds.putint(EXT_ACK)
    cds.putint(EXT_VERSION)

    return cds
Ejemplo n.º 10
0
 def send(self,
          channel: int,
          data: CubeDataStream,
          reliable: bool,
          no_allocate: bool = False) -> None:
     if type(data) == memoryview:
         data = data.tobytes()
     elif type(data) == CubeDataStream:
         data = memoryview(data.data).tobytes()
     elif type(data) != str:
         data = str(data)
     self.protocol_wrapper.send(channel, data, reliable, no_allocate)
Ejemplo n.º 11
0
class PlayerState(object):
    def __init__(self):
        self.game_clock = None
        self.messages = CubeDataStream()
        self.state = -1
        self.reset()

    def use_game_clock(self, game_clock):
        self.game_clock = game_clock

    @property
    def has_quad(self):
        if self._quadexpiry is not None:
            return not self._quadexpiry.is_expired
        return False

    @property
    def quad_multiplier(self):
        if self.has_quad:
            return 4
        else:
            return 1

    @property
    def quadremaining(self):
        if self.has_quad:
            return self._quadexpiry.remaining
        else:
            return 0

    @property
    def can_shoot(self):
        if not self.is_alive:
            return False
        if self.shotwait is not None:
            return self.shotwait.is_expired
        return True

    @property
    def can_spawn(self):
        if self.is_spectator:
            return False
        if self.is_alive:
            return False
        if self._pending_spawn:
            return False
        if self.spawnwait is not None:
            return self.spawnwait.is_expired
        return True

    @property
    def kpd(self):
        return KPD(self.frags, self.deaths)

    @property
    def acc_formatted(self):
        acc = self.acc_percent
        if acc is Ellipsis:
            return "inf"
        else:
            return "{:.2f}%".format(acc)

    @property
    def acc_percent(self):
        if self.damage_spent == 0:
            return Ellipsis
        return (100 * self.damage_dealt) / self.damage_spent

    @property
    def acc_percent_int(self):
        acc = self.acc_percent
        if acc is Ellipsis:
            return 0
        else:
            return int(acc)

    @property
    def time_playing_this_match(self):
        if self.playing_timer is not None:
            return self.playing_timer.time_elapsed
        else:
            return 0.0

    @property
    def is_alive(self):
        return self.state == client_states.CS_ALIVE

    @property
    def millis_since_death(self):
        if self.death_timer is None: return None
        return self.death_timer.time_elapsed * 1000

    def check_alive(self, threshold=None):
        if threshold is None: return self.is_alive
        if self.is_alive:
            return True
        else:
            millis_since_death = self.millis_since_death
            return millis_since_death is not None and millis_since_death < threshold

    @property
    def is_spectator(self):
        return self.state == client_states.CS_SPECTATOR

    @is_spectator.setter
    def is_spectator(self, value):
        if value and not self.is_spectator:
            self.state = client_states.CS_SPECTATOR
            if self.playing_timer is not None:
                self.playing_timer.pause()
        elif not value and self.is_spectator:
            self.state = client_states.CS_DEAD
            if self.playing_timer is not None:
                self.playing_timer.resume()
        else:
            print("failed to set is_spectator")

    def respawn(self):
        self._pending_spawn = True
        self.lifesequence = (self.lifesequence + 1) & 0x7F
        self._quadexpiry = None
        self.position = None

    def on_respawn(self, lifesequence, gunselect):
        if lifesequence != self.lifesequence: return
        self._pending_spawn = False
        self.state = client_states.CS_ALIVE
        self.gunselect = gunselect

        swh.put_spawn(self.messages, self)

    def update_position(self, position, raw_position):
        self.position = raw_position
        self.pos.v = position

    def clear_flushed_state(self):
        self.messages = CubeDataStream()
        self.position = None

    def map_change_reset(self):
        if self.state != client_states.CS_SPECTATOR:
            self.state = client_states.CS_DEAD

        self.frags = 0
        self.deaths = 0
        self.suicides = 0
        self.teamkills = 0
        self.damage_dealt = 0
        self.damage_spent = 0
        self.flags = 0
        self.flag_returns = 0
        self.health = 100
        self.maxhealth = 100
        self.armour = 0
        self.armourtype = armor_types.A_BLUE
        self.gunselect = weapon_types.GUN_PISTOL
        self.ammo = [0] * weapon_types.NUMGUNS

        if self.game_clock is not None:
            self.playing_timer = Timer(self.game_clock)
        else:
            self.playing_timer = None

        self.death_timer = None

        self.pos = vec(0, 0, 0)

        self._quadexpiry = None
        self.shotwait = None
        self.spawnwait = None
        self._pending_spawn = False

        self.rockets = {}
        self.grenades = {}

        self.messages.clear()
        self.position = None

    def reset(self):
        self.map_change_reset()
        self.state = client_states.CS_ALIVE
        self.lifesequence = -1

    def receive_damage(self, damage):
        # let armour absorb when possible
        ad = damage * (self.armourtype + 1) * (25.0 / 100.0)
        if ad > self.armour:
            ad = self.armour
        self.armour -= int(ad)
        damage = int(damage - int(ad))
        self.health -= damage
        return damage

    def suicide(self):
        self.frags -= 1
        self.deaths += 1
        self.suicides += 1
        self.state = client_states.CS_DEAD

    def died(self):
        if self.game_clock is not None:
            self.death_timer = Timer(self.game_clock)
        else:
            self.death_timer = None

    def pickup_item(self, item_type):
        if item_type < item_types.I_SHELLS or item_type > item_types.I_QUAD:
            print("Item out of range could not be picked up.")
            return

        itemstat = itemstats[item_type - item_types.I_SHELLS]

        if item_type == item_types.I_BOOST:  # boost also adds to health
            if self.maxhealth >= itemstat.max: return False
            self.maxhealth = min(self.maxhealth + itemstat.add, itemstat.max)

        if item_type in (item_types.I_BOOST, item_types.I_HEALTH):
            self.health = min(self.health + itemstat.add, self.maxhealth)

        elif item_type in [
                item_types.I_GREENARMOUR, item_types.I_YELLOWARMOUR
        ]:
            if self.armour >= itemstat.max: return False
            self.armour = min(self.armour + itemstat.add, itemstat.max)
            self.armourtype = itemstat.info

        elif item_type == item_types.I_QUAD:
            if self.has_quad:
                self._quadexpiry.extend(
                    float(itemstat.add) / 1000.0,
                    float(itemstat.max) / 1000.0)
            else:
                self._quadexpiry = Expiry(self.game_clock,
                                          float(itemstat.add) / 1000.0)

        else:  # is an ammo
            if self.ammo[itemstat.info] >= itemstat.max: return False
            self.ammo[itemstat.info] = min(
                self.ammo[itemstat.info] + itemstat.add, itemstat.max)

        return True
Ejemplo n.º 12
0
 def clear_flushed_state(self):
     self.messages = CubeDataStream()
     self.position = None
Ejemplo n.º 13
0
 def clear_flushed_state(self):
     self.messages = CubeDataStream()
     self.position = None
Ejemplo n.º 14
0
 def broadcastbuffer(self, channel, reliable=False, exclude=[], clients=None):
     cds = CubeDataStream()
     yield cds
     self.broadcast(channel, cds, reliable, exclude, clients)
Ejemplo n.º 15
0
    def flush_messages(self):
        try:
            class ClientBufferReference(object):
                def __init__(self, client, positions_next_byte, positions_size, messages_next_byte, messages_size):
                    self.client = client
                    self.positions_next_byte = positions_next_byte
                    self.positions_size = positions_size
                    self.messages_next_byte = messages_next_byte
                    self.messages_size = messages_size

            room_positions = CubeDataStream()
            room_messages = CubeDataStream()

            references = []

            positions_next_byte = 0
            messages_next_byte = 0

            for client in self._client_collection.to_iterator():
                player = client.get_player()

                positions_first_byte = positions_next_byte
                messages_first_byte = messages_next_byte

                player.write_state(room_positions, room_messages)

                positions_next_byte = len(room_positions)
                messages_next_byte = len(room_messages)

                positions_size = positions_next_byte - positions_first_byte
                messages_size = messages_next_byte - messages_first_byte

                references.append(ClientBufferReference(client, positions_next_byte, positions_size, messages_next_byte, messages_size))

            positions_len = len(room_positions)
            messages_len = len(room_messages)

            room_positions.write(room_positions)
            room_messages.write(room_messages)

            position_data = memoryview(room_positions.data)
            message_data = memoryview(room_messages.data)

            for ref in references:
                client = ref.client

                pnb = ref.positions_next_byte
                mnb = ref.messages_next_byte

                psize = ref.positions_size
                msize = ref.messages_size

                if positions_len - psize > 0:
                    # TODO: Use no_allocate option here
                    client.send(0, position_data[pnb:pnb + (positions_len - psize)], False, False)

                if messages_len - msize > 0:
                    # TODO: Use no_allocate option here
                    client.send(1, message_data[mnb:mnb + (messages_len - msize)], True, False)

            for player in self._player_collection.to_iterator():
                player.state.clear_flushed_state()
        except:
            traceback.print_exc()
Ejemplo n.º 16
0
 def sendbuffer(self, channel: int,
                reliable: bool) -> Iterator[CubeDataStream]:
     cds = CubeDataStream()
     yield cds
     self.send(channel, cds, reliable)
Ejemplo n.º 17
0
 def sound(self, sound):
     for client in self._client_collection.to_iterator():
         with client.sendbuffer(1, True) as cds:
             tm = CubeDataStream()
             swh.put_sound(tm, sound)
             swh.put_clientdata(cds, client, str(tm))
Ejemplo n.º 18
0
 def on_edit_mode(self, room, player, editmode):
     with room.broadcastbuffer(1, True, [player]) as cds:
         tm = CubeDataStream()
         swh.put_editmode(tm, editmode)
         swh.put_clientdata(cds, player.client, str(tm))
Ejemplo n.º 19
0
    def flush_messages(self) -> None:
        try:

            class ClientBufferReference(object):
                def __init__(self, client, positions_next_byte, positions_size,
                             messages_next_byte, messages_size):
                    self.client = client
                    self.positions_next_byte = positions_next_byte
                    self.positions_size = positions_size
                    self.messages_next_byte = messages_next_byte
                    self.messages_size = messages_size

            room_positions = CubeDataStream()
            room_messages = CubeDataStream()

            references = []

            positions_next_byte = 0
            messages_next_byte = 0

            for client in self._client_collection.to_iterator():
                player = client.get_player()

                positions_first_byte = positions_next_byte
                messages_first_byte = messages_next_byte

                player.write_state(room_positions, room_messages)

                positions_next_byte = len(room_positions)
                messages_next_byte = len(room_messages)

                positions_size = positions_next_byte - positions_first_byte
                messages_size = messages_next_byte - messages_first_byte

                references.append(
                    ClientBufferReference(client, positions_next_byte,
                                          positions_size, messages_next_byte,
                                          messages_size))

            positions_len = len(room_positions)
            messages_len = len(room_messages)

            room_positions.write(room_positions)
            room_messages.write(room_messages)

            position_data = memoryview(room_positions.data)
            message_data = memoryview(room_messages.data)

            for ref in references:
                client = ref.client

                pnb = ref.positions_next_byte
                mnb = ref.messages_next_byte

                psize = ref.positions_size
                msize = ref.messages_size

                if positions_len - psize > 0:
                    # TODO: Use no_allocate option here
                    client.send(
                        0, position_data[pnb:pnb + (positions_len - psize)],
                        False, False)

                if messages_len - msize > 0:
                    # TODO: Use no_allocate option here
                    client.send(1,
                                message_data[mnb:mnb + (messages_len - msize)],
                                True, False)

            for player in self._player_collection.to_iterator():
                player.state.clear_flushed_state()
        except:
            traceback.print_exc()
Ejemplo n.º 20
0
 def __init__(self):
     self.game_clock = None
     self.messages = CubeDataStream()
     self.state = -1
     self.reset()
Ejemplo n.º 21
0
 def sendbuffer(self, channel, reliable):
     cds = CubeDataStream()
     yield cds
     self.send(channel, cds, reliable)
Ejemplo n.º 22
0
class PlayerState(object):
    def __init__(self):
        self.game_clock = None
        self.messages = CubeDataStream()
        self.state = -1
        self.reset()

    def use_game_clock(self, game_clock):
        self.game_clock = game_clock

    @property
    def has_quad(self):
        if self._quadexpiry is not None:
            return not self._quadexpiry.is_expired
        return False

    @property
    def quad_multiplier(self):
        if self.has_quad:
            return 4
        else:
            return 1

    @property
    def quadremaining(self):
        if self.has_quad:
            return self._quadexpiry.remaining
        else:
            return 0

    @property
    def can_shoot(self):
        if not self.is_alive:
            return False
        if self.shotwait is not None:
            return self.shotwait.is_expired
        return True

    @property
    def can_spawn(self):
        if self.is_spectator:
            return False
        if self.is_alive:
            return False
        if self._pending_spawn:
            return False
        if self.spawnwait is not None:
            return self.spawnwait.is_expired
        return True

    @property
    def kpd(self):
        return KPD(self.frags, self.deaths)

    @property
    def acc_formatted(self):
        acc = self.acc_percent
        if acc is Ellipsis:
            return "inf"
        else:
            return "{:.2f}%".format(acc)

    @property
    def acc_percent(self):
        if self.damage_spent == 0:
            return Ellipsis
        return (100 * self.damage_dealt) / self.damage_spent

    @property
    def acc_percent_int(self):
        acc = self.acc_percent
        if acc is Ellipsis:
            return 0
        else:
            return int(acc)

    @property
    def time_playing_this_match(self):
        if self.playing_timer is not None:
            return self.playing_timer.time_elapsed
        else:
            return 0.0

    @property
    def is_alive(self):
        return self.state == client_states.CS_ALIVE

    @property
    def millis_since_death(self):
        if self.death_timer is None: return None
        return self.death_timer.time_elapsed * 1000

    def check_alive(self, threshold=None):
        if threshold is None: return self.is_alive
        if self.is_alive:
            return True
        else:
            millis_since_death = self.millis_since_death
            return millis_since_death is not None and millis_since_death < threshold

    @property
    def is_spectator(self):
        return self.state == client_states.CS_SPECTATOR

    @is_spectator.setter
    def is_spectator(self, value):
        if value and not self.is_spectator:
            self.state = client_states.CS_SPECTATOR
            if self.playing_timer is not None:
                self.playing_timer.pause()
        elif not value and self.is_spectator:
            self.state = client_states.CS_DEAD
            if self.playing_timer is not None:
                self.playing_timer.resume()
        else:
            print "failed to set is_spectator"

    def respawn(self):
        self._pending_spawn = True
        self.lifesequence = (self.lifesequence + 1) & 0x7F
        self._quadexpiry = None
        self.position = None

    def on_respawn(self, lifesequence, gunselect):
        if lifesequence != self.lifesequence: return
        self._pending_spawn = False
        self.state = client_states.CS_ALIVE
        self.gunselect = gunselect

        swh.put_spawn(self.messages, self)

    def update_position(self, position, raw_position):
        self.position = raw_position
        self.pos.v = position

    def clear_flushed_state(self):
        self.messages = CubeDataStream()
        self.position = None

    def map_change_reset(self):
        if self.state != client_states.CS_SPECTATOR:
            self.state = client_states.CS_DEAD

        self.frags = 0
        self.deaths = 0
        self.suicides = 0
        self.teamkills = 0
        self.damage_dealt = 0
        self.damage_spent = 0
        self.flags = 0
        self.flag_returns = 0
        self.health = 100
        self.maxhealth = 100
        self.armour = 0
        self.armourtype = armor_types.A_BLUE
        self.gunselect = weapon_types.GUN_PISTOL
        self.ammo = [0] * weapon_types.NUMGUNS

        if self.game_clock is not None:
            self.playing_timer = Timer(self.game_clock)
        else:
            self.playing_timer = None

        self.death_timer = None

        self.pos = vec(0, 0, 0)

        self._quadexpiry = None
        self.shotwait = None
        self.spawnwait = None
        self._pending_spawn = False

        self.rockets = {}
        self.grenades = {}

        self.messages.clear()
        self.position = None

    def reset(self):
        self.map_change_reset()
        self.state = client_states.CS_ALIVE
        self.lifesequence = -1

    def receive_damage(self, damage):
        # let armour absorb when possible
        ad = damage * (self.armourtype + 1) * (25.0 / 100.0)
        if ad > self.armour:
            ad = self.armour
        self.armour -= int(ad)
        damage = int(damage - int(ad))
        self.health -= damage
        return damage

    def suicide(self):
        self.frags -= 1
        self.deaths += 1
        self.suicides += 1
        self.state = client_states.CS_DEAD

    def died(self):
        if self.game_clock is not None:
            self.death_timer = Timer(self.game_clock)
        else:
            self.death_timer = None

    def pickup_item(self, item_type):
        if item_type < item_types.I_SHELLS or item_type > item_types.I_QUAD:
            print "Item out of range could not be picked up."
            return

        itemstat = itemstats[item_type - item_types.I_SHELLS]

        if item_type == item_types.I_BOOST:  # boost also adds to health
            if self.maxhealth >= itemstat.max: return False
            self.maxhealth = min(self.maxhealth + itemstat.add, itemstat.max)

        if item_type in (item_types.I_BOOST, item_types.I_HEALTH):
            self.health = min(self.health + itemstat.add, self.maxhealth)

        elif item_type in [item_types.I_GREENARMOUR, item_types.I_YELLOWARMOUR]:
            if self.armour >= itemstat.max: return False
            self.armour = min(self.armour + itemstat.add, itemstat.max)
            self.armourtype = itemstat.info

        elif item_type == item_types.I_QUAD:
            if self.has_quad:
                self._quadexpiry.extend(float(itemstat.add) / 1000.0, float(itemstat.max) / 1000.0)
            else:
                self._quadexpiry = Expiry(self.game_clock, float(itemstat.add) / 1000.0)

        else:  # is an ammo
            if self.ammo[itemstat.info] >= itemstat.max: return False
            self.ammo[itemstat.info] = min(self.ammo[itemstat.info] + itemstat.add, itemstat.max)

        return True
Ejemplo n.º 23
0
 def __init__(self):
     self.game_clock = None
     self.messages = CubeDataStream()
     self.state = -1
     self.reset()