Skip to content

Commit

Permalink
Merge pull request #254 from MatthewMarinets/mm/misc_client_fixes
Browse files Browse the repository at this point in the history
Mm/misc client fixes
  • Loading branch information
Ziktofel authored Jul 27, 2024
2 parents cdca567 + 47c7b2a commit 2f95d0f
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 9 deletions.
2 changes: 2 additions & 0 deletions worlds/sc2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
get_enabled_campaigns, SpearOfAdunAutonomouslyCastAbilityPresence, Starcraft2Options,
GrantStoryTech, GenericUpgradeResearch, GenericUpgradeItems,
)
from . import settings
from .pool_filter import filter_items
from .mission_tables import (
MissionInfo, SC2Campaign, SC2Mission, SC2Race, MissionFlag
Expand Down Expand Up @@ -84,6 +85,7 @@ class SC2World(World):

game = "Starcraft 2"
web = Starcraft2WebWorld()
settings: ClassVar[settings.Starcraft2Settings]

item_name_to_id = {name: data.code for name, data in get_full_item_list().items()}
location_name_to_id = {location.name: location.code for location in get_locations(None)}
Expand Down
38 changes: 34 additions & 4 deletions worlds/sc2/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
SpearOfAdunAutonomouslyCastPresentInNoBuild, NerfUnitBaselines, LEGACY_GRID_ORDERS,
)
from .mission_tables import MissionFlag
from . import SC2World


if __name__ == "__main__":
Expand Down Expand Up @@ -417,6 +418,17 @@ def _cmd_color(self, faction: str = "", color: str = "") -> None:
self.ctx.pending_color_update = True
self.output(f"Color for {faction} set to " + player_colors[self.ctx.__dict__[var_names[faction]]])

def _cmd_windowed_mode(self, value="") -> None:
if not value:
pass
elif value.casefold() in ('t', 'true', 'yes', 'y'):
SC2World.settings.game_windowed_mode = True
force_settings_save_on_close()
else:
SC2World.settings.game_windowed_mode = False
force_settings_save_on_close()
sc2_logger.info(f"Windowed mode is: {SC2World.settings.game_windowed_mode}")

def _cmd_disable_mission_check(self) -> bool:
"""Disables the check to see if a mission is available to play. Meant for co-op runs where one player can play
the next mission in a chain the other player is doing."""
Expand Down Expand Up @@ -731,9 +743,10 @@ def on_print_json(self, args: dict) -> None:
super(SC2Context, self).on_print_json(args)

def run_gui(self) -> None:
from .gui_config import apply_window_defaults
warnings = apply_window_defaults()
from .client_gui import start_gui
start_gui(self)

start_gui(self, warnings)

async def shutdown(self) -> None:
await super(SC2Context, self).shutdown()
Expand Down Expand Up @@ -1076,8 +1089,11 @@ async def starcraft_launch(ctx: SC2Context, mission_id: int):
sc2_logger.info(f"Launching {lookup_id_to_mission[mission_id].mission_name}. If game does not launch check log file for errors.")

with DllDirectory(None):
run_game(bot.maps.get(lookup_id_to_mission[mission_id].map_file), [Bot(Race.Terran, ArchipelagoBot(ctx, mission_id),
name="Archipelago", fullscreen=True)], realtime=True)
run_game(
bot.maps.get(lookup_id_to_mission[mission_id].map_file),
[Bot(Race.Terran, ArchipelagoBot(ctx, mission_id), name="Archipelago", fullscreen=not SC2World.settings.game_windowed_mode)],
realtime=True,
)


class ArchipelagoBot(bot.bot_ai.BotAI):
Expand Down Expand Up @@ -1728,6 +1744,20 @@ def get_location_offset(mission_id):
else (SC2HOTS_LOC_ID_OFFSET - SC2Mission.ALL_IN.id * VICTORY_MODULO)


_has_forced_save = False
def force_settings_save_on_close() -> None:
"""
Settings has an existing auto-save feature, but it only triggers if a new key was introduced.
Force it to mark things as changed by introducing a new key and then cleaning up.
"""
global _has_forced_save
if _has_forced_save:
return
SC2World.settings.update({'invalid_attribute': True})
del SC2World.settings.invalid_attribute
_has_forced_save = True


def launch():
colorama.init()
asyncio.run(main())
Expand Down
38 changes: 33 additions & 5 deletions worlds/sc2/client_gui.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import *
import asyncio
import logging

from kvui import GameManager, HoverBehavior, ServerToolTip
from kivy.app import App
Expand All @@ -13,7 +14,7 @@
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty, BooleanProperty

from worlds.sc2.client import SC2Context, calc_unfinished_missions, parse_unlock
from worlds.sc2.client import SC2Context, calc_unfinished_missions, parse_unlock, force_settings_save_on_close
from worlds.sc2.mission_tables import lookup_id_to_mission, lookup_name_to_mission, campaign_race_exceptions, \
SC2Mission, SC2Race, SC2Campaign
from worlds.sc2.locations import LocationType, lookup_location_id_to_type
Expand Down Expand Up @@ -72,6 +73,7 @@ class MissionLayout(GridLayout):
class MissionCategory(GridLayout):
pass


