示例#1
0
def download_slot_file(room_id, player_id: int):
    room = Room.get(id=room_id)
    slot_data: Slot = select(patch for patch in room.seed.slots
                             if patch.player_id == player_id).first()

    if not slot_data:
        return "Slot Data not found"
    else:
        import io

        if slot_data.game == "Minecraft":
            from worlds.minecraft import mc_update_output
            fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_P{slot_data.player_id}_{slot_data.player_name}.apmc"
            data = mc_update_output(slot_data.data,
                                    server=app.config['PATCH_TARGET'],
                                    port=room.last_port)
            return send_file(io.BytesIO(data),
                             as_attachment=True,
                             attachment_filename=fname)
        elif slot_data.game == "Factorio":
            with zipfile.ZipFile(io.BytesIO(slot_data.data)) as zf:
                for name in zf.namelist():
                    if name.endswith("info.json"):
                        fname = name.rsplit("/", 1)[0] + ".zip"
        elif slot_data.game == "Ocarina of Time":
            fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_P{slot_data.player_id}_{slot_data.player_name}.apz5"
        elif slot_data.game == "VVVVVV":
            fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_SP.apv6"
        elif slot_data.game == "Super Mario 64":
            fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_SP.apsm64ex"
        else:
            return "Game download not supported."
        return send_file(io.BytesIO(slot_data.data),
                         as_attachment=True,
                         attachment_filename=fname)
示例#2
0
def download_patch(room_id, patch_id):
    patch = Patch.get(id=patch_id)
    if not patch:
        return "Patch not found"
    else:
        import io

        room = Room.get(id=room_id)
        last_port = room.last_port

        patch_data = update_patch_data(
            patch.data, server=f"{app.config['PATCH_TARGET']}:{last_port}")
        patch_data = io.BytesIO(patch_data)

        fname = f"P{patch.player_id}_{patch.player_name}_{app.jinja_env.filters['suuid'](room_id)}.apbp"
        return send_file(patch_data,
                         as_attachment=True,
                         attachment_filename=fname)
示例#3
0
def download_patch(room_id, patch_id):
    patch = Slot.get(id=patch_id)
    if not patch:
        return "Patch not found"
    else:
        room = Room.get(id=room_id)
        last_port = room.last_port
        filelike = BytesIO(patch.data)
        greater_than_version_3 = zipfile.is_zipfile(filelike)
        if greater_than_version_3:
            # Python's zipfile module cannot overwrite/delete files in a zip, so we recreate the whole thing in ram
            new_file = BytesIO()
            with zipfile.ZipFile(filelike, "a") as zf:
                with zf.open("archipelago.json", "r") as f:
                    manifest = json.load(f)
                manifest[
                    "server"] = f"{app.config['PATCH_TARGET']}:{last_port}" if last_port else None
                with zipfile.ZipFile(new_file, "w") as new_zip:
                    for file in zf.infolist():
                        if file.filename == "archipelago.json":
                            new_zip.writestr("archipelago.json",
                                             json.dumps(manifest))
                        else:
                            new_zip.writestr(file.filename, zf.read(file),
                                             file.compress_type, 9)

            fname = f"P{patch.player_id}_{patch.player_name}_{app.jinja_env.filters['suuid'](room_id)}" \
                    f"{AutoPatchRegister.patch_types[patch.game].patch_file_ending}"
            new_file.seek(0)
            return send_file(new_file,
                             as_attachment=True,
                             attachment_filename=fname)
        else:
            patch_data = update_patch_data(
                patch.data, server=f"{app.config['PATCH_TARGET']}:{last_port}")
            patch_data = BytesIO(patch_data)

            fname = f"P{patch.player_id}_{patch.player_name}_{app.jinja_env.filters['suuid'](room_id)}." \
                    f"{preferred_endings[patch.game]}"
        return send_file(patch_data,
                         as_attachment=True,
                         attachment_filename=fname)
示例#4
0
def download_patch(room_id, patch_id):
    patch = Patch.get(id=patch_id)
    if not patch:
        return "Patch not found"
    else:
        import io

        room = Room.get(id=room_id)
        last_port = room.last_port
        pname = room.seed.multidata["names"][0][patch.player - 1]

        patch_data = update_patch_data(patch.data,
                                       server="berserkermulti.world:" +
                                       str(last_port))
        patch_data = io.BytesIO(patch_data)

        fname = f"P{patch.player}_{pname}_{app.jinja_env.filters['suuid'](room_id)}.bmbp"
        return send_file(patch_data,
                         as_attachment=True,
                         attachment_filename=fname)
