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
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