diff --git a/basic_machines/grinder.lua b/basic_machines/grinder.lua new file mode 100644 index 0000000..dd01329 --- /dev/null +++ b/basic_machines/grinder.lua @@ -0,0 +1,294 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + TA2/TA3/TA4 Grinding Cobble/Basalt to Gravel + +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta +-- Techage Related Data +local TRD = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).techage end + +-- Load support for intllib. +local MP = minetest.get_modpath("tubelib2") +local I,_ = dofile(MP.."/intllib.lua") + +local STANDBY_TICKS = 10 +local COUNTDOWN_TICKS = 10 +local CYCLE_TIME = 4 + + +-- Grinder recipes +local Recipes = {} + +local function formspec(self, pos, mem) + return "size[8,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;src;0,0;3,3;]".. + "item_image[0,0;1,1;default:cobble]".. + "image[0,0;1,1;techage_form_mask.png]".. + "image[3.5,1;1,1;techage_form_arrow.png]".. + "image_button[3.5,2;1,1;".. self:get_state_button_image(mem) ..";state_button;]".. + "list[context;dst;5,0;3,3;]".. + "item_image[5,0;1,1;default:gravel]".. + "image[5,0;1,1;techage_form_mask.png]".. + "list[current_player;main;0,4;8,4;]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]" +end + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + if listname == "src" and TRD(pos).State:get_state(M(pos)) == techage.STANDBY then + TRD(pos).State:start(pos, M(pos)) + end + return stack:get_count() +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local inv = M(pos):get_inventory() + local stack = inv:get_stack(from_list, from_index) + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +local function src_to_dst(src_stack, idx, num_items, inv, dst_name) + local taken = src_stack:take_item(num_items) + local output = ItemStack(dst_name) + print("taken:get_count()", taken:get_count(), output:get_count() * taken:get_count()) + output:set_count(output:get_count() * taken:get_count()) + if inv:room_for_item("dst", output) then + print("output:get_count()", output:get_count()) + inv:set_stack("src", idx, src_stack) + inv:add_item("dst", output) + return true + end + return false +end + +local function grinding(pos, trd, mem, inv) + local num_items = 0 + for idx,stack in ipairs(inv:get_list("src")) do + if not stack:is_empty() then + local name = stack:get_name() + if Recipes[name] then + if src_to_dst(stack, idx, trd.num_items, inv, Recipes[name]) then + trd.State:keep_running(pos, mem, COUNTDOWN_TICKS) + else + trd.State:blocked(pos, mem) + end + else + trd.State:fault(pos, mem) + end + return + end + end + trd.State:idle(pos, mem) +end + +local function keep_running(pos, elapsed) + local mem = tubelib2.get_mem(pos) + local trd = TRD(pos) + local inv = M(pos):get_inventory() + grinding(pos, trd, mem, inv) + return trd.State:is_active(mem) +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + local mem = tubelib2.get_mem(pos) + TRD(pos).State:state_button_event(pos, mem, fields) +end + +local function can_dig(pos, player) + if minetest.is_protected(pos, player:get_player_name()) then + return false + end + local inv = M(pos):get_inventory() + return inv:is_empty("dst") and inv:is_empty("src") +end + + +local tiles = {} +-- '#' will be replaced by the stage number +-- '{power}' will be replaced by the power PNG +tiles.pas = { + -- up, down, right, left, back, front + "techage_appl_grinder.png^techage_frame_ta#_top.png", + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + "techage_filling_ta#.png^{power}^techage_frame_ta#.png", + "techage_filling_ta#.png^{power}^techage_frame_ta#.png", +} +tiles.act = { + -- up, down, right, left, back, front + { + image = "techage_appl_grinder4.png^techage_frame4_ta#_top.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 1.0, + }, + }, + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + "techage_filling_ta#.png^{power}^techage_frame_ta#.png", + "techage_filling_ta#.png^{power}^techage_frame_ta#.png", +} +tiles.def = { + -- up, down, right, left, back, front + "techage_appl_grinder.png^techage_frame_ta#_top.png", + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png^techage_appl_defect.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png^techage_appl_defect.png", + "techage_filling_ta#.png^{power}^techage_frame_ta#.png^techage_appl_defect.png", + "techage_filling_ta#.png^{power}^techage_frame_ta#.png^techage_appl_defect.png", +} + +local tubing = { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + if meta:get_int("pull_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.get_items(inv, "dst", num) + end + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("push_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.put_items(inv, "src", stack) + end + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("pull_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.put_items(inv, "dst", stack) + end + end, + on_recv_message = function(pos, topic, payload) + local resp = TRD(pos).State:on_receive_message(pos, topic, payload) + if resp then + return resp + else + return "unsupported" + end + end, + on_node_load = function(pos) + TRD(pos).State:on_node_load(pos) + end, + on_node_repair = function(pos) + return TRD(pos).State:on_node_repair(pos) + end, +} + +local node_name_ta2, node_name_ta3, node_name_ta4 = + techage.register_consumer("grinder", I("Grinder"), tiles, { + cycle_time = CYCLE_TIME, + standby_ticks = STANDBY_TICKS, + has_item_meter = true, + aging_factor = 10, + formspec = formspec, + tubing = tubing, + after_place_node = function(pos, placer) + print("my after_place_node") + local inv = M(pos):get_inventory() + inv:set_size('src', 9) + inv:set_size('dst', 9) + end, + can_dig = can_dig, + node_timer = keep_running, + on_receive_fields = on_receive_fields, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, + groups = {choppy=2, cracky=2, crumbly=2}, + sounds = default.node_sound_wood_defaults(), + num_items = {0,1,2,4}, + power_consumption = {0,2,3,4}, + }) + +minetest.register_craft({ + output = node_name_ta2, + recipe = { + {"group:wood", "default:tin_ingot", "group:wood"}, + {"tubelib:tubeS", "default:mese_crystal", "tubelib:tubeS"}, + {"group:wood", "default:tin_ingot", "group:wood"}, + }, +}) + +if minetest.global_exists("unified_inventory") then + unified_inventory.register_craft_type("grinding", { + description = I("Grinding"), + icon = 'techage_appl_grinder.png', + width = 1, + height = 1, + }) +end + +function techage.add_grinder_recipe(recipe) + Recipes[recipe.input] = recipe.output + if minetest.global_exists("unified_inventory") then + recipe.items = {recipe.input} + recipe.type = "grinding" + unified_inventory.register_craft(recipe) + end +end + + +techage.add_grinder_recipe({input="default:cobble", output="default:gravel"}) +techage.add_grinder_recipe({input="default:desert_cobble", output="default:gravel"}) +techage.add_grinder_recipe({input="default:mossycobble", output="default:gravel"}) +techage.add_grinder_recipe({input="default:gravel", output="default:sand"}) +techage.add_grinder_recipe({input="gravelsieve:sieved_gravel", output="default:sand"}) +techage.add_grinder_recipe({input="default:coral_skeleton", output="default:silver_sand"}) +techage.add_grinder_recipe({input="tubelib:basalt_stone", output="default:silver_sand"}) + +if minetest.global_exists("skytest") then + techage.add_grinder_recipe({input="default:desert_sand", output="skytest:dust"}) + techage.add_grinder_recipe({input="default:silver_sand", output="skytest:dust"}) + techage.add_grinder_recipe({input="default:sand", output="skytest:dust"}) +else + techage.add_grinder_recipe({input="default:desert_sand", output="default:clay"}) + techage.add_grinder_recipe({input="default:silver_sand", output="default:clay"}) + techage.add_grinder_recipe({input="default:sand", output="default:clay"}) +end + +techage.add_grinder_recipe({input="default:sandstone", output="default:sand 4"}) +techage.add_grinder_recipe({input="default:desert_sandstone", output="default:desert_sand 4"}) +techage.add_grinder_recipe({input="default:silver_sandstone", output="default:silver_sand 4"}) + +techage.add_grinder_recipe({input="default:tree", output="default:leaves 8"}) +techage.add_grinder_recipe({input="default:jungletree", output="default:jungleleaves 8"}) +techage.add_grinder_recipe({input="default:pine_tree", output="default:pine_needles 8"}) +techage.add_grinder_recipe({input="default:acacia_tree", output="default:acacia_leaves 8"}) +techage.add_grinder_recipe({input="default:aspen_tree", output="default:aspen_leaves 8"}) diff --git a/basic_machines/pusher.lua b/basic_machines/pusher.lua index 2ce7cfb..1fb6697 100644 --- a/basic_machines/pusher.lua +++ b/basic_machines/pusher.lua @@ -185,10 +185,10 @@ local function register_pusher(stage, num_items) -- up, down, right, left, back, front "techage_filling_ta"..stage..".png^techage_frame_ta"..stage.."_top.png^techage_appl_arrow.png", "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png", - "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png^techage_appl_outp.png^tubelib_defect.png", - "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png^techage_appl_inp.png^tubelib_defect.png", - "techage_appl_pusher.png^[transformR180]^techage_frame_ta"..stage..".png^tubelib_defect.png", - "techage_appl_pusher.png^techage_frame_ta"..stage..".png^tubelib_defect.png", + "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png^techage_appl_outp.png^techage_appl_defect.png", + "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png^techage_appl_inp.png^techage_appl_defect.png", + "techage_appl_pusher.png^[transformR180]^techage_frame_ta"..stage..".png^techage_appl_defect.png", + "techage_appl_pusher.png^techage_frame_ta"..stage..".png^techage_appl_defect.png", }, techage = { diff --git a/basis/consumer.lua b/basis/consumer.lua new file mode 100644 index 0000000..05063eb --- /dev/null +++ b/basis/consumer.lua @@ -0,0 +1,227 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + Consumer node basis functionality. + It handles: + - 3 stages of nodes (TA2/TA3/TA4) + - power consumption + - node state handling + - registration of passive, active and defect nodes + - Tube connections are on left and right side (from left to right) + - Power connection are on front and back side (front or back) +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta +-- Techage Related Data +local TRD = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).techage end +local TRDN = function(node) return (minetest.registered_nodes[node.name] or {}).techage end + +local consumer = techage.consumer + +local function valid_power_dir(pos, power_dir, in_dir) + return power_dir == in_dir or power_dir == tubelib2.Turn180Deg[in_dir] +end + +local function start_node(pos, mem, state) + consumer.turn_power_on(pos, TRD(pos).power_consumption) +end + +local function stop_node(pos, mem, state) + consumer.turn_power_on(pos, 0) +end + +local function turn_on_clbk(pos, in_dir, sum) + local mem = tubelib2.get_mem(pos) + local trd = TRD(pos) + local state = trd.State:get_state(mem) + if sum <= 0 and state == techage.RUNNING then + trd.State:fault(pos, mem) + end +end + +local function prepare_tiles(tiles, stage, power_png) + local tbl = {} + for _,item in ipairs(tiles) do + if type(item) == "string" then + tbl[#tbl+1] = item:gsub("#", stage):gsub("{power}", power_png) + else + local temp = table.copy(item) + temp.image = temp.image:gsub("#", stage):gsub("{power}", power_png) + tbl[#tbl+1] = temp + end + end + return tbl +end + +function techage.register_consumer(base_name, inv_name, tiles, tNode) + local names = {} + for stage = 2,4 do + local name_pas = "techage:ta"..stage.."_"..base_name.."_pas" + local name_act = "techage:ta"..stage.."_"..base_name.."_act" + local name_def = "techage:ta"..stage.."_"..base_name.."_def" + local name_inv = "TA"..stage.." "..inv_name + names[#names+1] = name_pas + + local power_network = techage.Axle + local on_recv_message = tNode.tubing.on_recv_message + local power_png = 'techage_axle_clutch.png' + + if stage > 2 then + power_network = techage.ElectricCable + on_recv_message = function(pos, topic, payload) + return "unsupported" + end + power_png = 'techage_appl_hole_electric.png' + end + + local tState = techage.NodeStates:new({ + node_name_passive = name_pas, + node_name_active = name_act, + node_name_defect = name_def, + infotext_name = name_inv, + cycle_time = tNode.cycle_time, + standby_ticks = tNode.standby_ticks, + has_item_meter = tNode.has_item_meter, + aging_factor = tNode.aging_factor, + formspec_func = tNode.formspec, + start_node = start_node, + stop_node = stop_node, + }) + local tTechage = { + State = tState, + num_items = tNode.num_items[stage], + turn_on = turn_on_clbk, + read_power_consumption = consumer.read_power_consumption, + power_network = power_network, + power_side = "F", + valid_power_dir = valid_power_dir, + power_consumption = tNode.power_consumption[stage], + } + + tNode.groups.not_in_creative_inventory = 0 + + minetest.register_node(name_pas, { + description = name_inv, + tiles = prepare_tiles(tiles.pas, stage, power_png), + techage = tTechage, + + after_place_node = function(pos, placer, itemstack, pointed_thing) + local mem = consumer.after_place_node(pos, placer) + local meta = M(pos) + local node = minetest.get_node(pos) + meta:set_int("push_dir", techage.side_to_indir("L", node.param2)) + meta:set_int("pull_dir", techage.side_to_indir("R", node.param2)) + local number = "-" + if stage > 2 then + number = techage.add_node(pos, name_pas) + end + if tNode.after_place_node then + tNode.after_place_node(pos, placer, itemstack, pointed_thing) + end + TRD(pos).State:node_init(pos, mem, number) + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if tNode.after_dig_node then + tNode.after_dig_node(pos, oldnode, oldmetadata, digger) + end + techage.remove_node(pos) + TRDN(oldnode).State:after_dig_node(pos, oldnode, oldmetadata, digger) + consumer.after_dig_node(pos, oldnode) + end, + + after_tube_update = consumer.after_tube_update, + can_dig = tNode.can_dig, + on_rotate = screwdriver.disallow, + on_timer = tNode.node_timer, + on_receive_fields = tNode.on_receive_fields, + allow_metadata_inventory_put = tNode.allow_metadata_inventory_put, + allow_metadata_inventory_move = tNode.allow_metadata_inventory_move, + allow_metadata_inventory_take = tNode.allow_metadata_inventory_take, + + drop = "", + paramtype2 = "facedir", + groups = table.copy(tNode.groups), + is_ground_content = false, + sounds = tNode.sounds, + }) + + tNode.groups.not_in_creative_inventory = 1 + + minetest.register_node(name_act, { + description = name_inv, + tiles = prepare_tiles(tiles.act, stage, power_png), + techage = tTechage, + + after_tube_update = consumer.after_tube_update, + on_rotate = screwdriver.disallow, + on_timer = tNode.node_timer, + on_receive_fields = tNode.on_receive_fields, + allow_metadata_inventory_put = tNode.allow_metadata_inventory_put, + allow_metadata_inventory_move = tNode.allow_metadata_inventory_move, + allow_metadata_inventory_take = tNode.allow_metadata_inventory_take, + + paramtype2 = "facedir", + diggable = false, + groups = tNode.groups, + is_ground_content = false, + sounds = tNode.sounds, + }) + + minetest.register_node(name_def, { + description = name_inv, + tiles = prepare_tiles(tiles.def, stage, power_png), + techage = tTechage, + + after_place_node = function(pos, placer, itemstack, pointed_thing) + local mem = consumer.after_place_node(pos, placer) + local meta = M(pos) + local node = minetest.get_node(pos) + meta:set_int("push_dir", techage.side_to_indir("L", node.param2)) + meta:set_int("pull_dir", techage.side_to_indir("R", node.param2)) + local number = "-" + if stage > 2 then + number = techage.add_node(pos, name_pas) + end + if tNode.after_place_node then + tNode.after_place_node(pos, placer, itemstack, pointed_thing) + end + TRD(pos).State:defect(pos, mem) + end, + + after_tube_update = consumer.after_tube_update, + on_rotate = screwdriver.disallow, + on_receive_fields = tNode.on_receive_fields, + allow_metadata_inventory_put = tNode.allow_metadata_inventory_put, + allow_metadata_inventory_move = tNode.allow_metadata_inventory_move, + allow_metadata_inventory_take = tNode.allow_metadata_inventory_take, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if tNode.after_dig_node then + tNode.after_dig_node(pos, oldnode, oldmetadata, digger) + end + techage.remove_node(pos) + consumer.after_dig_node(pos, oldnode) + end, + + paramtype2 = "facedir", + groups = tNode.groups, + is_ground_content = false, + sounds = tNode.sounds, + }) + + techage.register_node(name_pas, {name_act, name_def}, tNode.tubing) + power_network:add_secondary_node_names({name_pas, name_act}) + end + return names[1], names[2], names[3] +end diff --git a/basis/node_states.lua b/basis/node_states.lua index 69fc134..42d68f4 100644 --- a/basis/node_states.lua +++ b/basis/node_states.lua @@ -406,6 +406,13 @@ function NodeStates:on_node_load(pos, not_start_timer) return end + -- wrong number? + local info = techage.get_node_info(number) + if not info or not info.pos or not vector.equals(pos, info.pos) then + swap_node(pos, "techage:defect_dummy") + return + end + -- state corrupt? local state = mem.techage_state if state == 0 then @@ -472,10 +479,10 @@ minetest.register_node("techage:defect_dummy", { tiles = { "techage_filling_ta2.png^techage_frame_ta2.png", "techage_filling_ta2.png^techage_frame_ta2.png", - "techage_filling_ta2.png^techage_frame_ta2.png^techage_defect.png", - "techage_filling_ta2.png^techage_frame_ta2.png^techage_defect.png", - "techage_filling_ta2.png^techage_frame_ta2.png^techage_defect.png", - "techage_filling_ta2.png^techage_frame_ta2.png^techage_defect.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png", }, drop = "", groups = {cracky=2, crumbly=2, choppy=2, not_in_creative_inventory=1}, diff --git a/init.lua b/init.lua index e299c05..a6cb66f 100644 --- a/init.lua +++ b/init.lua @@ -19,6 +19,7 @@ dofile(MP.."/basis/trowel.lua") -- hidden networks dofile(MP.."/basis/junction.lua") -- network junction box dofile(MP.."/basis/tubes.lua") -- tubelib replacement dofile(MP.."/basis/command.lua") -- tubelib replacement +dofile(MP.."/basis/consumer.lua") -- consumer base model -- Steam Engine dofile(MP.."/steam_engine/drive_axle.lua") @@ -44,5 +45,5 @@ dofile(MP.."/basic_machines/grinder.lua") --dofile(MP.."/fermenter/gasflare.lua") -dofile(MP.."/nodes/test.lua") +--dofile(MP.."/nodes/test.lua") --dofile(MP.."/mechanic/perf_test.lua") diff --git a/textures/techage_defect.png b/textures/techage_appl_defect.png similarity index 100% rename from textures/techage_defect.png rename to textures/techage_appl_defect.png diff --git a/textures/techage_appl_grinder.png b/textures/techage_appl_grinder.png new file mode 100644 index 0000000..87e5c58 Binary files /dev/null and b/textures/techage_appl_grinder.png differ diff --git a/textures/techage_appl_grinder4.png b/textures/techage_appl_grinder4.png new file mode 100644 index 0000000..11f8bd3 Binary files /dev/null and b/textures/techage_appl_grinder4.png differ diff --git a/textures/techage_appl_hole_electric.png b/textures/techage_appl_hole_electric.png new file mode 100644 index 0000000..916592e Binary files /dev/null and b/textures/techage_appl_hole_electric.png differ diff --git a/textures/techage_pusher.png b/textures/techage_appl_pusher.png similarity index 100% rename from textures/techage_pusher.png rename to textures/techage_appl_pusher.png diff --git a/textures/techage_pusher14.png b/textures/techage_appl_pusher14.png similarity index 100% rename from textures/techage_pusher14.png rename to textures/techage_appl_pusher14.png diff --git a/textures/techage_frame4_ta2_top.png b/textures/techage_frame4_ta2_top.png new file mode 100644 index 0000000..52f3a95 Binary files /dev/null and b/textures/techage_frame4_ta2_top.png differ diff --git a/textures/techage_frame4_ta3_top.png b/textures/techage_frame4_ta3_top.png new file mode 100644 index 0000000..e0866fd Binary files /dev/null and b/textures/techage_frame4_ta3_top.png differ diff --git a/textures/techage_frame4_ta4_top.png b/textures/techage_frame4_ta4_top.png new file mode 100644 index 0000000..38d61be Binary files /dev/null and b/textures/techage_frame4_ta4_top.png differ