示例#5
0
def getTracker(tracker: UUID):
    room = Room.get(tracker=tracker)
    if not room:
        abort(404)
    locations, names, use_door_tracker, seed_checks_in_area, player_location_to_area = get_static_room_data(
        room)

    inventory = {
        teamnumber: {
            playernumber: collections.Counter()
            for playernumber in range(1,
                                      len(team) + 1)
        }
        for teamnumber, team in enumerate(names)
    }

    checks_done = {
        teamnumber: {
            playernumber: {loc_name: 0
                           for loc_name in default_locations}
            for playernumber in range(1,
                                      len(team) + 1)
        }
        for teamnumber, team in enumerate(names)
    }
    precollected_items = room.seed.multidata.get("precollected_items", None)
    hints = {team: set() for team in range(len(names))}
    if "hints" in room.multisave:
        for key, hintdata in room.multisave["hints"]:
            for hint in hintdata:
                hints[key[0]].add(Hint(*hint))

    for (team, player), locations_checked in room.multisave.get(
            "location_checks", {}):
        if precollected_items:
            precollected = precollected_items[player - 1]
            for item_id in precollected:
                attribute_item(inventory, team, player, item_id)
        for location in locations_checked:
            if (location, player
                ) not in locations or location not in player_location_to_area[
                    player]:
                continue

            item, recipient = locations[location, player]
            attribute_item(inventory, team, recipient, item)
            checks_done[team][player][player_location_to_area[player]
                                      [location]] += 1
            checks_done[team][player]["Total"] += 1

    for (team,
         player), game_state in room.multisave.get("client_game_state", []):
        if game_state:
            inventory[team][player][106] = 1  # Triforce

    activity_timers = {}
    now = datetime.datetime.utcnow()
    for (team,
         player), timestamp in room.multisave.get("client_activity_timers",
                                                  []):
        activity_timers[
            team, player] = now - datetime.datetime.utcfromtimestamp(timestamp)

    player_names = {}
    for team, names in enumerate(names):
        for player, name in enumerate(names, 1):
            player_names[(team, player)] = name
    long_player_names = player_names.copy()
    for (team, player), alias in room.multisave.get("name_aliases", []):
        player_names[(team, player)] = alias
        long_player_names[(
            team, player)] = f"{alias} ({long_player_names[(team, player)]})"

    video = {}
    for (team, player), data in room.multisave.get("video", []):
        video[(team, player)] = data

    return render_template("tracker.html",
                           inventory=inventory,
                           get_item_name_from_id=get_item_name_from_id,
                           lookup_id_to_name=Items.lookup_id_to_name,
                           player_names=player_names,
                           tracking_names=tracking_names,
                           tracking_ids=tracking_ids,
                           room=room,
                           icons=icons,
                           multi_items=multi_items,
                           checks_done=checks_done,
                           ordered_areas=ordered_areas,
                           checks_in_area=seed_checks_in_area,
                           activity_timers=activity_timers,
                           key_locations=key_locations,
                           small_key_ids=small_key_ids,
                           big_key_ids=big_key_ids,
                           video=video,
                           big_key_locations=key_locations
                           if use_door_tracker else big_key_locations,
                           hints=hints,
                           long_player_names=long_player_names)
示例#6
0
def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int):
    # Team and player must be positive and greater than zero
    if tracked_team < 0 or tracked_player < 1:
        abort(404)

    room = Room.get(tracker=tracker)
    if not room:
        abort(404)

    # Collect seed information and pare it down to a single player
    locations, names, use_door_tracker, seed_checks_in_area, player_location_to_area, player_big_key_locations, player_small_key_locations, precollected_items = get_static_room_data(
        room)
    player_name = names[tracked_team][tracked_player - 1]
    seed_checks_in_area = seed_checks_in_area[tracked_player]
    location_to_area = player_location_to_area[tracked_player]
    inventory = collections.Counter()
    checks_done = {loc_name: 0 for loc_name in default_locations}

    # Add starting items to inventory
    starting_items = precollected_items[tracked_player - 1]
    if starting_items:
        for item_id in starting_items:
            attribute_item_solo(inventory, item_id)

    if room.multisave:
        multisave = restricted_loads(room.multisave)
    else:
        multisave = {}

    # Add items to player inventory
    for (ms_team,
         ms_player), locations_checked in multisave.get("location_checks", {}):
        # logging.info(f"{ms_team}, {ms_player}, {locations_checked}")
        # Skip teams and players not matching the request

        if ms_team == tracked_team:
            # If the player does not have the item, do nothing
            for location in locations_checked:
                if (location, ms_player) not in locations:
                    continue

                item, recipient = locations[location, ms_player]
                if recipient == tracked_player:  # a check done for the tracked player
                    attribute_item_solo(inventory, item)
                if ms_player == tracked_player:  # a check done by the tracked player
                    checks_done[location_to_area[location]] += 1
                    checks_done["Total"] += 1

    # Note the presence of the triforce item
    for (ms_team,
         ms_player), game_state in multisave.get("client_game_state", []):
        # Skip teams and players not matching the request
        if ms_team != tracked_team or ms_player != tracked_player:
            continue

        if game_state:
            inventory[106] = 1  # Triforce

    acquired_items = []
    for itm in inventory:
        acquired_items.append(get_item_name_from_id(itm))

    # Progressive items need special handling for icons and class
    progressive_items = {
        "Progressive Sword": 94,
        "Progressive Glove": 97,
        "Progressive Bow": 100,
        "Progressive Mail": 96,
        "Progressive Shield": 95,
    }

    # Determine which icon to use for the sword
    sword_url = icons["Fighter Sword"]
    sword_acquired = False
    sword_names = [
        'Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword'
    ]
    if "Progressive Sword" in acquired_items:
        sword_url = icons[sword_names[
            min(inventory[progressive_items["Progressive Sword"]], 4) - 1]]
        sword_acquired = True
    else:
        for sword in reversed(sword_names):
            if sword in acquired_items:
                sword_url = icons[sword]
                sword_acquired = True
                break

    gloves_url = icons["Power Glove"]
    gloves_acquired = False
    glove_names = ["Power Glove", "Titan Mitts"]
    if "Progressive Glove" in acquired_items:
        gloves_url = icons[glove_names[
            min(inventory[progressive_items["Progressive Glove"]], 2) - 1]]
        gloves_acquired = True
    else:
        for glove in reversed(glove_names):
            if glove in acquired_items:
                gloves_url = icons[glove]
                gloves_acquired = True
                break

    bow_url = icons["Bow"]
    bow_acquired = False
    bow_names = ["Bow", "Silver Bow"]
    if "Progressive Bow" in acquired_items:
        bow_url = icons[bow_names[
            min(inventory[progressive_items["Progressive Bow"]], 2) - 1]]
        bow_acquired = True
    else:
        for bow in reversed(bow_names):
            if bow in acquired_items:
                bow_url = icons[bow]
                bow_acquired = True
                break

    mail_url = icons["Green Mail"]
    mail_names = ["Blue Mail", "Red Mail"]
    if "Progressive Mail" in acquired_items:
        mail_url = icons[mail_names[
            min(inventory[progressive_items["Progressive Mail"]], 2) - 1]]
    else:
        for mail in reversed(mail_names):
            if mail in acquired_items:
                mail_url = icons[mail]
                break

    shield_url = icons["Blue Shield"]
    shield_acquired = False
    shield_names = ["Blue Shield", "Red Shield", "Mirror Shield"]
    if "Progressive Shield" in acquired_items:
        shield_url = icons[shield_names[
            min(inventory[progressive_items["Progressive Shield"]], 3) - 1]]
        shield_acquired = True
    else:
        for shield in reversed(shield_names):
            if shield in acquired_items:
                shield_url = icons[shield]
                shield_acquired = True
                break

    # The single player tracker doesn't care about overworld, underworld, and total checks. Maybe it should?
    sp_areas = ordered_areas[2:15]

    return render_template(
        "playerTracker.html",
        inventory=inventory,
        get_item_name_from_id=get_item_name_from_id,
        player_name=player_name,
        room=room,
        icons=icons,
        checks_done=checks_done,
        checks_in_area=seed_checks_in_area,
        acquired_items=acquired_items,
        sword_url=sword_url,
        sword_acquired=sword_acquired,
        gloves_url=gloves_url,
        gloves_acquired=gloves_acquired,
        bow_url=bow_url,
        bow_acquired=bow_acquired,
        small_key_ids=small_key_ids,
        big_key_ids=big_key_ids,
        sp_areas=sp_areas,
        key_locations=player_small_key_locations[tracked_player],
        big_key_locations=player_big_key_locations[tracked_player],
        mail_url=mail_url,
        shield_url=shield_url,
        shield_acquired=shield_acquired)