Factorio: add DeathLink option
This commit is contained in:
		
							parent
							
								
									c152790011
								
							
						
					
					
						commit
						4472ef20fe
					
				| 
						 | 
					@ -5,6 +5,7 @@ import asyncio
 | 
				
			||||||
import urllib.parse
 | 
					import urllib.parse
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import typing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import websockets
 | 
					import websockets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,6 +92,7 @@ class ClientCommandProcessor(CommandProcessor):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CommonContext():
 | 
					class CommonContext():
 | 
				
			||||||
 | 
					    tags:typing.Set[str] = {"AP"}
 | 
				
			||||||
    starting_reconnect_delay: int = 5
 | 
					    starting_reconnect_delay: int = 5
 | 
				
			||||||
    current_reconnect_delay: int = starting_reconnect_delay
 | 
					    current_reconnect_delay: int = starting_reconnect_delay
 | 
				
			||||||
    command_processor: int = ClientCommandProcessor
 | 
					    command_processor: int = ClientCommandProcessor
 | 
				
			||||||
| 
						 | 
					@ -489,7 +491,10 @@ if __name__ == '__main__':
 | 
				
			||||||
    # Text Mode to use !hint and such with games that have no text entry
 | 
					    # Text Mode to use !hint and such with games that have no text entry
 | 
				
			||||||
    init_logging("TextClient")
 | 
					    init_logging("TextClient")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class TextContext(CommonContext):
 | 
					    class TextContext(CommonContext):
 | 
				
			||||||
 | 
					        tags = {"AP", "IgnoreGame"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        async def server_auth(self, password_requested: bool = False):
 | 
					        async def server_auth(self, password_requested: bool = False):
 | 
				
			||||||
            if password_requested and not self.password:
 | 
					            if password_requested and not self.password:
 | 
				
			||||||
                await super(TextContext, self).server_auth(password_requested)
 | 
					                await super(TextContext, self).server_auth(password_requested)
 | 
				
			||||||
| 
						 | 
					@ -499,10 +504,11 @@ if __name__ == '__main__':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await self.send_msgs([{"cmd": 'Connect',
 | 
					            await self.send_msgs([{"cmd": 'Connect',
 | 
				
			||||||
                                   'password': self.password, 'name': self.auth, 'version': Utils.version_tuple,
 | 
					                                   'password': self.password, 'name': self.auth, 'version': Utils.version_tuple,
 | 
				
			||||||
                                   'tags': ['AP', 'IgnoreGame'],
 | 
					                                   'tags': self.tags,
 | 
				
			||||||
                                   'uuid': Utils.get_unique_identifier(), 'game': self.game
 | 
					                                   'uuid': Utils.get_unique_identifier(), 'game': self.game
 | 
				
			||||||
                                   }])
 | 
					                                   }])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def main(args):
 | 
					    async def main(args):
 | 
				
			||||||
        ctx = TextContext(args.connect, args.password)
 | 
					        ctx = TextContext(args.connect, args.password)
 | 
				
			||||||
        ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop")
 | 
					        ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,10 +54,12 @@ class FactorioContext(CommonContext):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, server_address, password):
 | 
					    def __init__(self, server_address, password):
 | 
				
			||||||
        super(FactorioContext, self).__init__(server_address, password)
 | 
					        super(FactorioContext, self).__init__(server_address, password)
 | 
				
			||||||
        self.send_index = 0
 | 
					        self.send_index: int = 0
 | 
				
			||||||
        self.rcon_client = None
 | 
					        self.rcon_client = None
 | 
				
			||||||
        self.awaiting_bridge = False
 | 
					        self.awaiting_bridge = False
 | 
				
			||||||
        self.write_data_path = None
 | 
					        self.write_data_path = None
 | 
				
			||||||
 | 
					        self.last_death_link: float = time.time()  # last send/received death link on AP layer
 | 
				
			||||||
 | 
					        self.death_link_tick: int = 0  # last send death link on Factorio layer
 | 
				
			||||||
        self.factorio_json_text_parser = FactorioJSONtoTextParser(self)
 | 
					        self.factorio_json_text_parser = FactorioJSONtoTextParser(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def server_auth(self, password_requested: bool = False):
 | 
					    async def server_auth(self, password_requested: bool = False):
 | 
				
			||||||
| 
						 | 
					@ -76,13 +78,13 @@ class FactorioContext(CommonContext):
 | 
				
			||||||
            'password': self.password,
 | 
					            'password': self.password,
 | 
				
			||||||
            'name': self.auth,
 | 
					            'name': self.auth,
 | 
				
			||||||
            'version': Utils.version_tuple,
 | 
					            'version': Utils.version_tuple,
 | 
				
			||||||
            'tags': ['AP'],
 | 
					            'tags': self.tags,
 | 
				
			||||||
            'uuid': Utils.get_unique_identifier(),
 | 
					            'uuid': Utils.get_unique_identifier(),
 | 
				
			||||||
            'game': "Factorio"
 | 
					            'game': "Factorio"
 | 
				
			||||||
        }])
 | 
					        }])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def on_print(self, args: dict):
 | 
					    def on_print(self, args: dict):
 | 
				
			||||||
        logger.info(args["text"])
 | 
					        super(FactorioContext, self).on_print(args)
 | 
				
			||||||
        if self.rcon_client:
 | 
					        if self.rcon_client:
 | 
				
			||||||
            self.print_to_game(args['text'])
 | 
					            self.print_to_game(args['text'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,6 +109,12 @@ class FactorioContext(CommonContext):
 | 
				
			||||||
                self.rcon_client.send_commands({item_name: f'/ap-get-technology ap-{item_name}-\t-1' for
 | 
					                self.rcon_client.send_commands({item_name: f'/ap-get-technology ap-{item_name}-\t-1' for
 | 
				
			||||||
                                                item_name in args["checked_locations"]})
 | 
					                                                item_name in args["checked_locations"]})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif cmd == "Bounced":
 | 
				
			||||||
 | 
					            if self.rcon_client:
 | 
				
			||||||
 | 
					                tags = args.get("tags", [])
 | 
				
			||||||
 | 
					                if "DeathLink" in tags and self.last_death_link != args["data"]["time"]:
 | 
				
			||||||
 | 
					                    self.rcon_client.send_command(f"/ap-deathlink {args['data']['source']}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def game_watcher(ctx: FactorioContext):
 | 
					async def game_watcher(ctx: FactorioContext):
 | 
				
			||||||
    bridge_logger = logging.getLogger("FactorioWatcher")
 | 
					    bridge_logger = logging.getLogger("FactorioWatcher")
 | 
				
			||||||
| 
						 | 
					@ -139,6 +147,17 @@ async def game_watcher(ctx: FactorioContext):
 | 
				
			||||||
                            f"{[lookup_id_to_name[rid] for rid in research_data - ctx.locations_checked]}")
 | 
					                            f"{[lookup_id_to_name[rid] for rid in research_data - ctx.locations_checked]}")
 | 
				
			||||||
                        ctx.locations_checked = research_data
 | 
					                        ctx.locations_checked = research_data
 | 
				
			||||||
                        await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": tuple(research_data)}])
 | 
					                        await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": tuple(research_data)}])
 | 
				
			||||||
 | 
					                    death_link_tick = data.get("death_link_tick", 0)
 | 
				
			||||||
 | 
					                    if death_link_tick != ctx.death_link_tick:
 | 
				
			||||||
 | 
					                        ctx.death_link_tick = death_link_tick
 | 
				
			||||||
 | 
					                        ctx.last_death_link = time.time()
 | 
				
			||||||
 | 
					                        await ctx.send_msgs([{
 | 
				
			||||||
 | 
					                            "cmd": "Bounce", "tags": ["DeathLink"],
 | 
				
			||||||
 | 
					                            "data": {
 | 
				
			||||||
 | 
					                                "time": ctx.last_death_link,
 | 
				
			||||||
 | 
					                                "source": ctx.player_names[ctx.slot]
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }])
 | 
				
			||||||
            await asyncio.sleep(0.1)
 | 
					            await asyncio.sleep(0.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    except Exception as e:
 | 
					    except Exception as e:
 | 
				
			||||||
| 
						 | 
					@ -227,6 +246,10 @@ def get_info(ctx, rcon_client):
 | 
				
			||||||
    info = json.loads(rcon_client.send_command("/ap-rcon-info"))
 | 
					    info = json.loads(rcon_client.send_command("/ap-rcon-info"))
 | 
				
			||||||
    ctx.auth = info["slot_name"]
 | 
					    ctx.auth = info["slot_name"]
 | 
				
			||||||
    ctx.seed_name = info["seed_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")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def factorio_spinup_server(ctx: FactorioContext) -> bool:
 | 
					async def factorio_spinup_server(ctx: FactorioContext) -> bool:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,7 +122,7 @@ class Context(CommonContext):
 | 
				
			||||||
        auth = base64.b64encode(self.rom).decode()
 | 
					        auth = base64.b64encode(self.rom).decode()
 | 
				
			||||||
        await self.send_msgs([{"cmd": 'Connect',
 | 
					        await self.send_msgs([{"cmd": 'Connect',
 | 
				
			||||||
                              'password': self.password, 'name': auth, 'version': Utils.version_tuple,
 | 
					                              'password': self.password, 'name': auth, 'version': Utils.version_tuple,
 | 
				
			||||||
                              'tags': get_tags(self),
 | 
					                              'tags': self.tags,
 | 
				
			||||||
                              'uuid': Utils.get_unique_identifier(), 'game': "A Link to the Past"
 | 
					                              'uuid': Utils.get_unique_identifier(), 'game': "A Link to the Past"
 | 
				
			||||||
                              }])
 | 
					                              }])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -705,12 +705,6 @@ async def snes_flush_writes(ctx: Context):
 | 
				
			||||||
    await snes_write(ctx, writes)
 | 
					    await snes_write(ctx, writes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# kept as function for easier wrapping by plugins
 | 
					 | 
				
			||||||
def get_tags(ctx: Context):
 | 
					 | 
				
			||||||
    tags = ['AP']
 | 
					 | 
				
			||||||
    return tags
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def track_locations(ctx: Context, roomid, roomdata):
 | 
					async def track_locations(ctx: Context, roomid, roomdata):
 | 
				
			||||||
    new_locations = []
 | 
					    new_locations = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -489,7 +489,7 @@ async def on_client_connected(ctx: Context, client: Client):
 | 
				
			||||||
        'cmd': 'RoomInfo',
 | 
					        'cmd': 'RoomInfo',
 | 
				
			||||||
        'password': bool(ctx.password),
 | 
					        'password': bool(ctx.password),
 | 
				
			||||||
        'players': players,
 | 
					        'players': players,
 | 
				
			||||||
        'games': [ctx.games[x] for x in range(1, len(ctx.games)+1)],
 | 
					        'games': [ctx.games[x] for x in range(1, len(ctx.games) + 1)],
 | 
				
			||||||
        # tags are for additional features in the communication.
 | 
					        # tags are for additional features in the communication.
 | 
				
			||||||
        # Name them by feature or fork, as you feel is appropriate.
 | 
					        # Name them by feature or fork, as you feel is appropriate.
 | 
				
			||||||
        'tags': ctx.tags,
 | 
					        'tags': ctx.tags,
 | 
				
			||||||
| 
						 | 
					@ -1245,7 +1245,6 @@ async def process_client_cmd(ctx: Context, client: Client, args: dict):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await ctx.send_msgs(client, reply)
 | 
					            await ctx.send_msgs(client, reply)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    elif cmd == "GetDataPackage":
 | 
					    elif cmd == "GetDataPackage":
 | 
				
			||||||
        exclusions = set(args.get("exclusions", []))
 | 
					        exclusions = set(args.get("exclusions", []))
 | 
				
			||||||
        if exclusions:
 | 
					        if exclusions:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ def generate_mod(world, output_directory: str):
 | 
				
			||||||
    random = multiworld.slot_seeds[player]
 | 
					    random = multiworld.slot_seeds[player]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def flop_random(low, high, base=None):
 | 
					    def flop_random(low, high, base=None):
 | 
				
			||||||
        """Guarentees 50% bwlo base and 50% above base, uniform distribution in each direction."""
 | 
					        """Guarentees 50% below base and 50% above base, uniform distribution in each direction."""
 | 
				
			||||||
        if base:
 | 
					        if base:
 | 
				
			||||||
            distance = random.random()
 | 
					            distance = random.random()
 | 
				
			||||||
            if random.randint(0, 1):
 | 
					            if random.randint(0, 1):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
import typing
 | 
					import typing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from Options import Choice, OptionDict, ItemDict, Option, DefaultOnToggle, Range
 | 
					from Options import Choice, OptionDict, ItemDict, Option, DefaultOnToggle, Range, Toggle
 | 
				
			||||||
from schema import Schema, Optional, And, Or
 | 
					from schema import Schema, Optional, And, Or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# schema helpers
 | 
					# schema helpers
 | 
				
			||||||
| 
						 | 
					@ -284,6 +284,11 @@ class ImportedBlueprint(DefaultOnToggle):
 | 
				
			||||||
    displayname = "Blueprints"
 | 
					    displayname = "Blueprints"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeathLink(Toggle):
 | 
				
			||||||
 | 
					    """When you die, everyone dies. Of course the reverse is true too."""
 | 
				
			||||||
 | 
					    displayname = "Death Link"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
factorio_options: typing.Dict[str, type(Option)] = {
 | 
					factorio_options: typing.Dict[str, type(Option)] = {
 | 
				
			||||||
    "max_science_pack": MaxSciencePack,
 | 
					    "max_science_pack": MaxSciencePack,
 | 
				
			||||||
    "tech_tree_layout": TechTreeLayout,
 | 
					    "tech_tree_layout": TechTreeLayout,
 | 
				
			||||||
| 
						 | 
					@ -300,4 +305,5 @@ factorio_options: typing.Dict[str, type(Option)] = {
 | 
				
			||||||
    "evolution_traps": EvolutionTrapCount,
 | 
					    "evolution_traps": EvolutionTrapCount,
 | 
				
			||||||
    "attack_traps": AttackTrapCount,
 | 
					    "attack_traps": AttackTrapCount,
 | 
				
			||||||
    "evolution_trap_increase": EvolutionTrapIncrease,
 | 
					    "evolution_trap_increase": EvolutionTrapIncrease,
 | 
				
			||||||
 | 
					    "death_link": DeathLink
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,9 @@ SLOT_NAME = "{{ slot_name }}"
 | 
				
			||||||
SEED_NAME = "{{ seed_name }}"
 | 
					SEED_NAME = "{{ seed_name }}"
 | 
				
			||||||
FREE_SAMPLE_BLACKLIST = {{ dict_to_lua(free_sample_blacklist) }}
 | 
					FREE_SAMPLE_BLACKLIST = {{ dict_to_lua(free_sample_blacklist) }}
 | 
				
			||||||
TRAP_EVO_FACTOR = {{ evolution_trap_increase }} / 100
 | 
					TRAP_EVO_FACTOR = {{ evolution_trap_increase }} / 100
 | 
				
			||||||
 | 
					DEATH_LINK = {{ death_link | int }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CURRENTLY_DEATH_LOCK = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% if not imported_blueprints -%}
 | 
					{% if not imported_blueprints -%}
 | 
				
			||||||
function set_permissions()
 | 
					function set_permissions()
 | 
				
			||||||
| 
						 | 
					@ -57,6 +60,7 @@ function on_force_created(event)
 | 
				
			||||||
    local data = {}
 | 
					    local data = {}
 | 
				
			||||||
    data['earned_samples'] = {{ dict_to_lua(starting_items) }}
 | 
					    data['earned_samples'] = {{ dict_to_lua(starting_items) }}
 | 
				
			||||||
    data["victory"] = 0
 | 
					    data["victory"] = 0
 | 
				
			||||||
 | 
					    data["death_link_tick"] = 0
 | 
				
			||||||
    global.forcedata[event.force] = data
 | 
					    global.forcedata[event.force] = data
 | 
				
			||||||
{%- if silo == 2 %}
 | 
					{%- if silo == 2 %}
 | 
				
			||||||
    check_spawn_silo(force)
 | 
					    check_spawn_silo(force)
 | 
				
			||||||
| 
						 | 
					@ -250,6 +254,17 @@ function chain_lookup(table, ...)
 | 
				
			||||||
    return table
 | 
					    return table
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function kill_players(force)
 | 
				
			||||||
 | 
					    CURRENTLY_DEATH_LOCK = 1
 | 
				
			||||||
 | 
					    local current_character = nil
 | 
				
			||||||
 | 
					    for _, player in ipairs(force.players) do
 | 
				
			||||||
 | 
					        current_character = player.character
 | 
				
			||||||
 | 
					        if current_character ~= nil then
 | 
				
			||||||
 | 
					            current_character.die()
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    CURRENTLY_DEATH_LOCK = 0
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function spawn_entity(surface, force, name, x, y, radius, randomize, avoid_ores)
 | 
					function spawn_entity(surface, force, name, x, y, radius, randomize, avoid_ores)
 | 
				
			||||||
    local prototype = game.entity_prototypes[name]
 | 
					    local prototype = game.entity_prototypes[name]
 | 
				
			||||||
| 
						 | 
					@ -351,6 +366,20 @@ function spawn_entity(surface, force, name, x, y, radius, randomize, avoid_ores)
 | 
				
			||||||
end
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- add / commands
 | 
					-- add / commands
 | 
				
			||||||
commands.add_command("ap-sync", "Used by the Archipelago client to get progress information", function(call)
 | 
					commands.add_command("ap-sync", "Used by the Archipelago client to get progress information", function(call)
 | 
				
			||||||
    local force
 | 
					    local force
 | 
				
			||||||
| 
						 | 
					@ -363,7 +392,8 @@ commands.add_command("ap-sync", "Used by the Archipelago client to get progress
 | 
				
			||||||
    local data_collection = {
 | 
					    local data_collection = {
 | 
				
			||||||
        ["research_done"] = research_done,
 | 
					        ["research_done"] = research_done,
 | 
				
			||||||
        ["victory"] = chain_lookup(global, "forcedata", force.name, "victory"),
 | 
					        ["victory"] = chain_lookup(global, "forcedata", force.name, "victory"),
 | 
				
			||||||
        }
 | 
					        ["death_link_tick"] = chain_lookup(global, "forcedata", force.name, "death_link_tick")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for tech_name, tech in pairs(force.technologies) do
 | 
					    for tech_name, tech in pairs(force.technologies) do
 | 
				
			||||||
        if tech.researched and string.find(tech_name, "ap%-") == 1 then
 | 
					        if tech.researched and string.find(tech_name, "ap%-") == 1 then
 | 
				
			||||||
| 
						 | 
					@ -442,7 +472,7 @@ end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
commands.add_command("ap-rcon-info", "Used by the Archipelago client to get information", function(call)
 | 
					commands.add_command("ap-rcon-info", "Used by the Archipelago client to get information", function(call)
 | 
				
			||||||
    rcon.print(game.table_to_json({["slot_name"] = SLOT_NAME, ["seed_name"] = SEED_NAME}))
 | 
					    rcon.print(game.table_to_json({["slot_name"] = SLOT_NAME, ["seed_name"] = SEED_NAME, ["death_link"] = DEATH_LINK}))
 | 
				
			||||||
end)
 | 
					end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -453,5 +483,13 @@ end)
 | 
				
			||||||
{% endif -%}
 | 
					{% endif -%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					commands.add_command("ap-deathlink", "Kill all players", function(call)
 | 
				
			||||||
 | 
					    local force = game.forces["player"]
 | 
				
			||||||
 | 
					    local source = call.parameter or "Archipelago"
 | 
				
			||||||
 | 
					    kill_players(force)
 | 
				
			||||||
 | 
					    game.print("Death was granted by " .. source)
 | 
				
			||||||
 | 
					end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- data
 | 
					-- data
 | 
				
			||||||
progressive_technologies = {{ dict_to_lua(progressive_technology_table) }}
 | 
					progressive_technologies = {{ dict_to_lua(progressive_technology_table) }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue