This commit is contained in:
theFox6 2024-01-24 11:06:44 +01:00
commit 593d477583
44 changed files with 2069 additions and 496 deletions

@ -5,6 +5,7 @@ read_globals = {
"dump", "dump",
"ItemStack", "ItemStack",
"pipeworks", "pipeworks",
"unified_inventory",
"PseudoRandom", "PseudoRandom",
"stairsplus", "stairsplus",
"intllib", "intllib",

49
api.lua

@ -27,6 +27,7 @@ function microexpansion.register_oredef(ore, defs)
for _,d in ipairs(defs) do for _,d in ipairs(defs) do
d.ore = "microexpansion:"..ore d.ore = "microexpansion:"..ore
minetest.log("verbose", minetest.serialize(d))
minetest.register_ore(d) minetest.register_ore(d)
end end
end end
@ -72,6 +73,13 @@ end
-- [function] Register Node -- [function] Register Node
function microexpansion.register_node(itemstring, def) function microexpansion.register_node(itemstring, def)
if minetest.get_modpath("mcl_core") then
def._mcl_hardness = def._mcl_hardness or 3
def._mcl_blast_resistance = def._mcl_blast_resistance or 3
def._mcl_hardness = def._mcl_hardness or 3
def._mcl_silk_touch_drop = def._mcl_silk_touch_drop or true
def.groups.pickaxey = def.groups.pickaxey or 3
end
-- Check if disabled -- Check if disabled
if def.disabled == true then if def.disabled == true then
return return
@ -133,3 +141,44 @@ function microexpansion.update_node(pos,event)
def.me_update(pos,node,ev) def.me_update(pos,node,ev)
end end
end end
-- [function] Move items from inv to inv
function microexpansion.move_inv(inv1, inv2, max, filter)
if max <= 0 then return end
local finv, tinv = inv1.inv, inv2.inv
local fname, tname = inv1.name, inv2.name
local huge = inv2.huge
local inserted = 0
for _,v in ipairs(finv:get_list(fname) or {}) do
local left = max-inserted
if left <= 0 then
break;
end
if not v:is_empty() then
if v:get_count() > left then
v = v:peek_item(left)
end
if tinv and tinv:room_for_item(tname, v) and (not filter or not filter(v)) then
if huge then
microexpansion.insert_item(v, tinv, tname)
finv:remove_item(fname, v)
else
--TODO: continue inserting from the same stack if it is bigger than max
if v:get_count() > v:get_stack_max() then
v = v:peek_item(v:get_stack_max())
end
local leftover = tinv:add_item(tname, v)
finv:remove_item(fname, v)
if leftover and not(leftover:is_empty()) then
microexpansion.log("leftover items when transferring inventory","warning")
finv:add_item(fname, leftover)
end
end
inserted = inserted + v:get_count()
end
end
end
return inserted
end

@ -1,2 +1,3 @@
default default
pipeworks? pipeworks?
basic_materials?

@ -11,15 +11,18 @@ microexpansion.gui_bg = "bgcolor[#080808BB;true]background[5,5;1,1;gui_formbg.pn
microexpansion.gui_slots = "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]" microexpansion.gui_slots = "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]"
microexpansion.settings = { microexpansion.settings = {
huge_stacks = minetest.settings:get_bool("microexpansion_huge_stacks") huge_stacks = minetest.settings:get_bool("microexpansion_huge_stacks"),
simple_craft = minetest.settings:get_bool("microexpansion_simple_craft")
} }
microexpansion.uinv_category_enabled = minetest.global_exists("unified_inventory") and unified_inventory.add_category_item and true or false
-- logger -- logger
function microexpansion.log(content, log_type) function microexpansion.log(content, log_type)
assert(content, "microexpansion.log: missing content") assert(content, "microexpansion.log: missing content")
if not content then return false end if not content then return false end
if log_type == nil then log_type = "action" end if log_type == nil then log_type = "action" end
minetest.log(log_type, "[MicroExpansion] "..content) minetest.log(log_type, "[MicroExpansion] "..content)
end end
-- Load API -- Load API
@ -37,45 +40,45 @@ local settings = Settings(modpath.."/modules.conf"):to_table()
-- [function] Get module path -- [function] Get module path
function microexpansion.get_module_path(name) function microexpansion.get_module_path(name)
local module_path = modpath.."/modules/"..name local module_path = modpath.."/modules/"..name
local handle = io.open(module_path.."/init.lua") local handle = io.open(module_path.."/init.lua")
if handle then if handle then
io.close(handle) io.close(handle)
return module_path return module_path
end end
end end
-- [function] Load module (overrides modules.conf) -- [function] Load module (overrides modules.conf)
function microexpansion.load_module(name) function microexpansion.load_module(name)
if not loaded_modules[name] then if not loaded_modules[name] then
local module_path = microexpansion.get_module_path(name) local module_path = microexpansion.get_module_path(name)
if module_path then if module_path then
dofile(module_path.."/init.lua") dofile(module_path.."/init.lua")
loaded_modules[name] = true loaded_modules[name] = true
return true return true
else else
microexpansion.log("Invalid module \""..name.."\". The module either does not exist ".. microexpansion.log("Invalid module \""..name.."\". The module either does not exist "..
"or is missing an init.lua file.", "error") "or is missing an init.lua file.", "error")
end end
else else
return true return true
end end
end end
-- [function] Require module (does not override modules.conf) -- [function] Require module (does not override modules.conf)
function microexpansion.require_module(name) function microexpansion.require_module(name)
if settings[name] then if settings[name] then
microexpansion.log("loading module " .. name) microexpansion.log("loading module " .. name)
return microexpansion.load_module(name) return microexpansion.load_module(name)
else else
microexpansion.log("not loading module " .. name) microexpansion.log("not loading module " .. name)
end end
end end
for name,enabled in pairs(settings) do for name,enabled in pairs(settings) do
if enabled ~= false then if enabled ~= false then
microexpansion.load_module(name) microexpansion.load_module(name)
end end
end end

@ -1,4 +1,5 @@
name = microexpansion name = microexpansion
description = A storage managing solution to get an overview over all your items. description = A storage managing solution to get an overview over all your items.
depends = default optional_depends = pipeworks,basic_materials,mcl_furnaces,mcl_core,drawers,technic,technic_plus
optional_depends = pipeworks, drawers, technic, technic_plus supported_games = mineclone2,mineclonia,minetest_game

@ -1,5 +1,6 @@
shared = true
network = true network = true
power = false power = false
storage = true storage = true
ores = true ores = true
item_transfer = true
crafting = true

@ -0,0 +1,37 @@
---
-- craftitems that offer alternative craft recipes
local me = microexpansion
--TODO: build specialized integrated circuits / chips out of the ic and other stuff that are required to build the devices / machines instead of the control unit being an alternative
---
-- [Microexpansion Control Unit]
-- a different logic chip that uses gold, quartz and wood
-- for use instead of basic_materials:ic that requires sand, coal and copper
me.register_item("logic_chip", {
description = "Control Unit",
recipe = {
{ 2,
{
{"basic_materials:gold_wire"},
{"basic_materials:silicon"},
{"basic_materials:plastic_sheet"}
},
},
{ 2,
{
{"basic_materials:gold_wire"},
{"microexpansion:quartz_crystal"},
{"basic_materials:plastic_sheet"}
},
},
{ 2,
{
{"microexpansion:gold_wire"},
{"microexpansion:quartz_crystal"},
{"group:wood"}
},
},
},
})

@ -0,0 +1,8 @@
local module_path = microexpansion.get_module_path("crafting")
-- basic_materials replacements
dofile(module_path.."/materials.lua")
-- shared items used for various machine recipes
dofile(module_path.."/shared.lua")
-- items that allow for alternative recipes
dofile(module_path.."/alternatives.lua")

@ -0,0 +1,32 @@
---
-- Craft materials, that are normally registered by basic_materials
local me = microexpansion
local substitute_basic_materials = microexpansion.settings.simple_craft == true or not minetest.get_modpath("basic_materials")
local gold_wire_recipe
if minetest.get_modpath("mcl_core") then
gold_wire_recipe = {
{ 2, {
{"mcl_core:gold_ingot", "mcl_core:stick"},
{"mcl_core:stick", ""}
},
},
}
else
gold_wire_recipe = {
{ 2, {
{"default:gold_ingot", "default:stick"},
{"default:stick", ""}
},
},
}
end
-- [register item] Gold Wire
me.register_item("gold_wire", {
description = "Gold Wire",
groups = { wire = 1 },
recipe = substitute_basic_materials and gold_wire_recipe or nil,
})

@ -0,0 +1,53 @@
-- crafting/shared.lua
local me = microexpansion
-- custom items that are used by multiple devices
local steel_infused_obsidian_ingot_recipe, machine_casing_recipe
if minetest.get_modpath("mcl_core") then
steel_infused_obsidian_ingot_recipe = {
{ 2, {
{ "mcl_core:iron_ingot", "mcl_core:obsidian", "mcl_core:iron_ingot" },
},
},
}
machine_casing_recipe = {
{ 1, {
{"mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_copper:copper_ingot", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
},
},
}
else
steel_infused_obsidian_ingot_recipe = {
{ 2, {
{ "default:steel_ingot", "default:obsidian_shard", "default:steel_ingot" },
},
},
}
machine_casing_recipe = {
{ 1, {
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
{"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
},
}
end
-- [register item] Steel Infused Obsidian Ingot
me.register_item("steel_infused_obsidian_ingot", {
description = "Steel Infused Obsidian Ingot",
recipe = steel_infused_obsidian_ingot_recipe,
})
-- [register item] Machine Casing
me.register_item("machine_casing", {
description = "Machine Casing",
recipe = machine_casing_recipe,
})

@ -0,0 +1,263 @@
-- item_transfer/api.lua
local me = microexpansion
local item_transfer = {}
me.item_transfer = item_transfer
function item_transfer.get_output_inventory(pos,metadata,inventory)
local meta = metadata or minetest.get_meta(pos)
local inv = inventory or meta:get_inventory()
local lists = inv:get_lists()
if not lists then
return
elseif lists["dst"] then
return "dst", inv
elseif lists["main"] then
return "main", inv
end
end
function item_transfer.get_input_inventory(pos,metadata,inventory)
local meta = metadata or minetest.get_meta(pos)
local inv = inventory or meta:get_inventory()
local lists = inv:get_lists()
if not lists then
return
elseif lists["src"] then
return "src", inv
elseif lists["main"] then
return "main", inv
end
end
function microexpansion.vector_cross(a, b)
return {
x = a.y * b.z - a.z * b.y,
y = a.z * b.x - a.x * b.z,
z = a.x * b.y - a.y * b.x
}
end
function microexpansion.facedir_to_top_dir(facedir)
return ({[0] = {x = 0, y = 1, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1},
{x = 1, y = 0, z = 0},
{x = -1, y = 0, z = 0},
{x = 0, y = -1, z = 0}})
[math.floor(facedir / 4)]
end
function microexpansion.facedir_to_right_dir(facedir)
return microexpansion.vector_cross(
microexpansion.facedir_to_top_dir(facedir),
minetest.facedir_to_dir(facedir)
)
end
function microexpansion.count_upgrades(inv)
local upgrades = {}
for i = 0, inv:get_size("upgrades") do
local stack = inv:get_stack("upgrades", i)
local item = stack:get_name()
if item == "microexpansion:upgrade_filter" then
upgrades.filter = (upgrades.filter or 0) + stack:get_count()
elseif item == "microexpansion:upgrade_bulk" then
upgrades.bulk = (upgrades.bulk or 0) + stack:get_count()
end
end
return upgrades
end
function item_transfer.update_timer_based(pos,_,ev)
if ev then
if ev.type ~= "disconnect"
and ev.type ~= "connect"
and ev.type ~= "construct" then
return
end
end
local meta = minetest.get_meta(pos)
if me.get_connected_network(pos) then
meta:set_string("infotext", "Network connected")
if not minetest.get_node_timer(pos):is_started() then
minetest.get_node_timer(pos):start(2)
end
else
meta:set_string("infotext", "No Network")
minetest.get_node_timer(pos):stop()
end
end
function item_transfer.setup_io_device(title, pos, metadata, inventory)
local meta = metadata or minetest.get_meta(pos)
local inv = inventory or meta:get_inventory()
local formspec = [[
formspec_version[2]
size[11,11]
]] ..
microexpansion.gui_bg ..
microexpansion.gui_slots
if title then
formspec = formspec .. "label[9,0.5;"..title.."]"
end
local upgrades = me.count_upgrades(inv)
if upgrades.filter then
inv:set_size("filter", math.pow(2, upgrades.filter - 1))
formspec = formspec .. [[
label[0.5,0.75;filter]
list[context;filter;0.5,1;5,3]
]]
else
inv:set_size("filter",0)
end
--TODO: target inventory dropdown
inv:set_size("upgrades", 4)
meta:set_string("formspec",
formspec ..
[[
label[8.5,2.5;upgrades]
list[context;upgrades;8,2.75;2,2]
list[current_player;main;0.5,5.5;8,1;]
list[current_player;main;0.5,7;8,3;8]
listring[current_name;upgrades]
listring[current_player;main]
]])
end
local access_level = microexpansion.constants.security.access_levels
local io_device_base = {
is_ground_content = false,
groups = { crumbly = 1, me_connect = 1 },
paramtype = "light",
paramtype2 = "facedir",
me_update = item_transfer.update_timer_based,
after_place_node = function(pos, placer)
if not placer then
return false
end
local name = placer:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
-- prevent placing exporters on a network that a player doesn't have access to
--Do we need to send a disconnect or stop any node timers?
minetest.remove_node(pos)
return true
else
return false
end
elseif minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
--protection probably handles this itself
--minetest.remove_node(pos)
return true
end
end,
can_dig = function(pos, player)
if not player then
return false
end
local name = player:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
return false
end
elseif minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("upgrades")
end,
allow_metadata_inventory_put = function(pos, listname, _, stack, player)
local max_allowed = stack:get_count()
if listname == "upgrades" then
local item = stack:get_name()
if item == "microexpansion:upgrade_filter" then
local filter_upgrades = me.count_upgrades(minetest.get_meta(pos):get_inventory()).filter
if filter_upgrades then
max_allowed = math.max(0, math.min(stack:get_count(), 5 - filter_upgrades))
else
max_allowed = math.min(stack:get_count(), 5)
end
elseif item == "microexpansion:upgrade_bulk" then
local bulk_upgrades = me.count_upgrades(minetest.get_meta(pos):get_inventory()).bulk
if bulk_upgrades then
max_allowed = math.max(0, math.min(stack:get_count(), 10 - bulk_upgrades))
else
max_allowed = math.min(stack:get_count(), 10)
end
else
return 0
end
end
if not player then
return max_allowed
end
local name = player:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
return 0
end
elseif minetest.is_protected(pos, name) then
--minetest.record_protection_violation(pos, name)
return 0
end
if listname == "filter" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local filter = stack:peek_item()
if inv:room_for_item(listname,filter) and not inv:contains_item(listname, filter) then
inv:add_item(listname, filter)
end
return 0
else
return max_allowed
end
end,
allow_metadata_inventory_take = function(pos, listname, _, stack, player)
if not player then
return 0
end
local name = player:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
return 0
end
elseif minetest.is_protected(pos, name) then
--minetest.record_protection_violation(pos, name)
return 0
end
if listname == "filter" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:remove_item(listname, stack)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_move = function(pos, from_list, _, to_list, _, count, player)
--perhaps allow filtering for upgrades and removing filters in this way
if from_list ~= to_list then
return 0
end
return count
end,
}
function item_transfer.register_io_device(itemstring, def)
for k,v in pairs(io_device_base) do
if def[k] == nil then
def[k] = v
end
end
if not def.groups.me_connect then
def.groups.me_connect = 1
end
microexpansion.register_node(itemstring, def)
end

@ -0,0 +1,93 @@
-- microexpansion/machines.lua
local me = microexpansion
local item_transfer = me.item_transfer
local access_level = microexpansion.constants.security.access_levels
local function exporter_timer(pos, elapsed)
local net, cp = me.get_connected_network(pos)
if not net then
return false
end
local node = minetest.get_node(pos)
local target = vector.add(pos, microexpansion.facedir_to_right_dir(node.param2))
--TODO: allow setting list with control upgrade
--TODO: perhaps allow setting limits with control upgrade
local list, inv = item_transfer.get_input_inventory(target)
if list then
--TODO: move more with upgrades
local own_inv = minetest.get_meta(pos):get_inventory()
local upgrades = me.count_upgrades(own_inv)
local export_filter = upgrades.filter and function(stack)
return not own_inv:contains_item("filter",stack:peek_item())
end
local max_count = math.pow(2, upgrades.bulk or 0)
microexpansion.move_inv({inv=net:get_inventory(),name="main",huge=true}, {inv=inv,name=list}, max_count, export_filter)
--TODO: perhaps call allow_insert and on_insert callbacks
end
return true
end
-- [MicroExpansion Exporter] Register node
item_transfer.register_io_device("exporter", {
description = "ME exporter",
usedfor = "Exports items from ME Networks into machines",
tiles = {
"exporter",
"exporter",
"interface",
"cable",
"microexpansion_exporter.png^[transform4",
"exporter",
},
drawtype = "nodebox",
node_box = {
--perhaps convert to connectable
type = "fixed",
fixed = {
{-0.5, -0.25, -0.25, 0.25, 0.25, 0.25},
{0.25, -0.375, -0.375, 0.5, 0.375, 0.375},
},
},
connect_sides = { "left" },
recipe = {
{ 1, {
{"", "basic_materials:ic", microexpansion.iron_ingot_ingredient },
{"", "microexpansion:cable", "group:shovel" },
{"", "", microexpansion.iron_ingot_ingredient },
},
},
{ 1, {
{"", "microexpansion:logic_chip", microexpansion.iron_ingot_ingredient },
{"", "microexpansion:cable", "group:shovel" },
{"", "", microexpansion.iron_ingot_ingredient },
},
}
},
groups = { crumbly = 1 },
on_timer = exporter_timer,
on_construct = function(pos)
item_transfer.setup_io_device("ME Exporter",pos)
me.send_event(pos,"connect")
--perhaps write a propper update self function
item_transfer.update_timer_based(pos,nil,{type="construct"})
end,
after_destruct = function(pos)
minetest.get_node_timer(pos):stop()
me.send_event(pos,"disconnect")
end,
on_metadata_inventory_put = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Exporter",pos)
end
end,
on_metadata_inventory_take = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Exporter",pos)
end
end
})
if me.uinv_category_enabled then
unified_inventory.add_category_item("storage", "microexpansion:exporter")
end

@ -0,0 +1,100 @@
-- microexpansion/machines.lua
local me = microexpansion
local item_transfer = me.item_transfer
local access_level = microexpansion.constants.security.access_levels
function importer_timer(pos, elapsed)
local net, cp = me.get_connected_network(pos)
if not net then
return false
end
local node = minetest.get_node(pos)
local target = vector.add(pos, microexpansion.facedir_to_right_dir(node.param2))
--TODO: allow setting list with upgrade
local list, inv = item_transfer.get_output_inventory(target)
if list then
local own_inv = minetest.get_meta(pos):get_inventory()
local upgrades = me.count_upgrades(own_inv)
local count = math.min(net:get_inventory_space(),math.pow(2, upgrades.bulk or 0))
if count <= 0 then
return true
end
local import_filter = function(stack)
local stack_name = stack:get_name()
if minetest.get_item_group(stack_name, "microexpansion_cell") > 0 then
return true
end
if upgrades.filter then
return not own_inv:contains_item("filter",stack:peek_item())
end
return false
end
microexpansion.move_inv({inv=inv,name=list}, {inv=net:get_inventory(),name="main",huge=true}, count, import_filter)
net:set_storage_space(true)
end
return true
end
-- [MicroExpansion Importer] Register node
item_transfer.register_io_device("importer", {
description = "ME Importer",
usedfor = "Imports items from machines into ME Networks",
tiles = {
"importer",
"importer",
"interface",
"cable",
"microexpansion_importer.png^[transform4",
"importer",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.25, -0.25, 0.25, 0.25, 0.25},
{0.25, -0.375, -0.375, 0.5, 0.375, 0.375},
},
},
connect_sides = { "left" },
recipe = {
{ 1, {
{"", "basic_materials:ic", microexpansion.iron_ingot_ingredient },
{"", "microexpansion:cable", "group:hoe" },
{"", "", microexpansion.iron_ingot_ingredient },
},
},
{ 1, {
{"", "microexpansion:logic_chip", microexpansion.iron_ingot_ingredient },
{"", "microexpansion:cable", "group:hoe" },
{"", "", microexpansion.iron_ingot_ingredient },
},
}
},
is_ground_content = false,
groups = { crumbly = 1 },
on_timer = importer_timer,
on_construct = function(pos)
item_transfer.setup_io_device("ME Importer",pos)
me.send_event(pos,"connect")
item_transfer.update_timer_based(pos)
end,
after_destruct = function(pos)
minetest.get_node_timer(pos):stop()
me.send_event(pos,"disconnect")
end,
on_metadata_inventory_put = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Importer",pos)
end
end,
on_metadata_inventory_take = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Importer",pos)
end
end
})
if me.uinv_category_enabled then
unified_inventory.add_category_item("storage", "microexpansion:importer")
end

@ -0,0 +1,25 @@
-- storage/init.lua
local module_path = microexpansion.get_module_path("item_transfer")
microexpansion.require_module("network")
-- Iron Ingot Ingredient for MineClone2
microexpansion.iron_ingot_ingredient = nil
if minetest.get_modpath("mcl_core") then
microexpansion.iron_ingot_ingredient = "mcl_core:iron_ingot"
else
microexpansion.iron_ingot_ingredient = "default:steel_ingot"
end
-- Load API
dofile(module_path.."/api.lua")
-- Load upgrade cards
dofile(module_path.."/upgrades.lua")
-- Load ports
dofile(module_path.."/importer.lua")
dofile(module_path.."/exporter.lua")
--dofile(module_path.."/interface.lua")

@ -0,0 +1,67 @@
-- shared/init.lua
local me = microexpansion
-- TODO: regulation upgrade (1: disable in formspec, mesecon control; 2: requests from the me network and perhaps digiline)
-- [register item] Upgrade Base
me.register_item("upgrade_base", {
description = "Upgrade Base",
usedfor = "the base for crafting upgrades",
recipe = {
{ 1, {
{ "microexpansion:quartz_crystal" },
{ microexpansion.iron_ingot_ingredient },
},
},
},
})
-- [register item] Bulk Upgrade
me.register_item("upgrade_bulk", {
description = "Bulk Upgrade",
usedfor = "upgrades components to process more at the same time",
recipe = {
{ 1, {
{"basic_materials:gold_wire"},
{"microexpansion:upgrade_base"}
},
},
{ 1, {
{"microexpansion:gold_wire"},
{"microexpansion:upgrade_base"}
},
},
},
})
-- [register item] Filter Upgrade
me.register_item("upgrade_filter", {
description = "Filter Upgrade",
usedfor = "allows setting up filters for components",
recipe = {
{ 1, {
{"microexpansion:quartz_crystal"},
{"microexpansion:upgrade_base"}
},
},
},
})
-- [register item] Control Upgrade
me.register_item("upgrade_control", {
description = "Control Upgrade",
usedfor = "allows more fine tuned control over components",
recipe = {
{ 1, {
{"basic_materials:ic"},
{"microexpansion:upgrade_base"}
},
},
{ 1, {
{"microexpansion:logic_chip"},
{"microexpansion:upgrade_base"}
},
},
},
})

@ -0,0 +1,57 @@
local me = microexpansion
if not me.constants then
me.constants = {}
end
local constants = me.constants
local access_levels = {
-- cannot interact at all with the network or it's components
blocked = 0,
-- can only look into the network but not move, modify, etc.
view = 20,
-- can use chests, craft terminals, etc.
interact = 40,
-- can use all components except security, can build and dig (except core)
modify = 60,
-- can use security terminal, can modify all players with less access
manage = 80,
-- can modify all players with less access and self
full = 100
}
local access_level_descriptions = {}
access_level_descriptions[access_levels.blocked] = {
name = "Blocked",
color = "gray",
index = 1
}
access_level_descriptions[access_levels.view] = {
name = "View",
color = "orange",
index = 2
}
access_level_descriptions[access_levels.interact] = {
color = "yellow",
name = "Interact",
index = 3
}
access_level_descriptions[access_levels.modify] = {
name = "Modify",
color = "yellowgreen",
index = 4
}
access_level_descriptions[access_levels.manage] = {
name = "Manage",
color = "green",
index = 5
}
access_level_descriptions[access_levels.full] = {
name = "Full",
color = "blue",
index = 6
}
constants.security = {
access_levels = access_levels,
access_level_descriptions = access_level_descriptions
}

@ -2,9 +2,19 @@
local me = microexpansion local me = microexpansion
local network = me.network local network = me.network
local access_level = microexpansion.constants.security.access_levels
--FIXME: accept multiple controllers in one network local ctrl_recipe = nil
ctrl_recipe = {
{ 1, {
{microexpansion.iron_ingot_ingredient, "microexpansion:steel_infused_obsidian_ingot", microexpansion.iron_ingot_ingredient},
{microexpansion.iron_ingot_ingredient, "microexpansion:machine_casing", microexpansion.iron_ingot_ingredient},
{microexpansion.iron_ingot_ingredient, "microexpansion:cable", microexpansion.iron_ingot_ingredient},
},
}
}
-- [register node] Controller -- [register node] Controller
me.register_node("ctrl", { me.register_node("ctrl", {
description = "ME Controller", description = "ME Controller",
@ -16,14 +26,7 @@ me.register_node("ctrl", {
"ctrl_sides", "ctrl_sides",
"ctrl_sides" "ctrl_sides"
}, },
recipe = { recipe = ctrl_recipe,
{ 1, {
{"default:steel_ingot", "microexpansion:steel_infused_obsidian_ingot", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
},
}
},
drawtype = "nodebox", drawtype = "nodebox",
paramtype = "light", paramtype = "light",
node_box = { node_box = {
@ -48,6 +51,7 @@ me.register_node("ctrl", {
-- for on/off switch to conserve power -- for on/off switch to conserve power
mesecon_effector_off = 1, mesecon = 2, mesecon_effector_off = 1, mesecon = 2,
}, },
connect_sides = "nobottom",
--HV_EU_demand = 10, --HV_EU_demand = 10,
-- typical technic connections: -- typical technic connections:
-- connect_sides = {"bottom", "front", "left", "right"}, -- connect_sides = {"bottom", "front", "left", "right"},
@ -74,11 +78,14 @@ me.register_node("ctrl", {
me.send_event(pos, "power") me.send_event(pos, "power")
end end
end, end,
connect_sides = "nobottom",
me_update = function(pos,_,ev) me_update = function(pos,_,ev)
local net = me.get_network(pos) local meta = minetest.get_meta(pos)
if net == nil then if meta:get_string("source") ~= "" then
me.log("no network for ctrl at pos "..minetest.pos_to_string(pos),"error") return
end
local cnet = me.get_network(pos)
if cnet == nil then
microexpansion.log("no network for ctrl at pos "..minetest.pos_to_string(pos),"error")
return return
end end
net:update() net:update()
@ -103,8 +110,13 @@ me.register_node("ctrl", {
}}, }},
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local net = network.new({controller_pos = pos}) local net,cp = me.get_connected_network(pos)
table.insert(me.networks,net) if net then
meta:set_string("source", vector.to_string(cp))
else
net = network.new({controller_pos = pos})
table.insert(me.networks,net)
end
me.send_event(pos,"connect",{net=net}) me.send_event(pos,"connect",{net=net})
meta:set_int("enabled", 0) meta:set_int("enabled", 0)
@ -116,12 +128,59 @@ me.register_node("ctrl", {
meta:set_string("infotext", "Network Controller (owned by "..name..")") meta:set_string("infotext", "Network Controller (owned by "..name..")")
meta:set_string("owner", name) meta:set_string("owner", name)
end, end,
after_place_node = function(pos, player)
local name = player:get_player_name()
local meta = minetest.get_meta(pos)
meta:set_string("infotext", "Network Controller")
meta:set_string("owner", name)
local net,idx = me.get_network(pos)
if net then
net:set_access_level(name, me.constants.security.access_levels.full)
elseif meta:get_string("source") == "" then
me.log("no network after placing controller", "warning")
end
end,
can_dig = function(pos, player)
if not player then
return false
end
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local meta = minetest.get_meta(pos)
local net
if meta:get_string("source") == "" then
net = me.get_network(pos)
else
net = me.get_connected_network(pos)
end
if not net then
me.log("ME Network Controller without Network","error")
return true
end
return net:get_access_level(name) >= access_level.full
end,
on_destruct = function(pos) on_destruct = function(pos)
local net,idx = me.get_network(pos) local net,idx = me.get_network(pos)
--disconnect all those who need the network --disconnect all those who need the network
me.send_event(pos,"disconnect",{net=net}) me.send_event(pos,"disconnect",{net=net})
if net then if net then
net:destruct() if me.promote_controller(pos,net) then
--reconnect with new controller
me.send_event(pos,"reconnect",{net=net})
else
net:destruct()
if idx then
table.remove(me.networks,idx)
end
--disconnect all those that haven't realized the network is gone
me.send_event(pos,"disconnect")
end
else
-- disconnect just in case
me.send_event(pos,"disconnect")
end end
if idx then if idx then
table.remove(me.networks,idx) table.remove(me.networks,idx)
@ -137,6 +196,8 @@ me.register_node("ctrl", {
type = "controller", type = "controller",
}, },
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
--FIXME: we don't do that here (no goto statements please)
-- replace with loop or zero timer (next worldstep)
::top:: ::top::
me.log("TIMER: starting service", "error") me.log("TIMER: starting service", "error")
local net = me.get_network(pos) local net = me.get_network(pos)
@ -170,6 +231,39 @@ me.register_node("ctrl", {
end, end,
}) })
minetest.register_lbm({
name = "microexpansion:update_network",
label = "integrate new ME Network data",
nodenames = {"microexpansion:ctrl"},
run_at_every_load = true,
action = function(pos)
local meta = minetest.get_meta(pos)
local net,idx = me.get_network(pos)
if not meta then
me.log("activated controller before metadata was available", "warning")
return
end
local source = meta:get_string("source")
if not net then
if source == "" then
me.log("activated controller without network", "warning")
return
else
net = me.get_network(vector.from_string(source))
if not net then
me.log("activated controller that is linked to an unloaded controller", "info")
return
end
end
end
if not net.access then
me.log("added access table to old network", "action")
net.access = {}
end
net:fallback_access()
end
})
-- [register node] Cable -- [register node] Cable
me.register_machine("cable", { me.register_machine("cable", {
description = "ME Cable", description = "ME Cable",
@ -196,10 +290,49 @@ me.register_machine("cable", {
paramtype = "light", paramtype = "light",
groups = { crumbly = 1, }, groups = { crumbly = 1, },
--TODO: move these functions into the registration --TODO: move these functions into the registration
can_dig = function(pos, player)
if not player then
return false
end
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local net,cp = me.get_connected_network(pos)
if not net then
return true
end
return net:get_access_level(name) >= access_level.modify
end,
on_construct = function(pos) on_construct = function(pos)
--perhaps this needs to be done after the check if it can be placed
me.send_event(pos,"connect") me.send_event(pos,"connect")
end, end,
after_place_node = function(pos, placer)
if not placer then
return false
end
local name = placer:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
--protection probably handles this itself
--minetest.remove_node(pos)
return true
end
--TODO: prevent connecting multiple networks
local net,cp = me.get_connected_network(pos)
if not net then
return false
end
if net:get_access_level(name) < access_level.modify then
-- prevent placing cables on a network that a player doesn't have access to
minetest.remove_node(pos)
return true
end
end,
after_destruct = function(pos) after_destruct = function(pos)
--FIXME: write drives before disconnecting
me.send_event(pos,"disconnect") me.send_event(pos,"disconnect")
end, end,
me_update = function(pos,_,ev) me_update = function(pos,_,ev)
@ -207,14 +340,12 @@ me.register_machine("cable", {
if ev.type ~= "disconnect" then return end if ev.type ~= "disconnect" then return end
end end
--maybe this shouldn't be called on every update --maybe this shouldn't be called on every update
if false then
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if me.get_connected_network(pos) then if me.get_connected_network(pos) then
meta:set_string("infotext", "Network connected") meta:set_string("infotext", "Network connected")
else else
meta:set_string("infotext", "No Network") meta:set_string("infotext", "No Network")
end end
end
end, end,
machine = { machine = {
type = "conductor", type = "conductor",
@ -226,3 +357,9 @@ if technic then
-- producer receiver, producer_receiver, battery -- producer receiver, producer_receiver, battery
technic.register_machine("HV", "microexpansion:ctrl", technic.receiver) technic.register_machine("HV", "microexpansion:ctrl", technic.receiver)
end end
if me.uinv_category_enabled then
unified_inventory.add_category_item("storage", "microexpansion:ctrl")
unified_inventory.add_category_item("storage", "microexpansion:cable")
end

@ -2,6 +2,9 @@ local me = microexpansion
me.networks = {} me.networks = {}
local networks = me.networks local networks = me.networks
local path = me.get_module_path("network") local path = me.get_module_path("network")
local storage = minetest.get_mod_storage()
dofile(path.."/constants.lua")
local annotate_large_stack = function(stack, count) local annotate_large_stack = function(stack, count)
local description = minetest.registered_items[stack:get_name()] local description = minetest.registered_items[stack:get_name()]
@ -361,7 +364,7 @@ function me.connected_nodes(start_pos,include_ctrl)
if vector.equals(closed,current.pos) then if vector.equals(closed,current.pos) then
--found one was closed --found one was closed
open = false open = false
end end
end end
end end
-- get all connected nodes -- get all connected nodes
@ -382,14 +385,36 @@ end
function me.get_connected_network(start_pos) function me.get_connected_network(start_pos)
for npos,nn in me.connected_nodes(start_pos,true) do for npos,nn in me.connected_nodes(start_pos,true) do
if nn == "microexpansion:ctrl" then if nn == "microexpansion:ctrl" then
local net = me.get_network(npos) local source = minetest.get_meta(npos):get_string("source")
if net then local network
return net,npos if source == "" then
network = me.get_network(npos)
else
network = me.get_network(vector.from_string(source))
end
if network then
return network,npos
end end
end end
end end
end end
function me.promote_controller(start_pos,net)
local promoted = false
for npos,nn in me.connected_nodes(start_pos,true) do
if nn == "microexpansion:ctrl" and npos ~= start_pos then
if promoted then
minetest.get_meta(npos):set_string("source", promoted)
else
promoted = vector.to_string(npos)
minetest.get_meta(npos):set_string("source", "")
net.controller_pos = npos
end
end
end
return promoted and true or false
end
function me.update_connected_machines(start_pos,event,include_start) function me.update_connected_machines(start_pos,event,include_start)
me.log("updating connected machines", "action") me.log("updating connected machines", "action")
local ev = event or {type = "n/a"} local ev = event or {type = "n/a"}
@ -430,20 +455,33 @@ function me.get_network(pos)
end end
dofile(path.."/ctrl.lua") -- Controller/wires dofile(path.."/ctrl.lua") -- Controller/wires
dofile(path.."/security.lua") --Security Terminal
-- load networks -- load networks
function me.load() function me.load()
local f = io.open(me.worldpath.."/microexpansion_networks", "r") local res = storage:get_string("networks")
if f then if res == "" then
local res = minetest.deserialize(f:read("*all")) local f = io.open(me.worldpath.."/microexpansion_networks", "r")
f:close() if f then
if type(res) == "table" then me.log("loading network data from file","action")
for _,n in pairs(res) do res = minetest.deserialize(f:read("*all"))
local net = me.network.new(n) f:close()
net:load() else
table.insert(me.networks,net) me.log("no network data loaded","action")
end return
end end
else
me.log("loading network data from mod storage","action")
res = minetest.deserialize(res)
end
if type(res) == "table" then
for _,n in pairs(res) do
local net = me.network.new(n)
net:load()
table.insert(me.networks,net)
end
else
me.log("network data in unexpected format","error")
end end
end end
@ -461,9 +499,35 @@ function me.save()
net.process = nil net.process = nil
table.insert(data,net:serialize()) table.insert(data,net:serialize())
end end
local f = io.open(me.worldpath.."/microexpansion_networks", "w") if storage then
f:write(minetest.serialize(data)) me.log("saving network data to mod storage","info")
f:close() storage:set_string("networks", minetest.serialize(data))
else
me.log("saving network data to file","info")
local f = io.open(me.worldpath.."/microexpansion_networks", "w")
f:write(minetest.serialize(data))
f:close()
end
end
function me.do_autosave()
me.last_autosave = -1
minetest.after(1, function()
--print("autosaving ME Networks")
me.save()
me.last_autosave = minetest.get_server_uptime()
end)
end
function me.autosave()
--TODO: make max autosave interval settable
if not me.last_autosave then
me.do_autosave()
elseif me.last_autosave == -1 then
return
elseif minetest.get_server_uptime() - me.last_autosave >= 600 then
me.do_autosave()
end
end end
-- save on server shutdown -- save on server shutdown

@ -1,15 +1,20 @@
--- Microexpansion network --- Microexpansion network
-- @type network -- @type network
-- @field #table controller_pos the position of the controller -- @field #table controller_pos the position of the controller
-- @field #table access a table of players and their respective access levels
-- @field #number default_access_level the access level of unlisted players
-- @field #number power_load the power currently provided to the network -- @field #number power_load the power currently provided to the network
-- @field #number power_storage the power that can be stored for the next tick -- @field #number power_storage the power that can be stored for the next tick
local network = { local network = {
default_access_level = microexpansion.constants.security.access_levels.view,
power_load = 0, power_load = 0,
power_storage = 0 power_storage = 0
} }
local me = microexpansion local me = microexpansion
me.network = network me.network = network
local access_level = microexpansion.constants.security.access_levels
--- construct a new network --- construct a new network
-- @function [parent=#network] new -- @function [parent=#network] new
-- @param #table or the object to become a network or nil -- @param #table or the object to become a network or nil
@ -82,16 +87,79 @@ function network.adjacent_connected_nodes(pos, include_ctrl)
if include_ctrl == false then if include_ctrl == false then
if nn ~= "microexpansion:ctrl" then if nn ~= "microexpansion:ctrl" then
table.insert(nodes,{pos = apos, name = nn}) table.insert(nodes,{pos = apos, name = nn})
end end
else else
table.insert(nodes,{pos = apos, name = nn}) table.insert(nodes,{pos = apos, name = nn})
end end
end end
end end
return nodes return nodes
end end
function network:get_access_level(player)
local name
local has_bypass = minetest.check_player_privs(player, "protection_bypass")
if not player then
return self.default_access_level
elseif has_bypass then
return me.constants.security.access_levels.full
elseif type(player) == "string" then
name = player
else
name = player:get_player_name()
end
if not self.access and not has_bypass then
return self.default_access_level
end
return self.access[name] or self.default_access_level
end
function network:set_access_level(player, level)
local name
if not player then
self.default_access_level = level
elseif type(player) == "string" then
name = player
else
name = player:get_player_name()
end
if not self.access then
self.access = {}
end
self.access[name] = level
self:fallback_access()
-- autosave network data
me.autosave()
end
function network:fallback_access()
local full_access = access_level.full
if not self.access then
--something must have gone badly wrong
me.log("no network access table in fallback method","error")
self.access = {}
end
for _,l in pairs(self.access) do
if l == full_access then
return
end
end
local meta = minetest.get_meta(self.controller_pos)
local owner = meta:get_string("owner")
if owner == "" then
me.log("ME Network Controller without owner at: " .. vector.to_string(self.controller_pos), "warning")
else
self.access[owner] = full_access
end
end
function network:list_access()
if not self.access then
self.access = {}
end
return self.access
end
--- provide power to the network --- provide power to the network
-- @function [parent=#network] provide -- @function [parent=#network] provide
-- @param #number power the amount of power provided -- @param #number power the amount of power provided
@ -169,7 +237,7 @@ function network:get_item_capacity()
end end
end end
self.capacity_cache = cap self.capacity_cache = cap
me.log("total capacity is "..cap, "error") me.log("total capacity is "..cap, "verbose")
return cap return cap
end end
@ -233,6 +301,8 @@ function network:set_storage_space(count, listname)
needed = needed + csize needed = needed + csize
self:remove_slots(inv, listname, needed, csize) self:remove_slots(inv, listname, needed, csize)
end end
-- autosave network data
me.autosave()
end end
function network:update() function network:update()
@ -279,10 +349,33 @@ function network:find_loan(inv, stack)
return nil return nil
end end
function network:get_inventory_space(inv, list)
local inv = inv or self:get_inventory()
local listname = list or "main"
local max_slots = inv:get_size(listname)
local max_items = self.capacity_cache
local slots, items = 0, 0
-- Get amount of items in drive
for i = 1, max_slots do
local dstack = inv:get_stack(listname, i)
if dstack:get_name() ~= "" then
slots = slots + 1
local num = dstack:get_count()
if num == 0 then num = 1 end
items = items + num
end
end
return math.max(max_items-items,0)
end
local function create_inventory(net) local function create_inventory(net)
local invname = net:get_inventory_name() local invname = net:get_inventory_name()
net.inv = minetest.create_detached_inventory(invname, { net.inv = minetest.create_detached_inventory(invname, {
allow_put = function(inv, listname, index, stack) allow_put = function(inv, listname, index, stack, player)
if net:get_access_level(player) < access_level.interact then
return 0
end
local inside_stack = inv:get_stack(listname, index) local inside_stack = inv:get_stack(listname, index)
local stack_name = stack:get_name() local stack_name = stack:get_name()
if minetest.get_item_group(stack_name, "microexpansion_cell") > 0 and if minetest.get_item_group(stack_name, "microexpansion_cell") > 0 and
@ -318,6 +411,9 @@ local function create_inventory(net)
net:set_storage_space(true) net:set_storage_space(true)
end, end,
allow_take = function(inv, listname, slot, stack, player) allow_take = function(inv, listname, slot, stack, player)
if net:get_access_level(player) < access_level.interact then
return 0
end
-- This is not remove_item, we only remove the loan. This real -- This is not remove_item, we only remove the loan. This real
-- item will be removed. -- item will be removed.
me.log("REMOVE: network allow taking of "..stack:get_name().." from "..listname, "error") me.log("REMOVE: network allow taking of "..stack:get_name().." from "..listname, "error")

@ -0,0 +1,292 @@
-- microexpansion/network/security.lua
local me = microexpansion
local access_level = me.constants.security.access_levels
local access_desc = me.constants.security.access_level_descriptions
-- [me security] Get formspec
local function security_formspec(pos, player, rule, q)
local list
local buttons
local logout = true
local query = q or ""
local net,cp = me.get_connected_network(pos)
if player and cp then
local access = net:get_access_level(player)
if access < access_level.manage then -- Blocked dialog
logout = false
list = "label[2.5,3;"..minetest.colorize("red", "Access Denied").."]"
buttons = "button[3.5,6;2,1;logout;back]"
elseif (not rule) or rule == "" then -- Main Screen
--TODO: show button or entry for default access level
list = "tablecolumns[color,span=1;text;color,span=1;text]"
.. "table[0.5,2;6,7;access_table;"
local first = true
--TODO: filter
local name_list = {}
for p,l in pairs(net:list_access()) do
if first then
first = false
else
list = list .. ","
end
table.insert(name_list, p)
local desc = access_desc[l] or {name = "Unknown", color = "red"}
list = list .. "cyan," .. p .. "," .. desc.color .. "," .. desc.name
end
list = list .. ";]"
minetest.get_meta(pos):set_string("table_index", minetest.serialize(name_list))
list = list .. [[
field[0.5,1;2,0.5;filter;;]]..query..[[]
button[3,1;0.8,0.5;search;?]
button[4,1;0.8,0.5;clear;X]
tooltip[search;Search]
tooltip[clear;Reset]
field_close_on_enter[filter;false]
]]
buttons = [[
button[7,7;1.5,0.8;new;new rule]
button[7,8;1.5,0.8;edit_sel;edit rule]
]]
--button[7,6;1.5,0.8;del_sel;delete rule]
elseif rule == "<new>" then -- Creation screen
logout = false
local players = ""
for _,p in pairs(minetest.get_connected_players()) do
if players ~= "" then
players = players .. ","
end
players = players .. p:get_player_name()
end
--TODO: add a text field (maybe toggelable)
list = [[
dropdown[3,2.75;5,0.5;new_player;]]..players..[[;]
label[1.5,3;rule for:]
]]
buttons = [[
button[2,6;2,0.8;edit;add/edit]
button[5,6;2,0.8;back;cancel]
]]
elseif (access < access_level.full and net:get_access_level(rule) >= access_level.manage) or (player ~= rule and access >= access_level.full and net:get_access_level(rule) >= access_level.full) then
-- low access dialog
list = "label[1,3;"..minetest.colorize("red", "You can only modify rules with lower access than yourself.").."]"
buttons = "button[3.5,6;2,1;back;back]"
else
local rule_level = net:get_access_level(rule)
local current = rule_level == access_level.blocked and "1" or
rule_level == access_level.view and "2" or
rule_level == access_level.interact and "3" or
rule_level == access_level.modify and "4" or
rule_level == access_level.manage and "5" or
rule_level == access_level.full and "6" or ""
list = [[
label[1,3;rule for:]].."\t"..minetest.colorize("cyan", rule)..[[]
label[1,4;access level:]
dropdown[3,3.75;2,0.5;access;Blocked,View,Interact,Modify,Manage,Full;]]..current..[[]
]]
buttons = [[
button[1,6;1,0.8;save;save]
button[3,6;2,0.8;reset;reset to default]
button[6,6;1,0.8;back;cancel]
]]
end
elseif cp then
logout = false
list = "label[2.5,3;Welcome to the security Terminal!]"
buttons = [[
button[3.5,6;2,1;login;login]
button_exit[8,0.5;0.5,0.5;close;x]
]]
else
logout = false
list = "label[2.5,3;" .. minetest.colorize("red", "No connected network!") .. "]"
buttons = "button_exit[3,6;2,1;close;close]"
end
return [[
formspec_version[2]
size[9,9.5]
]]..
microexpansion.gui_bg ..
list ..
(logout and "button[7.5,0.5;1,0.5;logout;logout]" or "") ..
"label[0.5,0.5;ME Security Terminal]" ..
buttons
end
local function update_security(pos,_,ev)
--for now all events matter
local network = me.get_connected_network(pos)
local meta = minetest.get_meta(pos)
if network == nil then
meta:set_string("editing_rule", "")
meta:set_string("formspec", security_formspec(pos))
end
meta:set_string("formspec", security_formspec(pos))
end
local security_recipe = nil
if minetest.get_modpath("mcl_core") then
security_recipe = {
{ 1, {
{"mcl_core:iron_ingot", "mcl_copper:copper_ingot", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "microexpansion:machine_casing", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "microexpansion:cable", "mcl_core:iron_ingot"},
},
}
}
else
security_recipe = {
{ 1, {
{"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
},
}
}
end
-- [me chest] Register node
microexpansion.register_node("security", {
description = "ME Security Terminal",
usedfor = "Allows controlling access to ME networks",
tiles = {
"security_bottom",
"security_bottom",
"chest_side",
"chest_side",
"chest_side",
"security_front",
},
recipe = security_recipe,
is_ground_content = false,
groups = { cracky = 1, me_connect = 1 },
paramtype = "light",
paramtype2 = "facedir",
me_update = update_security,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local net = me.get_connected_network(pos)
me.send_event(pos,"connect",{net=net})
update_security(pos)
end,
after_destruct = function(pos)
me.send_event(pos,"disconnect")
end,
can_dig = function(pos, player)
if not player then
return false
end
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local net,cp = me.get_connected_network(pos)
if not net then
return true
end
return net:get_access_level(name) >= access_level.manage
end,
on_receive_fields = function(pos, _, fields, sender)
if fields.close then
return
end
local net,cp = me.get_connected_network(pos)
if net then
if cp then
microexpansion.log("network and ctrl_pos","info")
else
microexpansion.log("network but no ctrl_pos","warning")
end
else
if cp then
microexpansion.log("no network but ctrl_pos","warning")
else
microexpansion.log("no network and no ctrl_pos","info")
end
end
local meta = minetest.get_meta(pos)
local name = sender:get_player_name()
if not net then
microexpansion.log("no network connected to security terminal","warning")
return
end
if fields.logout then
meta:set_string("formspec", security_formspec(pos))
elseif fields.login or fields.back then
-- carry over networks from old versions
net:fallback_access()
meta:set_string("formspec", security_formspec(pos, name))
elseif fields.search or fields.key_enter_field == "filter" then
meta:set_string("formspec", security_formspec(pos, name), false, fields.filter)
elseif fields.clear then
meta:set_string("formspec", security_formspec(pos, name))
elseif fields.new then
meta:set_string("formspec", security_formspec(pos, name, "<new>"))
elseif fields.edit then
local access = net:get_access_level(name)
if not fields.new_player then
me.log("edit button without new player field","warning")
meta:set_string("formspec", security_formspec(pos, name))
return
end
if net:get_access_level(fields.new_player) == nil then
if access >= access_level.manage then
net:set_access_level(fields.new_player, net:get_access_level())
end
end
meta:set_string("editing_rule", fields.new_player)
meta:set_string("formspec", security_formspec(pos, name, fields.new_player))
elseif fields.edit_sel then
meta:set_string("formspec", security_formspec(pos, name, meta:get_string("editing_rule")))
elseif fields.access_table then
local ev = minetest.explode_table_event(fields.access_table)
local table_index = minetest.deserialize(meta:get_string("table_index"))
local edit_player = table_index[ev.row]
if net:get_access_level(edit_player) == nil then
me.log("playerlist changed before editing","warning")
meta:set_string("formspec", security_formspec(pos, name))
return
else
meta:set_string("editing_rule", edit_player)
if ev.type == "DCL" then
meta:set_string("formspec", security_formspec(pos, name, edit_player))
end
end
elseif fields.reset then
local rule = meta:get_string("editing_rule")
local access = net:get_access_level(name)
local old_level = net:get_access_level(rule)
local new_level = net.default_access_level
if (access > old_level or name == rule) and (access > new_level or access >= access_level.full) then
net:set_access_level(rule, nil)
--TODO: show fail dialog if access violation
end
meta:set_string("formspec", security_formspec(pos, name))
elseif fields.save then
local rule = meta:get_string("editing_rule")
local access = net:get_access_level(name)
local old_level = net:get_access_level(rule)
local new_level = fields.access == "Blocked" and access_level.blocked or
fields.access == "View" and access_level.view or
fields.access == "Interact" and access_level.interact or
fields.access == "Modify" and access_level.modify or
fields.access == "Manage" and access_level.manage or
fields.access == "Full" and access_level.full
if not new_level then
me.log("unknown access level selection " .. fields.access, "error")
--TODO: show fail dialog
return
end
if (access > old_level or name == rule) and access > new_level then
net:set_access_level(rule, new_level)
--TODO: show fail dialog if access violation
end
meta:set_string("formspec", security_formspec(pos, name))
end
end,
})

@ -1,45 +1,86 @@
-- ores/init.lua -- ores/init.lua
local me = microexpansion local me = microexpansion
local mcl_core_modpath = minetest.get_modpath("mcl_core")
stone_ingrediant = mcl_core_modpath and "mcl_core:stone" or "default:stone"
local incranium_y_min = -300
local incranium_y_max = -90
local quartz_y_min = -31000
local quartz_y_max = -5
local incranium_cracky = 3
local quartz_cracky = 3
if mcl_core_modpath then
incranium_y_min = -55
incranium_y_max = -20
quartz_y_min = -50
quartz_y_max = 0
incranium_cracky = 3
quartz_cracky = 3
end
local quartz_nodedef = {
description = "Quartz Ore",
tiles = { "default_stone.png^microexpansion_ore_quartz.png" },
is_ground_content = true,
type = "ore",
groups = {cracky=quartz_cracky,material_stone=1, stone=1, pickaxey=3},
drop = "microexpansion:quartz_crystal",
oredef = {{
ore_type = "scatter",
wherein = stone_ingrediant,
clust_scarcity = 10*10*10,
clust_num_ores = 6,
clust_size = 5,
y_min = quartz_y_min,
y_max = quartz_y_max,
}},
}
incranium_nodedef = {
description = "Incranium Ore",
tiles = { "incranium" },
is_ground_content = true,
groups = {cracky=incranium_cracky, material_stone=1, stone=1,pickaxey=3 },
type = "ore",
oredef = {
{
ore_type = "blob",
wherein = stone_ingrediant,
clust_scarcity = 4*4*4,
clust_num_ores = 4,
clust_size = 3,
y_min = incranium_y_min,
y_max = incranium_y_max,
},
},
disabled = true,
}
if mcl_core_modpath then
quartz_nodedef._mcl_hardness = 3
quartz_nodedef._mcl_blast_resistance = 3
quartz_nodedef._mcl_hardness = 3
quartz_nodedef._mcl_silk_touch_drop = true
quartz_nodedef._mcl_fortune_drop = mcl_core.fortune_drop_ore
incranium_nodedef._mcl_hardness = 3
incranium_nodedef._mcl_blast_resistance = 3
incranium_nodedef._mcl_hardness = 3
incranium_nodedef._mcl_silk_touch_drop = true
incranium_nodedef._mcl_fortune_drop = mcl_core.fortune_drop_ore
end
-- [register] Incranium Ore -- [register] Incranium Ore
me.register_node("incranium", { me.register_node("incranium", incranium_nodedef)
description = "Incranium Ore",
tiles = { "incranium" }, me.register_item("quartz_crystal", {
is_ground_content = true, description = "Quartz Crystal",
groups = { cracky=3, stone=1 },
type = "ore",
oredef = {
{
ore_type = "blob",
wherein = "default:stone",
clust_scarcity = 4*4*4,
clust_num_ores = 4,
clust_size = 3,
y_min = -300,
y_max = -90,
},
},
disabled = true,
}) })
-- "Supernatet", pronounced "Super-nat-et" is Latin for "float", this ore will
-- float up if there are no blocks above it, so be careful! me.register_node("quartz", quartz_nodedef)
-- Supernatet ore will be used to craft wings of flight
me.register_node("supernatet", {
description = "Supernatant Ore",
tiles = { "default_stone.png^microexpansion_ore_supernatet.png" },
is_ground_content = true,
type = "ore",
groups = { cracky=3, stone=1 },
oredef = {
ore_type = "blob",
wherein = "default:stone",
clust_scarcity = 4*4*4,
clust_num_ores = 4,
clust_size = 3,
y_min = -300,
y_max = -90,
},
status = "unstable",
})

@ -1,90 +1,104 @@
-- power/gen.lua -- power/gen.lua
local me = microexpansion local me = microexpansion
local fuel_fired_generator_recipe = nil
if minetest.get_modpath("mcl_core") then
fuel_fired_generator_recipe = {
{ 1, {
{"mcl_core:iron_ingot", "mcl_furnaces:furnace", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "microexpansion:machine_casing", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
},
}
}
else
fuel_fired_generator_recipe = {
{ 1, {
{"default:steel_ingot", "default:furnace", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
}
}
end
-- [register node] Fuel Fired Generator -- [register node] Fuel Fired Generator
me.register_machine("fuel_fired_generator", { me.register_machine("fuel_fired_generator", {
description = "Fuel-Fired Generator", description = "Fuel-Fired Generator",
tiles = { tiles = {
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"fuelgen_front", "fuelgen_front",
}, },
recipe = { recipe = fuel_fired_generator_recipe,
{ 1, { groups = { cracky = 1 },
{ "default:steel_ingot", "default:furnace", "default:steel_ingot" }, connect_sides = "machine",
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" }, paramtype2 = "facedir",
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" }, status = "unstable",
}, machine = {
} type = "provider",
}, on_survey = function() -- args: pos
groups = { cracky = 1 }, --TODO: burn fuel
connect_sides = "machine", return 5 -- Generate 5 ME/tick
paramtype2 = "facedir", end,
status = "unstable", },
machine = {
type = "provider",
on_survey = function() -- args: pos
--TODO: burn fuel
return 5 -- Generate 5 ME/tick
end,
},
}) })
--[[register node] Super Smelter --[[register node] Super Smelter
me.register_node("super_smelter", { me.register_node("super_smelter", {
description = "Super Smelter", description = "Super Smelter",
tiles = { tiles = {
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"super_smelter_front", "super_smelter_front",
}, },
recipe = { recipe = {
{ 1, { { 1, {
{ "default:furnace", "default:furnace", "default:furnace" }, {"default:furnace", "default:furnace", "default:furnace"},
{ "default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" }, {"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" }, {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
}, },
}, },
}, },
groups = { cracky = 1, me_connect = 1, }, groups = { cracky = 1, me_connect = 1, },
connect_sides = "machine", connect_sides = "machine",
paramtype2 = "facedir", paramtype2 = "facedir",
status = "unstable", status = "unstable",
machine = { machine = {
type = "consumer", type = "consumer",
on_survey = function(pos) on_survey = function(pos)
return 5 -- Consume 5 ME/tick return 5 -- Consume 5 ME/tick
end, end,
}, },
}) })
-- [register item] Geothermal Generator -- [register item] Geothermal Generator
me.register_node("geo_generator", { me.register_node("geo_generator", {
description = "Geothermal Generator", description = "Geothermal Generator",
tiles = { tiles = {
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"machine_sides", "machine_sides",
"geogen_front", "geogen_front",
}, },
groups = { cracky = 1, me_connect = 1, }, groups = { cracky = 1, me_connect = 1, },
connect_sides = "machine", connect_sides = "machine",
paramtype2 = "facedir", paramtype2 = "facedir",
status = "unstable", status = "unstable",
machine = { machine = {
type = "provider", type = "provider",
on_survey = function(pos) on_survey = function(pos)
return 10 -- Generate 10 ME/tick return 10 -- Generate 10 ME/tick
end, end,
}, },
})]] })]]

@ -9,16 +9,16 @@ local power = me.power
-- [local function] Get netitem by position -- [local function] Get netitem by position
local function get_netitem_by_pos(list, pos) local function get_netitem_by_pos(list, pos)
for _, i in pairs(list) do for _, i in pairs(list) do
if vector.equals(pos, i.pos) then if vector.equals(pos, i.pos) then
return i return i
end end
end end
end end
-- [function] Generate new network ID -- [function] Generate new network ID
function power.new_id() function power.new_id()
return "network_"..#me.networks+1 return "network_"..#me.networks+1
end end
-- [function] Add machine to network -- [function] Add machine to network
@ -28,84 +28,84 @@ end
-- [function] Remove machine from network -- [function] Remove machine from network
function power.remove_machine(pos) function power.remove_machine(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("network_ignore", "true") meta:set_string("network_ignore", "true")
end end
-- [function] Trace network -- [function] Trace network
function power.trace(pos) function power.trace(pos)
local netpos = me.networks[minetest.get_meta(pos):get_string("network_id")] local netpos = me.networks[minetest.get_meta(pos):get_string("network_id")]
-- if no network, return -- if no network, return
if not netpos then if not netpos then
return return
end end
local meta = minetest.get_meta(netpos) local meta = minetest.get_meta(netpos)
local netid = meta:get_string("network_id") local netid = meta:get_string("network_id")
local list = {} local list = {}
local delete = false local delete = false
if meta:get_string("network_ignore") == "true" then if meta:get_string("network_ignore") == "true" then
delete = true delete = true
end end
-- [local function] Indexed -- [local function] Indexed
local function indexed(p) local function indexed(p)
for _, i in pairs(list) do for _, i in pairs(list) do
if vector.equals(p, i.pos) then if vector.equals(p, i.pos) then
return true return true
end end
end end
end end
-- [local function] Trace -- [local function] Trace
local function trace(nodes) local function trace(nodes)
for _, p in pairs(nodes) do for _, p in pairs(nodes) do
if not indexed(p) then if not indexed(p) then
local machine = minetest.get_meta(p) local machine = minetest.get_meta(p)
if machine:get_string("network_ignore") ~= "true" then if machine:get_string("network_ignore") ~= "true" then
local node = me.get_node(p).name local node = me.get_node(p).name
local desc = minetest.registered_nodes[node].description local desc = minetest.registered_nodes[node].description
if delete then if delete then
machine:set_string("network_id", nil) machine:set_string("network_id", nil)
machine:set_string("infotext", desc.."\nNo Network") machine:set_string("infotext", desc.."\nNo Network")
me.network_set_demand(p, 0) me.network_set_demand(p, 0)
else else
machine:set_string("network_id", netid) machine:set_string("network_id", netid)
machine:set_string("infotext", desc.."\nNetwork ID: "..netid) machine:set_string("infotext", desc.."\nNetwork ID: "..netid)
end end
list[#list + 1] = { pos = p, demand = machine:get_int("demand") } list[#list + 1] = { pos = p, demand = machine:get_int("demand") }
trace(power.get_connected_nodes(p, false)) trace(power.get_connected_nodes(p, false))
end end
end end
end end
end end
trace(power.get_connected_nodes(netpos)) trace(power.get_connected_nodes(netpos))
-- Check original list -- Check original list
local original = minetest.deserialize(meta:get_string("netitems")) local original = minetest.deserialize(meta:get_string("netitems"))
if original then if original then
for _, i in pairs(original) do for _, i in pairs(original) do
if not indexed(i.pos) then if not indexed(i.pos) then
local node = me.get_node(i.pos).name local node = me.get_node(i.pos).name
local desc = minetest.registered_nodes[node].description local desc = minetest.registered_nodes[node].description
local machine = minetest.get_meta(i.pos) local machine = minetest.get_meta(i.pos)
machine:set_string("network_id", nil) machine:set_string("network_id", nil)
machine:set_string("infotext", desc.."\nNo Network") machine:set_string("infotext", desc.."\nNo Network")
me.network_set_demand(pos, 0) me.network_set_demand(pos, 0)
end end
end end
end end
meta:set_string("netitems", minetest.serialize(list)) meta:set_string("netitems", minetest.serialize(list))
-- Update infotext -- Update infotext
meta:set_string("infotext", "Network Controller (owned by ".. meta:set_string("infotext", "Network Controller (owned by "..
meta:get_string("owner")..")\nNetwork ID: "..meta:get_string("network_id").. meta:get_string("owner")..")\nNetwork ID: "..meta:get_string("network_id")..
"\nDemand: "..dump(me.network_get_demand(netpos))) "\nDemand: "..dump(me.network_get_demand(netpos)))
end end
--- ---
@ -114,11 +114,11 @@ end
-- [function] Get load information -- [function] Get load information
function me.network_get_load(pos) function me.network_get_load(pos)
local ctrl = me.networks[minetest.get_meta(pos):get_string("network_id")] local ctrl = me.networks[minetest.get_meta(pos):get_string("network_id")]
if ctrl then if ctrl then
local meta = minetest.get_meta(ctrl) local meta = minetest.get_meta(ctrl)
local list = minetest.deserialize(meta:get_string("netitems")) local list = minetest.deserialize(meta:get_string("netitems"))
end end
end end
---- Generators ---- ---- Generators ----
@ -127,53 +127,53 @@ end
-- [function] Get total network demand -- [function] Get total network demand
function me.network_get_demand(pos) function me.network_get_demand(pos)
local ctrl = me.networks[minetest.get_meta(pos):get_string("network_id")] local ctrl = me.networks[minetest.get_meta(pos):get_string("network_id")]
-- if no network, return -- if no network, return
if not ctrl then if not ctrl then
return return
end end
local meta = minetest.get_meta(ctrl) local meta = minetest.get_meta(ctrl)
local list = minetest.deserialize(meta:get_string("netitems")) local list = minetest.deserialize(meta:get_string("netitems"))
local demand = 0 local demand = 0
for _, i in pairs(list) do for _, i in pairs(list) do
if i.demand then if i.demand then
demand = demand + i.demand demand = demand + i.demand
end end
end end
return demand return demand
end end
-- [function] Set demand for machine -- [function] Set demand for machine
function me.network_set_demand(pos, demand) function me.network_set_demand(pos, demand)
-- Update original metadata -- Update original metadata
minetest.get_meta(pos):set_int("demand", demand) minetest.get_meta(pos):set_int("demand", demand)
local ctrl = me.networks[minetest.get_meta(pos):get_string("network_id")] local ctrl = me.networks[minetest.get_meta(pos):get_string("network_id")]
-- if no network, return -- if no network, return
if not ctrl then if not ctrl then
return return
end end
local meta = minetest.get_meta(ctrl) local meta = minetest.get_meta(ctrl)
local list = minetest.deserialize(meta:get_string("netitems")) local list = minetest.deserialize(meta:get_string("netitems"))
local item = get_netitem_by_pos(list, pos) local item = get_netitem_by_pos(list, pos)
if not item then if not item then
return return
end end
item.demand = demand item.demand = demand
meta:set_string("netitems", minetest.serialize(list)) meta:set_string("netitems", minetest.serialize(list))
-- Update infotext -- Update infotext
meta:set_string("infotext", "Network Controller (owned by ".. meta:set_string("infotext", "Network Controller (owned by "..
meta:get_string("owner")..")\nNetwork ID: "..meta:get_string("network_id").. meta:get_string("owner")..")\nNetwork ID: "..meta:get_string("network_id")..
"\nDemand: "..dump(me.network_get_demand(pos))) "\nDemand: "..dump(me.network_get_demand(pos)))
end end
---- Storage ---- ---- Storage ----

@ -1,30 +0,0 @@
-- shared/init.lua
local me = microexpansion
-- This mostly contains items that are used by multiple modules and
-- don't really fit with anything else.
-- [register item] Steel Infused Obsidian Ingot
me.register_item("steel_infused_obsidian_ingot", {
description = "Steel Infused Obsidian Ingot",
recipe = {
{ 2, {
{ "default:steel_ingot", "default:obsidian_shard", "default:steel_ingot" },
},
},
},
})
-- [register item] Machine Casing
me.register_item("machine_casing", {
description = "Machine Casing",
recipe = {
{ 1, {
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
{"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
},
},
})

@ -2,53 +2,60 @@
local BASENAME = "microexpansion" local BASENAME = "microexpansion"
--FIXME: either consolidate or forbid crafting with filled cells
-- [function] register cell -- [function] register cell
function microexpansion.register_cell(itemstring, def) function microexpansion.register_cell(itemstring, def)
if not def.inventory_image then if not def.inventory_image then
def.inventory_image = itemstring def.inventory_image = itemstring
end end
-- register craftitem -- register craftitem
minetest.register_craftitem(BASENAME..":"..itemstring, { minetest.register_craftitem(BASENAME..":"..itemstring, {
description = def.description, description = def.description,
inventory_image = BASENAME.."_"..def.inventory_image..".png", inventory_image = BASENAME.."_"..def.inventory_image..".png",
groups = {microexpansion_cell = 1}, groups = {microexpansion_cell = 1},
stack_max = 1, stack_max = 1,
microexpansion = { microexpansion = {
base_desc = def.description, base_desc = def.description,
drive = { drive = {
capacity = def.capacity or 5000, capacity = def.capacity or 5000,
}, },
}, },
}) })
-- if recipe, register recipe -- if recipe, register recipe
if def.recipe then if def.recipe then
microexpansion.register_recipe(BASENAME..":"..itemstring, def.recipe) microexpansion.register_recipe(BASENAME..":"..itemstring, def.recipe)
end end
if microexpansion.uinv_category_enabled then
unified_inventory.add_category_item("storage", BASENAME..":"..itemstring)
end
end end
-- [function] Get cell size -- [function] Get cell size
function microexpansion.get_cell_size(name) function microexpansion.get_cell_size(name)
if minetest.get_item_group(name, "microexpansion_cell") == 0 then if minetest.get_item_group(name, "microexpansion_cell") == 0 then
return 0 return 0
end end
local item = minetest.registered_craftitems[name] local item = minetest.registered_craftitems[name]
return item.microexpansion.drive.capacity return item.microexpansion.drive.capacity
end end
-- [function] Calculate max stacks -- [function] Calculate max stacks
function microexpansion.int_to_stacks(int) function microexpansion.int_to_stacks(int)
return math.ceil(int / 99) return math.ceil(int / 99)
end end
-- [function] Calculate number of pages -- [function] Calculate number of pages
function microexpansion.int_to_pagenum(int) function microexpansion.int_to_pagenum(int)
return math.floor(microexpansion.int_to_stacks(int) / 32) return math.floor(microexpansion.int_to_stacks(int) / 32)
end end
-- [function] Move items from inv to inv --[[ [function] Move items from inv to inv
function microexpansion.move_inv(net, inv1, inv2, max) function microexpansion.move_inv(inv1, inv2, max)
>>>>>>> a21dbd9b825ab9727a42d597bc86f52342da7d44
if max <= 0 then return end if max <= 0 then return end
local finv, tinv = inv1.inv, inv2.inv local finv, tinv = inv1.inv, inv2.inv
local fname, tname = inv1.name, inv2.name local fname, tname = inv1.name, inv2.name
@ -81,3 +88,5 @@ function microexpansion.move_inv(net, inv1, inv2, max)
end end
end end
end end
]]

@ -1,6 +1,7 @@
-- microexpansion/machines.lua -- microexpansion/machines.lua
local me = microexpansion local me = microexpansion
local access_level = microexpansion.constants.security.access_levels
local netdrives local netdrives
@ -312,6 +313,26 @@ local function update_drive(pos,_,ev)
end end
end end
if minetest.get_modpath("mcl_core") then
drive_recipe = {
{ 1, {
{"mcl_core:iron_ingot", "mcl_chests:chest", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "microexpansion:machine_casing", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_chests:chest", "mcl_core:iron_ingot"},
},
}}
else
drive_recipe = {
{ 1, {
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" },
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
},
}
}
end
-- [me chest] Register node -- [me chest] Register node
microexpansion.register_node("drive", { microexpansion.register_node("drive", {
description = "ME Drive", description = "ME Drive",
@ -324,14 +345,7 @@ microexpansion.register_node("drive", {
"chest_side", "chest_side",
"drive_full", "drive_full",
}, },
recipe = { recipe = drive_recipe,
{ 1, {
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" },
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
},
}
},
is_ground_content = false, is_ground_content = false,
groups = { cracky = 1, me_connect = 1 }, groups = { cracky = 1, me_connect = 1 },
paramtype = "light", paramtype = "light",
@ -340,14 +354,14 @@ microexpansion.register_node("drive", {
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", meta:set_string("formspec",
"size[9,7.5]".. "size[9,9.5]"..
microexpansion.gui_bg .. microexpansion.gui_bg ..
microexpansion.gui_slots .. microexpansion.gui_slots ..
[[ [[
label[0,-0.23;ME Drive] label[0,-0.23;ME Drive]
list[context;main;0,0.3;5,2] list[context;main;0,0.3;8,4]
list[current_player;main;0,3.5;8,1;] list[current_player;main;0,5.5;8,1;]
list[current_player;main;0,4.73;8,3;8] list[current_player;main;0,6.73;8,3;8]
listring[current_name;main] listring[current_name;main]
listring[current_player;main] listring[current_player;main]
field_close_on_enter[filter;false] field_close_on_enter[filter;false]
@ -357,7 +371,19 @@ microexpansion.register_node("drive", {
me.send_event(pos, "connect") me.send_event(pos, "connect")
end, end,
can_dig = function(pos, player) can_dig = function(pos, player)
if minetest.is_protected(pos, player) then if not player then
return false
end
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local net,cp = me.get_connected_network(pos)
if not net then
return true
end
if net:get_access_level(name) < access_level.modify then
return false return false
end end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -368,11 +394,21 @@ microexpansion.register_node("drive", {
me.send_event(pos, "disconnect") me.send_event(pos, "disconnect")
end, end,
allow_metadata_inventory_put = function(pos, _, _, stack, player) allow_metadata_inventory_put = function(pos, _, _, stack, player)
if minetest.is_protected(pos, player) local name = player:get_player_name()
or minetest.get_item_group(stack:get_name(), "microexpansion_cell") == 0 then local network = me.get_connected_network(pos)
if network then
if network:get_access_level(player) < access_level.interact then
return 0
end
elseif minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0 return 0
end end
return 1 if minetest.get_item_group(stack:get_name(), "microexpansion_cell") == 0 then
return 0
else
return 1
end
end, end,
on_metadata_inventory_put = function(pos, _, _, stack) on_metadata_inventory_put = function(pos, _, _, stack)
me.send_event(pos, "item_cap") me.send_event(pos, "item_cap")
@ -387,8 +423,10 @@ microexpansion.register_node("drive", {
me.send_event(pos, "items", {net=network}) me.send_event(pos, "items", {net=network})
return return
end end
-- TODO: adjust for correct space
-- network:set_storage_space(#items) -- network:set_storage_space(#items)
for _,stack in pairs(items) do for _,stack in pairs(items) do
-- TODO: do not change storage space in a loop
network:set_storage_space(true) network:set_storage_space(true)
me.insert_item(stack, network, ctrl_inv, "main") me.insert_item(stack, network, ctrl_inv, "main")
end end
@ -396,10 +434,19 @@ microexpansion.register_node("drive", {
me.send_event(pos, "items", {net=network}) me.send_event(pos, "items", {net=network})
end, end,
allow_metadata_inventory_take = function(pos,_,_,stack, player) --args: pos, listname, index, stack, player allow_metadata_inventory_take = function(pos,_,_,stack, player) --args: pos, listname, index, stack, player
if minetest.is_protected(pos, player) then local name = player:get_player_name()
local network = me.get_connected_network(pos)
if network then
write_drive_cells(pos,network)
if network:get_access_level(player) < access_level.interact then
return 0
end
elseif minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0 return 0
end end
local network = me.get_connected_network(pos) local network = me.get_connected_network(pos)
-- should the drives really be written every take action? (performance)
write_drive_cells(pos,network) write_drive_cells(pos,network)
return stack:get_count() return stack:get_count()
end, end,
@ -418,8 +465,7 @@ microexpansion.register_node("drive", {
for _,ostack in pairs(items) do for _,ostack in pairs(items) do
local postack = ItemStack(ostack) local postack = ItemStack(ostack)
-- me.log("drive meta_inv_take remove_item "..tostring(postack:get_count()).." "..postack:get_name(), "error") -- me.log("drive meta_inv_take remove_item "..tostring(postack:get_count()).." "..postack:get_name(), "error")
-- TODO: this was here, but did nothing? me.remove_item(network, ctrl_inv, "main", postack) -- This is the main item removal on cell removal from drive
-- No, this is the main item removal on cell removal from drive
me.remove_item(network, ctrl_inv, "main", postack) me.remove_item(network, ctrl_inv, "main", postack)
--this returns 99 (max count) even if it removes more --this returns 99 (max count) even if it removes more
--ctrl_inv:remove_item("main", ostack) --ctrl_inv:remove_item("main", ostack)
@ -430,3 +476,7 @@ microexpansion.register_node("drive", {
me.send_event(pos, "items", {net=network}) me.send_event(pos, "items", {net=network})
end, end,
}) })
if me.uinv_category_enabled then
unified_inventory.add_category_item("storage", "microexpansion:drive")
end

@ -2,15 +2,42 @@
--TODO: use storagecomp for crafting --TODO: use storagecomp for crafting
if minetest.get_modpath("mcl_core") then
microexpansion.register_cell("cell_1k", {
description = "1k ME Storage Cell",
capacity = 1000,
recipe = {
{ 1, {
{"moreores:tin_ingot", "mcl_copper:copper_ingot", "moreores:tin_ingot"},
{"mcl_copper:copper_ingot", "microexpansion:steel_infused_obsidian_ingot", "mcl_copper:copper_ingot"},
{"moreores:tin_ingot", "mcl_copper:copper_ingot", "moreores:tin_ingot"}
}},
},
})
microexpansion.register_cell("cell_2k", {
description = "2k ME Storage Cell",
capacity = 2000,
recipe = {
{ 1, {
{"mcl_copper:copper_ingot", "mcl_core:iron_ingot", "mcl_copper:copper_ingot"},
{"mcl_core:iron_ingot", "mcl_core:obsidian", "mcl_core:iron_ingot"},
{"mcl_copper:copper_ingot", "mcl_core:iron_ingot", "mcl_copper:copper_ingot"}
}},
{ 1, "shapeless", {"microexpansion:cell_1k", "microexpansion:cell_1k"}}
},
})
else
-- [drive] 1k -- [drive] 1k
microexpansion.register_cell("cell_1k", { microexpansion.register_cell("cell_1k", {
description = "1k ME Storage Cell", description = "1k ME Storage Cell",
capacity = 1000, capacity = 1000,
recipe = { recipe = {
{ 1, { { 1, {
{"default:tin_ingot", "default:copper_ingot", "default:tin_ingot"}, {"default:tin_ingot", "default:copper_ingot", "default:tin_ingot"},
{"default:copper_ingot","microexpansion:steel_infused_obsidian_ingot","default:copper_ingot"}, {"default:copper_ingot", "microexpansion:steel_infused_obsidian_ingot", "default:copper_ingot"},
{"default:tin_ingot", "default:copper_ingot", "default:tin_ingot"}, {"default:tin_ingot", "default:copper_ingot", "default:tin_ingot"},
}, },
} }
}, },
@ -18,64 +45,66 @@ microexpansion.register_cell("cell_1k", {
-- [drive] 2k -- [drive] 2k
microexpansion.register_cell("cell_2k", { microexpansion.register_cell("cell_2k", {
description = "2k ME Storage Cell", description = "2k ME Storage Cell",
capacity = 2000, capacity = 2000,
recipe = { recipe = {
{ 1, { { 1, {
{"default:copper_ingot","default:steel_ingot", "default:copper_ingot"}, {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"},
{"default:steel_ingot", "default:obsidian_shard", "default:steel_ingot"}, {"default:steel_ingot", "default:obsidian_shard", "default:steel_ingot"},
{"default:copper_ingot","default:steel_ingot", "default:copper_ingot"}, {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"},
}, },
}, },
{ 1, "shapeless", {"microexpansion:cell_1k","microexpansion:cell_1k"}} { 1, "shapeless", {"microexpansion:cell_1k", "microexpansion:cell_1k"}}
}, },
}) })
end
-- [drive] 4k -- [drive] 4k
microexpansion.register_cell("cell_4k", { microexpansion.register_cell("cell_4k", {
description = "4k ME Storage Cell", description = "4k ME Storage Cell",
capacity = 4000, capacity = 4000,
recipe = { recipe = {
{ 1, "shapeless", { { 1, "shapeless", {
"microexpansion:steel_infused_obsidian_ingot", "microexpansion:machine_casing", "microexpansion:steel_infused_obsidian_ingot" "microexpansion:steel_infused_obsidian_ingot", "microexpansion:machine_casing", "microexpansion:steel_infused_obsidian_ingot"
}, },
}, },
{ 1, "shapeless", {"microexpansion:cell_2k","microexpansion:cell_2k"}} { 1, "shapeless", {"microexpansion:cell_2k", "microexpansion:cell_2k"}}
}, },
}) })
-- [drive] 8k -- [drive] 8k
microexpansion.register_cell("cell_8k", { microexpansion.register_cell("cell_8k", {
description = "8k ME Storage Cell", description = "8k ME Storage Cell",
capacity = 8000, capacity = 8000,
recipe = { recipe = {
{ 1, "shapeless", {"microexpansion:cell_4k","microexpansion:cell_4k"}} { 1, "shapeless", {"microexpansion:cell_4k", "microexpansion:cell_4k"}}
}, },
}) })
-- [drive] 16k -- [drive] 16k
microexpansion.register_cell("cell_16k", { microexpansion.register_cell("cell_16k", {
description = "16k ME Storage Cell", description = "16k ME Storage Cell",
capacity = 16000, capacity = 16000,
recipe = { recipe = {
{ 1, "shapeless", {"microexpansion:cell_8k","microexpansion:cell_8k"}} { 1, "shapeless", {"microexpansion:cell_8k", "microexpansion:cell_8k"}}
}, },
}) })
-- [drive] 32k -- [drive] 32k
microexpansion.register_cell("cell_32k", { microexpansion.register_cell("cell_32k", {
description = "32k ME Storage Cell", description = "32k ME Storage Cell",
capacity = 32000, capacity = 32000,
recipe = { recipe = {
{ 1, "shapeless", {"microexpansion:cell_16k","microexpansion:cell_16k"}} { 1, "shapeless", {"microexpansion:cell_16k", "microexpansion:cell_16k"}}
}, },
}) })
-- [drive] 64k -- [drive] 64k
microexpansion.register_cell("cell_64k", { microexpansion.register_cell("cell_64k", {
description = "64k ME Storage Cell", description = "64k ME Storage Cell",
capacity = 64000, capacity = 64000,
recipe = { recipe = {
{ 1, "shapeless", {"microexpansion:cell_32k","microexpansion:cell_32k"}} { 1, "shapeless", {"microexpansion:cell_32k", "microexpansion:cell_32k"}}
}, },
}) })

@ -3,6 +3,7 @@
local me = microexpansion local me = microexpansion
local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
local access_level = microexpansion.constants.security.access_levels
-- [me chest] Get formspec -- [me chest] Get formspec
local function chest_formspec(pos, start_id, listname, page_max, q) local function chest_formspec(pos, start_id, listname, page_max, q)
@ -16,10 +17,10 @@ local function chest_formspec(pos, start_id, listname, page_max, q)
if listname and net:get_item_capacity() > 0 then if listname and net:get_item_capacity() > 0 then
local ctrlinvname = net:get_inventory_name() local ctrlinvname = net:get_inventory_name()
if listname == "main" then if listname == "main" then
list = "list[detached:"..ctrlinvname..";" list = "list[detached:"..ctrlinvname..";"
.. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
else else
list = "list[context;" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]" list = "list[context;" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
end end
if minetest.get_modpath("i3") then if minetest.get_modpath("i3") then
list = list .. [[ list = list .. [[
@ -32,8 +33,8 @@ local function chest_formspec(pos, start_id, listname, page_max, q)
]] ]]
end end
list = list .. [[ list = list .. [[
listring[detached:]]..ctrlinvname..[[;main] listring[detached:]]..ctrlinvname..[[;main]
listring[current_player;main] listring[current_player;main]
]] ]]
buttons = [[ buttons = [[
button[3.56,4.35;1.8,0.9;tochest;To Drive] button[3.56,4.35;1.8,0.9;tochest;To Drive]
@ -64,7 +65,6 @@ local function chest_formspec(pos, start_id, listname, page_max, q)
buttons = "" buttons = ""
page_number = "" page_number = ""
end end
return [[ return [[
size[9,9.5] size[9,9.5]
]].. ]]..
@ -96,8 +96,31 @@ local function update_chest(pos,_,ev)
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max)) meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
end end
local term_recipe = nil
if minetest.get_modpath("mcl_core") then
term_recipe = {
{ 1, {
{"mcl_core:iron_ingot", "mcl_chests:chest", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "microexpansion:machine_casing", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "microexpansion:cable", "mcl_core:iron_ingot"},
},
}
}
else
term_recipe = {
{ 1, {
{"default:steel_ingot", "default:chest", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
},
}
}
end
-- [me chest] Register node -- [me chest] Register node
me.register_node("term", { microexpansion.register_node("term", {
description = "ME Terminal", description = "ME Terminal",
usedfor = "Can interact with storage cells in ME networks", usedfor = "Can interact with storage cells in ME networks",
tiles = { tiles = {
@ -108,14 +131,7 @@ me.register_node("term", {
"chest_side", "chest_side",
"chest_front", "chest_front",
}, },
recipe = { recipe = term_recipe,
{ 1, {
{"default:steel_ingot", "default:chest", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
},
}
},
is_ground_content = false, is_ground_content = false,
groups = { cracky = 1, me_connect = 1, tubedevice = 1, tubedevice_receiver = 1 }, groups = { cracky = 1, me_connect = 1, tubedevice = 1, tubedevice_receiver = 1 },
paramtype = "light", paramtype = "light",
@ -123,6 +139,7 @@ me.register_node("term", {
me_update = update_chest, me_update = update_chest,
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", chest_formspec(pos, 1))
meta:set_string("inv_name", "none") meta:set_string("inv_name", "none")
meta:set_int("page", 1) meta:set_int("page", 1)
@ -131,13 +148,38 @@ me.register_node("term", {
local net = me.get_connected_network(pos) local net = me.get_connected_network(pos)
me.send_event(pos, "connect", {net=net}) me.send_event(pos, "connect", {net=net})
update_chest(pos) if net then
update_chest(pos)
end
end, end,
after_destruct = function(pos) after_destruct = function(pos)
me.send_event(pos, "disconnect") me.send_event(pos, "disconnect")
end, end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player) can_dig = function(pos, player)
-- TODO: Check capacity, only allow if room if not player then
return false
end
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local net,cp = me.get_connected_network(pos)
if not net then
return true
end
return net:get_access_level(name) >= access_level.modify
end,
allow_metadata_inventory_put = function(pos, _, _, stack, player)
local network = me.get_connected_network(pos)
if network then
if network:get_access_level(player) < access_level.interact then
return 0
end
elseif minetest.is_protected(pos, player) then
minetest.record_protection_violation(pos, player)
return 0
end
return stack:get_count() return stack:get_count()
end, end,
on_metadata_inventory_put = function(pos, listname, _, stack) on_metadata_inventory_put = function(pos, listname, _, stack)
@ -146,6 +188,18 @@ me.register_node("term", {
me.insert_item(stack, net, inv, "main") me.insert_item(stack, net, inv, "main")
net:set_storage_space(true) net:set_storage_space(true)
end, end,
allow_metadata_inventory_take = function(pos,_,_,stack, player)
local network = me.get_connected_network(pos)
if network then
if network:get_access_level(player) < access_level.interact then
return 0
end
elseif minetest.is_protected(pos, player) then
minetest.record_protection_violation(pos, player)
return 0
end
return math.min(stack:get_count(),stack:get_stack_max())
end,
on_metadata_inventory_take = function(pos, listname, _, stack) on_metadata_inventory_take = function(pos, listname, _, stack)
local net = me.get_connected_network(pos) local net = me.get_connected_network(pos)
local inv = net:get_inventory() local inv = net:get_inventory()
@ -154,6 +208,9 @@ me.register_node("term", {
tube = { tube = {
can_insert = function(pos, _, stack) --pos, node, stack, direction can_insert = function(pos, _, stack) --pos, node, stack, direction
local net = me.get_connected_network(pos) local net = me.get_connected_network(pos)
if not net then
return false
end
local inv = net:get_inventory() local inv = net:get_inventory()
local max_slots = inv:get_size("main") local max_slots = inv:get_size("main")
local max_items = net.capacity_cache local max_items = net.capacity_cache
@ -174,6 +231,9 @@ me.register_node("term", {
end, end,
insert_object = function(pos, _, stack) insert_object = function(pos, _, stack)
local net = me.get_connected_network(pos) local net = me.get_connected_network(pos)
if not net then
return stack
end
local inv = net:get_inventory() local inv = net:get_inventory()
local leftovers = me.insert_item(stack, net, inv, "main") local leftovers = me.insert_item(stack, net, inv, "main")
net:set_storage_space(true) net:set_storage_space(true)
@ -206,7 +266,7 @@ me.register_node("term", {
if cp then if cp then
ctrl_inv = net:get_inventory() ctrl_inv = net:get_inventory()
else else
me.log("no network connected","warning") microexpansion.log("no network connected","warning")
return return
end end
local inv local inv
@ -258,8 +318,12 @@ me.register_node("term", {
meta:set_string("inv_name", "main") meta:set_string("inv_name", "main")
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max)) meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
elseif fields.tochest then elseif fields.tochest then
if net:get_access_level(sender) < access_level.interact then
return
end
local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()}) local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()})
-- TODO: test and fix, net:set_storage_space(pinv:get_size("main")) -- TODO: test and fix
-- net:set_storage_space(pinv:get_size("main"))
local space = net:get_item_capacity() local space = net:get_item_capacity()
local contents = ctrl_inv:get_list("main") or {} local contents = ctrl_inv:get_list("main") or {}
for _,s in pairs(contents) do for _,s in pairs(contents) do
@ -272,3 +336,7 @@ me.register_node("term", {
end end
end, end,
}) })
if me.uinv_category_enabled then
unified_inventory.add_category_item("storage", "microexpansion:term")
end

@ -5,90 +5,99 @@
local me = microexpansion local me = microexpansion
local power = me.power local power = me.power
if me.uinv_category_enabled and unified_inventory.registered_categories then
if not unified_inventory.registered_categories["storage"] then
unified_inventory.register_category("storage", {
symbol = "default:chest",
label = "Storage"
})
end
end
-- [function] Register machine -- [function] Register machine
function me.register_machine(itemstring, def) function me.register_machine(itemstring, def)
-- Set after_place_node -- Set after_place_node
local def_afterplace = def.after_place_node local def_afterplace = def.after_place_node
def.after_place_node = function(pos, player) def.after_place_node = function(pos, player)
if def_afterplace then if def_afterplace then
def_afterplace(pos, player) def_afterplace(pos, player)
end end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local nodes = me.network.adjacent_connected_nodes(pos) local nodes = me.network.adjacent_connected_nodes(pos)
meta:set_string("infotext", def.description.."\nNo Network") meta:set_string("infotext", def.description.."\nNo Network")
for _, pos2 in pairs(nodes) do for _, pos2 in pairs(nodes) do
local id = minetest.get_meta(pos2):get_string("network_id") local id = minetest.get_meta(pos2):get_string("network_id")
if id ~= "" then if id ~= "" then
meta:set_string("infotext", def.description.."\nNetwork ID: "..id) meta:set_string("infotext", def.description.."\nNetwork ID: "..id)
meta:set_string("network_id", id) meta:set_string("network_id", id)
end end
end end
-- Trace Network -- Trace Network
--power.trace(pos) --power.trace(pos)
-- Set demand -- Set demand
if def.demand then if def.demand then
me.network_set_demand(pos, def.demand) me.network_set_demand(pos, def.demand)
end end
if type(def.machine) == "table" then if type(def.machine) == "table" then
if power then if power then
power.add_machine(pos, def.machine) power.add_machine(pos, def.machine)
end end
end end
end end
-- Set on_destruct -- Set on_destruct
local def_destruct = def.on_destruct local def_destruct = def.on_destruct
def.on_destruct = function(pos, player) def.on_destruct = function(pos, player)
if def_destruct then if def_destruct then
def_destruct(pos, player) def_destruct(pos, player)
end end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_string("network_id") ~= "" then if meta:get_string("network_id") ~= "" then
-- Set demand -- Set demand
me.network_set_demand(pos, 0) me.network_set_demand(pos, 0)
-- Remove item from network -- Remove item from network
me.network_remove(pos) me.network_remove(pos)
-- Retrace Network -- Retrace Network
--power.trace(pos) --power.trace(pos)
end end
end end
-- Set connects_to -- Set connects_to
def.connects_to = {"group:me_connect"} def.connects_to = {"group:me_connect"}
-- Set me_connect group -- Set me_connect group
def.groups = def.groups or {} def.groups = def.groups or {}
def.groups.me_connect = 1 def.groups.me_connect = 1
me.register_node(itemstring, def) me.register_node(itemstring, def)
end end
-- [function] Get machine definition -- [function] Get machine definition
function me.get_def(name, key) function me.get_def(name, key)
if type(name) == "table" then if type(name) == "table" then
local node = me.get_node(name) local node = me.get_node(name)
if node then if node then
name = node.name name = node.name
end end
end end
local def = minetest.registered_nodes[name] local def = minetest.registered_nodes[name]
-- Check name and if registered -- Check name and if registered
if not name or not def then if not name or not def then
return return
end end
if key then if key then
return def[key] return def[key]
else else
return def return def
end end
end end
microexpansion.log("Machine Registration API loaded") microexpansion.log("Machine Registration API loaded")

@ -1,2 +1,5 @@
#Stack items in networks higher than their max size. #Stack items in networks higher than their max size.
microexpansion_huge_stacks (huge stacks) bool true microexpansion_huge_stacks (huge stacks) bool true
#Enable the "simple" craft recipes that do not require basic_materials even if basic_materials is present.
microexpansion_simple_craft (simple craft recipes) bool false

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 309 B

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB