Esempio n. 1
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        speed = 0.0
        if world_session.player_mgr.is_gm:
            if len(reader.data
                   ) >= 52:  # Avoid handling empty speed cheat packet.
                speed = unpack('<f', reader.data[48:52])[0]
        else:
            # Disconnect if the player is not a GM.
            Logger.anticheat(
                f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to use speed cheats.'
            )
            return -1

        if reader.opcode == OpCode.MSG_MOVE_SET_RUN_SPEED_CHEAT:
            world_session.player_mgr.change_speed(speed)
        elif reader.opcode == OpCode.MSG_MOVE_SET_SWIM_SPEED_CHEAT:
            world_session.player_mgr.change_swim_speed(speed)
        elif reader.opcode == OpCode.MSG_MOVE_SET_WALK_SPEED_CHEAT:
            world_session.player_mgr.change_walk_speed(speed)
        elif reader.opcode == OpCode.MSG_MOVE_SET_TURN_RATE_CHEAT:
            world_session.player_mgr.change_turn_speed(speed)
        else:
            return -1

        return 0
Esempio n. 2
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        speed = 0.0
        if world_session.player_mgr.is_gm:
            if len(reader.data
                   ) >= 52:  # Avoid handling empty speed cheat packet.
                speed = unpack('<f', reader.data[48:52])[0]
        else:
            Logger.anticheat(
                f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to use speed hacks.'
            )

        # A speed of 0 will ensure that the speed is reset to the default values if the player is not a GM.
        if reader.opcode == OpCode.MSG_MOVE_SET_RUN_SPEED_CHEAT:
            world_session.player_mgr.change_speed(speed)
        elif reader.opcode == OpCode.MSG_MOVE_SET_SWIM_SPEED_CHEAT:
            world_session.player_mgr.change_swim_speed(speed)
        elif reader.opcode == OpCode.MSG_MOVE_SET_WALK_SPEED_CHEAT:
            world_session.player_mgr.change_walk_speed(speed)
        elif reader.opcode == OpCode.MSG_MOVE_SET_TURN_RATE_CHEAT:
            world_session.player_mgr.change_turn_speed(speed)
            # Disconnect if the player is not a GM as I haven't found a way to change turn speed back to normal.
            if not world_session.player_mgr.is_gm:
                return -1
        else:
            return -1

        return 0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if world_session.player_mgr.is_gm:  # GM only.
            world_session.player_mgr.taxi_manager.disable_all_taxi_nodes()
        else:
            Logger.anticheat(
                f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to clear all known taxi nodes.'
            )

        return 0
Esempio n. 4
0
    def handle(world_session, socket, reader):
        if world_session.player_mgr.is_gm:
            pack_guid, map_, x, y, z, o = unpack('<IB4f', reader.data)
            world_session.player_mgr.teleport(map_, Vector(x, y, z, o))
        else:
            Logger.anticheat('Player %s (%s) tried to teleport himself.' % (world_session.player_mgr.player.name,
                                                                            world_session.player_mgr.guid))

        return 0
Esempio n. 5
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data) >= 4:  # Avoid handling empty create item packet.
            item_entry = unpack('<I', reader.data[:4])[0]
            if not world_session.player_mgr.is_gm:
                Logger.anticheat(f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried create item {item_entry}.')
                return 0

            CommandManager.additem(world_session, str(item_entry))
        return 0
Esempio n. 6
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if not world_session.player_mgr.is_gm:
            Logger.anticheat(
                f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to recharge powers.'
            )
            return 0

        world_session.player_mgr.recharge_power()

        return 0
Esempio n. 7
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data) >= 1:  # Avoid handling empty god mode packet.
            if not world_session.player_mgr.is_gm:
                Logger.anticheat(f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to set godmode.')
                return 0

            world_session.player_mgr.is_god = unpack('<B', reader.data[:1])[0] >= 1
            world_session.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_GODMODE, reader.data[:1]))

        return 0
Esempio n. 8
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        player_mgr = world_session.player_mgr
        if not player_mgr:
            return 0

        if not player_mgr.is_gm:
            Logger.anticheat(f'Player {player_mgr.player.name} ({player_mgr.guid}) tried to clear all taxi nodes.')
            return 0

        player_mgr.taxi_manager.disable_all_taxi_nodes()

        return 0
Esempio n. 9
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data) >= 4:  # Avoid empty packet level cheat packet.
            new_level = unpack('<I', reader.data[:4])[0]
            if not world_session.player_mgr.is_gm:
                Logger.anticheat(
                    f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to level to {new_level}.'
                )
                return 0

            world_session.player_mgr.mod_level(new_level)

        return 0
Esempio n. 10
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data
               ) >= 4:  # Avoid handling empty cheat set money packet.
            new_money = unpack('<I', reader.data[:4])[0]
            if not world_session.player_mgr.is_gm:
                Logger.anticheat(
                    f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to give himself {new_money} copper.'
                )
                return 0

            world_session.player_mgr.mod_money(new_money)

        return 0
    def handle(world_session, socket, reader):
        if len(reader.data
               ) >= 4:  # Avoid handling empty learn spell cheat packet.
            spell_id = unpack('<I', reader.data[:4])[0]
            if not world_session.player_mgr.is_gm:
                Logger.anticheat(
                    f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to learn the spell {spell_id}.'
                )
                return 0

            world_session.player_mgr.spell_manager.learn_spell(spell_id)

        return 0
Esempio n. 12
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        player_mgr = world_session.player_mgr
        if not player_mgr:
            return 0

        if not player_mgr.is_gm:
            Logger.anticheat(
                f'Player {player_mgr.player.name} ({player_mgr.guid}) tried to modify level.'
            )
            return 0

        player_mgr.mod_level(player_mgr.level + 1)

        return 0
