-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from theRustyKnife/0.2-dev
0 2 dev
- Loading branch information
Showing
15 changed files
with
748 additions
and
679 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
local config = {} | ||
|
||
|
||
-- GENRAL -- | ||
-- The name of the mod FML is installed in - will be used for checking on_configuration_changed and saving some data (needs to be unique) | ||
config.MOD_NAME = "circuit-network-switch" | ||
|
||
-- The directory FML is installed in - will be used for adressing graphics | ||
config.FML_PATH = "/FML" | ||
|
||
-- If set to true modules won't be loaded using pcall, therefore crashing if there are errors - good for debugging | ||
config.FORCE_LOAD_MODULES = false | ||
|
||
-- If set to true then the on_load event will be raised after on_init too | ||
config.ON_LOAD_AFTER_INIT = true | ||
|
||
-- The module names with paths that init will attempt to load | ||
config.MODULES_TO_LOAD = { | ||
Object = ".modules.Object", | ||
surface = ".modules.surface", | ||
table = ".modules.table", | ||
data = ".modules.data", | ||
blueprint_data = ".modules.blueprint_data", | ||
format = ".modules.format", | ||
} | ||
|
||
-- The name of the global table FML will use. You shouldn't need to change this unless you have a global table with my name for some reason... | ||
-- Changing this will likely break backwards compatibility. | ||
config.GLOBAL_NAME = "therustyknife" | ||
|
||
|
||
-- DATA -- | ||
-- Default icon to use where none was specified and it's mandatory | ||
config.DEFAULT_ICON_PATH = "__core__/graphics/clear.png" | ||
|
||
-- The default base for auto-generated items | ||
config.ITEM_BASE = { | ||
type = "item", | ||
icon = DEFAULT_ICON_PATH, | ||
flags = {"goes-to-quickbar"}, | ||
subgroup = "transport", | ||
order = "unspecified", | ||
stack_size = 50, | ||
} | ||
|
||
-- The default base for auto-generated recipes | ||
config.RECIPE_BASE = { | ||
type = "recipe", | ||
enabled = false, | ||
} | ||
|
||
-- Default minable values | ||
config.DEFAULT_MINABLE = {hardness = 0.2, mining_time = 0.5} | ||
|
||
|
||
-- BLUEPRINT_DATA -- | ||
-- The path to the settings definition, nil if none | ||
config.BLUEPRINT_DATA_PATH = nil | ||
|
||
-- The name to use for the prototype, will be prefixed with mod name and FML | ||
config.BLUEPRINT_DATA_PROTOTYPE_NAME = "blueprint-data-prototype" | ||
|
||
-- The size of the proxy - should be the same as the size of your entity | ||
config.BLUEPRINT_PROXY_SIZE = {{-0.35, -0.35}, {0.35, 0.35}} | ||
|
||
|
||
return config |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
local FML_VERSION_CODE = 3 | ||
local FML_VERSION_NAME = "0.1.0-alpha.3.0" | ||
|
||
|
||
local _M = {} | ||
|
||
|
||
-- requires a module without interfering with any other required modules | ||
-- it is recommended that any FML modules use this instead of the regular require to prevent name/path clashes with the actual mod code | ||
function _M.safe_require(path) | ||
-- store the original value | ||
local t = package.loaded[path] | ||
package.loaded[path] = nil | ||
-- try to load | ||
local res | ||
local status, err = pcall(function() res = require(path); end) | ||
package.loaded[path] = t -- set the value back to the original | ||
|
||
-- if loading failed, re-raise the error | ||
if (not status) then error(err); end | ||
|
||
return res | ||
end | ||
|
||
|
||
local config = _M.safe_require(".config") | ||
|
||
|
||
package.loaded["therustyknife.FML"] = _M -- global access to this instance of FML | ||
package.loaded["therustyknife.FML.config"] = config -- global access to the FML general config | ||
|
||
|
||
-- this only runs when loaded from control | ||
-- a better way to check for that would be good since if there appears a variable named script in the data loading stage it'll fail | ||
if script and script.on_init then | ||
local global_handlers = {init = {}, load = {}, config_change = {}, fml_config_change = {}, mod_config_change = {}, fml_init = {}} -- handlers to be run on load and init | ||
|
||
-- the global table before global is accessible | ||
-- contains functions for registering various event handlers | ||
_M.global = { | ||
loaded = false, -- indicate that the global table is not yet loaded | ||
on_init = function(f) table.insert(global_handlers.init, f) end, -- same as script.on_init | ||
on_load = function(f) table.insert(global_handlers.load, f) end, -- same as script.on_load, except it also runs when on_init does | ||
on_config_change = function(f) table.insert(global_handlers.config_change, f) end, -- same as script.on_configuration_changed | ||
on_fml_config_change = function(f) table.insert(global_handlers.fml_config_change, f) end, -- runs when FML version changes, except when FML was first installed - passes a table containing the old and new versions | ||
on_mod_config_change = function(f) table.insert(global_handlers.mod_config_change, f) end, -- runs whenever there's an entry for the current MOD_NAME in on_config_change - passes the same data as on_config_change | ||
on_fml_init = function(f) table.insert(global_handlers.fml_init, f) end, -- called when FML is first installed (after on_init) - FML's global table is passed as argument | ||
} | ||
-- runs all the handlers from a table passing an argument to them | ||
local function run(handlers, arg) for _, handler in ipairs(handlers) do handler(arg); end end | ||
|
||
-- create the global table if it doesn't exist - if everything works properly it should be safe to call this from on_load | ||
local function init_global() | ||
global[config.GLOBAL_NAME] = global[config.GLOBAL_NAME] or {} | ||
_M.global = global[config.GLOBAL_NAME] -- get the reference to our global table | ||
|
||
-- this will return a table from the global, creating a new one if it's not present | ||
function _M.global.get(name) | ||
_M.global[name] = _M.global[name] or {} | ||
return _M.global[name] | ||
end | ||
end | ||
|
||
script.on_init(function() | ||
init_global() | ||
|
||
global.loaded = true -- indicate that the global table is loaded and contains the actual global values | ||
global.fml_version = {code = FML_VERSION_CODE, name = FML_VERSION_NAME} | ||
|
||
-- call all the respective handlers | ||
run(global_handlers.init) | ||
run(global_handlers.fml_init, _M.global) | ||
if config.ON_LOAD_AFTER_INIT then run(global_handlers.load); end | ||
end) | ||
|
||
script.on_load(function() | ||
run(global_handlers.load) | ||
end) | ||
|
||
script.on_configuration_changed(function(data) | ||
run(global_handlers.config_change, data) | ||
|
||
if not global.fml_version then -- FML was just added to the mod | ||
global.fml_version = {code = FML_VERSION_CODE, name = FML_VERSION_NAME} | ||
run(global_handlers.fml_init, _M.global) | ||
elseif global.fml_version.code ~= FML_VERSION_CODE then -- FML version has changed | ||
local arg = { | ||
old = global.fml_version, | ||
new = {code = FML_VERSION_CODE, name = FML_VERSION_NAME}, | ||
} | ||
global.fml_version = arg.new | ||
run(global_handlers.fml_config_change, arg) | ||
end | ||
|
||
if data.mod_changes[config.MOD_NAME] then | ||
init_global() | ||
run(global_handlers.mod_config_change, data) | ||
end | ||
end) | ||
end | ||
|
||
|
||
-- here we load the modules | ||
for name, path in pairs(config.MODULES_TO_LOAD) do | ||
local function t_load() _M[name] = _M.safe_require(path); end | ||
|
||
if config.FORCE_LOAD_MODULES then t_load() | ||
else pcall(t_load) | ||
end | ||
|
||
if type(_M[name]) ~= "table" then _M[name] = nil; end | ||
end | ||
|
||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
if not data then return nil; end -- requires data to load | ||
|
||
|
||
local config = require "therustyknife.FML.config" | ||
local FML = require "therustyknife.FML" | ||
|
||
|
||
local function make_item_for(prototype, properties) | ||
properties = properties or {} | ||
local item = FML.table.deep_copy(properties.base or config.ITEM_BASE) -- get the base item | ||
|
||
-- try to extract data from the prototype | ||
item.name = prototype.name | ||
item.place_result = prototype.name | ||
item.icon = prototype.icon or item.icon | ||
item.order = prototype.order or item.order | ||
item.subgroup = prototype.subgroup or item.subgroup | ||
|
||
if properties.properties then FML.table.insert_all(item, properties.properties, true, true); end -- override with explicitly defined properties | ||
|
||
data:extend{item} | ||
|
||
prototype.minable = prototype.minable or FML.table.deep_copy(config.DEFAULT_MINABLE) -- make sure there's a minable table | ||
prototype.minable.result = item.name | ||
end | ||
|
||
local function make_recipe_for(prototype, properties) | ||
properties = properties or {} | ||
local recipe = FML.table.deep_copy(properties.base or config.RECIPE_BASE) -- get the base recipe | ||
|
||
recipe.name = prototype.name | ||
recipe.result = prototype.name | ||
|
||
if properties.properties then FML.table.insert_all(recipe, properties.properties, true, true); end -- override with explicitly defined properties | ||
|
||
data:extend{recipe} | ||
|
||
if properties.unlock_with then -- add the recipe to the appropriate tech | ||
if data.raw["technology"] and data.raw["technology"][properties.unlock_with] then | ||
table.insert(data.raw["technology"][properties.unlock_with].effects, {type = "unlock-recipe", recipe = recipe.name}) | ||
else | ||
error("Can't add recipe " .. recipe.name .. " to the " .. tostring(properties.unlock_with) .. " technology because it does not (yet) exist.") | ||
end | ||
end | ||
end | ||
|
||
local auto_gen_mapping = {item = make_item_for, recipe = make_recipe_for} | ||
local function handle_auto_gen(prototype, auto_generate) | ||
if type(auto_generate) == "string" and auto_gen_mapping[auto_generate] then | ||
auto_gen_mapping[auto_generate](prototype) | ||
|
||
elseif type(auto_generate) == "table" then | ||
for i, v in pairs(auto_generate) do | ||
if type(v) == "string" and auto_gen_mapping[v] then | ||
auto_gen_mapping[v](prototype) | ||
elseif type(v) == "table" and type(i) == "string" and auto_gen_mapping[i] then | ||
auto_gen_mapping[i](prototype, v) | ||
end | ||
end | ||
end | ||
end | ||
|
||
|
||
local _M = {} | ||
|
||
|
||
function _M.inherit(base_type, base_name) | ||
if not base_name then base_name = base_type; end -- use type as name if no name is specified | ||
if type(base_type) ~= "string" or type(base_name) ~= "string" or not data.raw[base_type] or not data.raw[base_type][base_name] then -- only inherit from valid entries | ||
error("can't inherit from type: " .. tostring(base_type) .. ", name: " .. tostring(base_name)) | ||
end | ||
|
||
return FML.table.deep_copy(data.raw[base_type][base_name]) | ||
end | ||
|
||
--[[ | ||
prototypes format: | ||
prototype definition or { | ||
{ | ||
base (optional) = {a table with a full or partial prototype definition, can be created from an exisiting prototype with inherit(base_type, base_name)}, | ||
properties (optional) = { | ||
name = string, -- at least this should be overriden, otherwise you're just changing the base prototype (unless you defined base as a new prototype with a unique name) | ||
-- if base is not defined, this table should look like the usual prototype definition | ||
-- there's no checking for validity of the definition - the game's data loader will handle that | ||
... | ||
}, | ||
auto_generate = one of the strings in the table or { | ||
"item", "recipe", | ||
item = {base = {a table with a full or partial item definition, can be created with inherit}, properties = {these will have the highest priority}}, | ||
recipe = {base = {a table with a full or partial recipe definition, can be created with inherit}, properties = {these will have the highest priority}, unlock_with = string}, | ||
} | ||
}, | ||
... | ||
} | ||
]] | ||
|
||
function _M.make_prototypes(prototypes) | ||
for _, p in ipairs(prototypes) do _M.make_prototype(p); end | ||
end | ||
|
||
function _M.make_prototype(prototype) | ||
local res | ||
if prototype.type then -- if it's a regular prototype definition, we add it to data right away | ||
data:extend{prototype} | ||
res = prototype | ||
else | ||
res = FML.table.deep_copy(prototype.base) or {} -- get the base prototype | ||
|
||
if prototype.properties and type(prototype.properties == "table") then FML.table.insert_all(res, prototype.properties, true, true); end -- override with explicitly defined properties | ||
|
||
if prototype.auto_generate then handle_auto_gen(res, prototype.auto_generate); end -- auto-generate item and recipe | ||
|
||
data:extend{res} | ||
end | ||
|
||
return data.raw[res.type][res.name] | ||
end | ||
|
||
function _M.is_result(recipe, item) | ||
if type(recipe) == "string" then recipe = data.raw["recipe"][recipe]; end | ||
if type(item) == "table" then item = item.name; end | ||
assert(type(recipe) == "table", "Invalid recipe: " .. tostring(recipe)) | ||
assert(type(item) == "string", "Invalid item: " .. tostring(item)) | ||
|
||
if recipe.result and recipe.result == item then return true | ||
elseif recipe.results then | ||
for _, v in pairs(recipe.results) do | ||
if v.name == item then return true; end | ||
end | ||
end | ||
|
||
return false | ||
end | ||
|
||
|
||
return _M |
Oops, something went wrong.