Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 1 addition & 46 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import logging
import os
from typing import Callable, Optional, ClassVar, Counter, Any
import webbrowser

import Utils
from worlds.generic.Rules import forbid_items_for_player
from worlds.LauncherComponents import Component, SuffixIdentifier, components, Type, launch_subprocess, icon_paths

from .Data import item_table, location_table, event_table, region_table, category_table
from .Game import game_name, filler_item_name, starting_items
Expand Down Expand Up @@ -418,7 +416,7 @@ def fill_slot_data(self):
if option_key in common_options:
continue
slot_data[option_key] = get_option_value(self.multiworld, self.player, option_key)

slot_data["visible_events"] = {}
for _, event in self.event_name_to_event.items():
event_name = event["name"]
Expand Down Expand Up @@ -543,46 +541,3 @@ def get_item_counts(self, player: Optional[int] = None, pool: list[Item] | None
else:
return self.item_counts.get(player, Counter())


###
# Non-world client methods
###

def launch_client(*args):
import CommonClient
from .ManualClient import launch as Main

if CommonClient.gui_enabled:
launch_subprocess(Main, name="Manual client")
else:
Main()

class VersionedComponent(Component):
def __init__(self, display_name: str, script_name: Optional[str] = None, func: Optional[Callable] = None, version: int = 0, file_identifier: Optional[Callable[[str], bool]] = None, icon: Optional[str] = None):
super().__init__(display_name=display_name, script_name=script_name, func=func, component_type=Type.CLIENT, file_identifier=file_identifier, icon=icon)
self.version = version

def add_client_to_launcher() -> None:
version = 2025_12_25 # YYYYMMDD
found = False

if "manual" not in icon_paths:
icon_paths["manual"] = Utils.user_path('data', 'manual.png')

discord_component = None
for c in components:
if c.display_name == "Manual Client":
found = True
if getattr(c, "version", 0) < version: # We have a newer version of the Manual Client than the one the last apworld added
c.version = version
c.func = launch_client
c.icon = "manual"
elif c.display_name == "Manual Discord Server":
discord_component = c

if not found:
components.append(VersionedComponent("Manual Client", "ManualClient", func=launch_client, version=version, file_identifier=SuffixIdentifier('.apmanual'), icon="manual"))
if not discord_component:
components.append(Component("Manual Discord Server", "ManualDiscord", func=lambda: webbrowser.open("https://discord.gg/hm4rQnTzQ5"), icon="discord", component_type=Type.ADJUSTER))

add_client_to_launcher()
12 changes: 8 additions & 4 deletions src/ManualClient.py → src_client/ManualClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from CommonClient import gui_enabled, logger, get_base_parser, ClientCommandProcessor, server_loop
from MultiServer import mark_raw

from . import CLIENT_VERSION

tracker_loaded = False
try:
from worlds.tracker.TrackerClient import TrackerGameContext as SuperContext, TrackerCommandProcessor
Expand Down Expand Up @@ -195,8 +197,7 @@ async def connection_closed(self):
def suggested_game(self) -> str:
if self.game:
return self.game
from .Game import game_name # This will at least give us the name of a manual they've installed
return Utils.persistent_load().get("client", {}).get("last_manual_game", game_name)
return Utils.persistent_load().get("client", {}).get("last_manual_game", "")

def get_location_by_name(self, name) -> dict[str, Any]:
location = self.location_table.get(name)
Expand Down Expand Up @@ -392,7 +393,7 @@ class ManualControlsStyledLayout(BoxLayout):
background_color = ColorProperty()

class ManualManager(ui):
base_title = "Archipelago Manual Client"
base_title = f"Manual for AP Client - Manual {CLIENT_VERSION}, AP"
listed_items = {"(No Category)": []}
item_categories = ["(No Category)"]
listed_locations = {"(No Category)": []}
Expand All @@ -419,9 +420,10 @@ def build(self) -> Layout:
self.manual_game_layout = BoxLayout(orientation="horizontal", size_hint_y=None, height=dp(30))

game_bar_label = Label(text="Manual Game ID", size=(dp(150), dp(30)), size_hint_y=None, size_hint_x=None)
manuals = [w for w in AutoWorldRegister.world_types.keys() if "Manual_" in w]
manuals = [w for w in AutoWorldRegister.world_types.keys() if "Manual_" in w and w != "Manual_Client"]
manuals.sort() # Sort by alphabetical order, not load order
self.manual_game_layout.add_widget(game_bar_label)

self.game_bar_text = Spinner(text=self.ctx.suggested_game, size_hint_y=None, height=dp(30), sync_height=True,
values=manuals, option_cls=GameSelectOption, dropdown_cls=GameSelectDropDown)
self.manual_game_layout.add_widget(self.game_bar_text)
Expand Down Expand Up @@ -1117,6 +1119,7 @@ async def main(args):
config_file = {}
if args.apmanual_file:
config_file = read_apmanual_file(args.apmanual_file)

ctx = ManualContext(args.connect, args.password, config_file.get("game"), config_file.get("player_name"))
ctx.server_task = asyncio.create_task(server_loop(ctx), name="server loop")

Expand Down Expand Up @@ -1163,3 +1166,4 @@ def launch() -> None:

if __name__ == '__main__':
launch()

46 changes: 46 additions & 0 deletions src_client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import webbrowser

from typing import Callable, Optional

import Utils
from worlds.LauncherComponents import Component, SuffixIdentifier, components, Type, launch_subprocess, icon_paths

CLIENT_VERSION = 2026_01_08 # YYYYMMDD

def launch_client(*args):
import CommonClient
from .ManualClient import launch as Main

if CommonClient.gui_enabled:
launch_subprocess(Main, name="Manual client")
else:
Main()

class VersionedComponent(Component):
def __init__(self, display_name: str, script_name: Optional[str] = None, func: Optional[Callable] = None, version: int = 0, file_identifier: Optional[Callable[[str], bool]] = None, icon: Optional[str] = None):
super().__init__(display_name=display_name, script_name=script_name, func=func, component_type=Type.CLIENT, file_identifier=file_identifier, icon=icon)
self.version = version

def add_client_to_launcher() -> None:
found = False

if "manual" not in icon_paths:
icon_paths["manual"] = Utils.user_path('data', 'manual.png')

discord_component = None
for c in components:
if c.display_name == "Manual Client":
found = True
if getattr(c, "version", 0) < CLIENT_VERSION: # We have a newer version of the Manual Client than the one the last apworld added
c.version = CLIENT_VERSION
c.func = launch_client
c.icon = "manual"
elif c.display_name == "Manual Discord Server":
discord_component = c

if not found:
components.append(VersionedComponent(f"Manual Client", "ManualClient", func=launch_client, version=CLIENT_VERSION, file_identifier=SuffixIdentifier('.apmanual'), icon="manual"))
if not discord_component:
components.append(Component("Manual Discord Server", "ManualDiscord", func=lambda: webbrowser.open("https://discord.gg/hm4rQnTzQ5"), icon="discord", component_type=Type.ADJUSTER))

add_client_to_launcher()