From a8b105267cb64ae79be73c7f566138750d29637a Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Mon, 11 Oct 2021 00:46:18 +0200 Subject: [PATCH] WebHost: add hint cost and forfeit mode to webgen page --- Main.py | 30 +++++++++++++++++---------- WebHostLib/autolauncher.py | 2 +- WebHostLib/generate.py | 28 +++++++++++++++++++------ WebHostLib/static/styles/generate.css | 2 +- WebHostLib/templates/generate.html | 12 +++++++++++ WebHostLib/templates/viewSeed.html | 16 -------------- 6 files changed, 55 insertions(+), 35 deletions(-) diff --git a/Main.py b/Main.py index 3c2fb39b..abf3a380 100644 --- a/Main.py +++ b/Main.py @@ -7,7 +7,7 @@ import concurrent.futures import pickle import tempfile import zipfile -from typing import Dict, Tuple +from typing import Dict, Tuple, Optional from BaseClasses import MultiWorld, CollectionState, Region, RegionType from worlds.alttp.Items import item_name_groups @@ -19,7 +19,16 @@ from worlds.generic.Rules import locality_rules, exclusion_rules from worlds import AutoWorld -def main(args, seed=None): +ordered_areas = ( + 'Light World', 'Dark World', 'Hyrule Castle', 'Agahnims Tower', 'Eastern Palace', 'Desert Palace', + 'Tower of Hera', 'Palace of Darkness', 'Swamp Palace', 'Skull Woods', 'Thieves Town', 'Ice Palace', + 'Misery Mire', 'Turtle Rock', 'Ganons Tower', "Total" +) + + +def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = None): + if not baked_server_options: + baked_server_options = get_options()["server_options"] if args.outputpath: os.makedirs(args.outputpath, exist_ok=True) output_path.cached_path = args.outputpath @@ -159,15 +168,15 @@ def main(args, seed=None): output = tempfile.TemporaryDirectory() with output as temp_dir: - with concurrent.futures.ThreadPoolExecutor(world.players+2) as pool: + with concurrent.futures.ThreadPoolExecutor(world.players + 2) as pool: check_accessibility_task = pool.submit(world.fulfills_accessibility) output_file_futures = [pool.submit(AutoWorld.call_stage, world, "generate_output", temp_dir)] for player in world.player_ids: # skip starting a thread for methods that say "pass". if AutoWorld.World.generate_output.__code__ is not world.worlds[player].generate_output.__code__: - output_file_futures.append(pool.submit(AutoWorld.call_single, world, "generate_output", player, temp_dir)) - + output_file_futures.append( + pool.submit(AutoWorld.call_single, world, "generate_output", player, temp_dir)) def get_entrance_to_region(region: Region): for entrance in region.entrances: @@ -188,9 +197,7 @@ def main(args, seed=None): if lookup_vanilla_location_to_entrance[location.address] != main_entrance.name: er_hint_data[region.player][location.address] = main_entrance.name - ordered_areas = ('Light World', 'Dark World', 'Hyrule Castle', 'Agahnims Tower', 'Eastern Palace', 'Desert Palace', - 'Tower of Hera', 'Palace of Darkness', 'Swamp Palace', 'Skull Woods', 'Thieves Town', 'Ice Palace', - 'Misery Mire', 'Turtle Rock', 'Ganons Tower', "Total") + checks_in_area = {player: {area: list() for area in ordered_areas} for player in range(1, world.players + 1)} @@ -219,8 +226,9 @@ def main(args, seed=None): for index, take_any in enumerate(takeanyregions): for region in [world.get_region(take_any, player) for player in world.get_game_players("A Link to the Past") if world.retro[player]]: - item = world.create_item(region.shop.inventory[(0 if take_any == "Old Man Sword Cave" else 1)]['item'], - region.player) + item = world.create_item( + region.shop.inventory[(0 if take_any == "Old Man Sword Cave" else 1)]['item'], + region.player) player = region.player location_id = SHOP_ID_START + total_shop_slots + index @@ -286,7 +294,7 @@ def main(args, seed=None): world.worlds[player].remote_start_inventory}, "locations": locations_data, "checks_in_area": checks_in_area, - "server_options": get_options()["server_options"], + "server_options": baked_server_options, "er_hint_data": er_hint_data, "precollected_items": precollected_items, "precollected_hints": precollected_hints, diff --git a/WebHostLib/autolauncher.py b/WebHostLib/autolauncher.py index b2f60812..0c1c2b6d 100644 --- a/WebHostLib/autolauncher.py +++ b/WebHostLib/autolauncher.py @@ -89,7 +89,7 @@ def launch_generator(pool: multiprocessing.pool.Pool, generation: Generation): options = restricted_loads(generation.options) logging.info(f"Generating {generation.id} for {len(options)} players") pool.apply_async(gen_game, (options,), - {"race": meta["race"], + {"meta": meta, "sid": generation.id, "owner": generation.owner}, handle_generation_success, handle_generation_failure) diff --git a/WebHostLib/generate.py b/WebHostLib/generate.py index 60251ca3..ac16d7c9 100644 --- a/WebHostLib/generate.py +++ b/WebHostLib/generate.py @@ -4,6 +4,7 @@ import random import json import zipfile from collections import Counter +from typing import Dict, Optional as TypeOptional from flask import request, flash, redirect, url_for, session, render_template @@ -33,6 +34,14 @@ def generate(race=False): flash(options) else: results, gen_options = roll_options(options) + # get form data -> server settings + hint_cost = int(request.form.get("hint_cost", 10)) + forfeit_mode = request.form.get("forfeit_mode", "goal") + meta = {"race": race, "hint_cost": hint_cost, "forfeit_mode": forfeit_mode} + if race: + meta["item_cheat"] = False + meta["remaining"] = False + if any(type(result) == str for result in results.values()): return render_template("checkResult.html", results=results) elif len(gen_options) > app.config["MAX_ROLL"]: @@ -42,7 +51,8 @@ def generate(race=False): gen = Generation( options=pickle.dumps({name: vars(options) for name, options in gen_options.items()}), # convert to json compatible - meta=json.dumps({"race": race}), state=STATE_QUEUED, + meta=json.dumps(meta), + state=STATE_QUEUED, owner=session["_id"]) commit() @@ -50,18 +60,24 @@ def generate(race=False): else: try: seed_id = gen_game({name: vars(options) for name, options in gen_options.items()}, - race=race, owner=session["_id"].int) + meta=meta, owner=session["_id"].int) except BaseException as e: from .autolauncher import handle_generation_failure handle_generation_failure(e) - return render_template("seedError.html", seed_error=(e.__class__.__name__ + ": "+ str(e))) + return render_template("seedError.html", seed_error=(e.__class__.__name__ + ": " + str(e))) return redirect(url_for("viewSeed", seed=seed_id)) return render_template("generate.html", race=race) -def gen_game(gen_options, race=False, owner=None, sid=None): +def gen_game(gen_options, meta: TypeOptional[Dict[str, object]] = None, owner=None, sid=None): + if not meta: + meta: Dict[str, object] = {} + + meta.setdefault("hint_cost", 10) + race = meta.get("race", False) + del (meta["race"]) try: target = tempfile.TemporaryDirectory() playercount = len(gen_options) @@ -95,7 +111,7 @@ def gen_game(gen_options, race=False, owner=None, sid=None): erargs.name[player] = os.path.splitext(os.path.split(playerfile)[-1])[0] erargs.name[player] = handle_name(erargs.name[player], player, name_counter) - ERmain(erargs, seed) + ERmain(erargs, seed, baked_server_options=meta) return upload_to_db(target.name, sid, owner, race) except BaseException as e: @@ -105,7 +121,7 @@ def gen_game(gen_options, race=False, owner=None, sid=None): if gen is not None: gen.state = STATE_ERROR meta = json.loads(gen.meta) - meta["error"] = (e.__class__.__name__ + ": "+ str(e)) + meta["error"] = (e.__class__.__name__ + ": " + str(e)) gen.meta = json.dumps(meta) commit() diff --git a/WebHostLib/static/styles/generate.css b/WebHostLib/static/styles/generate.css index d7406682..676865c0 100644 --- a/WebHostLib/static/styles/generate.css +++ b/WebHostLib/static/styles/generate.css @@ -25,6 +25,6 @@ margin-bottom: 1rem; } -#generate-game-form{ +#file-input{ display: none; } diff --git a/WebHostLib/templates/generate.html b/WebHostLib/templates/generate.html index 398463a6..57bc25f8 100644 --- a/WebHostLib/templates/generate.html +++ b/WebHostLib/templates/generate.html @@ -37,6 +37,18 @@
+ +
diff --git a/WebHostLib/templates/viewSeed.html b/WebHostLib/templates/viewSeed.html index d8ba3d1c..36271cad 100644 --- a/WebHostLib/templates/viewSeed.html +++ b/WebHostLib/templates/viewSeed.html @@ -12,10 +12,6 @@

Seed Info

- {% if not seed.multidata and not seed.spoiler %} -

Single Player Race Rom: No spoiler or multidata exists, parts of the rom are encrypted and rooms - cannot be created.

- {% endif %} @@ -33,18 +29,6 @@ {% endif %} {% if seed.multidata %} - - - -
Players:  - -
Rooms: