diff --git a/BaseClasses.py b/BaseClasses.py
index 3c13c868..af864165 100644
--- a/BaseClasses.py
+++ b/BaseClasses.py
@@ -1028,11 +1028,12 @@ class Location:
access_rule = staticmethod(lambda state: True)
item_rule = staticmethod(lambda item: True)
item: Optional[Item] = None
+ parent_region: Optional[Region]
def __init__(self, player: int, name: str = '', address: int = None, parent=None):
self.name: str = name
self.address: Optional[int] = address
- self.parent_region: Region = parent
+ self.parent_region = parent
self.player: int = player
def can_fill(self, state: CollectionState, item: Item, check_access=True) -> bool:
diff --git a/WebHostLib/__init__.py b/WebHostLib/__init__.py
index be7c442a..6d31ac15 100644
--- a/WebHostLib/__init__.py
+++ b/WebHostLib/__init__.py
@@ -112,7 +112,7 @@ def games():
worlds = {}
for game, world in AutoWorldRegister.world_types.items():
if not world.hidden:
- worlds[game] = world.__doc__ if world.__doc__ else "No description provided."
+ worlds[game] = world
return render_template("supportedGames.html", worlds=worlds)
diff --git a/WebHostLib/options.py b/WebHostLib/options.py
index e1483442..d54b3217 100644
--- a/WebHostLib/options.py
+++ b/WebHostLib/options.py
@@ -132,7 +132,7 @@ def create():
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:
+ 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
diff --git a/WebHostLib/templates/supportedGames.html b/WebHostLib/templates/supportedGames.html
index 7ed14ce0..90e16781 100644
--- a/WebHostLib/templates/supportedGames.html
+++ b/WebHostLib/templates/supportedGames.html
@@ -9,12 +9,17 @@
{% include 'header/grassHeader.html' %}
Currently Supported Games
- {% for game, description in worlds.items() | sort %}
-
+ {% for game_name, world in worlds.items() | sort %}
+
- Settings Page
+ {% if world.web.settings_page is string %}
+ Settings Page
- {{ description }}
+ {% elif world.web.settings_page %}
+ Settings Page
+
+ {% endif %}
+ {{ world.__doc__ | default("No description provided.", true) }}
{% endfor %}
diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py
index c906c97c..5445f2cf 100644
--- a/worlds/AutoWorld.py
+++ b/worlds/AutoWorld.py
@@ -1,7 +1,7 @@
from __future__ import annotations
import logging
-from typing import Dict, Set, Tuple, List, Optional, TextIO, Any, Callable
+from typing import Dict, Set, Tuple, List, Optional, TextIO, Any, Callable, Union
from BaseClasses import MultiWorld, Item, CollectionState, Location
from Options import Option
@@ -73,6 +73,12 @@ def call_stage(world: MultiWorld, method_name: str, *args):
stage_callable(world, *args)
+class WebWorld:
+ """Webhost integration"""
+ # display a settings page. Can be a link to an out-of-ap settings tool too.
+ settings_page: Union[bool, str] = True
+
+
class World(metaclass=AutoWorldRegister):
"""A World object encompasses a game's Items, Locations, Rules and additional data or functionality required.
A Game should have its own subclass of World in which it defines the required data structures."""
@@ -130,6 +136,8 @@ class World(metaclass=AutoWorldRegister):
# For example the "full" tech tree information option in Factorio
sending_visible: bool = False
+ web: WebWorld = WebWorld()
+
def __init__(self, world: MultiWorld, player: int):
self.world = world
self.player = player
@@ -250,3 +258,4 @@ class World(metaclass=AutoWorldRegister):
# please use a prefix as all of them get clobbered together
class LogicMixin(metaclass=AutoLogicRegister):
pass
+
diff --git a/worlds/ff1/__init__.py b/worlds/ff1/__init__.py
index 487259a9..7cb09fc7 100644
--- a/worlds/ff1/__init__.py
+++ b/worlds/ff1/__init__.py
@@ -3,7 +3,11 @@ from BaseClasses import Item, Location, MultiWorld
from .Items import ItemData, FF1Items, FF1_STARTER_ITEMS, FF1_PROGRESSION_LIST, FF1_BRIDGE
from .Locations import EventId, FF1Locations, generate_rule, CHAOS_TERMINATED_EVENT
from .Options import ff1_options
-from ..AutoWorld import World
+from ..AutoWorld import World, WebWorld
+
+
+class FF1Web(WebWorld):
+ settings_page = "https://finalfantasyrandomizer.com/"
class FF1World(World):
@@ -28,6 +32,8 @@ class FF1World(World):
item_name_to_id = ff1_items.get_item_name_to_code_dict()
location_name_to_id = ff1_locations.get_location_name_to_address_dict()
+ web = FF1Web()
+
def __init__(self, world: MultiWorld, player: int):
super().__init__(world, player)
self.locked_items = []