2022-03-18 03:53:09 +00:00
|
|
|
import zipfile
|
|
|
|
import json
|
|
|
|
from io import BytesIO
|
|
|
|
|
2021-08-31 16:58:54 +00:00
|
|
|
from flask import send_file, Response, render_template
|
2020-08-03 17:27:40 +00:00
|
|
|
from pony.orm import select
|
|
|
|
|
2022-09-29 22:36:30 +00:00
|
|
|
from worlds.Files import AutoPatchRegister
|
|
|
|
from . import app, cache
|
|
|
|
from .models import Slot, Room, Seed
|
2020-08-03 17:27:40 +00:00
|
|
|
|
2021-11-13 19:52:30 +00:00
|
|
|
|
2020-08-03 17:27:40 +00:00
|
|
|
@app.route("/dl_patch/<suuid:room_id>/<int:patch_id>")
|
|
|
|
def download_patch(room_id, patch_id):
|
2021-05-14 13:25:57 +00:00
|
|
|
patch = Slot.get(id=patch_id)
|
2020-08-03 17:27:40 +00:00
|
|
|
if not patch:
|
|
|
|
return "Patch not found"
|
|
|
|
else:
|
|
|
|
room = Room.get(id=room_id)
|
|
|
|
last_port = room.last_port
|
2022-03-18 03:53:09 +00:00
|
|
|
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)
|
2022-06-07 22:35:35 +00:00
|
|
|
manifest["server"] = f"{app.config['PATCH_TARGET']}:{last_port}" if last_port else None
|
2022-03-18 03:53:09 +00:00
|
|
|
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)
|
2022-09-02 21:37:37 +00:00
|
|
|
if "patch_file_ending" in manifest:
|
|
|
|
patch_file_ending = manifest["patch_file_ending"]
|
|
|
|
else:
|
|
|
|
patch_file_ending = AutoPatchRegister.patch_types[patch.game].patch_file_ending
|
2022-03-24 16:03:05 +00:00
|
|
|
fname = f"P{patch.player_id}_{patch.player_name}_{app.jinja_env.filters['suuid'](room_id)}" \
|
2022-09-02 21:37:37 +00:00
|
|
|
f"{patch_file_ending}"
|
2022-03-18 03:53:09 +00:00
|
|
|
new_file.seek(0)
|
2022-08-05 13:53:28 +00:00
|
|
|
return send_file(new_file, as_attachment=True, download_name=fname)
|
2022-03-18 03:53:09 +00:00
|
|
|
else:
|
2022-09-29 22:36:30 +00:00
|
|
|
return "Old Patch file, no longer compatible."
|
2020-08-03 17:27:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
@app.route("/dl_spoiler/<suuid:seed_id>")
|
|
|
|
def download_spoiler(seed_id):
|
|
|
|
return Response(Seed.get(id=seed_id).spoiler, mimetype="text/plain")
|
|
|
|
|
|
|
|
|
2021-08-05 18:17:01 +00:00
|
|
|
@app.route("/slot_file/<suuid:room_id>/<int:player_id>")
|
|
|
|
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
|
2022-06-07 22:35:35 +00:00
|
|
|
patch.player_id == player_id).first()
|
2021-05-15 23:16:51 +00:00
|
|
|
|
|
|
|
if not slot_data:
|
|
|
|
return "Slot Data not found"
|
|
|
|
else:
|
|
|
|
import io
|
|
|
|
|
|
|
|
if slot_data.game == "Minecraft":
|
2021-08-05 18:17:01 +00:00
|
|
|
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)
|
2022-08-05 13:53:28 +00:00
|
|
|
return send_file(io.BytesIO(data), as_attachment=True, download_name=fname)
|
2021-05-16 20:59:45 +00:00
|
|
|
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"):
|
2022-06-07 22:35:35 +00:00
|
|
|
fname = name.rsplit("/", 1)[0] + ".zip"
|
Ocarina of Time (#64)
* first commit (not including OoT data files yet)
* added some basic options
* rule parser works now at least
* make sure to commit everything this time
* temporary change to BaseClasses for oot
* overworld location graph builds mostly correctly
* adding oot data files
* commenting out world options until later since they only existed to make the RuleParser work
* conversion functions between AP ids and OOT ids
* world graph outputs
* set scrub prices
* itempool generates, entrances connected, way too many options added
* fixed set_rules and set_shop_rules
* temp baseclasses changes
* Reaches the fill step now, old event-based system retained in case the new way breaks
* Song placements and misc fixes everywhere
* temporary changes to make oot work
* changed root exits for AP fill framework
* prevent infinite recursion due to OoT sharing usage of the address field
* age reachability works hopefully, songs are broken again
* working spoiler log generation on beatable-only
* Logic tricks implemented
* need this for logic tricks
* fixed map/compass being placed on Serenade location
* kill unreachable events before filling the world
* add a bunch of utility functions to prepare for rom patching
* move OptionList into generic options
* fixed some silly bugs with OptionList
* properly seed all random behavior (so far)
* ROM generation working
* fix hints trying to get alttp dungeon hint texts
* continue fixing hints
* add oot to network data package
* change item and location IDs to 66000 and 67000 range respectively
* push removed items to precollected items
* fixed various issues with cross-contamination with multiple world generation
* reenable glitched logic (hopefully)
* glitched world files age-check fix
* cleaned up some get_locations calls
* added token shuffle and scrub shuffle, modified some options slightly to make the parsing work
* reenable MQ dungeons
* fix forest mq exception
* made targeting style an option for now, will be cosmetic later
* reminder to move targeting to cosmetics
* some oot option maintenance
* enabled starting time of day
* fixed issue breaking shop slots in multiworld generation
* added "off" option for text shuffle and hints
* shopsanity functionality restored
* change patch file extension
* remove unnecessary utility functions + imports
* update MIT license
* change option to "patch_uncompressed_rom" instead of "compress_rom"
* compliance with new AutoWorld systems
* Kill only internal events, remove non-internal big poe event in code
* re-add the big poe event and handle it correctly
* remove extra method in Range option
* fix typo
* Starting items, starting with consumables option
* do not remove nonexistent item
* move set_shop_rules to after shop items are placed
* some cleanup
* add retries for song placement
* flagged Skull Mask and Mask of Truth as advancement items
* update OoT to use LogicMixin
* Fixed trying to assign starting items from the wrong players
* fixed song retry step
* improved option handling, comments, and starting item replacements
* DefaultOnToggle writes Yes or No to spoiler
* enable compression of output if Compress executable is present
* clean up compression
* check whether (de)compressor exists before running the process
* allow specification of rom path in host.yaml
* check if decompressed file already exists before decompressing again
* fix triforce hunt generation
* rename all the oot state functions with prefix
* OoT: mark triforce pieces as completion goal for triforce hunt
* added overworld and any-dungeon shuffle for dungeon items
* Hide most unshuffled locations and events from the list of locations in spoiler
* build oot option ranges with a generic function instead of defining each separately
* move oot output-type control to host.yaml instead of individual yamls
* implement dungeon song shuffle
* minor improvements to overworld dungeon item shuffle
* remove random ice trap names in shops, mostly to avoid maintaining a massive censor list
* always output patch file to folder, remove option to generate ROM in preparation for removal
* re-add the fix for infinite recursion due to not being light or dark world
* change AP-sendable to Ocarina of Time model, since the triforce piece has some extra code apparently
* oot: remove item_names and location_names
* oot: minor fixes
* oot: comment out ROM patching
* oot: only add CollectionState objects on creation if actually needed
* main entrance shuffle method and entrances-based rules
* fix entrances based rules
* disable master quest and big poe count options for client compatibility
* use get_player_name instead of get_player_names
* fix OptionList
* fix oot options for new option system
* new coop section in oot rom: expand player names to 16 bytes, write AP_PLAYER_NAME at end of PLAYER_NAMES
* fill AP player name in oot rom with 0 instead of 0xDF
* encode player name with ASCII for fixed-width
* revert oot player name array to 8 bytes per name
* remove Pierre location if fast scarecrow is on
* check player name length
* "free_scarecrow" not "fast_scarecrow"
* OoT locations now properly store the AP ID instead of the oot internal ID
* oot __version__ updates in lockstep with AP version
* pull in unmodified oot cosmetic files
* also grab JSONDump since it's needed apparently
* gather extra needed methods, modify imports
* delete cosmetics log, replace all instances of SettingsList with OOTWorld
* cosmetic options working, except for sound effects (due to ear-safe issues)
* SFX, Music, and Fanfare randomization reenabled
* move OoT data files into the worlds folder
* move Compress and Decompress into oot data folder
* Replace get_all_state with custom method to avoid the cache
* OoT ROM: increment item counter before setting incoming item/player values to 0, preventing desync issues
* set data_version to 0
* make Kokiri Sword shuffle off by default
* reenable "Random Choice" for various cosmetic options
* kill Ruto's Letter turnin if open fountain
also fix for shopsanity
* place Buy Goron/Zora Tunic first in shop shuffle
* make ice traps appear as other items instead of breaking generation
* managed to break ice traps on non-major-only
* only handle ice traps if they are on
* fix shopsanity for non-oot games, and write player name instead of player number
* light arrows hint uses player name instead of player number
* Reenable "skip child zelda" option
* fix entrances_based_rules
* fix ganondorf hint if starting with light arrows
* fix dungeonitem shuffle and shopsanity interaction
* remove has_all_of, has_any_of, count_of in BaseClasses, replace usage with has_all, has_any, has_group
* force local giveable item on ZL if skip_child_zelda and shuffle_song_items is any
* keep bosses and bombchu bowling chus out of data package
* revert workaround for infinite recursion and fix it properly
* fix shared shop id caches during patching process
* fix shop text box overflows, as much as possible
* add default oot host.yaml option
* add .apz5, .n64, .z64 to gitignore
* Properly document and name all (functioning) OOT options
* clean up some imports
* remove unnecessary files from oot's data
* fix typo in gitignore
* readd the Compress and Decompress utilities, since they are needed for generation
* cleanup of imports and some minor optimizations
* increase shop offset for item IDs to 0xCB
* remove shop item AP ids entirely
* prevent triforce pieces for other players from being received by yourself
* add "excluded" property to Location
* Hint system adapted and reenabled; hints still unseeded
* make hints deterministic with lists instead of sets
* do not allow hints to point to Light Arrows on non-vanilla bridge
* foreign locations hint as their full name in OoT rather than their region
* checkedLocations now stores hint names by player ID, so that the same location in different worlds can have hints associated
* consolidate versioning in Utils
* ice traps appear as major items rather than any progression item
* set prescription and claim check as defaults for adult trade item settings
* add oot options to playerSettings
* allow case-insensitive logic tricks in yaml
* fix oot shopsanity option formatting
* Write OoT override info even if local item, enabling local checks to show up immediately in the client
* implement CollectionState.can_live_dmg for oot glitched logic
* filter item names for invalid characters when patching shops
* make ice traps appear according to the settings of the world they are shuffled into, rather than the original world
* set hidden-spoiler items and locations with Shop items to events
* make GF carpenters, Gerudo Card, Malon, ZL, and Impa events if the relevant settings are enabled, preventing them from appearing in the client on game start
* Fix oot Glitched and No Logic generation
* fix indenting
* Greatly reduce displayed cosmetic options
* Change oot data version to 1
* add apz5 distribution to webhost
* print player name if an ALttP dungeon contains a good item for OoT world
* delete unneeded commented code
* remove OcarinaSongs import to satisfy lint
2021-09-02 12:35:05 +00:00
|
|
|
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"
|
2022-03-12 21:05:54 +00:00
|
|
|
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"
|
2022-07-20 10:48:14 +00:00
|
|
|
elif slot_data.game == "Dark Souls III":
|
|
|
|
fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}.json"
|
2021-05-15 23:16:51 +00:00
|
|
|
else:
|
|
|
|
return "Game download not supported."
|
2022-08-05 13:53:28 +00:00
|
|
|
return send_file(io.BytesIO(slot_data.data), as_attachment=True, download_name=fname)
|
2021-08-31 16:58:54 +00:00
|
|
|
|
2022-06-07 22:35:35 +00:00
|
|
|
|
2021-08-31 16:58:54 +00:00
|
|
|
@app.route("/templates")
|
|
|
|
@cache.cached()
|
|
|
|
def list_yaml_templates():
|
|
|
|
files = []
|
2021-08-31 17:06:24 +00:00
|
|
|
from worlds.AutoWorld import AutoWorldRegister
|
|
|
|
for world_name, world in AutoWorldRegister.world_types.items():
|
|
|
|
if not world.hidden:
|
|
|
|
files.append(world_name)
|
2022-06-07 22:35:35 +00:00
|
|
|
return render_template("templates.html", files=files)
|