#Mod Framework

1 messages · Page 1 of 1 (latest)

sonic thorn
#

Let's discuss details and get feedback on the overall style of the library.
This library enables modders to easily add buildings and other things to the game without having to create graphics or much code for them. It brings graphics and the boilerplate code together with some default code and builders to configure the object to their needs.

#

First working example is the Lumber Mill from Hurricane. The concept I went with currently looks like this for a real mod I'm working on:

local LumberMill = MF.Buildings.LumberMill()

data:extend({
    {
        type = "recipe-category",
        name = "wood-processing-or-assembling"
    }
})

LumberMill.entityBuilder
        :burnerEnergySource({ emissions_per_minute = { noise = 50 } })
        :baseProductivity(0.5)
        :apply({
            crafting_categories = { "wood-processing-or-assembling" },
            crafting_speed = 4,
            energy_usage = "1000kW",
        })

LumberMill.itemBuilder:apply({
    default_import_location = "lignumis"
})

LumberMill.recipeBuilder
        :ingredients({
            { type = "item", name = "stone-brick", amount = 40 },
            { type = "item", name = "lumber", amount = 100 },
            { type = "item", name = "wooden-gear-wheel", amount = 100 },
            { type = "item", name = "copper-plate", amount = 60 },
            { type = "item", name = "burner-assembling-machine", amount = 5 }
        })
        :apply({
            category = "wood-processing-or-assembling"
        })

LumberMill.technologyBuilder
        :prerequisites({ "wood-science-pack" })
        :ingredients({{ "wood-science-pack", 1 }})
        :apply()
#

I use the builder pattern to create the entity, item, recipe and a technology. apply combines build and data:extend. Some default values are overridden and some value are mandatory because there are no defaults (recipe ingredients, tech prerequisites and tech ingredients).

#

As an example, I post the current code of the itemBuilder (currently the builder with the fewest lines of code, currently everything is undocumented):

local itemBuilder = function(name)
    local _weight = 200 * kg

    return {
        itemsPerRocket = function(self, count)
            _weight = (1000 / count) * kg
            return self
        end,

        build = function(self, overrides)
            local result = {
                type = "item",
                name = name,
                icon = img("lumber-mill-icon.png"),
                subgroup = "production-machine",
                order = "d[" .. name .. "]",
                inventory_move_sound = item_sounds.mechanical_large_inventory_move,
                pick_sound = item_sounds.mechanical_large_inventory_pickup,
                drop_sound = item_sounds.mechanical_large_inventory_move,
                place_result = name,
                stack_size = 20,
                default_import_location = "Nauvis",
                weight = _weight
            }

            if (overrides) then
                result = util.merge({ result, overrides })
            end

            return result
        end,

        apply = function(self, overrides)
            local result = self:build(overrides)
            data:extend({ result })
            return result
        end
    }
end
#

This reduced the lua file for the lumber mill in my actual mod from 162 to 38 lines (including empty lines).

#

The framework doesn't add anything on its own and with all defaults you are still missing recipe ingredients and proper placement in the technology tree. That's up to the mod author that is using this framework.

vagrant heath
#

I will dig into this momentarily, just trying to wrap up my latest content.

vagrant heath
#

I don't know if I'm smart enough for this. lol

hard frigate
#

Ill check this when i have time

sonic thorn
#

I switched to using classes and added belts with several hand crafted recolors of the vanilla belts. This code adds a purple belt, underground and splitter with 90 items/s, all the items, remnants and next_upgrade handling:

local BeltFactory = require(MF.logistics .. "Belts")
local Belt = BeltFactory("ludicrous-speed", "purple", "fast")

Belt.EntityBuilder:new()
    :itemsPerSecond(90)
    :previousTier("turbo")
    :undergroundDistance(15)
    :animationSpeedMultiplier(0.9)
    :apply()

Belt.ItemBuilder:new():apply()
#

How about a black belt with 2.5 items/s with pretty much useless undergrounds?

local BeltFactory = require(MF.logistics .. "Belts")
local Belt = BeltFactory("snail-speed", "black", "slow")

Belt.EntityBuilder:new()
    :itemsPerSecond(2.5)
    :nextTier("")
    :undergroundDistance(2)
    :apply()

Belt.ItemBuilder:new():apply()
heavy wren
#

Hello, I've been added here by someone?

sonic thorn
#

I don't know 🤷

#

You can add people to a thread without their consent!? Wasn't me 😄

heavy wren
#

Ah I clicked the link 😄 Sorry I'm not familiar with threads on discord.

sonic thorn
#

Recipes and technology for the belts:

Belt.RecipeBuilder:new()
    :ingredients("transportBelt", {
        { type = "item", name = "lumber", amount = 1 }
    })
    :ingredients("undergroundBelt", {
        { type = "item", name = "lumber", amount = 2 }
    })
    :ingredients("splitter", {
        { type = "item", name = "lumber", amount = 3 }
    })
    :apply()

Belt.TechnologyBuilder:new()
    :prerequisites({ "wood-science-pack" })
    :ingredients({{ "wood-science-pack", 1 }})
    :apply()
sonic thorn
#

The big question is, how to properly document this?

hard frigate
#

Like yk
120 secs 60 secs yada yada

sonic thorn
#

It's all very customizable. The apply/build functions accept a table to set/override anything in the generated result before data:extend is called. For non trivial things I added convenience functions.
For multiple tiers, you can call the BeltFactory multiple times with different params. Or apply multiple times with different overrides.

#

I can post more examples tomorrow to make it clearer.

hard frigate
sonic thorn
# hard frigate I mean even examples for idk The researches i conceptualized for my mod For exam...

In the end, the code generates regular prototype data. You can adjust it however you like. These all create the same result:

LumberMill.TechnologyBuilder:new()
        :prerequisites({ "wood-science-pack" })
        :ingredients({{ "wood-science-pack", 1 }})
        :count(500)
        :time(60)
        :apply()
LumberMill.TechnologyBuilder:new()
        :prerequisites({ "wood-science-pack" })
        :apply({
            unit = {
                count = 500,
                ingredients = {{ "wood-science-pack", 1 }},
                time = 60
            }
        })
local lumberMillTech = LumberMill.TechnologyBuilder:new():build()
lumberMillTech.prerequisites = { "wood-science-pack" }
lumberMillTech.unit = {
    count = 500,
    ingredients = {{ "wood-science-pack", 1 }},
    time = 60
}
data:extend({ lumberMillTech  })

As this is still a proof of concept, the quantum stabilizer is not yet included but imagine it working the same as the lumber mill. Also graphics are included, so you don't have to care about that.

#

For more recipes/effects unlocked I created convenience functions additionalRecipes and additionalEffects but you can of course also add them in a more regular way as an override passed to apply/build or set it in the result like the other things in the last example.

hard frigate