diff --git a/CommonClient.py b/CommonClient.py index c71337359269..4fc82b5e67b4 100644 --- a/CommonClient.py +++ b/CommonClient.py @@ -312,6 +312,12 @@ def slot_concerns_self(self, slot) -> bool: return self.slot in self.slot_info[slot].group_members return False + def is_uninteresting_item_send(self, print_json_packet: dict) -> bool: + """Helper function for filtering out ItemSend prints that do not concern the local player.""" + return print_json_packet.get("type", "") == "ItemSend" \ + and not self.slot_concerns_self(print_json_packet["receiving"]) \ + and not self.slot_concerns_self(print_json_packet["item"].player) + def on_print(self, args: dict): logger.info(args["text"]) diff --git a/FactorioClient.py b/FactorioClient.py index 1efca05d3c65..8ab9799b7c66 100644 --- a/FactorioClient.py +++ b/FactorioClient.py @@ -4,6 +4,7 @@ import json import string import copy +import re import subprocess import time import random @@ -46,6 +47,10 @@ def _cmd_resync(self): """Manually trigger a resync.""" self.ctx.awaiting_bridge = True + def _cmd_toggle_send_filter(self): + """Toggle filtering of item sends that get displayed in-game to only those that involve you.""" + self.ctx.toggle_filter_item_sends() + class FactorioContext(CommonContext): command_processor = FactorioCommandProcessor @@ -65,6 +70,7 @@ def __init__(self, server_address, password): self.factorio_json_text_parser = FactorioJSONtoTextParser(self) self.energy_link_increment = 0 self.last_deplete = 0 + self.filter_item_sends: bool = False async def server_auth(self, password_requested: bool = False): if password_requested and not self.password: @@ -85,8 +91,9 @@ def on_print(self, args: dict): def on_print_json(self, args: dict): if self.rcon_client: - text = self.factorio_json_text_parser(copy.deepcopy(args["data"])) - self.print_to_game(text) + if not self.filter_item_sends or not self.is_uninteresting_item_send(args): + text = self.factorio_json_text_parser(copy.deepcopy(args["data"])) + self.print_to_game(text) super(FactorioContext, self).on_print_json(args) @property @@ -123,6 +130,15 @@ def on_package(self, cmd: str, args: dict): f"{Utils.format_SI_prefix(args['value'])}J remaining.") self.rcon_client.send_command(f"/ap-energylink {gained}") + def toggle_filter_item_sends(self) -> None: + self.filter_item_sends = not self.filter_item_sends + if self.filter_item_sends: + announcement = "Item sends are now filtered." + else: + announcement = "Item sends are no longer filtered." + logger.info(announcement) + self.print_to_game(announcement) + def run_gui(self): from kvui import GameManager @@ -262,6 +278,9 @@ async def factorio_server_watcher(ctx: FactorioContext): if not ctx.awaiting_bridge and "Archipelago Bridge Data available for game tick " in msg: ctx.awaiting_bridge = True factorio_server_logger.debug(msg) + elif re.match(r"^[0-9.]+ Script @[^ ]+\.lua:\d+: Player command toggle-ap-send-filter", msg): + factorio_server_logger.debug(msg) + ctx.toggle_filter_item_sends() else: factorio_server_logger.info(msg) if ctx.rcon_client: @@ -363,6 +382,7 @@ async def factorio_spinup_server(ctx: FactorioContext) -> bool: async def main(args): ctx = FactorioContext(args.connect, args.password) + ctx.filter_item_sends = initial_filter_item_sends ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop") if gui_enabled: @@ -415,6 +435,9 @@ def _handle_color(self, node: JSONMessagePart): server_settings = args.server_settings if args.server_settings else options["factorio_options"].get("server_settings", None) if server_settings: server_settings = os.path.abspath(server_settings) + if not isinstance(options["factorio_options"]["filter_item_sends"], bool): + logging.warning(f"Warning: Option filter_item_sends should be a bool.") + initial_filter_item_sends = bool(options["factorio_options"]["filter_item_sends"]) if not os.path.exists(os.path.dirname(executable)): raise FileNotFoundError(f"Path {os.path.dirname(executable)} does not exist or could not be accessed.") diff --git a/Utils.py b/Utils.py index 64a028fc33a2..b2e98358bce6 100644 --- a/Utils.py +++ b/Utils.py @@ -231,6 +231,7 @@ def get_default_options() -> OptionsType: }, "factorio_options": { "executable": os.path.join("factorio", "bin", "x64", "factorio"), + "filter_item_sends": False, }, "sni_options": { "sni": "SNI", diff --git a/host.yaml b/host.yaml index 2c5a8e3e1d3f..0bdd95356e77 100644 --- a/host.yaml +++ b/host.yaml @@ -99,6 +99,8 @@ factorio_options: executable: "factorio/bin/x64/factorio" # by default, no settings are loaded if this file does not exist. If this file does exist, then it will be used. # server_settings: "factorio\\data\\server-settings.json" + # Whether to filter item send messages displayed in-game to only those that involve you. + filter_item_sends: false minecraft_options: forge_directory: "Minecraft Forge server" max_heap_size: "2G" diff --git a/worlds/factorio/data/mod_template/control.lua b/worlds/factorio/data/mod_template/control.lua index 51cd21e4da50..86e83b9f4dff 100644 --- a/worlds/factorio/data/mod_template/control.lua +++ b/worlds/factorio/data/mod_template/control.lua @@ -596,5 +596,9 @@ commands.add_command("ap-energylink", "Used by the Archipelago client to manage global.forcedata[force].energy = global.forcedata[force].energy + change end) +commands.add_command("toggle-ap-send-filter", "Toggle filtering of item sends that get displayed in-game to only those that involve you.", function(call) + log("Player command toggle-ap-send-filter") -- notifies client +end) + -- data progressive_technologies = {{ dict_to_lua(progressive_technology_table) }} diff --git a/worlds/factorio/docs/setup_en.md b/worlds/factorio/docs/setup_en.md index 560a37d1e3f1..8b24da13d57a 100644 --- a/worlds/factorio/docs/setup_en.md +++ b/worlds/factorio/docs/setup_en.md @@ -141,6 +141,18 @@ you can also issue the `!help` command to learn about additional commands like ` 4. Provide your IP address to anyone you want to join your game, and have them follow the steps for "Connecting to Someone Else's Factorio Game" above. +## Other Settings + +- By default, all item sends are displayed in-game. In larger async seeds this may become overly spammy. + To hide all item sends that are not to or from your factory, do one of the following: + - Type `/toggle-ap-send-filter` in-game + - Type `/toggle_send_filter` in the Archipelago Client + - In your `host.yaml` set + ``` + factorio_options: + filter_item_sends: true + ``` + ## Troubleshooting In case any problems should occur, the Archipelago Client will create a file `FactorioClient.txt` in the `/logs`. The