Esempio n. 13
0
    def handle(world_session, socket, reader):
        if not world_session.player_mgr.is_gm:
            Logger.anticheat(f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to remove his cooldowns.')
            return 0

        # Clear server-side cooldowns.
        for cooldown_entry in list(world_session.player_mgr.spell_manager.cooldowns):
            world_session.player_mgr.spell_manager.cooldowns.remove(cooldown_entry)

        # Clear client-side cooldowns.
        data = pack('<Q', world_session.player_mgr.guid)
        world_session.player_mgr.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_COOLDOWN_CHEAT, data))

        return 0
Esempio n. 14
0
    def handle(world_session, socket, reader):
        # Don't teleport if player is in the middle of a flight.
        if world_session.player_mgr.movement_spline and world_session.player_mgr.movement_spline.flags == SplineFlags.SPLINEFLAG_FLYING:
            return 0

        if world_session.player_mgr.is_gm:
            if len(reader.data
                   ) >= 21:  # Avoid handling empty world teleport packet.
                pack_guid, map_, x, y, z, o = unpack('<IB4f', reader.data[:21])
                world_session.player_mgr.teleport(map_, Vector(x, y, z, o))
        else:
            Logger.anticheat(
                f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to teleport himself.'
            )

        return 0
Esempio n. 15
0
    def handle(world_session, socket, reader):
        if len(reader.data) < 8:  # Avoid handling wrong player login packet
            return -1

        guid = unpack('<Q', reader.data[:8])[0]

        world_session.player_mgr = PlayerManager(
            RealmDatabaseManager.character_get_by_guid(guid), world_session)
        world_session.player_mgr.session = world_session
        if not world_session.player_mgr.player:
            Logger.anticheat('Character with wrong guid (%u) tried to login.' %
                             guid)
            return -1

        socket.sendall(
            PacketWriter.get_packet(OpCode.SMSG_LOGIN_SETTIMESPEED,
                                    PlayerLoginHandler._get_login_timespeed()))

        world_session.player_mgr.load_skills()
        world_session.player_mgr.load_spells()

        world_session.player_mgr.deathbind = RealmDatabaseManager.character_get_deathbind(
            world_session.player_mgr.guid)

        socket.sendall(world_session.player_mgr.get_deathbind_packet())
        #  Tutorials aren't implemented in 0.5.3
        #  socket.sendall(world_session.player_mgr.get_tutorial_packet())
        socket.sendall(world_session.player_mgr.get_initial_spells())
        socket.sendall(world_session.player_mgr.get_action_buttons())

        # MotD
        ChatManager.send_system_message(world_session,
                                        config.Server.General.motd)

        world_session.player_mgr.inventory.load_items()
        world_session.player_mgr.stat_manager.init_stats()
        world_session.player_mgr.stat_manager.apply_bonuses()
        world_session.player_mgr.send_update_self(create=True)
        world_session.player_mgr.reset_fields()

        PlayerLoginHandler._send_cinematic(world_session,
                                           world_session.player_mgr.player,
                                           socket)
        world_session.player_mgr.complete_login()

        return 0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data
               ) >= 4:  # Avoid handling empty trigger cinematic cheat packet.
            if not world_session.player_mgr.is_gm:
                Logger.anticheat(
                    f'Player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}) tried to force trigger a cinematic.'
                )
                return 0

            cinematic_id = unpack('<I', reader.data[:4])[0]
            if DbcDatabaseManager.cinematic_sequences_get_by_id(cinematic_id):
                data = pack('<I', cinematic_id)
                world_session.enqueue_packet(
                    PacketWriter.get_packet(OpCode.SMSG_TRIGGER_CINEMATIC,
                                            data))

        return 0
Esempio n. 17
0
    def handle(world_session, socket, reader):
        if not world_session.player_mgr.is_gm:
            Logger.anticheat('Player %s (%s) tried to use speed hacks.' %
                             (world_session.player_mgr.player.name,
                              world_session.player_mgr.guid))
            if reader.opcode == OpCode.MSG_MOVE_SET_RUN_SPEED_CHEAT:
                world_session.player_mgr.change_speed()
            elif reader.opcode == OpCode.MSG_MOVE_SET_SWIM_SPEED_CHEAT:
                world_session.player_mgr.change_swim_speed()
            elif reader.opcode == OpCode.MSG_MOVE_SET_WALK_SPEED_CHEAT:
                world_session.player_mgr.change_walk_speed()
            elif reader.opcode == OpCode.MSG_MOVE_SET_TURN_RATE_CHEAT:
                # world_session.player_mgr.change_turn_speed()
                # Disconnect as I haven't found a way to change turn speed back to normal
                return -1

        return 0
Esempio n. 18
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        player_mgr = world_session.player_mgr
        if not player_mgr:
            return 0

        if not player_mgr.is_gm:
            Logger.anticheat(
                f'Player {player_mgr.player.name} ({player_mgr.guid}) tried to give himself Beastmaster.'
            )
            return 0

        if len(reader.data) >= 1:  # Avoid handling empty beast master packet.
            # Client sends `0` if you type `beastmaster off`, and `1` if you type `beastmaster`.
            player_mgr.beast_master = unpack('<B', reader.data[:1])[0] >= 1
        ChatManager.send_system_message(
            world_session, f'Beastmaster '
            f'{"enabled" if player_mgr.beast_master else "disabled"}')

        return 0
