From 49063dd23a4ce8d974b96277be40c62ec6b0a7a4 Mon Sep 17 00:00:00 2001 From: Emoji <55009343+Emojigit@users.noreply.github.com> Date: Fri, 12 Aug 2022 16:27:39 +0800 Subject: [PATCH] digilne printer --- init.lua | 214 ++---------------------------------- mod.conf | 2 +- src/copybooks.lua | 208 +++++++++++++++++++++++++++++++++++ src/crafting.lua | 46 ++++++++ src/digiline_writers.lua | 230 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 493 insertions(+), 207 deletions(-) create mode 100644 src/copybooks.lua create mode 100644 src/crafting.lua create mode 100644 src/digiline_writers.lua diff --git a/init.lua b/init.lua index 4934605..cf3cbe3 100644 --- a/init.lua +++ b/init.lua @@ -1,208 +1,10 @@ -local S = minetest.get_translator("copybooks") -local F = minetest.formspec_escape - -local status_idle = S("Book Copier Idle") -local status_active = S("Book Copier Active") -local status_full = S("Book Copier Full") -local status_nopaper = S("Book Copier No Paper") - -local copybooks_formspec = function(status) - return "" .. - "size[8,9]".. - - "label[0,0;"..S("Inputs").."]".. - "list[context;input;0,0.5;3,3;]" .. - "listring[current_player;main]".. - - "label[2.9,0;"..S("Master").."]".. - "list[context;master;3,0.5;1,1;]".. - - "label[0.25,4;" .. status .. "]" .. - - "button_exit[3,1.5;1,1;quit;" .. S("Quit") .. "]".. - - "label[6.7,0;"..S("Copies").."]".. - "list[context;output;4,0.5;4,4;]".. - - "list[current_player;main;0,5;8,4;]" .. - "listring[context;input]" +copybooks = {} +local MN = minetest.get_current_modname() +local MP = minetest.get_modpath(MN) +local function require(name) + dofile(MP .. "/src/" .. name .. ".lua") end -local on_construct = function( pos ) - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - - inv:set_size("input", 9) - inv:set_size("output", 16) - inv:set_size("master", 1) - meta:set_string('formspec', copybooks_formspec(status_idle)) - meta:set_string('infotext', status_idle) -end - -local mfu_allow_metadata_inventory_put = function(pos, listname, index, stack, player) - local iname = stack:get_name() - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - - if listname == "input" then - if iname == "default:book" or iname == "default:paper" then - return inv:room_for_item("input", stack) and stack:get_count() or 0 - else - return 0 - end - elseif listname == "output" then - return 0 - elseif listname == "master" then - if iname == "default:book_written" and inv:room_for_item("master", stack) then - return 1 - else - return 0 - end - end - return 0 -end - -local mfu_allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) - if to_list == "input" then - return -1 - else - return 0 - end -end - -local mfu_can_dig = function(pos, player) - 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 inv = meta:get_inventory() - return (inv:is_empty("input") and inv:is_empty("output") and inv:is_empty("master")) -end - -local mfu_tube = minetest.get_modpath("pipeworks") and { - -- using a different stack from defaut when inserting - insert_object = function(pos, node, stack, direction) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - return inv:add_item("input", stack) - end, - can_insert = function(pos, node, stack, direction) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - if stack:get_name() == "default:paper" or stack:get_name() == "default:book" then - return inv:room_for_item("input", stack) - else - return false - end - end, - -- the default stack, from which objects will be taken - input_inventory = "output", - connect_sides = {left = 1, right = 1, back = 1, bottom = 1,} - } or nil - -minetest.register_node("copybooks:copybooks_active", { - description = S("Book Copier"), - tiles = { {name="mfu_top_active.png", - animation={type="vertical_frames", - aspect_w=32, - aspect_h=32, - length=3}}, - "mfu_bottom.png", - "mfu_side.png", - "mfu_side.png", - "mfu_back.png", - "mfu_front_active.png", - }, - groups = {cracky = 1, not_in_creative_inventory = 1, tubedevice = 1, tubedevice_receiver = 1, copybooks = 1}, - light_source = 3, - allow_metadata_inventory_put = mfu_allow_metadata_inventory_put, - allow_metadata_inventory_move = mfu_allow_metadata_inventory_move, - paramtype = "light", - paramtype2 = "facedir", - drop = "copybooks:copybooks", - can_dig = mfu_can_dig, - tube = mfu_tube, -}) - -minetest.register_node("copybooks:copybooks", { - description = S("Book Copier"), - tiles = { "mfu_top.png", - "mfu_bottom.png", - "mfu_side.png", - "mfu_side.png", - "mfu_back.png", - "mfu_front.png", - }, - groups = {cracky = 1, tubedevice = 1, tubedevice_receiver = 1, copybooks = 1}, - allow_metadata_inventory_put = mfu_allow_metadata_inventory_put, - allow_metadata_inventory_move = mfu_allow_metadata_inventory_move, - paramtype = "light", - paramtype2 = "facedir", - drop = "copybooks:copybooks", - can_dig = mfu_can_dig, - tube = mfu_tube, - on_construct = on_construct, -}) - -local function inactive_state(pos,meta,state) - minetest.swap_node(pos,{name="copybooks:copybooks"}) - meta:set_string("infotext",state or status_idle) - meta:set_string("formspec",copybooks_formspec(state or status_idle)) -end - -local function active_state(pos,meta) - minetest.swap_node(pos,{name="copybooks:copybooks_active"}) - meta:set_string("infotext",status_active) - meta:set_string("formspec",copybooks_formspec(status_active)) -end - -minetest.register_abm({ - label = "copybooks:copy", - nodenames = {"group:copybooks"}, - interval = 1.0, - chance = 1, - catch_up = true, - action = function(pos, node, active_object_count, active_object_count_wider) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - if inv:is_empty("master") then - inactive_state(pos,meta) - return - elseif inv:is_empty("input") then - inactive_state(pos,meta,status_nopaper) - return - end - - local input = inv:get_list("input") - local output = inv:get_list("output") - local master = inv:get_list("master") - - local master_copy = inv:get_stack("master", 1) - local master_contents = master_copy:get_meta():to_table() - - master_contents.fields.owner = S("@1 (copy)",master_contents.fields.owner or "???") - - local copy = ItemStack({name = "default:book_written", count = 1}) - copy:get_meta():from_table(master_contents) - - if inv:room_for_item("output", copy) then - if inv:contains_item("input", {name = "default:book", count = 1}) then - inv:remove_item("input", {name = "default:book", count = 1}) - inv:add_item("output", copy) - elseif inv:contains_item("input", {name = "default:paper", count = 3}) then - inv:remove_item("input", {name = "default:paper", count = 3}) - inv:add_item("output", copy) - else - inactive_state(pos,meta,status_nopaper) - return - end - active_state(pos,meta) - else - inactive_state(pos,meta,status_full) - end - end, -}) - - +require("copybooks") +require("digiline_writers") +require("crafting") diff --git a/mod.conf b/mod.conf index 0450380..586fb34 100644 --- a/mod.conf +++ b/mod.conf @@ -1,3 +1,3 @@ name = copybooks depends = default -optional_depends = technic, pipeworks +optional_depends = technic, pipeworks, digilines diff --git a/src/copybooks.lua b/src/copybooks.lua new file mode 100644 index 0000000..4934605 --- /dev/null +++ b/src/copybooks.lua @@ -0,0 +1,208 @@ +local S = minetest.get_translator("copybooks") +local F = minetest.formspec_escape + +local status_idle = S("Book Copier Idle") +local status_active = S("Book Copier Active") +local status_full = S("Book Copier Full") +local status_nopaper = S("Book Copier No Paper") + +local copybooks_formspec = function(status) + return "" .. + "size[8,9]".. + + "label[0,0;"..S("Inputs").."]".. + "list[context;input;0,0.5;3,3;]" .. + "listring[current_player;main]".. + + "label[2.9,0;"..S("Master").."]".. + "list[context;master;3,0.5;1,1;]".. + + "label[0.25,4;" .. status .. "]" .. + + "button_exit[3,1.5;1,1;quit;" .. S("Quit") .. "]".. + + "label[6.7,0;"..S("Copies").."]".. + "list[context;output;4,0.5;4,4;]".. + + "list[current_player;main;0,5;8,4;]" .. + "listring[context;input]" +end + +local on_construct = function( pos ) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + + inv:set_size("input", 9) + inv:set_size("output", 16) + inv:set_size("master", 1) + meta:set_string('formspec', copybooks_formspec(status_idle)) + meta:set_string('infotext', status_idle) +end + +local mfu_allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local iname = stack:get_name() + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + if listname == "input" then + if iname == "default:book" or iname == "default:paper" then + return inv:room_for_item("input", stack) and stack:get_count() or 0 + else + return 0 + end + elseif listname == "output" then + return 0 + elseif listname == "master" then + if iname == "default:book_written" and inv:room_for_item("master", stack) then + return 1 + else + return 0 + end + end + return 0 +end + +local mfu_allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + if to_list == "input" then + return -1 + else + return 0 + end +end + +local mfu_can_dig = function(pos, player) + 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 inv = meta:get_inventory() + return (inv:is_empty("input") and inv:is_empty("output") and inv:is_empty("master")) +end + +local mfu_tube = minetest.get_modpath("pipeworks") and { + -- using a different stack from defaut when inserting + insert_object = function(pos, node, stack, direction) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:add_item("input", stack) + end, + can_insert = function(pos, node, stack, direction) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if stack:get_name() == "default:paper" or stack:get_name() == "default:book" then + return inv:room_for_item("input", stack) + else + return false + end + end, + -- the default stack, from which objects will be taken + input_inventory = "output", + connect_sides = {left = 1, right = 1, back = 1, bottom = 1,} + } or nil + +minetest.register_node("copybooks:copybooks_active", { + description = S("Book Copier"), + tiles = { {name="mfu_top_active.png", + animation={type="vertical_frames", + aspect_w=32, + aspect_h=32, + length=3}}, + "mfu_bottom.png", + "mfu_side.png", + "mfu_side.png", + "mfu_back.png", + "mfu_front_active.png", + }, + groups = {cracky = 1, not_in_creative_inventory = 1, tubedevice = 1, tubedevice_receiver = 1, copybooks = 1}, + light_source = 3, + allow_metadata_inventory_put = mfu_allow_metadata_inventory_put, + allow_metadata_inventory_move = mfu_allow_metadata_inventory_move, + paramtype = "light", + paramtype2 = "facedir", + drop = "copybooks:copybooks", + can_dig = mfu_can_dig, + tube = mfu_tube, +}) + +minetest.register_node("copybooks:copybooks", { + description = S("Book Copier"), + tiles = { "mfu_top.png", + "mfu_bottom.png", + "mfu_side.png", + "mfu_side.png", + "mfu_back.png", + "mfu_front.png", + }, + groups = {cracky = 1, tubedevice = 1, tubedevice_receiver = 1, copybooks = 1}, + allow_metadata_inventory_put = mfu_allow_metadata_inventory_put, + allow_metadata_inventory_move = mfu_allow_metadata_inventory_move, + paramtype = "light", + paramtype2 = "facedir", + drop = "copybooks:copybooks", + can_dig = mfu_can_dig, + tube = mfu_tube, + on_construct = on_construct, +}) + +local function inactive_state(pos,meta,state) + minetest.swap_node(pos,{name="copybooks:copybooks"}) + meta:set_string("infotext",state or status_idle) + meta:set_string("formspec",copybooks_formspec(state or status_idle)) +end + +local function active_state(pos,meta) + minetest.swap_node(pos,{name="copybooks:copybooks_active"}) + meta:set_string("infotext",status_active) + meta:set_string("formspec",copybooks_formspec(status_active)) +end + +minetest.register_abm({ + label = "copybooks:copy", + nodenames = {"group:copybooks"}, + interval = 1.0, + chance = 1, + catch_up = true, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if inv:is_empty("master") then + inactive_state(pos,meta) + return + elseif inv:is_empty("input") then + inactive_state(pos,meta,status_nopaper) + return + end + + local input = inv:get_list("input") + local output = inv:get_list("output") + local master = inv:get_list("master") + + local master_copy = inv:get_stack("master", 1) + local master_contents = master_copy:get_meta():to_table() + + master_contents.fields.owner = S("@1 (copy)",master_contents.fields.owner or "???") + + local copy = ItemStack({name = "default:book_written", count = 1}) + copy:get_meta():from_table(master_contents) + + if inv:room_for_item("output", copy) then + if inv:contains_item("input", {name = "default:book", count = 1}) then + inv:remove_item("input", {name = "default:book", count = 1}) + inv:add_item("output", copy) + elseif inv:contains_item("input", {name = "default:paper", count = 3}) then + inv:remove_item("input", {name = "default:paper", count = 3}) + inv:add_item("output", copy) + else + inactive_state(pos,meta,status_nopaper) + return + end + active_state(pos,meta) + else + inactive_state(pos,meta,status_full) + end + end, +}) + + diff --git a/src/crafting.lua b/src/crafting.lua new file mode 100644 index 0000000..f1feb0e --- /dev/null +++ b/src/crafting.lua @@ -0,0 +1,46 @@ +local mfu_item_a = "default:meselamp" +if minetest.get_modpath("technic") and technic.mod == "linuxforks" then + mfu_item_a = "technic:lv_led" +end + +local mfu_item_b = "default:book" +if minetest.get_modpath("digilines") then + mfu_item_b = "digilines:wire_std_00000000" +end + +local mfu_item_c = "default:diamond" +if minetest.get_modpath("pipeworks") then + mfu_item_c = "pipeworks:tube_1" +end + + +if minetest.get_modpath("technic") then + minetest.register_craft({ + output = "copybooks:copybooks", + recipe = { + {"homedecor:plastic_sheeting", "default:obsidian_glass", "homedecor:plastic_sheeting"}, + {mfu_item_c, mfu_item_a, mfu_item_c}, + {"technic:stainless_steel_ingot", mfu_item_b, "technic:stainless_steel_ingot"}, + } + }) +else + minetest.register_craft({ + output = "copybooks:copybooks", + recipe = { + {"default:copper_ingot", "default:obsidian_glass", "default:copper_ingot"}, + {mfu_item_c, mfu_item_a, mfu_item_c}, + {"default:steel_ingot", mfu_item_b, "default:steel_ingot"}, + } + }) +end + +if copybooks.digiline_writer then + minetest.register_craft({ + output = "copybooks:copybooks", + recipe = {{"copybooks:digiline_writer"}} + }) + minetest.register_craft({ + output = "copybooks:digiline_writer", + recipe = {{"copybooks:copybooks"}} + }) +end diff --git a/src/digiline_writers.lua b/src/digiline_writers.lua new file mode 100644 index 0000000..10eb978 --- /dev/null +++ b/src/digiline_writers.lua @@ -0,0 +1,230 @@ +if not minetest.get_modpath("digilines") then + return +end + +copybooks.digiline_writer = true + +local S = minetest.get_translator("copybooks") +local F = minetest.formspec_escape + +local infotext = S("Digiline Printer") + +local function formspec(c) + return "" .. + "size[8,9]".. + + "label[0,0;"..S("Inputs").."]".. + "list[context;input;0,0.5;3,3;]" .. + "listring[current_player;main]".. + + "button_exit[3,1.5;1,1;quit;" .. S("Quit") .. "]".. + "button_exit[3,2.5;1,1;set;" .. S("Save") .. "]".. + + "label[6.7,0;"..S("Copies").."]".. + "list[context;output;4,0.5;4,4;]".. + + "field[0.25,4;4,1;channel;" .. S("Digiline channel:") .. ";" .. F(c or "") .. "]".. + + "list[current_player;main;0,5;8,4;]" .. + "listring[context;input]" +end + +local on_construct = function( pos ) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + + inv:set_size("input", 9) + inv:set_size("output", 16) + inv:set_size("master", 1) + meta:set_string("channel", "") + meta:set_string('formspec', formspec()) + meta:set_string('infotext', infotext) +end + +local mfu_allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local iname = stack:get_name() + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + if listname == "input" then + if iname == "default:book" or iname == "default:paper" then + return inv:room_for_item("input", stack) and stack:get_count() or 0 + else + return 0 + end + end + return 0 +end + +local mfu_allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + if to_list == "input" then + return -1 + else + return 0 + end +end + +local mfu_can_dig = function(pos, player) + 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 inv = meta:get_inventory() + return (inv:is_empty("input") and inv:is_empty("output")) +end + +local mfu_tube = minetest.get_modpath("pipeworks") and { + -- using a different stack from defaut when inserting + insert_object = function(pos, node, stack, direction) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:add_item("input", stack) + end, + can_insert = function(pos, node, stack, direction) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if stack:get_name() == "default:paper" or stack:get_name() == "default:book" then + return inv:room_for_item("input", stack) + else + return false + end + end, + -- the default stack, from which objects will be taken + input_inventory = "output", + connect_sides = {left = 1, right = 1, back = 1, bottom = 1,} + } or nil + +minetest.register_node("copybooks:digiline_writer", { + description = infotext, + tiles = { "mfu_top.png", + "mfu_bottom.png", + "mfu_side.png", + "mfu_side.png", + "mfu_back.png", + "mfu_front.png", + }, + groups = {cracky = 1, tubedevice = 1, tubedevice_receiver = 1}, + allow_metadata_inventory_put = mfu_allow_metadata_inventory_put, + allow_metadata_inventory_move = mfu_allow_metadata_inventory_move, + paramtype = "light", + paramtype2 = "facedir", + drop = "copybooks:copybooks", + can_dig = mfu_can_dig, + tube = mfu_tube, + on_construct = on_construct, + digiline = { + receptor = {}, + effector = { + action = function(pos,_,channel,msg) + local meta = minetest.get_meta(pos) + local listen_on = meta:get_string('channel') + local inv = meta:get_inventory() + + if listen_on == "" or channel ~= listen_on then + return + end + + if type(msg) ~= "table" then + return + end + + if msg.command == "STATUS" then + if not inv:contains_item("input", {name = "default:book", count = 1}) and + not inv:contains_item("input", {name = "default:paper", count = 3}) then + digilines.receptor_send(pos, digilines.rules.default, channel, { STATUS = "NO PAPER" }) + elseif not inv:room_for_item("output", {name = "default:book_written", count = 1}) then + digilines.receptor_send(pos, digilines.rules.default, channel, { STATUS = "OUTPUT FULL" }) + else + digilines.receptor_send(pos, digilines.rules.default, channel, { STATUS = "IDLE" }) + end + elseif msg.command == "SUPPLIES" then + local data = { + ["default:paper"] = 0, + ["default:book"] = 0, + empty = 0, + } + + for i = 1,9,1 do + local s = inv:get_stack("input", i) + if not s:is_empty() then + local name = s:get_name() + data[name] = data[name] + s:get_count() + else + data.empty = data.empty + 1 + end + end + + local message = { + STATUS = "OK", + FREE = data.empty, + PAPER = tonumber(data["default:paper"]), + BOOKS = tonumber(data["default:book"]), + COPIES = math.floor(tonumber(data["default:paper"]) / 3) + tonumber(data["default:book"]), + } + + digilines.receptor_send(pos, digilines.rules.default, channel, message) + elseif msg.command == "PRINT" then + local max_text_size = 10000 + local max_title_size = 80 + local short_title_size = 35 + local lpp = 14 + + local book = ItemStack({name = "default:book_written", count = 1}) + local data = {} + data.owner = msg.author and S("@1 (printed)",msg.author) or S("Digiline Printer (automatic)") + data.title = msg.title and msg.title:sub(1, max_title_size) or S("Untitled") + + local short_title = data.title + -- Don't bother triming the title if the trailing dots would make it longer + if #short_title > short_title_size + 3 then + short_title = short_title:sub(1, short_title_size) .. "..." + end + + data.description = default.get_translator("\"@1\" by @2", short_title, data.owner) + data.text = msg.text:sub(1, max_text_size) + data.text = data.text:gsub("\r\n", "\n"):gsub("\r", "\n") + data.page = 1 + data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp) + + if msg.watermark then + data.watermark = msg.watermark + end + + book:get_meta():from_table({ fields = data }) + + local n = tonumber(msg.copies) or 1 + + while inv:room_for_item("output", book) and n > 0 do + if inv:contains_item("input", {name = "default:book", count = 1}) then + inv:remove_item("input", {name = "default:book", count = 1}) + inv:add_item("output", book) + n = n - 1 + elseif inv:contains_item("input", {name = "default:paper", count = 3}) then + inv:remove_item("input", {name = "default:paper", count = 3}) + inv:add_item("output", book) + n = n - 1 + else + break + end + end + if n == 0 then + digilines.receptor_send(pos, digilines.rules.default, channel, { STATUS = "OK", COUNT = msg.copies }) + else + digilines.receptor_send(pos, digilines.rules.default, channel, { STATUS = "OUTPUT FULL", COUNT = msg.copies - n, DROPPED = n }) + end + end + end, + }, + }, + on_receive_fields = function(pos, formname, fields, sender) + if fields.set then + local meta = minetest.get_meta(pos); + meta:set_string('channel', fields.channel) + meta:set_string('formspec', formspec(fields.channel)) + end + end, +}) + +