Overhauls control.lua template (#1)
* Overhauls control.lua template - Adds buffering of received free-samples items. - Players with a full inventory will receive new items as space becomes available. - Players who do not yet exist in the world will receive all free samples upon joining. - When receiving new technologies, announce the technology BEFORE marking it as researched so that it appears before its free samples in the log. - If receiving a half-stack of free samples, use math.ceil on the division in case a mod uses an odd number as a stack size... or a stack size of 1 - Handle free_samples logic in the Lua side rather than as part of a Jinja template. This makes this hopefully more adaptable to a future setup where all the rando information is shipped as startup settings. * Apparently, I'm supposed to give myself credit. Or something.
This commit is contained in:
parent
2dd6dcab20
commit
65df153947
|
@ -1,7 +1,7 @@
|
|||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Berserker55
|
||||
Copyright (c) 2021 Berserker55 and Dewiniaid
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "archipelago-client",
|
||||
"version": "0.0.1",
|
||||
"title": "Archipelago",
|
||||
"author": "Berserker",
|
||||
"author": "Berserker and Dewiniaid",
|
||||
"homepage": "https://archipelago.gg",
|
||||
"description": "Integration client for the Archipelago Randomizer",
|
||||
"factorio_version": "1.1"
|
||||
|
|
|
@ -1,11 +1,135 @@
|
|||
require "lib"
|
||||
script.on_event(defines.events.on_player_created, function(event)
|
||||
require "util"
|
||||
|
||||
FREE_SAMPLES = {{ free_samples }}
|
||||
--SUPPRESS_INVENTORY_EVENTS = false
|
||||
|
||||
-- Initialize force data, either from it being created or already being part of the game when the mod was added.
|
||||
function on_force_created(event)
|
||||
game.forces[event.force].research_queue_enabled = true
|
||||
local data = {}
|
||||
if FREE_SAMPLES ~= 0 then
|
||||
data['earned_samples'] = {
|
||||
["burner-mining-drill"] = 19,
|
||||
["stone-furnace"] = 19
|
||||
}
|
||||
end
|
||||
global.forcedata[event.force] = data
|
||||
end
|
||||
script.on_event(defines.events.on_force_created, on_force_created)
|
||||
|
||||
-- Destroy force data. This doesn't appear to be currently possible with the Factorio API, but here for completeness.
|
||||
function on_force_destroyed(event)
|
||||
global.forcedata[event.force] = nil
|
||||
end
|
||||
|
||||
-- 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)
|
||||
local player = game.players[event.player_index]
|
||||
player.force.research_queue_enabled = true
|
||||
{% if free_samples %}
|
||||
player.insert({count=19, name="burner-mining-drill"})
|
||||
player.insert({count=19, name="stone-furnace"})
|
||||
{% endif %}
|
||||
-- FIXME: This (probably) fires before any other mod has a chance to change the player's force
|
||||
-- For now, they will (probably) always be on the 'player' force when this event fires.
|
||||
local data = {}
|
||||
if FREE_SAMPLES ~= 0 then
|
||||
data['pending_samples'] = table.deepcopy(global.forcedata[player.force.name]['earned_samples'])
|
||||
end
|
||||
global.playerdata[player.index] = data
|
||||
update_player(player.index) -- Attempt to send pending free samples, if relevant.
|
||||
end
|
||||
script.on_event(defines.events.on_player_created, on_player_created)
|
||||
|
||||
function on_player_removed(event)
|
||||
global.playerdata[event.player_index] = nil
|
||||
end
|
||||
script.on_event(defines.events.on_player_removed, on_player_removed)
|
||||
|
||||
-- Updates a player, attempting to send them any pending samples (if relevant)
|
||||
function update_player(index)
|
||||
if FREE_SAMPLES == 0 then -- This is effectively a noop
|
||||
return
|
||||
end
|
||||
local player = game.players[index]
|
||||
if not player or not player.valid then -- Do nothing if we reference an invalid player somehow
|
||||
return
|
||||
end
|
||||
local character = player.character or player.cutscene_character
|
||||
if not character or not character.valid then
|
||||
return
|
||||
end
|
||||
local data = global.playerdata[index]
|
||||
local samples = data['pending_samples']
|
||||
local sent
|
||||
--player.print(serpent.block(data['pending_samples']))
|
||||
local stack = {}
|
||||
--SUPPRESS_INVENTORY_EVENTS = true
|
||||
for name, count in pairs(samples) do
|
||||
stack.name = name
|
||||
stack.count = count
|
||||
if character.can_insert(stack) then
|
||||
sent = character.insert(stack)
|
||||
else
|
||||
sent = 0
|
||||
end
|
||||
if sent > 0 then
|
||||
player.print("Received " .. sent .. "x [item=" .. name .. "]")
|
||||
data.suppress_full_inventory_message = false
|
||||
end
|
||||
if sent ~= count then -- Couldn't full send.
|
||||
if not data.suppress_full_inventory_message then
|
||||
player.print("Additional items will be sent when inventory space is available.", {r=1, g=1, b=0.25})
|
||||
end
|
||||
data.suppress_full_inventory_message = true -- Avoid spamming them with repeated full inventory messages.
|
||||
samples[name] = count - sent -- Buffer the remaining items
|
||||
break -- Stop trying to send other things
|
||||
else
|
||||
samples[name] = nil -- Remove from the list
|
||||
end
|
||||
end
|
||||
--SUPPRESS_INVENTORY_EVENTS = false
|
||||
end
|
||||
|
||||
-- Update players upon them connecting, since updates while they're offline are suppressed.
|
||||
script.on_event(defines.events.on_player_joined_game, function(event) update_player(event.player_index) end)
|
||||
|
||||
function update_player_event(event)
|
||||
--if not SUPPRESS_INVENTORY_EVENTS then
|
||||
update_player(event.player_index)
|
||||
--end
|
||||
end
|
||||
|
||||
if FREE_SAMPLES then
|
||||
script.on_event(defines.events.on_player_main_inventory_changed, update_player_event)
|
||||
end
|
||||
|
||||
function add_samples(force, name, count)
|
||||
local function add_to_table(t)
|
||||
t[name] = (t[name] or 0) + count
|
||||
end
|
||||
-- Add to global table of earned samples for future new players
|
||||
add_to_table(global.forcedata[force.name]['earned_samples'])
|
||||
-- Add to existing players
|
||||
for _, player in pairs(force.players) do
|
||||
add_to_table(global.playerdata[player.index]['pending_samples'])
|
||||
update_player(player.index)
|
||||
end
|
||||
end
|
||||
|
||||
script.on_init(function()
|
||||
global.forcedata = {}
|
||||
global.playerdata = {}
|
||||
-- Fire dummy events for all currently existing forces.
|
||||
local e = {}
|
||||
for name, _ in pairs(game.forces) do
|
||||
e.force = name
|
||||
on_force_created(e)
|
||||
end
|
||||
e.force = nil
|
||||
|
||||
-- Fire dummy events for all currently existing players.
|
||||
for index, _ in pairs(game.players) do
|
||||
e.player_index = index
|
||||
on_player_created(e)
|
||||
end
|
||||
end)
|
||||
|
||||
-- for testing
|
||||
|
@ -19,31 +143,32 @@ end)
|
|||
script.on_event(defines.events.on_research_finished, function(event)
|
||||
local technology = event.research
|
||||
dumpTech(technology.force)
|
||||
{% if free_samples %}
|
||||
local players = technology.force.players
|
||||
if technology.effects then
|
||||
if FREE_SAMPLES == 0 then
|
||||
return -- Nothing else to do
|
||||
end
|
||||
if not technology.effects then
|
||||
return -- No technology effects, so nothing to do.
|
||||
end
|
||||
for _, effect in pairs(technology.effects) do
|
||||
if effect.type == "unlock-recipe" then
|
||||
local recipe = game.recipe_prototypes[effect.recipe]
|
||||
for _, result in pairs(recipe.products) do
|
||||
if result.type == "item" and result.amount then
|
||||
{% if free_samples == 1 %}
|
||||
local new = {count=result.amount, name=result.name}
|
||||
{% elif free_samples == 2 %}
|
||||
local new = {count=get_any_stack_size(result.name) * 0.5, name=result.name}
|
||||
{% else %}
|
||||
local new = {count=get_any_stack_size(result.name), name=result.name}
|
||||
{% endif %}
|
||||
for _, player in pairs(players) do
|
||||
player.insert(new)
|
||||
local name = result.name
|
||||
local count
|
||||
if FREE_SAMPLES == 1 then
|
||||
count = result.amount
|
||||
else
|
||||
count = get_any_stack_size(result.name)
|
||||
if FREE_SAMPLES == 2 then
|
||||
count = math.ceil(count / 2)
|
||||
end
|
||||
end
|
||||
add_samples(technology.force, name, count)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
{% endif %}
|
||||
|
||||
end)
|
||||
|
||||
function dumpTech(force)
|
||||
|
@ -80,9 +205,9 @@ commands.add_command("ap-get-technology", "Grant a technology, used by the Archi
|
|||
local tech = force.technologies[tech_name]
|
||||
if tech ~= nil then
|
||||
if tech.researched ~= true then
|
||||
tech.researched = true
|
||||
game.print({"", "Received [technology=" .. tech.name .. "] from ", source})
|
||||
game.play_sound({path="utility/research_completed"})
|
||||
tech.researched = true
|
||||
end
|
||||
else
|
||||
game.print("Unknown Technology " .. tech_name)
|
||||
|
|
Loading…
Reference in New Issue