Esempio n. 19
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        player_mgr = world_session.player_mgr
        if not player_mgr:
            return 0

        if not player_mgr.is_gm:
            Logger.anticheat(
                f'Player {player_mgr.player.name} ({player_mgr.guid}) tried to set god mode.'
            )
            return 0

        if len(reader.data) >= 1:  # Avoid handling empty god mode packet.
            # Client sends `0` if you type `godmode`, and `1` if you type `godmode 1` (or a number greater than 1).
            player_mgr.is_god = unpack('<B', reader.data[:1])[0] >= 1
            world_session.enqueue_packet(
                PacketWriter.get_packet(OpCode.SMSG_GODMODE, reader.data[:1]))
        ChatManager.send_system_message(
            world_session, f'Godmode '
            f'{"enabled" if player_mgr.is_god else "disabled"}')

        return 0
Esempio n. 20
0
    def handle(world_session, socket, reader):
        if len(reader.data) < 8:  # Avoid handling wrong player login packet
            return -1

        guid = unpack('<Q', reader.data[:8])[0]

        world_session.player_mgr = PlayerManager(
            RealmDatabaseManager.character_get_by_guid(guid), world_session)
        world_session.player_mgr.session = world_session
        if not world_session.player_mgr.player:
            Logger.anticheat('Character with wrong guid (%u) tried to login.' % guid)
            return -1

        socket.sendall(PacketWriter.get_packet(OpCode.SMSG_LOGIN_SETTIMESPEED,
                                               PlayerLoginHandler._get_login_timespeed()))

        world_session.player_mgr.load_skills()
        world_session.player_mgr.load_spells()

        socket.sendall(world_session.player_mgr.get_tutorial_packet())
        socket.sendall(world_session.player_mgr.get_initial_spells())
        socket.sendall(world_session.player_mgr.get_action_buttons())

        # MotD
        ChatManager.send_system_message(world_session, config.Server.General.motd)

        # Clear Who list on login, otherwise the last search will appear
        PlayerLoginHandler._clear_who_list(socket)

        world_session.player_mgr.inventory.load_items()

        update_packet = UpdatePacketFactory.compress_if_needed(PacketWriter.get_packet(
            OpCode.SMSG_UPDATE_OBJECT,
            world_session.player_mgr.get_update_packet(update_type=UpdateTypes.UPDATE_FULL)))
        socket.sendall(update_packet)

        PlayerLoginHandler._send_cinematic(world_session, world_session.player_mgr.player, socket)
        world_session.player_mgr.complete_login()

        return 0
Esempio n. 21
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        player_mgr = world_session.player_mgr
        if not player_mgr:
            return 0

        if not player_mgr.is_gm:
            Logger.anticheat(
                f'Player {player_mgr.player.name} ({player_mgr.guid}) tried to modify speed.'
            )
            return 0

        if len(reader.data) >= 52:  # Avoid handling empty speed cheat packet.
            speed = unpack('<f', reader.data[48:52])[0]
            if reader.opcode == OpCode.MSG_MOVE_SET_RUN_SPEED_CHEAT:
                player_mgr.change_speed(speed)
            elif reader.opcode == OpCode.MSG_MOVE_SET_SWIM_SPEED_CHEAT:
                player_mgr.change_swim_speed(speed)
            elif reader.opcode == OpCode.MSG_MOVE_SET_WALK_SPEED_CHEAT:
                player_mgr.change_walk_speed(speed)
            elif reader.opcode == OpCode.MSG_MOVE_SET_TURN_RATE_CHEAT:
                player_mgr.change_turn_speed(speed)

        return 0
Esempio n. 22
0
    def handle_movement_status(world_session, socket, reader):
        # Avoid handling malformed movement packets, or handling them while no player or player teleporting
        if world_session.player_mgr and len(reader.data) >= 48:
            try:
                transport_guid, transport_x, transport_y, transport_z, transport_o, x, y, z, o, pitch, flags = \
                    unpack('<Q9fI', reader.data[:48])

                # Hacky way to prevent random teleports when colliding with elevators
                # Also acts as a rudimentary teleport cheat detection
                if not world_session.player_mgr.pending_taxi_destination and world_session.player_mgr.location.distance(
                        x=x, y=y, z=z) > 64:
                    Logger.anticheat(
                        f'Preventing coordinate desync from player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}).'
                    )
                    world_session.player_mgr.teleport(
                        world_session.player_mgr.map_,
                        world_session.player_mgr.location)

                    return 0

                # Send movement info to SpellManager until movement handling is merged to update system
                if flags & 0xF != 0:  # MoveFlags.MOVEFLAG_MOVE_MASK | MoveFlags.MOVEFLAG_STRAFE_MASK
                    world_session.player_mgr.spell_manager.flag_as_moved()

                world_session.player_mgr.transport_id = transport_guid

                world_session.player_mgr.transport.x = transport_x
                world_session.player_mgr.transport.y = transport_y
                world_session.player_mgr.transport.z = transport_z
                world_session.player_mgr.transport.o = transport_o

                world_session.player_mgr.location.x = x
                world_session.player_mgr.location.y = y
                world_session.player_mgr.location.z = z
                world_session.player_mgr.location.o = o

                world_session.player_mgr.pitch = pitch
                world_session.player_mgr.movement_flags = flags

                if flags & MoveFlags.MOVEFLAG_SPLINE_MOVER:
                    world_session.player_mgr.movement_spline = MovementManager.MovementSpline.from_bytes(
                        reader.data[48:])

                movement_data = pack(f'<Q{len(reader.data)}s',
                                     world_session.player_mgr.guid,
                                     reader.data)

                GridManager.send_surrounding(PacketWriter.get_packet(
                    OpCode(reader.opcode), movement_data),
                                             world_session.player_mgr,
                                             include_self=False)
                GridManager.update_object(world_session.player_mgr)
                world_session.player_mgr.sync_player()

                # Get up if you jump while not standing
                if reader.opcode == OpCode.MSG_MOVE_JUMP and \
                        world_session.player_mgr.stand_state != StandState.UNIT_DEAD and \
                        world_session.player_mgr.stand_state != StandState.UNIT_STANDING:
                    world_session.player_mgr.stand_state = StandState.UNIT_STANDING
                    world_session.player_mgr.set_dirty()

            except (AttributeError, error):
                Logger.error(
                    f'Error while handling {OpCode(reader.opcode).name}, skipping. Data: {reader.data}'
                )

        return 0