class SC2Manager(GameManager):
logging_pairs = [
("Client", "Archipelago"),
Expand All @@ -90,9 +92,35 @@ class SC2Manager(GameManager):
first_mission = ""
ctx: SC2Context

def __init__(self, ctx) -> None:
def __init__(self, ctx: SC2Context, startup_warnings: List[str]) -> None:
super().__init__(ctx)

self.startup_warnings = startup_warnings
self.minimized = False
from kivy.core.window import Window
Window.bind(on_maximize=self.on_maximize)
Window.bind(on_minimize=self.on_minimize)
Window.bind(on_restore=self.on_restore)

def on_start(self) -> None:
super().on_start()
for startup_warning in self.startup_warnings:
logging.getLogger("Starcraft2").warning(f"Startup WARNING: {startup_warning}")

def on_maximize(self, window) -> None:
SC2World.settings.window_maximized = True
force_settings_save_on_close()

def on_minimize(self, window) -> None:
self.minimized = True

def on_restore(self, window) -> None:
if self.minimized:
self.minimized = False
else:
# Restoring from maximized
SC2World.settings.window_maximized = False
force_settings_save_on_close()

def clear_tooltip(self) -> None:
if self.ctx.current_tooltip:
App.get_running_app().root.remove_widget(self.ctx.current_tooltip)
Expand Down Expand Up @@ -325,8 +353,8 @@ def get_location_type_title(self, location_type: LocationType) -> str:
title += ""
return title

def start_gui(context: SC2Context):
context.ui = SC2Manager(context)
def start_gui(context: SC2Context, startup_warnings: List[str]):
context.ui = SC2Manager(context, startup_warnings)
context.ui_task = asyncio.create_task(context.ui.async_run(), name="UI")
import pkgutil
data = pkgutil.get_data(SC2World.__module__, "starcraft2.kv").decode()
Expand Down
40 changes: 40 additions & 0 deletions worlds/sc2/gui_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
Import this before importing client_gui.py to set window defaults from world settings.
"""
from .settings import Starcraft2Settings
from typing import List

def apply_window_defaults() -> List[str]:
"""
Set the kivy config keys from the sc2world user settings.
Returns a list of warnings to be printed once the GUI is started.
"""
from . import SC2World
# This is necessary to prevent kivy from failing because it got invalid command-line args,
# or from spamming the logs.
# Must happen before importing kivy.config
import os
os.environ["KIVY_NO_CONSOLELOG"] = "1"
os.environ["KIVY_NO_FILELOG"] = "1"
os.environ["KIVY_NO_ARGS"] = "1"
os.environ["KIVY_LOG_ENABLE"] = "0"

# validate settings
warnings: List[str] = []
if isinstance(SC2World.settings.window_height, int) and SC2World.settings.window_height > 0:
window_height = SC2World.settings.window_height
else:
warnings.append(f"Invalid value for options.yaml key sc2_options.window_height: '{SC2World.settings.window_height}'. Expected a positive integer.")
window_height = Starcraft2Settings.window_height
if isinstance(SC2World.settings.window_width, int) and SC2World.settings.window_width > 0:
window_width = SC2World.settings.window_width
else:
warnings.append(f"Invalid value for options.yaml key sc2_options.window_width: '{SC2World.settings.window_width}'. Expected a positive integer.")
window_width = Starcraft2Settings.window_width

from kivy.config import Config
Config.set('graphics', 'width', str(window_width))
Config.set('graphics', 'height', str(window_height))
if SC2World.settings.window_maximized:
Config.set('graphics', 'window_state', 'maximized')
return warnings
6 changes: 6 additions & 0 deletions worlds/sc2/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ class PlayerColorZergPrimal(ColorChoice):
display_name = "Zerg Player Color (Primal)"


class PlayerColorNova(ColorChoice):
"""Determines in-game team color for playable Zerg factions after Kerrigan becomes Primal Kerrigan."""
display_name = "Terran Player Color (Nova)"


class EnableWolMissions(DefaultOnToggle):
"""
Enables missions from main Wings of Liberty campaign.
Expand Down Expand Up @@ -943,6 +948,7 @@ class Starcraft2Options(PerGameCommonOptions):
player_color_protoss: PlayerColorProtoss
player_color_zerg: PlayerColorZerg
player_color_zerg_primal: PlayerColorZergPrimal
player_color_nova: PlayerColorNova
selected_races: SelectRaces
enable_wol_missions: EnableWolMissions
enable_prophecy_missions: EnableProphecyMissions
Expand Down
18 changes: 18 additions & 0 deletions worlds/sc2/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Union
import settings


class Starcraft2Settings(settings.Group):
class WindowWidth(int):
"""The starting width the client window in pixels"""
class WindowHeight(int):
"""The starting height the client window in pixels"""
class StartMaximized(settings.Bool):
"""Controls whether the client window should start maximized"""
class GameWindowedMode(settings.Bool):
"""Controls whether the game should start in windowed mode"""

window_width = WindowWidth(1080)
window_height = WindowHeight(720)
window_maximized: Union[StartMaximized, bool] = False
game_windowed_mode: Union[GameWindowedMode, bool] = False

0 comments on commit 2f95d0f

Please sign in to comment.