From 9dbafd3b4b5946b3d4b6b237e08fd27249165ab0 Mon Sep 17 00:00:00 2001 From: CaitSith2 <d_good@caitsith2.com> Date: Wed, 24 Nov 2021 01:55:36 -0800 Subject: [PATCH] Factorio can now change death link state at runtime. --- FactorioClient.py | 23 ++++---- worlds/factorio/Mod.py | 8 ++- worlds/factorio/data/mod_template/control.lua | 55 ++++++++++++++----- .../data/mod_template/locale/en/locale.cfg | 8 ++- .../factorio/data/mod_template/settings.lua | 12 ++++ 5 files changed, 79 insertions(+), 27 deletions(-) create mode 100644 worlds/factorio/data/mod_template/settings.lua diff --git a/FactorioClient.py b/FactorioClient.py index 056dfc3f..292d926e 100644 --- a/FactorioClient.py +++ b/FactorioClient.py @@ -65,12 +65,11 @@ class FactorioContext(CommonContext): if password_requested and not self.password: await super(FactorioContext, self).server_auth(password_requested) - if not self.auth: - if self.rcon_client: - get_info(self, self.rcon_client) # retrieve current auth code - else: - raise Exception("Cannot connect to a server with unknown own identity, " - "bridge to Factorio first.") + if self.rcon_client: + await get_info(self, self.rcon_client) # retrieve current auth code + else: + raise Exception("Cannot connect to a server with unknown own identity, " + "bridge to Factorio first.") await self.send_connect() @@ -126,6 +125,8 @@ async def game_watcher(ctx: FactorioContext): research_data = data["research_done"] research_data = {int(tech_name.split("-")[1]) for tech_name in research_data} victory = data["victory"] + if "death_link" in data: # TODO: Remove this if statement around version 0.2.4 or so + await ctx.update_death_link(data["death_link"]) if not ctx.finished_game and victory: await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}]) @@ -140,7 +141,8 @@ async def game_watcher(ctx: FactorioContext): death_link_tick = data.get("death_link_tick", 0) if death_link_tick != ctx.death_link_tick: ctx.death_link_tick = death_link_tick - await ctx.send_death() + if "DeathLink" in ctx.tags: + await ctx.send_death() await asyncio.sleep(0.1) @@ -226,14 +228,13 @@ async def factorio_server_watcher(ctx: FactorioContext): factorio_process.wait(5) -def get_info(ctx, rcon_client): +async def get_info(ctx, rcon_client): info = json.loads(rcon_client.send_command("/ap-rcon-info")) ctx.auth = info["slot_name"] ctx.seed_name = info["seed_name"] # 0.2.0 addition, not present earlier death_link = bool(info.get("death_link", False)) - if death_link: - ctx.tags.add("DeathLink") + await ctx.update_death_link(death_link) async def factorio_spinup_server(ctx: FactorioContext) -> bool: @@ -272,7 +273,7 @@ async def factorio_spinup_server(ctx: FactorioContext) -> bool: rcon_client = factorio_rcon.RCONClient("localhost", rcon_port, rcon_password) if ctx.mod_version == ctx.__class__.mod_version: raise Exception("No Archipelago mod was loaded. Aborting.") - get_info(ctx, rcon_client) + await get_info(ctx, rcon_client) await asyncio.sleep(0.01) except Exception as e: diff --git a/worlds/factorio/Mod.py b/worlds/factorio/Mod.py index b47d7ed4..3a5dc569 100644 --- a/worlds/factorio/Mod.py +++ b/worlds/factorio/Mod.py @@ -56,7 +56,7 @@ recipe_time_ranges = { def generate_mod(world, output_directory: str): player = world.player multiworld = world.world - global data_final_template, locale_template, control_template, data_template + global data_final_template, locale_template, control_template, data_template, settings_template with template_load_lock: if not data_final_template: mod_template_folder = os.path.join(os.path.dirname(__file__), "data", "mod_template") @@ -66,6 +66,7 @@ def generate_mod(world, output_directory: str): data_final_template = template_env.get_template("data-final-fixes.lua") locale_template = template_env.get_template(r"locale/en/locale.cfg") control_template = template_env.get_template("control.lua") + settings_template = template_env.get_template("settings.lua") # get data for templates player_names = {x: multiworld.player_name[x] for x in multiworld.player_ids} locations = [] @@ -97,7 +98,7 @@ def generate_mod(world, output_directory: str): "mod_name": mod_name, "allowed_science_packs": multiworld.max_science_pack[player].get_allowed_packs(), "tech_cost_scale": tech_cost_scale, "custom_technologies": multiworld.worlds[player].custom_technologies, "tech_tree_layout_prerequisites": multiworld.tech_tree_layout_prerequisites[player], - "slot_name": multiworld.player_name[player], "seed_name": multiworld.seed_name, + "slot_name": multiworld.player_name[player], "seed_name": multiworld.seed_name, "slot_player": player, "starting_items": multiworld.starting_items[player], "recipes": recipes, "random": random, "flop_random": flop_random, "static_nodes": multiworld.worlds[player].static_nodes, @@ -121,6 +122,7 @@ def generate_mod(world, output_directory: str): control_code = control_template.render(**template_data) data_template_code = data_template.render(**template_data) data_final_fixes_code = data_final_template.render(**template_data) + settings_code = settings_template.render(**template_data) mod_dir = os.path.join(output_directory, mod_name + "_" + Utils.__version__) en_locale_dir = os.path.join(mod_dir, "locale", "en") @@ -132,6 +134,8 @@ def generate_mod(world, output_directory: str): f.write(data_final_fixes_code) with open(os.path.join(mod_dir, "control.lua"), "wt") as f: f.write(control_code) + with open(os.path.join(mod_dir, "settings.lua"), "wt") as f: + f.write(settings_code) locale_content = locale_template.render(**template_data) with open(os.path.join(en_locale_dir, "locale.cfg"), "wt") as f: f.write(locale_content) diff --git a/worlds/factorio/data/mod_template/control.lua b/worlds/factorio/data/mod_template/control.lua index 117fe7b9..d53a0b9c 100644 --- a/worlds/factorio/data/mod_template/control.lua +++ b/worlds/factorio/data/mod_template/control.lua @@ -9,7 +9,13 @@ SEED_NAME = "{{ seed_name }}" FREE_SAMPLE_BLACKLIST = {{ dict_to_lua(free_sample_blacklist) }} TRAP_EVO_FACTOR = {{ evolution_trap_increase }} / 100 MAX_SCIENCE_PACK = {{ max_science_pack }} -DEATH_LINK = {{ death_link | int }} +ARCHIPELAGO_DEATH_LINK_SETTING = "archipelago-death-link-{{ slot_player }}-{{ seed_name }}" + +if settings.global[ARCHIPELAGO_DEATH_LINK_SETTING].value then + DEATH_LINK = 1 +else + DEATH_LINK = 0 +end CURRENTLY_DEATH_LOCK = 0 @@ -77,6 +83,27 @@ function on_force_destroyed(event) global.forcedata[event.force.name] = nil end +function on_runtime_mod_setting_changed(event) + local force + if event.player_index == nil then + force = game.forces.player + else + force = game.players[event.player_index].force + end + + if event.setting == ARCHIPELAGO_DEATH_LINK_SETTING then + if settings.global[ARCHIPELAGO_DEATH_LINK_SETTING].value then + DEATH_LINK = 1 + else + DEATH_LINK = 0 + end + if force ~= nil then + dumpInfo(force) + end + end +end +script.on_event(defines.events.on_runtime_mod_setting_changed, on_runtime_mod_setting_changed) + -- Initialize player data, either from them joining the game or them already being part of the game when the mod was -- added.` function on_player_created(event) @@ -382,18 +409,19 @@ function spawn_entity(surface, force, name, x, y, radius, randomize, avoid_ores) end -if DEATH_LINK == 1 then - script.on_event(defines.events.on_entity_died, function(event) - if CURRENTLY_DEATH_LOCK == 1 then -- don't re-trigger on same event - return - end +script.on_event(defines.events.on_entity_died, function(event) + if DEATH_LINK == 0 then + return + end + if CURRENTLY_DEATH_LOCK == 1 then -- don't re-trigger on same event + return + end - local force = event.entity.force - global.forcedata[force.name].death_link_tick = game.tick - dumpInfo(force) - kill_players(force) - end, {LuaEntityDiedEventFilter = {["filter"] = "name", ["name"] = "character"}}) -end + local force = event.entity.force + global.forcedata[force.name].death_link_tick = game.tick + dumpInfo(force) + kill_players(force) +end, {LuaEntityDiedEventFilter = {["filter"] = "name", ["name"] = "character"}}) -- add / commands @@ -408,7 +436,8 @@ commands.add_command("ap-sync", "Used by the Archipelago client to get progress local data_collection = { ["research_done"] = research_done, ["victory"] = chain_lookup(global, "forcedata", force.name, "victory"), - ["death_link_tick"] = chain_lookup(global, "forcedata", force.name, "death_link_tick") + ["death_link_tick"] = chain_lookup(global, "forcedata", force.name, "death_link_tick"), + ["death_link"] = DEATH_LINK } for tech_name, tech in pairs(force.technologies) do diff --git a/worlds/factorio/data/mod_template/locale/en/locale.cfg b/worlds/factorio/data/mod_template/locale/en/locale.cfg index 25e9eb23..e970dbfa 100644 --- a/worlds/factorio/data/mod_template/locale/en/locale.cfg +++ b/worlds/factorio/data/mod_template/locale/en/locale.cfg @@ -22,4 +22,10 @@ ap-{{ tech_table[original_tech_name] }}-=Researching this technology sends somet {%- else %} ap-{{ tech_table[original_tech_name] }}-=Researching this technology sends something to someone. For purposes of hints, this location is called "{{ original_tech_name }}". {%- endif -%} -{% endfor %} \ No newline at end of file +{% endfor %} + +[mod-setting-name] +archipelago-death-link-{{ slot_player }}-{{ seed_name }}=Death Link + +[mod-setting-description] +archipelago-death-link-{{ slot_player }}-{{ seed_name }}=Kill other players in the same Archipelago Multiworld that also have Death Link turned on, when you die. \ No newline at end of file diff --git a/worlds/factorio/data/mod_template/settings.lua b/worlds/factorio/data/mod_template/settings.lua new file mode 100644 index 00000000..7703ebe2 --- /dev/null +++ b/worlds/factorio/data/mod_template/settings.lua @@ -0,0 +1,12 @@ +data:extend({ + { + type = "bool-setting", + name = "archipelago-death-link-{{ slot_player }}-{{ seed_name }}", + setting_type = "runtime-global", + {% if death_link %} + default_value = true + {% else %} + default_value = false + {% endif %} + } +}) \ No newline at end of file