Esempio n. 23
0
    def handle_movement_status(world_session, socket, reader):
        movement_fmt = '<QfffffffffI'

        if not world_session.player_mgr.is_teleporting and len(
                reader.data
        ) >= 48:  # Avoid handling malformed movement packets
            try:
                transport_guid, transport_x, transport_y, transport_z, transport_o, x, y, z, o, pitch, flags = \
                    unpack(movement_fmt, reader.data[:48])

                # Hacky way to prevent random teleports when colliding with elevators
                # Also acts as a rudimentary teleport cheat detection
                if world_session.player_mgr.location.distance(x=x, y=y,
                                                              z=z) > 64:
                    Logger.anticheat(
                        "Preventing coordinate desync from player %s (%s)." %
                        (world_session.player_mgr.player.name,
                         world_session.player_mgr.guid))
                    world_session.player_mgr.teleport(
                        world_session.player_mgr.map_,
                        world_session.player_mgr.location)

                    return 0

                world_session.player_mgr.transport_id = transport_guid

                world_session.player_mgr.transport.x = transport_x
                world_session.player_mgr.transport.y = transport_y
                world_session.player_mgr.transport.z = transport_z
                world_session.player_mgr.transport.o = transport_o

                world_session.player_mgr.location.x = x
                world_session.player_mgr.location.y = y
                world_session.player_mgr.location.z = z
                world_session.player_mgr.location.o = o

                world_session.player_mgr.pitch = pitch
                world_session.player_mgr.movement_flags = flags

                movement_data = pack('<Q%us' % len(reader.data),
                                     world_session.player_mgr.guid,
                                     reader.data)

                GridManager.send_surrounding(PacketWriter.get_packet(
                    OpCode(reader.opcode), movement_data),
                                             world_session.player_mgr,
                                             include_self=False)
                GridManager.update_object(world_session.player_mgr)
                world_session.player_mgr.sync_player()

                if reader.opcode == OpCode.MSG_MOVE_JUMP and \
                        world_session.player_mgr.stand_state != StandState.UNIT_DEAD and \
                        world_session.player_mgr.stand_state != StandState.UNIT_STANDING:
                    world_session.player_mgr.stand_state = StandState.UNIT_STANDING
                    world_session.player_mgr.flagged_for_update = True

            except (AttributeError, error):
                Logger.error('Error while handling %s, skipping. Data: %s' %
                             (OpCode(reader.opcode), reader.data))

        return 0
Esempio n. 24
0
    def send_trainer_list(self, world_session):
        if not self.can_train(world_session.player_mgr):
            Logger.anticheat(f'send_trainer_list called from NPC {self.entry} by player with GUID {world_session.player_mgr.guid} but this unit does not train that player\'s class. Possible cheating')
            return

        train_spell_bytes: bytes = b''
        train_spell_count: int = 0

        trainer_ability_list: list[TrainerTemplate] = WorldDatabaseManager.TrainerSpellHolder.trainer_spells_get_by_trainer(self.entry)

        if not trainer_ability_list or trainer_ability_list.count == 0:
            Logger.warning(f'send_trainer_list called from NPC {self.entry} but no trainer spells found!')
            return

        for trainer_spell in trainer_ability_list:  # trainer_spell: The spell the trainer uses to teach the player.
            player_spell_id = trainer_spell.playerspell
            
            ability_spell_chain: SpellChain = WorldDatabaseManager.SpellChainHolder.spell_chain_get_by_spell(player_spell_id)

            spell_level: int = trainer_spell.reqlevel  # Use this and not spell data, as there are differences between data source (2003 Game Guide) and what is in spell table.
            spell_rank: int = ability_spell_chain.rank
            prev_spell: int = ability_spell_chain.prev_spell

            spell_is_too_high_level: bool = spell_level > world_session.player_mgr.level

            if player_spell_id in world_session.player_mgr.spell_manager.spells:
                status = TrainerServices.TRAINER_SERVICE_USED
            else:
                if prev_spell in world_session.player_mgr.spell_manager.spells and spell_rank > 1 and not spell_is_too_high_level:
                    status = TrainerServices.TRAINER_SERVICE_AVAILABLE
                elif spell_rank == 1 and not spell_is_too_high_level:
                    status = TrainerServices.TRAINER_SERVICE_AVAILABLE
                else:
                    status = TrainerServices.TRAINER_SERVICE_UNAVAILABLE

            data: bytes = pack(
                '<IBI3B6I',
                player_spell_id,  # Spell id
                status,  # Status
                trainer_spell.spellcost,  # Cost
                trainer_spell.talentpointcost,  # Talent Point Cost
                trainer_spell.skillpointcost,  # Skill Point Cost
                spell_level,  # Required Level
                trainer_spell.reqskill,  # Required Skill Line
                trainer_spell.reqskillvalue,  # Required Skill Rank
                0,  # Required Skill Step
                prev_spell,  # Required Ability (1)
                0,  # Required Ability (2)
                0  # Required Ability (3)
            )
            train_spell_bytes += data
            train_spell_count += 1

        # TODO: Temp placeholder.
        greeting: str = f'Hello, {world_session.player_mgr.player.name}! Ready for some training?'
        greeting_bytes = PacketWriter.string_to_bytes(greeting)
        greeting_bytes = pack(
                    f'<{len(greeting_bytes)}s', 
                    greeting_bytes
        )

        data = pack('<Q2I', self.guid, TrainerTypes.TRAINER_TYPE_GENERAL, train_spell_count) + train_spell_bytes + greeting_bytes
        world_session.player_mgr.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_TRAINER_LIST, data))
