171 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
	
import json
 | 
						|
import logging
 | 
						|
import os
 | 
						|
import typing
 | 
						|
 | 
						|
import yaml
 | 
						|
from jinja2 import Template
 | 
						|
 | 
						|
import Options
 | 
						|
from Utils import __version__, local_path
 | 
						|
from worlds.AutoWorld import AutoWorldRegister
 | 
						|
 | 
						|
handled_in_js = {"start_inventory", "local_items", "non_local_items", "start_hints", "start_location_hints",
 | 
						|
                 "exclude_locations"}
 | 
						|
 | 
						|
 | 
						|
def create():
 | 
						|
    target_folder = local_path("WebHostLib", "static", "generated")
 | 
						|
    yaml_folder = os.path.join(target_folder, "configs")
 | 
						|
    os.makedirs(yaml_folder, exist_ok=True)
 | 
						|
 | 
						|
    for file in os.listdir(yaml_folder):
 | 
						|
        full_path: str = os.path.join(yaml_folder, file)
 | 
						|
        if os.path.isfile(full_path):
 | 
						|
            os.unlink(full_path)
 | 
						|
 | 
						|
    def dictify_range(option: typing.Union[Options.Range, Options.SpecialRange]):
 | 
						|
        data = {option.default: 50}
 | 
						|
        for sub_option in ["random", "random-low", "random-high"]:
 | 
						|
            if sub_option != option.default:
 | 
						|
                data[sub_option] = 0
 | 
						|
 | 
						|
        notes = {}
 | 
						|
        for name, number in getattr(option, "special_range_names", {}).items():
 | 
						|
            notes[name] = f"equivalent to {number}"
 | 
						|
            if number in data:
 | 
						|
                data[name] = data[number]
 | 
						|
                del data[number]
 | 
						|
            else:
 | 
						|
                data[name] = 0
 | 
						|
 | 
						|
        return data, notes
 | 
						|
 | 
						|
    def get_html_doc(option_type: type(Options.Option)) -> str:
 | 
						|
        if not option_type.__doc__:
 | 
						|
            return "Please document me!"
 | 
						|
        return "\n".join(line.strip() for line in option_type.__doc__.split("\n")).strip()
 | 
						|
 | 
						|
    weighted_settings = {
 | 
						|
        "baseOptions": {
 | 
						|
            "description": "Generated by https://archipelago.gg/",
 | 
						|
            "name": "Player",
 | 
						|
            "game": {},
 | 
						|
        },
 | 
						|
        "games": {},
 | 
						|
    }
 | 
						|
 | 
						|
    for game_name, world in AutoWorldRegister.world_types.items():
 | 
						|
 | 
						|
        all_options: typing.Dict[str, Options.AssembleOptions] = {
 | 
						|
            **Options.per_game_common_options,
 | 
						|
            **world.option_definitions
 | 
						|
        }
 | 
						|
        with open(local_path("WebHostLib", "templates", "options.yaml")) as f:
 | 
						|
            file_data = f.read()
 | 
						|
        res = Template(file_data).render(
 | 
						|
            options=all_options,
 | 
						|
            __version__=__version__, game=game_name, yaml_dump=yaml.dump,
 | 
						|
            dictify_range=dictify_range,
 | 
						|
        )
 | 
						|
 | 
						|
        del file_data
 | 
						|
 | 
						|
        with open(os.path.join(target_folder, "configs", game_name + ".yaml"), "w", encoding="utf-8") as f:
 | 
						|
            f.write(res)
 | 
						|
 | 
						|
        # Generate JSON files for player-settings pages
 | 
						|
        player_settings = {
 | 
						|
            "baseOptions": {
 | 
						|
                "description": "Generated by https://archipelago.gg/",
 | 
						|
                "game": game_name,
 | 
						|
                "name": "Player",
 | 
						|
            },
 | 
						|
        }
 | 
						|
 | 
						|
        game_options = {}
 | 
						|
        for option_name, option in all_options.items():
 | 
						|
            if option_name in handled_in_js:
 | 
						|
                pass
 | 
						|
 | 
						|
            elif option.options:
 | 
						|
                game_options[option_name] = this_option = {
 | 
						|
                    "type": "select",
 | 
						|
                    "displayName": option.display_name if hasattr(option, "display_name") else option_name,
 | 
						|
                    "description": get_html_doc(option),
 | 
						|
                    "defaultValue": None,
 | 
						|
                    "options": []
 | 
						|
                }
 | 
						|
 | 
						|
                for sub_option_id, sub_option_name in option.name_lookup.items():
 | 
						|
                    this_option["options"].append({
 | 
						|
                        "name": option.get_option_name(sub_option_id),
 | 
						|
                        "value": sub_option_name,
 | 
						|
                    })
 | 
						|
 | 
						|
                    if sub_option_id == option.default:
 | 
						|
                        this_option["defaultValue"] = sub_option_name
 | 
						|
 | 
						|
                if option.default == "random":
 | 
						|
                    this_option["defaultValue"] = "random"
 | 
						|
 | 
						|
            elif issubclass(option, Options.Range):
 | 
						|
                game_options[option_name] = {
 | 
						|
                    "type": "range",
 | 
						|
                    "displayName": option.display_name if hasattr(option, "display_name") else option_name,
 | 
						|
                    "description": get_html_doc(option),
 | 
						|
                    "defaultValue": option.default if hasattr(
 | 
						|
                        option, "default") and option.default != "random" else option.range_start,
 | 
						|
                    "min": option.range_start,
 | 
						|
                    "max": option.range_end,
 | 
						|
                }
 | 
						|
 | 
						|
                if issubclass(option, Options.SpecialRange):
 | 
						|
                    game_options[option_name]["type"] = 'special_range'
 | 
						|
                    game_options[option_name]["value_names"] = {}
 | 
						|
                    for key, val in option.special_range_names.items():
 | 
						|
                        game_options[option_name]["value_names"][key] = val
 | 
						|
 | 
						|
            elif getattr(option, "verify_item_name", False):
 | 
						|
                game_options[option_name] = {
 | 
						|
                    "type": "items-list",
 | 
						|
                    "displayName": option.display_name if hasattr(option, "display_name") else option_name,
 | 
						|
                    "description": get_html_doc(option),
 | 
						|
                }
 | 
						|
 | 
						|
            elif getattr(option, "verify_location_name", False):
 | 
						|
                game_options[option_name] = {
 | 
						|
                    "type": "locations-list",
 | 
						|
                    "displayName": option.display_name if hasattr(option, "display_name") else option_name,
 | 
						|
                    "description": get_html_doc(option),
 | 
						|
                }
 | 
						|
 | 
						|
            elif issubclass(option, Options.OptionList) or issubclass(option, Options.OptionSet):
 | 
						|
                if option.valid_keys:
 | 
						|
                    game_options[option_name] = {
 | 
						|
                        "type": "custom-list",
 | 
						|
                        "displayName": option.display_name if hasattr(option, "display_name") else option_name,
 | 
						|
                        "description": get_html_doc(option),
 | 
						|
                        "options": list(option.valid_keys),
 | 
						|
                    }
 | 
						|
 | 
						|
            else:
 | 
						|
                logging.debug(f"{option} not exported to Web Settings.")
 | 
						|
 | 
						|
        player_settings["gameOptions"] = game_options
 | 
						|
 | 
						|
        os.makedirs(os.path.join(target_folder, 'player-settings'), exist_ok=True)
 | 
						|
 | 
						|
        with open(os.path.join(target_folder, 'player-settings', game_name + ".json"), "w") as f:
 | 
						|
            json.dump(player_settings, f, indent=2, separators=(',', ': '))
 | 
						|
 | 
						|
        if not world.hidden and world.web.settings_page is True:
 | 
						|
            weighted_settings["baseOptions"]["game"][game_name] = 0
 | 
						|
            weighted_settings["games"][game_name] = {}
 | 
						|
            weighted_settings["games"][game_name]["gameSettings"] = game_options
 | 
						|
            weighted_settings["games"][game_name]["gameItems"] = tuple(world.item_names)
 | 
						|
            weighted_settings["games"][game_name]["gameLocations"] = tuple(world.location_names)
 | 
						|
 | 
						|
    with open(os.path.join(target_folder, 'weighted-settings.json'), "w") as f:
 | 
						|
        json.dump(weighted_settings, f, indent=2, separators=(',', ': '))
 |