Skip to content

Changes #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 188 additions & 49 deletions archipelago-extractor/control.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
function dumpModInfo()
game.write_file("mods.json", game.table_to_json(game.active_mods), false)
game.print("Exported Mod List")
end

recipe_data_collection = {}

function dumpRecipe(recipe, unlocked_at_start)
if recipe_data_collection[recipe] ~= nil then
-- recipe is already known.
return
end
local recipe_data = {}
recipe_data["ingredients"] = {}
recipe_data["products"] = {}
recipe_data["category"] = recipe.category
recipe_data["energy"] = recipe.energy
recipe_data["unlocked_at_start"] = unlocked_at_start
for _, ingredient in pairs(recipe.ingredients) do
recipe_data["ingredients"][ingredient.name] = ingredient.amount
end
for _, product in pairs(recipe.products) do
recipe_data["products"][product.name] = product.amount
end
recipe_data_collection[recipe.name] = recipe_data
end

function dumpRecipeInfo(force)
data_collection = {}
for recipe_name, recipe in pairs(force.recipes) do
if recipe.enabled then
dumpRecipe(recipe, true)
end
end
game.print("Exported Unlocked Recipe Data")
end

function dumpTechInfo(force)
local data_collection = {}

Expand All @@ -17,6 +54,7 @@ function dumpTechInfo(force)
for _, modifier in pairs(tech.effects) do
if modifier.type == "unlock-recipe" then
table.insert(unlocks, modifier.recipe)
dumpRecipe(force.recipes[modifier.recipe], false)
else
tech_data["has_modifier"] = true
end
Expand All @@ -28,48 +66,112 @@ function dumpTechInfo(force)
tech.researched = true -- enable all available recipes
end
game.write_file("techs.json", game.table_to_json(data_collection), false)
game.print("Exported Tech Data")
game.write_file("recipes.json", game.table_to_json(recipe_data_collection), false)
game.print("Exported Tech and Recipe Data")
end
end

function dumpRecipeInfo(force)
data_collection = {}
for recipe_name, recipe in pairs(force.recipes) do
if recipe.enabled then
local recipe_data = {}
recipe_data["ingredients"] = {}
recipe_data["products"] = {}
recipe_data["category"] = recipe.category
recipe_data["energy"] = recipe.energy
for _, ingredient in pairs(recipe.ingredients) do
recipe_data["ingredients"][ingredient.name] = ingredient.amount
end
for _, product in pairs(recipe.products) do
recipe_data["products"][product.name] = product.amount
end
data_collection[recipe_name] = recipe_data
end
end
game.write_file("recipes.json", game.table_to_json(data_collection), false)
game.print("Exported Recipe Data")
function get_items_to_place_prototype(proto)
if proto.type == "character" then
return nil
end
if not proto.items_to_place_this then
return nil
end
items = {}
for _, item in pairs(proto.items_to_place_this) do
if type(item) == "string" then
items[item] = true
else
items[item.name] = true
end
end
return items
end

function dumpMachineInfo()
data_collection = {}
for _, proto in pairs(game.entity_prototypes) do
if proto.crafting_categories or proto.resource_categories then
data_collection[proto.name] = {}
if proto.crafting_categories then
data_collection[proto.name]["crafting"] = {}
data_collection[proto.name]["crafting"]["speed"] = proto.crafting_speed
data_collection[proto.name]["crafting"]["categories"] = proto.crafting_categories
end
if proto.resource_categories then
data_collection[proto.name]["mining"] = {}
data_collection[proto.name]["mining"]["categories"] = proto.resource_categories
data_collection[proto.name]["mining"]["speed"] = proto.mining_speed
end
end
if proto.crafting_categories or proto.type == "character" then
data_collection[proto.name] = {}
data_collection[proto.name]["crafting"] = {}
data_collection[proto.name]["crafting"]["speed"] = proto.crafting_speed or 1
data_collection[proto.name]["crafting"]["categories"] = proto.crafting_categories
data_collection[proto.name]["crafting"]["fixed_recipe"] = proto.fixed_recipe
data_collection[proto.name]["crafting"]["input_fluid_box"] = 0
data_collection[proto.name]["crafting"]["output_fluid_box"] = 0
for _, fluid_box in pairs(proto.fluidbox_prototypes) do
for _, connection in pairs(fluid_box.pipe_connections) do
if connection.type == "input" then
data_collection[proto.name]["crafting"]["input_fluid_box"] = data_collection[proto.name]["crafting"]["input_fluid_box"] + 1
end
if connection.type == "output" then
data_collection[proto.name]["crafting"]["output_fluid_box"] = data_collection[proto.name]["crafting"]["output_fluid_box"] + 1
end
end
end
end
if proto.resource_categories then
data_collection[proto.name] = data_collection[proto.name] or {}
data_collection[proto.name]["mining"] = {}
data_collection[proto.name]["mining"]["categories"] = proto.resource_categories
data_collection[proto.name]["mining"]["speed"] = proto.mining_speed
data_collection[proto.name]["mining"]["input_fluid_box"] = false
data_collection[proto.name]["mining"]["output_fluid_box"] = false
for _, fluid_box in pairs(proto.fluidbox_prototypes) do
for _, connection in pairs(fluid_box.pipe_connections) do
if connection.type == "input-output" then
data_collection[proto.name]["mining"]["input_fluid_box"] = true
end
if connection.type == "output" then
data_collection[proto.name]["mining"]["output_fluid_box"] = true
end
end
end
end
if proto.lab_inputs then
data_collection[proto.name] = {}
data_collection[proto.name]["lab"] = {}
data_collection[proto.name]["lab"]["inputs"] = proto.lab_inputs
end
if proto.fluid then
data_collection[proto.name] = {}
data_collection[proto.name]["offshore-pump"] = {}
data_collection[proto.name]["offshore-pump"]["fluid"] = proto.fluid.name
data_collection[proto.name]["offshore-pump"]["speed"] = proto.pumping_speed
end
if proto.type == "boiler" then
local input_fluid = nil
local output_fluid = nil
for index, fluid_box in pairs(proto.fluidbox_prototypes) do
if fluid_box.production_type == "input-output" then
input_fluid = fluid_box
end
if fluid_box.production_type == "output" then
output_fluid = fluid_box
end
end
if input_fluid and output_fluid then
data_collection[proto.name] = {}
data_collection[proto.name]["boiler"] = {}
data_collection[proto.name]["boiler"]["input_fluid"] = input_fluid.filter.name
data_collection[proto.name]["boiler"]["output_fluid"] = output_fluid.filter.name
data_collection[proto.name]["boiler"]["target_temperature"] = proto.target_temperature
data_collection[proto.name]["boiler"]["energy_usage"] = proto.max_energy_usage
end
end
if proto.burner_prototype and proto.burner_prototype.burnt_inventory_size > 0 then
-- Only really care about burners that have at least one slot to store the burnt result.
data_collection[proto.name] = data_collection[proto.name] or {}
data_collection[proto.name]["fuel_burner"] = {}
data_collection[proto.name]["fuel_burner"]["categories"] = proto.burner_prototype.fuel_categories
data_collection[proto.name]["fuel_burner"]["energy_usage"] = proto.max_energy_usage
end
if data_collection[proto.name] then
data_collection[proto.name]["common"] = {}
data_collection[proto.name]["common"]["type"] = proto.type
data_collection[proto.name]["common"]["placeable_by"] = get_items_to_place_prototype(proto)
end
end
game.write_file("machines.json", game.table_to_json(data_collection), false)
game.print("Exported Machine Data")
Expand Down Expand Up @@ -114,22 +216,33 @@ function dumpResourceInfo()
game.print("Exported Minable Resource Data")
end