Esempio n. 25
0
    def handle(world_session, socket, reader):
        if len(reader.data) < 8:  # Avoid handling wrong player login packet.
            return -1

        guid = unpack('<Q', reader.data[:8])[0]

        world_session.player_mgr = PlayerManager(
            RealmDatabaseManager.character_get_by_guid(guid), world_session)
        world_session.player_mgr.session = world_session
        if not world_session.player_mgr.player:
            Logger.anticheat(
                f'Character with wrong guid ({guid}) tried to login.')
            return -1
        else:
            WorldSessionStateHandler.push_active_player_session(world_session)

        # Disabled race & class checks (only if not a GM)
        if not world_session.player_mgr.is_gm:
            disabled_race_mask = config.Server.General.disabled_race_mask
            disabled = disabled_race_mask & world_session.player_mgr.race_mask == world_session.player_mgr.race_mask

            if not disabled:
                disabled_class_mask = config.Server.General.disabled_class_mask
                disabled = disabled_class_mask & world_session.player_mgr.class_mask == world_session.player_mgr.class_mask

            if disabled:
                # Not 100% sure if CHAR_LOGIN_DISABLED matters here, but I don't know where else to send it
                data = pack('<B', CharLogin.CHAR_LOGIN_DISABLED)
                world_session.enqueue_packet(
                    PacketWriter.get_packet(OpCode.SMSG_CHARACTER_LOGIN_FAILED,
                                            data))
                return 0

        # Class & race allowed, continue with the login process

        world_session.enqueue_packet(
            PacketWriter.get_packet(OpCode.SMSG_LOGIN_SETTIMESPEED,
                                    PlayerLoginHandler._get_login_timespeed()))

        world_session.player_mgr.skill_manager.load_proficiencies()
        world_session.player_mgr.spell_manager.load_spells()

        world_session.player_mgr.deathbind = RealmDatabaseManager.character_get_deathbind(
            world_session.player_mgr.guid)
        world_session.player_mgr.friends_manager.load_from_db(
            RealmDatabaseManager.character_get_social(
                world_session.player_mgr.guid))

        world_session.enqueue_packet(
            world_session.player_mgr.get_deathbind_packet())
        # Tutorials aren't implemented in 0.5.3
        # world_session.enqueue_packet(world_session.player_mgr.get_tutorial_packet())
        world_session.player_mgr.skill_manager.init_proficiencies()
        world_session.enqueue_packet(
            world_session.player_mgr.spell_manager.get_initial_spells())
        world_session.enqueue_packet(
            world_session.player_mgr.get_action_buttons())

        # MotD
        ChatManager.send_system_message(world_session,
                                        config.Server.General.motd)

        world_session.player_mgr.inventory.load_items()
        world_session.player_mgr.stat_manager.init_stats()
        world_session.player_mgr.stat_manager.apply_bonuses()
        world_session.player_mgr.skill_manager.load_skills()
        world_session.player_mgr.quest_manager.load_quests()
        world_session.player_mgr.reputation_manager.load_reputations()
        GuildManager.set_character_guild(world_session.player_mgr)
        GroupManager.set_character_group(world_session.player_mgr)
        PetitionManager.load_petition(world_session.player_mgr)

        # First login
        if world_session.player_mgr.player.totaltime == 0:
            # Replenish health, and mana if needed.
            world_session.player_mgr.set_health(
                world_session.player_mgr.max_health)
            if world_session.player_mgr.power_type == PowerTypes.TYPE_MANA:
                world_session.player_mgr.set_mana(
                    world_session.player_mgr.max_power_1)

            # Load self before sending cinematic
            PlayerLoginHandler._load_self(world_session.player_mgr)

            # Send cinematic
            PlayerLoginHandler._send_cinematic(world_session,
                                               world_session.player_mgr.player,
                                               socket)
        else:
            PlayerLoginHandler._load_self(world_session.player_mgr)

        world_session.player_mgr.complete_login()

        return 0
