def from_json(entity_dict):
     """Convert a dict representing a JSON object into an entity."""
     entity_class = Entity.get_entity_by_id(entity_dict["entity_id"])
     entity_pos = Vec(entity_dict["pos"]["x"], entity_dict["pos"]["y"])
     entity_velocity = Vec(entity_dict["velocity"]["x"],
                           entity_dict["velocity"]["y"])
     entity_facing = Direction.str_to_direction(entity_dict["facing"])
     ent = entity_class(entity_pos, entity_velocity, entity_facing)
     ent.uuid = uuid.UUID(entity_dict["uuid"])
     return ent
Exemple #2
0
async def parseMessage(message, username, ws):
    """Handle a message from a client."""
    player = running_game.get_player(username)
    world = World.get_world_by_id(player.world_id)
    if message.startswith("move|") or message.startswith("fastmove|"):
        if running_game.player_in_battle(username) or player.talking_to:
            return
        multiplier = 1
        if message.startswith("fastmove|"):
            multiplier = SPEED_MULTIPLIER
        parts = message.split("|")
        direction = parts[1]
        dir_vec = sum(
            [Vec.vec_from_direction_str(char) for char in set(direction)],
            Vec(0, 0))
        if dir_vec:
            player.facing = Direction.str_to_direction(direction[-1])
            start_pos = player.pos
            start_tiles = player.get_tiles_touched()
            now = time.monotonic()
            dt = min(now - player.time_of_last_move, MAX_MOVE_DT)
            player.time_of_last_move = now
            offset = dir_vec * (PLAYER_SPEED * dt * multiplier)
            player.pos += offset
            tile_coords_touching = player.get_tiles_touched()
            wall_tiles = [
                tile_coord for tile_coord in tile_coords_touching
                if world.get_tile(tile_coord).blocks_movement
            ]
            if wall_tiles:
                wall_tiles = [tile_coord.to_pos() for tile_coord in wall_tiles]
                wall_tiles.sort(
                    key=lambda tile_pos: tile_pos.dist_to(player.pos))
                for wall_tile in wall_tiles:
                    block_movement(Tile.get_bounding_box(wall_tile), start_pos,
                                   player)
                tile_coords_touching = player.get_tiles_touched()
            wall_entities = [
                entity for entity in world.entities
                if entity.blocks_movement and player.is_touching(entity)
            ]
            if wall_entities:
                wall_entities.sort(key=lambda wall_entity: wall_entity.pos.
                                   dist_to(player.pos))
                for wall_entity in wall_entities:
                    block_movement(wall_entity.get_bounding_box(), start_pos,
                                   player)
            tile_coords_moved_on = [
                tile_coord for tile_coord in tile_coords_touching
                if tile_coord not in start_tiles
            ]
            for tile_coord in tile_coords_moved_on:
                tile_moved_on = world.get_tile(tile_coord)
                await tile_moved_on.on_move_on(
                    TileEventContext(game=running_game,
                                     ws=ws,
                                     username=username,
                                     world=world,
                                     player=player,
                                     tile_pos=tile_coord.to_pos()), start_pos)
            await Util.send_moved_to(ws, player.pos)
    elif message.startswith("interact"):
        if running_game.player_in_battle(username):
            return
        if player.talking_to:
            await player.talking_to.on_interact(
                EntityEventContext(game=running_game,
                                   ws=ws,
                                   username=username,
                                   world=world,
                                   player=player))
        else:
            for tile_coord in player.get_tiles_touched():
                tile_interacted = world.get_tile(tile_coord)
                await tile_interacted.on_interact(
                    TileEventContext(game=running_game,
                                     ws=ws,
                                     username=username,
                                     world=world,
                                     player=player,
                                     tile_pos=tile_coord.to_pos()))
            for entity_interacted in player.get_entities_can_interact(world):
                await entity_interacted.on_interact(
                    EntityEventContext(game=running_game,
                                       ws=ws,
                                       username=username,
                                       world=world,
                                       player=player))
            for player_in_game in running_game.players:
                if (player_in_game.world_id == player.world_id
                        and player_in_game.is_touching(player)
                        and player_in_game.username != username):
                    await Util.send_tag(running_game, username,
                                        player_in_game.username)
    elif message.startswith("getupdates"):
        if running_game.player_in_battle(username):
            return
        await Util.send_players(running_game, ws, username, player.world_id)
        await Util.send_entities(ws, world)
    elif message.startswith("dialoguechoose"):
        if running_game.player_in_battle(username):
            return
        parts = message.split("|")
        entity_uuid = uuid.UUID(hex=parts[1])
        entity_speaking_to = world.get_entity(entity_uuid)
        try:
            await entity_speaking_to.on_dialogue_choose(
                EntityEventContext(game=running_game,
                                   ws=ws,
                                   username=username,
                                   world=world,
                                   player=player), int(parts[2]))
        except ValueError:
            pass
    elif message.startswith("battlemove"):
        if not running_game.player_in_battle(username):
            return
        parts = message.split("|")
        try:
            move_choice = player.moves[int(parts[1])]
            battle = running_game.get_battle_by_username(username)
            battle_state = battle.process_player_move(move_choice)
            if battle_state is BattleState.ONGOING:
                await Util.send_move_request(ws, player.moves)
                await Util.send_battle_status(ws, player.hp,
                                              battle.ai_combatant.hp)
            elif battle_state is BattleState.PLAYER_WIN:
                await Util.send_battle_end(ws)
                running_game.del_battle_by_username(username)
            elif battle_state is BattleState.AI_WIN:
                await Util.send_battle_end(ws)
                await Util.send_death(ws)
                running_game.del_battle_by_username(username)
                player.respawn()
                await Util.send_world(ws,
                                      World.get_world_by_id(player.world_id),
                                      player.pos)
        except ValueError:
            pass