function dumpMachineInfo()
data_collection = {}
for _, proto in pairs(game.entity_prototypes) do
if proto.crafting_categories then
data_collection[proto.name] = proto.crafting_categories
end
end

game.write_file("machines.json", game.table_to_json(data_collection), false)
game.print("Exported Machine Data")
end

function dumpItemInfo()
data_collection = {}
for _, item in pairs(game.item_prototypes) do
data_collection[item.name] = item.stack_size
data_collection[item.name] = {}
data_collection[item.name]["stack_size"] = item.stack_size
if item.burnt_result then
data_collection[item.name]["fuel_value"] = item.fuel_value
data_collection[item.name]["fuel_category"] = item.fuel_category
data_collection[item.name]["burnt_result"] = item.burnt_result.name
end
for _, launch_product in pairs(item.rocket_launch_products) do
data_collection[item.name]["rocket_launch_products"] = data_collection[item.name]["rocket_launch_products"] or {}
if launch_product.amount then
data_collection[item.name]["rocket_launch_products"][launch_product.name] = launch_product.amount
else
amount = math.max(((launch_product.amount_min + launch_product.amount_max) / 2) * launch_product.probablility, 1)
data_collection[item.name]["rocket_launch_products"][launch_product.name] = amount
end
end
--stackable property incorrectly reports true for "spidertron-remote"
data_collection[item.name]["stackable"] = item.stackable
if item.type == "spidertron-remote" then
data_collection[item.name]["stackable"] = false
end
if item.place_result then
data_collection[item.name]["place_result"] = item.place_result.name
end
end

game.write_file("items.json", game.table_to_json(data_collection), false)
Expand All @@ -139,18 +252,44 @@ end
function dumpFluidInfo()
data_collection = {}
for _, item in pairs(game.fluid_prototypes) do
table.insert(data_collection, item.name)
fluid = {}
fluid["default_temperature"] = item.default_temperature
if item.max_temperature == math.huge then
fluid["max_temperature"] = "inf"
else
fluid["max_temperature"] = item.max_temperature
end
fluid["heat_capacity"] = item.heat_capacity
data_collection[item.name] = fluid
end

game.write_file("fluids.json", game.table_to_json(data_collection), false)
game.print("Exported Fluid Data")
end

function mod_is_AP(str)
-- lua string.match is way more restrictive than regex. Regex would be "^AP-W?\d{20}-P[1-9]\d*-.+$"
local result = string.match(str, "^AP%-W?%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%-P[1-9]%d-%-.+$")
if result ~= nil then
log("Archipelago Mod: " .. result .. " is loaded.")
end
return result ~= nil
end

function dumpGameInfo()
-- Verify that Archipelago is NOT running before dumping the info.
for name, _ in pairs(game.active_mods) do
if mod_is_AP(name) then
game.print("ERROR: Archipelago is running. Can't dump info")
return
end
end

-- dump Game Information that the Archipelago Randomizer needs.
local force = game.forces["player"]
dumpModInfo()
dumpRecipeInfo(force)
dumpTechInfo(force)
dumpRecipeInfo(force)
dumpResourceInfo()
dumpMachineInfo()
dumpItemInfo()
Expand Down