Esempio n. 26
0
    def handle_movement_status(world_session, socket, reader):
        # Avoid handling malformed movement packets, or handling them while no player or player teleporting
        if world_session.player_mgr and not world_session.player_mgr.is_teleporting and len(reader.data) >= 48:
            try:
                transport_guid, transport_x, transport_y, transport_z, transport_o, x, y, z, o, pitch, flags = \
                    unpack('<Q9fI', reader.data[:48])

                # Hacky way to prevent random teleports when colliding with elevators
                # Also acts as a rudimentary teleport cheat detection
                if not world_session.player_mgr.pending_taxi_destination and world_session.player_mgr.location.distance(
                        x=x, y=y, z=z) > 64:
                    Logger.anticheat("Preventing coordinate desync from player %s (%s)." %
                                     (world_session.player_mgr.player.name, world_session.player_mgr.guid))
                    world_session.player_mgr.teleport(world_session.player_mgr.map_,
                                                      world_session.player_mgr.location)

                    return 0

                world_session.player_mgr.transport_id = transport_guid

                world_session.player_mgr.transport.x = transport_x
                world_session.player_mgr.transport.y = transport_y
                world_session.player_mgr.transport.z = transport_z
                world_session.player_mgr.transport.o = transport_o

                world_session.player_mgr.location.x = x
                world_session.player_mgr.location.y = y
                world_session.player_mgr.location.z = z
                world_session.player_mgr.location.o = o

                world_session.player_mgr.pitch = pitch
                world_session.player_mgr.movement_flags = flags

                if flags & MoveFlags.MOVEFLAG_SPLINE_MOVER:
                    world_session.player_mgr.movement_spline = MovementManager.MovementSpline.from_bytes(
                        reader.data[48:])

                movement_data = pack('<Q%us' % len(reader.data),
                                     world_session.player_mgr.guid,
                                     reader.data)

                GridManager.send_surrounding(PacketWriter.get_packet(OpCode(reader.opcode), movement_data),
                                             world_session.player_mgr, include_self=False)
                GridManager.update_object(world_session.player_mgr)
                world_session.player_mgr.sync_player()

                # Hackfix for client not sending CMSG_ATTACKSWING.
                # m_combat.m_attackSent getting stuck in true: https://i.imgur.com/LLasM8i.png
                # if reader.opcode == OpCode.MSG_MOVE_STOP or \
                #        reader.opcode == OpCode.MSG_MOVE_STOP_PITCH or \
                #        reader.opcode == OpCode.MSG_MOVE_STOP_STRAFE or \
                #        reader.opcode == OpCode.MSG_MOVE_STOP_TURN:
                #    data = pack('<2QI', world_session.player_mgr.guid, 0, 0)
                #    socket.sendall(PacketWriter.get_packet(OpCode.SMSG_ATTACKSTOP, data))

                # Get up if you jump while not standing
                if reader.opcode == OpCode.MSG_MOVE_JUMP and \
                        world_session.player_mgr.stand_state != StandState.UNIT_DEAD and \
                        world_session.player_mgr.stand_state != StandState.UNIT_STANDING:
                    world_session.player_mgr.stand_state = StandState.UNIT_STANDING
                    world_session.player_mgr.set_dirty()

            except (AttributeError, error):
                Logger.error('Error while handling %s, skipping. Data: %s' % (OpCode(reader.opcode), reader.data))

        return 0
Esempio n. 27
0
    def handle_movement_status(world_session, socket,
                               reader: PacketReader) -> int:
        # Avoid handling malformed movement packets, or handling them while no player or player teleporting.
        if world_session.player_mgr and len(reader.data) >= 48:
            try:
                transport_guid, transport_x, transport_y, transport_z, transport_o, x, y, z, o, pitch, flags = \
                    unpack('<Q9fI', reader.data[:48])

                # Hacky way to prevent random teleports when colliding with elevators
                # Also acts as a rudimentary teleport cheat detection
                if not world_session.player_mgr.pending_taxi_destination and \
                        world_session.player_mgr.location.distance(x=x, y=y, z=z) > 64:
                    Logger.anticheat(
                        f'Preventing coordinate desync from player {world_session.player_mgr.player.name} '
                        f'({world_session.player_mgr.guid}).')
                    world_session.player_mgr.teleport(
                        world_session.player_mgr.map_,
                        world_session.player_mgr.location,
                        is_instant=True)

                    return 0

                jumped = reader.opcode == OpCode.MSG_MOVE_JUMP

                # Movement and jump actions.
                if flags & (MoveFlags.MOVEFLAG_MOVE_MASK
                            | MoveFlags.MOVEFLAG_STRAFE_MASK) or jumped:
                    # Don't mark player as moved if only jumping.
                    if not jumped:
                        world_session.player_mgr.set_has_moved(True)

                    # Cancel looting if moved.
                    if world_session.player_mgr.loot_selection:
                        world_session.player_mgr.send_loot_release(
                            world_session.player_mgr.loot_selection)
                    world_session.player_mgr.spell_manager.check_spell_interrupts(
                        moved=True)
                    world_session.player_mgr.aura_manager.check_aura_interrupts(
                        moved=True)

                # Turn actions.
                if flags & MoveFlags.MOVEFLAG_TURN_MASK:
                    world_session.player_mgr.spell_manager.check_spell_interrupts(
                        turned=True)

                world_session.player_mgr.transport_id = transport_guid

                world_session.player_mgr.transport.x = transport_x
                world_session.player_mgr.transport.y = transport_y
                world_session.player_mgr.transport.z = transport_z
                world_session.player_mgr.transport.o = transport_o

                world_session.player_mgr.location.x = x
                world_session.player_mgr.location.y = y
                world_session.player_mgr.location.z = z
                world_session.player_mgr.location.o = o

                world_session.player_mgr.pitch = pitch
                world_session.player_mgr.movement_flags = flags

                if flags & MoveFlags.MOVEFLAG_SPLINE_MOVER:
                    world_session.player_mgr.movement_spline = MovementManager.MovementSpline.from_bytes(
                        reader.data[48:])

                # Broadcast player movement to surroundings.
                movement_data = pack(f'<Q{len(reader.data)}s',
                                     world_session.player_mgr.guid,
                                     reader.data)
                movement_packet = PacketWriter.get_packet(
                    OpCode(reader.opcode), movement_data)
                MapManager.send_surrounding(movement_packet,
                                            world_session.player_mgr,
                                            include_self=False)

                # Get up if you jump while not standing.
                if jumped and world_session.player_mgr.stand_state != StandState.UNIT_DEAD and \
                        world_session.player_mgr.stand_state != StandState.UNIT_STANDING:
                    world_session.player_mgr.set_stand_state(
                        StandState.UNIT_STANDING)

            except (AttributeError, error):
                Logger.error(
                    f'Error while handling {OpCode(reader.opcode).name}, skipping. Data: {reader.data}'
                )

        return 0
Esempio n. 28
0
    def handle(world_session, socket, reader):
        if len(reader.data) < 8:  # Avoid handling wrong player login packet
            return -1

        guid = unpack('<Q', reader.data[:8])[0]

        world_session.player_mgr = PlayerManager(
            RealmDatabaseManager.character_get_by_guid(guid), world_session)
        world_session.player_mgr.session = world_session
        if not world_session.player_mgr.player:
            Logger.anticheat('Character with wrong guid (%u) tried to login.' %
                             guid)
            return -1

        # Disabled race & class checks (only if not a GM)
        if not world_session.player_mgr.is_gm:
            disabled_race_mask = config.Server.General.disabled_race_mask
            disabled = disabled_race_mask & world_session.player_mgr.race_mask == world_session.player_mgr.race_mask

            if not disabled:
                disabled_class_mask = config.Server.General.disabled_class_mask
                disabled = disabled_class_mask & world_session.player_mgr.class_mask == world_session.player_mgr.class_mask

            if disabled:
                # Not 100% sure if CHAR_LOGIN_DISABLED matters here, but I don't know where else to send it
                data = pack('<B', CharLogin.CHAR_LOGIN_DISABLED)
                socket.sendall(
                    PacketWriter.get_packet(OpCode.SMSG_CHARACTER_LOGIN_FAILED,
                                            data))
                return 0

        # Class & race allowed, continue with the login process

        socket.sendall(
            PacketWriter.get_packet(OpCode.SMSG_LOGIN_SETTIMESPEED,
                                    PlayerLoginHandler._get_login_timespeed()))

        world_session.player_mgr.load_skills()
        world_session.player_mgr.load_spells()

        world_session.player_mgr.deathbind = RealmDatabaseManager.character_get_deathbind(
            world_session.player_mgr.guid)

        socket.sendall(world_session.player_mgr.get_deathbind_packet())
        #  Tutorials aren't implemented in 0.5.3
        #  socket.sendall(world_session.player_mgr.get_tutorial_packet())
        socket.sendall(world_session.player_mgr.get_initial_spells())
        socket.sendall(world_session.player_mgr.get_action_buttons())

        # MotD
        ChatManager.send_system_message(world_session,
                                        config.Server.General.motd)

        world_session.player_mgr.inventory.load_items()
        world_session.player_mgr.stat_manager.init_stats()
        world_session.player_mgr.stat_manager.apply_bonuses()
        world_session.player_mgr.send_update_self(create=True)
        world_session.player_mgr.reset_fields()

        PlayerLoginHandler._send_cinematic(world_session,
                                           world_session.player_mgr.player,
                                           socket)
        world_session.player_mgr.complete_login()

        return 0
Esempio n. 29
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data
               ) >= 12:  # Avoid handling empty trainer buy spell packet.

            trainer_guid: int = unpack('<Q', reader.data[:8])[0]
            spell_id: int = unpack('<I', reader.data[8:12])[0]

            # If the guid equals to player guid, training through a talent.
            if trainer_guid == world_session.player_mgr.guid:
                talent_mgr = world_session.player_mgr.talent_manager
                talent_cost = talent_mgr.get_talent_cost_by_id(spell_id)
                trainer_spell_id = WorldDatabaseManager.TrainerSpellHolder.trainer_spell_id_get_from_player_spell_id(
                    WorldDatabaseManager.TrainerSpellHolder.
                    TRAINER_TEMPLATE_TALENT_ID, spell_id)

                if talent_cost > world_session.player_mgr.talent_points:
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_NOT_ENOUGH_POINTS)
                    return 0
                elif spell_id in world_session.player_mgr.spell_manager.spells:
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_UNAVAILABLE)
                    return 0
                else:
                    world_session.player_mgr.spell_manager.handle_cast_attempt(
                        trainer_spell_id,
                        world_session.player_mgr,
                        SpellTargetMask.SELF,
                        validate=False)

                    world_session.player_mgr.remove_talent_points(talent_cost)
                    TrainerBuySpellHandler.send_trainer_buy_succeeded(
                        world_session, trainer_guid, spell_id)
                    # Send talent list again to refresh it.
                    world_session.player_mgr.talent_manager.send_talent_list()

            # Otherwise, using a trainer NPC.
            else:
                npc: CreatureManager = MapManager.get_surrounding_unit_by_guid(
                    world_session.player_mgr, trainer_guid)
                trainer_creature_template: CreatureTemplate = WorldDatabaseManager.creature_get_by_entry(
                    npc.entry)
                trainer_spell_id = WorldDatabaseManager.TrainerSpellHolder.trainer_spell_id_get_from_player_spell_id(
                    trainer_creature_template.trainer_id, spell_id)
                trainer_spell = WorldDatabaseManager.TrainerSpellHolder.trainer_spell_entry_get_by_trainer_and_spell(
                    trainer_creature_template.trainer_id, trainer_spell_id)
                spell_money_cost = trainer_spell.spellcost
                spell_skill_cost = trainer_spell.skillpointcost

                if not npc.is_trainer():  # Not a trainer.
                    Logger.anticheat(
                        f'Player with GUID {world_session.player_mgr.guid} tried to train spell {spell_id} from NPC {npc.entry} but that NPC is not a trainer. Possible cheating.'
                    )
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_UNAVAILABLE)

                    return 0
                elif not npc.can_train(world_session.player_mgr):
                    Logger.anticheat(
                        f'Player with GUID {world_session.player_mgr.guid} tried to train spell {spell_id} from NPC {npc.entry} but that NPC does not train that player. Possible cheating.'
                    )
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_UNAVAILABLE)

                    return 0
                elif not npc.trainer_has_spell(
                        trainer_spell_id
                ):  # Doesn't have that spell in its train list.
                    Logger.anticheat(
                        f'Player with GUID {world_session.player_mgr.guid} tried to train spell {spell_id} from NPC {npc.entry} but that NPC does not train that spell. Possible cheating.'
                    )
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_UNAVAILABLE)

                    return 0
                elif spell_money_cost > 0 and spell_money_cost > world_session.player_mgr.coinage:
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_NOT_ENOUGH_MONEY)

                    return 0
                elif spell_skill_cost > 0 and spell_skill_cost > world_session.player_mgr.skill_points:
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_NOT_ENOUGH_POINTS)

                    return 0
                elif spell_id in world_session.player_mgr.spell_manager.spells:
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_UNAVAILABLE)

                    return 0
                elif not world_session.player_mgr.is_gm and not npc.is_within_interactable_distance(
                        world_session.player_mgr):  # buyspell console command.
                    TrainerBuySpellHandler.send_trainer_buy_fail(
                        world_session, trainer_guid, spell_id,
                        TrainingFailReasons.TRAIN_FAIL_UNAVAILABLE)

                    return 0
                else:
                    npc.spell_manager.handle_cast_attempt(
                        trainer_spell_id,
                        world_session.player_mgr,
                        SpellTargetMask.UNIT,
                        validate=False)

                    if spell_money_cost > 0:
                        world_session.player_mgr.mod_money(-spell_money_cost)

                    if spell_skill_cost > 0:  # Some trainer spells cost skill points in alpha - class trainers trained weapon skills, which cost skill points.
                        world_session.player_mgr.remove_skill_points(
                            spell_skill_cost)

                    TrainerBuySpellHandler.send_trainer_buy_succeeded(
                        world_session, trainer_guid, spell_id)
                    # TODO Revisit later - re-sending the list is (probably) not the way it should be done,
                    #  as it resets the selected spell & spell filters (avail, unavail etc.).
                    npc.send_trainer_list(world_session)

        return 0
Esempio n. 30
0
    def handle(world_session, socket, reader: PacketReader) -> int:
        if len(reader.data) < 8:  # Avoid handling wrong player login packet.
            return -1

        guid = unpack('<Q', reader.data[:8])[0]

        world_session.player_mgr = PlayerManager(
            RealmDatabaseManager.character_get_by_guid(guid), world_session)

        if not world_session.player_mgr.player:
            Logger.anticheat(
                f'Character with wrong guid ({guid}) tried to login.')
            return -1
        else:
            WorldSessionStateHandler.push_active_player_session(world_session)

        # Disabled race & class checks (only if not a GM).
        if not world_session.player_mgr.is_gm:
            disabled_race_mask = config.Server.General.disabled_race_mask
            disabled = disabled_race_mask & world_session.player_mgr.race_mask == world_session.player_mgr.race_mask

            if not disabled:
                disabled_class_mask = config.Server.General.disabled_class_mask
                disabled = disabled_class_mask & world_session.player_mgr.class_mask == world_session.player_mgr.class_mask

            if disabled:
                # Not 100% sure if CHAR_LOGIN_DISABLED matters here, but I don't know where else to send it.
                data = pack('<B', CharLogin.CHAR_LOGIN_DISABLED)
                world_session.enqueue_packet(
                    PacketWriter.get_packet(OpCode.SMSG_CHARACTER_LOGIN_FAILED,
                                            data))
                return 0

        # Class & race allowed, continue with the login process.

        world_session.enqueue_packet(
            PacketWriter.get_packet(OpCode.SMSG_LOGIN_SETTIMESPEED,
                                    PlayerLoginHandler._get_login_timespeed()))

        world_session.player_mgr.skill_manager.load_proficiencies()
        world_session.player_mgr.skill_manager.load_skills()
        world_session.player_mgr.spell_manager.load_spells()

        world_session.player_mgr.deathbind = RealmDatabaseManager.character_get_deathbind(
            world_session.player_mgr.guid)
        world_session.player_mgr.friends_manager.load_from_db(
            RealmDatabaseManager.character_get_social(
                world_session.player_mgr.guid))

        # Only send the deathbind packet if it's a Binder NPC what bound the player.
        if world_session.player_mgr.deathbind.creature_binder_guid > 0:
            world_session.enqueue_packet(
                world_session.player_mgr.get_deathbind_packet())
        # Tutorials aren't implemented in 0.5.3.
        # world_session.enqueue_packet(world_session.player_mgr.get_tutorial_packet())
        world_session.enqueue_packet(
            world_session.player_mgr.spell_manager.get_initial_spells())
        world_session.enqueue_packet(
            world_session.player_mgr.get_action_buttons())

        # MotD.
        ChatManager.send_system_message(world_session,
                                        config.Server.General.motd)

        world_session.player_mgr.inventory.load_items()

        # Initialize stats first to have existing base stats for further calculations.
        world_session.player_mgr.stat_manager.init_stats()

        # Passive spells contain skill and proficiency learning.
        # Perform passive spell casts after loading skills to avoid duplicate database entries.
        world_session.player_mgr.spell_manager.cast_passive_spells()
        world_session.player_mgr.spell_manager.apply_cast_when_learned_spells()
        world_session.player_mgr.skill_manager.init_proficiencies()

        world_session.player_mgr.quest_manager.load_quests()
        world_session.player_mgr.reputation_manager.load_reputations()
        GuildManager.set_character_guild(world_session.player_mgr)
        GroupManager.set_character_group(world_session.player_mgr)
        PetitionManager.load_petition(world_session.player_mgr)

        first_login = world_session.player_mgr.player.totaltime == 0
        # Send cinematic.
        if first_login:
            PlayerLoginHandler._send_cinematic(world_session,
                                               world_session.player_mgr.player,
                                               socket)

        world_session.player_mgr.complete_login(first_login=first_login)

        return 0