From 72ef48a6d11e07610d58db1aec7577e29e52e5f9 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sun, 17 Mar 2019 15:33:13 +0100 Subject: [PATCH] Hammer and sieve added --- basic_machines/chest.lua | 278 +++++++++++++++++ basic_machines/distributor.lua | 2 +- basic_machines/gravelsieve.lua | 266 ++++++++++++++++ basic_machines/grinder.lua | 31 +- basic_machines/pusher.lua | 242 +++++---------- basis/consumer.lua | 51 +-- basis/trowel.lua | 7 +- electric/consumer.lua | 2 +- electric/electric_cable.lua | 2 +- electric/generator.lua | 2 +- fermenter/biogas_pipe.lua | 2 +- init.lua | 9 + intllib.lua | 45 +++ iron_age/gravelsieve.lua | 376 +++++++++++++++++++++++ iron_age/hammer.lua | 141 +++++++++ mod.conf | 4 +- steam_engine/battery.lua | 2 +- steam_engine/boiler.lua | 2 +- steam_engine/cylinder.lua | 2 +- steam_engine/drive_axle.lua | 2 +- steam_engine/firebox.lua | 2 +- steam_engine/flywheel.lua | 2 +- steam_engine/gearbox.lua | 2 +- steam_engine/steam_pipe.lua | 2 +- textures/techage_appl_sieve.png | Bin 0 -> 264 bytes textures/techage_appl_sieve4.png | Bin 359 -> 355 bytes textures/techage_appl_sieve4_top.png | Bin 0 -> 6442 bytes textures/techage_appl_sieve_top.png | Bin 0 -> 920 bytes textures/techage_compressed_gravel.png | Bin 0 -> 753 bytes textures/techage_frame_ta2_top.png | Bin 402 -> 399 bytes textures/techage_handsieve_gravel.png | Bin 0 -> 2253 bytes textures/techage_handsieve_sieve.png | Bin 0 -> 1562 bytes textures/techage_handsieve_top.png | Bin 0 -> 934 bytes textures/techage_tool_hammer_bronze.png | Bin 0 -> 1454 bytes textures/techage_tool_hammer_diamond.png | Bin 0 -> 1466 bytes textures/techage_tool_hammer_mese.png | Bin 0 -> 1418 bytes textures/techage_tool_hammer_steel.png | Bin 0 -> 1426 bytes 37 files changed, 1267 insertions(+), 209 deletions(-) create mode 100644 basic_machines/chest.lua create mode 100644 basic_machines/gravelsieve.lua create mode 100644 intllib.lua create mode 100644 iron_age/gravelsieve.lua create mode 100644 iron_age/hammer.lua create mode 100644 textures/techage_appl_sieve.png create mode 100644 textures/techage_appl_sieve4_top.png create mode 100644 textures/techage_appl_sieve_top.png create mode 100644 textures/techage_compressed_gravel.png create mode 100644 textures/techage_handsieve_gravel.png create mode 100644 textures/techage_handsieve_sieve.png create mode 100644 textures/techage_handsieve_top.png create mode 100644 textures/techage_tool_hammer_bronze.png create mode 100644 textures/techage_tool_hammer_diamond.png create mode 100644 textures/techage_tool_hammer_mese.png create mode 100644 textures/techage_tool_hammer_steel.png diff --git a/basic_machines/chest.lua b/basic_machines/chest.lua new file mode 100644 index 0000000..a072764 --- /dev/null +++ b/basic_machines/chest.lua @@ -0,0 +1,278 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + TA2/TA3/TA4 Chest + +]]-- + +-- 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("techage") +local I,_ = dofile(MP.."/intllib.lua") + +local PlayerActions = {} +local InventoryState = {} + + +local function store_action(pos, player, action, stack) + local meta = minetest.get_meta(pos) + local name = player and player:get_player_name() or "" + local number = meta:get_string("number") + local item = stack:get_name().." "..stack:get_count() + PlayerActions[number] = {name, action, item} +end + +local function send_off_command(pos) + local meta = minetest.get_meta(pos) + local dest_num = meta:get_string("dest_num") + local own_num = meta:get_string("number") + local owner = meta:get_string("owner") + techage.send_message(dest_num, owner, nil, "off", own_num) +end + + +local function send_command(pos) + local meta = minetest.get_meta(pos) + local dest_num = meta:get_string("dest_num") + if dest_num ~= "" then + local own_num = meta:get_string("number") + local owner = meta:get_string("owner") + techage.send_message(dest_num, owner, nil, "on", own_num) + minetest.after(1, send_off_command, pos) + end +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 + store_action(pos, player, "put", stack) + send_command(pos) + return stack:get_count() +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 + store_action(pos, player, "take", stack) + send_command(pos) + return stack:get_count() +end + +local function can_dig(pos, player) + if minetest.is_protected(pos, player:get_player_name()) then + return false + end + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("main") +end + +local function after_dig_node(pos, oldnode, oldmetadata, digger) + techage.remove_node(pos) +end + +local function formspec2() + return "size[9,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;main;0.5,0;8,4;]".. + "list[current_player;main;0.5,4.3;8,4;]".. + "listring[context;main]".. + "listring[current_player;main]" +end + +minetest.register_node("techage:chest_ta2", { + description = I("TA2 Protected Chest"), + tiles = { + -- up, down, right, left, back, front + "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_appl_chest_back_ta3.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_front_ta3.png", + }, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size('main', 32) + end, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + local number = techage.add_node(pos, "techage:chest_ta2") + meta:set_string("number", number) + meta:set_string("owner", placer:get_player_name()) + meta:set_string("formspec", formspec2()) + meta:set_string("infotext", I("TA2 Protected Chest").." "..number) + end, + + can_dig = can_dig, + after_dig_node = after_dig_node, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_take = allow_metadata_inventory_take, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + +local function formspec3() + return "size[10,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;main;0,0;10,4;]".. + "list[current_player;main;1,4.3;8,4;]".. + "listring[context;main]".. + "listring[current_player;main]" +end + +minetest.register_node("techage:chest_ta3", { + description = I("TA3 Protected Chest"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_front_ta3.png", + }, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size('main', 40) + end, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + local number = techage.add_node(pos, "techage:chest_ta3") + meta:set_string("number", number) + meta:set_string("owner", placer:get_player_name()) + meta:set_string("formspec", formspec3()) + meta:set_string("infotext", I("TA3 Protected Chest").." "..number) + end, + + can_dig = can_dig, + after_dig_node = after_dig_node, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_take = allow_metadata_inventory_take, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + +local function formspec4() + return "size[10,9]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;main;0,0;10,5;]".. + "list[current_player;main;1,5.3;8,4;]".. + "listring[context;main]".. + "listring[current_player;main]" +end + +minetest.register_node("techage:chest_ta4", { + description = I("TA4 Protected Chest"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta4.png^techage_frame_ta4_top.png", + "techage_filling_ta4.png^techage_frame_ta4.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png", + }, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size('main', 50) + end, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + local number = techage.add_node(pos, "techage:chest_ta4") + meta:set_string("number", number) + meta:set_string("owner", placer:get_player_name()) + meta:set_string("formspec", formspec4()) + meta:set_string("infotext", I("TA4 Protected Chest").." "..number) + end, + + can_dig = can_dig, + after_dig_node = after_dig_node, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_take = allow_metadata_inventory_take, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_craft({ + type = "shapeless", + output = "techage:chest_ta2", + recipe = {"default:chest", "techage:tubeS", "default:steel_ingot"} +}) + +techage.register_node("techage:chest_ta2", {"techage:chest_ta3", "techage:chest_ta4"}, { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.get_items(inv, "main", num) + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, + + on_recv_message = function(pos, topic, payload) + if topic == "state" then + local meta = minetest.get_meta(pos) + return techage.get_inv_state(meta, "main") + elseif topic == "player_action" then + local meta = minetest.get_meta(pos) + local number = meta:get_string("number") + return PlayerActions[number] + elseif topic == "set_numbers" then + if techage.check_numbers(payload) then + local meta = minetest.get_meta(pos) + meta:set_string("dest_num", payload) + local number = meta:get_string("number") + meta:set_string("infotext", I("TA2 Protected Chest").." "..number.." connected with "..payload) + return true + end + else + return "unsupported" + end + end, +}) diff --git a/basic_machines/distributor.lua b/basic_machines/distributor.lua index 1f28df9..a27f0e3 100644 --- a/basic_machines/distributor.lua +++ b/basic_machines/distributor.lua @@ -21,7 +21,7 @@ local N = minetest.get_node 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 MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local SRC_INV_SIZE = 8 diff --git a/basic_machines/gravelsieve.lua b/basic_machines/gravelsieve.lua new file mode 100644 index 0000000..867cedf --- /dev/null +++ b/basic_machines/gravelsieve.lua @@ -0,0 +1,266 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + TA2/TA3/TA4 Gravel Sieve, sieving gravel to find ores + +]]-- + +-- 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("techage") +local I,_ = dofile(MP.."/intllib.lua") + +local STANDBY_TICKS = 10 +local COUNTDOWN_TICKS = 10 +local CYCLE_TIME = 4 + +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:gravel]".. + "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;]".. + "list[current_player;main;0,4;8,4;]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4) +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 + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if listname == "src" then + return stack:get_count() + elseif listname == "dst" then + return 0 + end +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta: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 + + +-- determine ore based on the calculated probability +local function get_random_ore() + for ore, probability in pairs(techage.ore_probability) do + if math.random(probability) == 1 then + local item = ItemStack(ore) + return item + end + end +end + +local function sieving(pos, trd, mem, inv) + local gravel = ItemStack("default:gravel") + + if not inv:contains_item("src", gravel) then + trd.State:idle(pos, mem) + return + end + + local dst = get_random_ore() + if not dst then + -- move gravel or sieved gravel to dst + mem.gravel_cnt = (mem.gravel_cnt or 0) + 1 + if (mem.gravel_cnt % 2) == 0 then + dst = gravel + else + dst = ItemStack("techage:sieved_gravel") + end + end + if not inv:room_for_item("dst", dst) then + --trd.State:blocked(pos, mem) + trd.State:idle(pos, mem) + return + end + + inv:add_item("dst", dst) + inv:remove_item("src", gravel) + trd.State:keep_running(pos, mem, COUNTDOWN_TICKS) +end + +local function keep_running(pos, elapsed) + local mem = tubelib2.get_mem(pos) + local trd = TRD(pos) + local inv = M(pos):get_inventory() + sieving(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_sieve_top.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^techage_appl_sieve.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png", +} +tiles.act = { + -- up, down, right, left, back, front + { + image = "techage_appl_sieve4_top.png^techage_frame4_ta#_top.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 2.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^techage_appl_sieve.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png", +} +tiles.def = { + -- up, down, right, left, back, front + "techage_appl_sieve_top.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^techage_appl_sieve.png^techage_frame_ta#.png^techage_appl_defect.png", + "techage_filling_ta#.png^techage_appl_sieve.png^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 or in_dir == 5 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("gravelsieve", I("Gravel Sieve"), tiles, { + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, 8/16, -6/16}, + {-8/16, -8/16, 6/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16}, + { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + {-6/16, -8/16, -6/16, 6/16, 4/16, 6/16}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + }, + 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) + 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:steel_ingot", "tubelib:tubeS"}, + {"group:wood", "default:tin_ingot", "group:wood"}, + }, +}) diff --git a/basic_machines/grinder.lua b/basic_machines/grinder.lua index 646c3b9..2f947fa 100644 --- a/basic_machines/grinder.lua +++ b/basic_machines/grinder.lua @@ -20,7 +20,7 @@ local M = minetest.get_meta 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 MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local STANDBY_TICKS = 10 @@ -141,8 +141,8 @@ tiles.pas = { "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", + "techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png", } tiles.act = { -- up, down, right, left, back, front @@ -159,8 +159,8 @@ tiles.act = { "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", + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png", } tiles.def = { -- up, down, right, left, back, front @@ -168,8 +168,8 @@ tiles.def = { "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", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_defect.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_defect.png", } local tubing = { @@ -182,7 +182,7 @@ local tubing = { end, on_push_item = function(pos, in_dir, stack) local meta = minetest.get_meta(pos) - if meta:get_int("push_dir") == in_dir then + if meta:get_int("push_dir") == in_dir or in_dir == 5 then local inv = M(pos):get_inventory() return techage.put_items(inv, "src", stack) end @@ -212,6 +212,21 @@ local tubing = { local node_name_ta2, node_name_ta3, node_name_ta4 = techage.register_consumer("grinder", I("Grinder"), tiles, { + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, 8/16, -6/16}, + {-8/16, -8/16, 6/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16}, + { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + {-6/16, -8/16, -6/16, 6/16, 6/16, 6/16}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + }, cycle_time = CYCLE_TIME, standby_ticks = STANDBY_TICKS, has_item_meter = true, diff --git a/basic_machines/pusher.lua b/basic_machines/pusher.lua index 1fb6697..746ea89 100644 --- a/basic_machines/pusher.lua +++ b/basic_machines/pusher.lua @@ -30,7 +30,7 @@ local M = minetest.get_meta 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 -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local STANDBY_TICKS = 10 @@ -64,6 +64,7 @@ end local function on_rightclick(pos, node, clicker) local mem = tubelib2.get_mem(pos) if not minetest.is_protected(pos, clicker:get_player_name()) then + print("on_rightclick", TRD(pos).State:is_active(mem), mem.techage_state) if TRD(pos).State:is_active(mem) then TRD(pos).State:stop(pos, mem) else @@ -77,190 +78,101 @@ local function after_dig_node(pos, oldnode, oldmetadata, digger) TRDN(oldnode).State:after_dig_node(pos, oldnode, oldmetadata, digger) end -local function register_pusher(stage, num_items) - local State = techage.NodeStates:new({ - node_name_passive= "techage:ta"..stage.."_pusher", - node_name_active = "techage:ta"..stage.."_pusher_active", - node_name_defect = "techage:ta"..stage.."_pusher_defect", - infotext_name = "TA"..stage..I(" Pusher"), +local tiles = {} +-- '#' will be replaced by the stage number +-- '{power}' will be replaced by the power PNG +tiles.pas = { + "techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.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_appl_pusher.png^[transformR180]^techage_frame_ta#.png", + "techage_appl_pusher.png^techage_frame_ta#.png", +} +tiles.act = { + -- up, down, right, left, back, front + "techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.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", + { + image = "techage_appl_pusher14.png^[transformR180]^techage_frame14_ta#.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 2.0, + }, + }, + { + image = "techage_appl_pusher14.png^techage_frame14_ta#.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 2.0, + }, + }, +} +tiles.def = { + -- up, down, right, left, back, front + "techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.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_appl_pusher.png^[transformR180]^techage_frame_ta#.png^techage_appl_defect.png", + "techage_appl_pusher.png^techage_frame_ta#.png^techage_appl_defect.png", +} + +local tubing = { + is_pusher = true, -- is a pulling/pushing node + + 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("pusher", I("Pusher"), tiles, { cycle_time = CYCLE_TIME, standby_ticks = STANDBY_TICKS, has_item_meter = true, aging_factor = 10, - }) - - minetest.register_node("techage:ta"..stage.."_pusher", { - description = "TA"..stage..I(" Pusher"), - tiles = { - -- 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", - "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png^techage_appl_inp.png", - "techage_appl_pusher.png^[transformR180]^techage_frame_ta"..stage..".png", - "techage_appl_pusher.png^techage_frame_ta"..stage..".png", - }, - - techage = { - State = State, - num_items = num_items, - }, - + tubing = tubing, after_place_node = function(pos, placer) - local mem = tubelib2.init_mem(pos) + local mem = tubelib2.get_mem(pos) local meta = M(pos) local node = minetest.get_node(pos) meta:set_int("pull_dir", techage.side_to_outdir("L", node.param2)) meta:set_int("push_dir", techage.side_to_outdir("R", node.param2)) - local number = "-" - if stage > 2 then - number = techage.add_node(pos, "techage:ta"..stage.."_pusher") - end - TRD(pos).State:node_init(pos, mem, number) end, on_rightclick = on_rightclick, after_dig_node = after_dig_node, - on_timer = keep_running, + node_timer = keep_running, on_rotate = screwdriver.disallow, - - drop = "", - paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, is_ground_content = false, sounds = default.node_sound_wood_defaults(), + num_items = {0,2,6,18}, }) - minetest.register_node("techage:ta"..stage.."_pusher_active", { - description = "TA"..stage..I(" Pusher"), - tiles = { - -- 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", - "techage_filling_ta"..stage..".png^techage_frame_ta"..stage..".png^techage_appl_inp.png", - { - image = "techage_appl_pusher14.png^[transformR180]^techage_frame14_ta"..stage..".png", - backface_culling = false, - animation = { - type = "vertical_frames", - aspect_w = 32, - aspect_h = 32, - length = 2.0, - }, - }, - { - image = "techage_appl_pusher14.png^techage_frame14_ta"..stage..".png", - backface_culling = false, - animation = { - type = "vertical_frames", - aspect_w = 32, - aspect_h = 32, - length = 2.0, - }, - }, - }, - - techage = { - State = State, - num_items = num_items, - }, - - on_rightclick = on_rightclick, - after_dig_node = after_dig_node, - on_timer = keep_running, - on_rotate = screwdriver.disallow, - on_timer = keep_running, - - paramtype2 = "facedir", - diggable = false, - groups = {crumbly=0, not_in_creative_inventory=1}, - is_ground_content = false, - sounds = default.node_sound_wood_defaults(), - }) - - minetest.register_node("techage:ta"..stage.."_pusher_defect", { - description = "TA"..stage.." Pusher", - tiles = { - -- 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^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 = { - State = State, - }, - - after_place_node = function(pos, placer) - local mem = tubelib2.get_init(pos) - local number = "-" - if stage > 2 then - number = techage.add_node(pos, "techage:ta"..stage.."_pusher") - end - TRD(pos).State:node_init(pos, mem, number) - TRD(pos).State:defect(pos, mem) - end, - - after_dig_node = function(pos) - techage.remove_node(pos) - end, - - on_rotate = screwdriver.disallow, - - paramtype2 = "facedir", - groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1}, - is_ground_content = false, - sounds = default.node_sound_wood_defaults(), - }) - - if stage == 2 then - techage.register_node("techage:ta"..stage.."_pusher", - {"techage:ta"..stage.."_pusher_active", "techage:ta"..stage.."_pusher_defect"}, { - is_pusher = true, -- is a pulling/pushing node - - on_recv_message = function(pos, topic, payload) - return "unsupported" - 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, - }) - else - techage.register_node("techage:ta"..stage.."_pusher", - {"techage:ta"..stage.."_pusher_active", "techage:ta"..stage.."_pusher_defect"}, { - is_pusher = true, -- is a pulling/pushing node - - 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, - }) - end -end - -register_pusher(2, 2) -register_pusher(3, 6) -register_pusher(4, 18) - minetest.register_craft({ - output = "techage:ta2_pusher 2", + output = node_name_ta2.." 2", recipe = { {"group:wood", "wool:dark_green", "group:wood"}, {"tubelib:tubeS", "default:mese_crystal", "tubelib:tubeS"}, diff --git a/basis/consumer.lua b/basis/consumer.lua index 740c17c..36e4eab 100644 --- a/basis/consumer.lua +++ b/basis/consumer.lua @@ -29,7 +29,7 @@ local TRDN = function(node) return (minetest.registered_nodes[node.name] or {}). 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] + return true end local function start_node(pos, mem, state) @@ -72,27 +72,24 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) 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 - -- No power needed? - if not tNode.power_consumption then - start_node = nil - stop_node = nil - turn_on_clbk = nil - valid_power_dir = nil - power_network = nil - tNode.power_consumption = {0,0,0,0} -- needed later - else + local power_network + local power_png = 'techage_axle_clutch.png' + local power_used = tNode.power_consumption ~= nil + -- power needed? + if power_used then + if stage > 2 then + power_network = techage.ElectricCable + power_png = 'techage_appl_hole_electric.png' + else + power_network = techage.Axle + end power_network:add_secondary_node_names({name_pas, name_act}) end @@ -106,18 +103,18 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) has_item_meter = tNode.has_item_meter, aging_factor = tNode.aging_factor, formspec_func = tNode.formspec, - start_node = start_node, - stop_node = stop_node, + start_node = power_used and start_node or nil, + stop_node = power_used and stop_node or nil, }) local tTechage = { State = tState, num_items = tNode.num_items[stage], - turn_on = turn_on_clbk, + turn_on = power_used and turn_on_clbk or nil, read_power_consumption = consumer.read_power_consumption, - power_network = power_network, + power_network = power_used and power_network or nil, power_side = "F", - valid_power_dir = valid_power_dir, - power_consumption = tNode.power_consumption[stage], + valid_power_dir = power_used and valid_power_dir or nil, + power_consumption = power_used and tNode.power_consumption[stage] or {0,0,0,0}, } tNode.groups.not_in_creative_inventory = 0 @@ -126,6 +123,9 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) description = name_inv, tiles = prepare_tiles(tiles.pas, stage, power_png), techage = tTechage, + drawtype = tNode.drawtype, + node_box = tNode.node_box, + selection_box = tNode.selection_box, after_place_node = function(pos, placer, itemstack, pointed_thing) local mem @@ -164,6 +164,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) on_rotate = screwdriver.disallow, on_timer = tNode.node_timer, on_receive_fields = tNode.on_receive_fields, + on_rightclick = tNode.on_rightclick, 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, @@ -184,11 +185,15 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) description = name_inv, tiles = prepare_tiles(tiles.act, stage, power_png), techage = tTechage, + drawtype = tNode.drawtype, + node_box = tNode.node_box, + selection_box = tNode.selection_box, after_tube_update = consumer.after_tube_update, on_rotate = screwdriver.disallow, on_timer = tNode.node_timer, on_receive_fields = tNode.on_receive_fields, + on_rightclick = tNode.on_rightclick, 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, @@ -207,6 +212,9 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) description = name_inv, tiles = prepare_tiles(tiles.def, stage, power_png), techage = tTechage, + drawtype = tNode.drawtype, + node_box = tNode.node_box, + selection_box = tNode.selection_box, after_place_node = function(pos, placer, itemstack, pointed_thing) local mem = consumer.after_place_node(pos, placer) @@ -227,6 +235,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode) after_tube_update = consumer.after_tube_update, on_rotate = screwdriver.disallow, on_receive_fields = tNode.on_receive_fields, + on_rightclick = tNode.on_rightclick, 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, diff --git a/basis/trowel.lua b/basis/trowel.lua index 344be43..3553530 100644 --- a/basis/trowel.lua +++ b/basis/trowel.lua @@ -18,9 +18,11 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") +-- used by other tools: dug_node[player_name] = pos +techage.dug_node = {} -- Overridden method of tubelib2! function techage.get_primary_node_param2(pos, dir) @@ -102,11 +104,14 @@ minetest.register_node("techage:trowel", { }) minetest.register_on_dignode(function(pos, oldnode, digger) + if not digger then return end -- If hidden nodes are arround, the removed one was probably -- a hidden node, too. if other_hidden_nodes(pos, "techage_hidden_nodename") then -- test both hidden networks techage.ElectricCable:after_dig_node(pos, oldnode, digger) techage.BiogasPipe:after_dig_node(pos, oldnode, digger) + else + techage.dug_node[digger:get_player_name()] = pos end end) diff --git a/electric/consumer.lua b/electric/consumer.lua index 0cf38c9..7a94db0 100644 --- a/electric/consumer.lua +++ b/electric/consumer.lua @@ -4,7 +4,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local POWER_CONSUMPTION = 2 diff --git a/electric/electric_cable.lua b/electric/electric_cable.lua index b0ecea9..2fe500b 100644 --- a/electric/electric_cable.lua +++ b/electric/electric_cable.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") diff --git a/electric/generator.lua b/electric/generator.lua index b5be9ad..20303e4 100644 --- a/electric/generator.lua +++ b/electric/generator.lua @@ -4,7 +4,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local STANDBY_TICKS = 4 diff --git a/fermenter/biogas_pipe.lua b/fermenter/biogas_pipe.lua index e9436f4..1854203 100644 --- a/fermenter/biogas_pipe.lua +++ b/fermenter/biogas_pipe.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") diff --git a/init.lua b/init.lua index bccecc1..149d58f 100644 --- a/init.lua +++ b/init.lua @@ -6,6 +6,7 @@ techage = { techage.max_num_forceload_blocks = tonumber(minetest.setting_get("techage_max_num_forceload_blocks")) or 12 techage.basalt_stone_enabled = minetest.setting_get("techage_basalt_stone_enabled") == "true" techage.machine_aging_value = tonumber(minetest.setting_get("techage_machine_aging_value")) or 100 +techage.ore_rarity = tonumber(minetest.setting_get("techage_ore_rarity")) or 1 local MP = minetest.get_modpath("techage") @@ -21,6 +22,11 @@ dofile(MP.."/basis/tubes.lua") -- tubelib replacement dofile(MP.."/basis/command.lua") -- tubelib replacement dofile(MP.."/basis/consumer.lua") -- consumer base model +-- Iron Age +dofile(MP.."/iron_age/gravelsieve.lua") +dofile(MP.."/iron_age/hammer.lua") + + -- Steam Engine dofile(MP.."/steam_engine/drive_axle.lua") dofile(MP.."/steam_engine/steam_pipe.lua") @@ -37,10 +43,13 @@ dofile(MP.."/electric/test.lua") dofile(MP.."/electric/generator.lua") dofile(MP.."/electric/consumer.lua") +-- Basic Machines dofile(MP.."/basic_machines/pusher.lua") dofile(MP.."/basic_machines/legacy_nodes.lua") dofile(MP.."/basic_machines/grinder.lua") dofile(MP.."/basic_machines/distributor.lua") +dofile(MP.."/basic_machines/gravelsieve.lua") +dofile(MP.."/basic_machines/chest.lua") --dofile(MP.."/fermenter/biogas_pipe.lua") diff --git a/intllib.lua b/intllib.lua new file mode 100644 index 0000000..6669d72 --- /dev/null +++ b/intllib.lua @@ -0,0 +1,45 @@ + +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/iron_age/gravelsieve.lua b/iron_age/gravelsieve.lua new file mode 100644 index 0000000..4ae7461 --- /dev/null +++ b/iron_age/gravelsieve.lua @@ -0,0 +1,376 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + TA2/TA3/TA4 Gravel Sieve, sieving gravel to find ores + +]]-- + +-- 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("techage") +local I,_ = dofile(MP.."/intllib.lua") + +-- Increase the probability over the natural occurrence +local PROBABILITY_FACTOR = 3 + +-- Ore probability table (1/n) +techage.ore_probability = { +} + +-- collect all registered ores and calculate the probability +local function add_ores() + for _,item in pairs(minetest.registered_ores) do + if minetest.registered_nodes[item.ore] then + local drop = minetest.registered_nodes[item.ore].drop + if type(drop) == "string" + and drop ~= item.ore + and drop ~= "" + and item.ore_type == "scatter" + and item.wherein == "default:stone" + and item.clust_scarcity ~= nil and item.clust_scarcity > 0 + and item.clust_num_ores ~= nil and item.clust_num_ores > 0 + and item.y_max ~= nil and item.y_min ~= nil then + local probability = (techage.ore_rarity / PROBABILITY_FACTOR) * item.clust_scarcity / + (item.clust_num_ores * ((item.y_max - item.y_min) / 65535)) + if techage.ore_probability[drop] == nil then + techage.ore_probability[drop] = probability + else + -- harmonic sum + techage.ore_probability[drop] = 1.0 / ((1.0 / techage.ore_probability[drop]) + + (1.0 / probability)) + end + end + end + end + local overall_probability = 0.0 + for name,probability in pairs(techage.ore_probability) do + minetest.log("info", string.format("[techage] %-32s %u", name, probability)) + overall_probability = overall_probability + 1.0/probability + end + minetest.log("info", string.format("[techage] Overall probability %g", overall_probability)) +end + +minetest.after(1, add_ores) + +local sieve_formspec = + "size[8,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;src;1,1.5;1,1;]".. + "image[3,1.5;1,1;techage_form_arrow.png]".. + "list[context;dst;4,0;4,4;]".. + "list[current_player;main;0,4.2;8,4;]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]" + + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if listname == "src" then + return stack:get_count() + elseif listname == "dst" then + return 0 + end +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta: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 + +-- handle the sieve animation +local function swap_node(pos, meta, start) + local node = minetest.get_node(pos) + local idx = meta:get_int("idx") + if start then + if idx == 3 then + idx = 0 + end + else + idx = (idx + 1) % 4 + end + meta:set_int("idx", idx) + node.name = meta:get_string("node_name")..idx + minetest.swap_node(pos, node) + return idx == 3 +end + +-- place ores to dst according to the calculated probability +local function random_ore(inv, src) + local num + for ore, probability in pairs(techage.ore_probability) do + if math.random(probability) == 1 then + local item = ItemStack(ore) + if inv:room_for_item("dst", item) then + inv:add_item("dst", item) + return true -- ore placed + end + end + end + return false -- gravel has to be moved +end + + +local function add_gravel_to_dst(meta, inv) + -- maintain a counter for gravel kind selection + local gravel_cnt = meta:get_int("gravel_cnt") + 1 + meta:set_int("gravel_cnt", gravel_cnt) + + if (gravel_cnt % 2) == 0 then -- gravel or sieved gravel? + inv:add_item("dst", ItemStack("default:gravel")) -- add to dest + else + inv:add_item("dst", ItemStack("techage:sieved_gravel")) -- add to dest + end +end + + +-- move gravel and ores to dst +local function move_src2dst(meta, pos, inv, src, dst) + if inv:room_for_item("dst", dst) and inv:contains_item("src", src) then + local res = swap_node(pos, meta, false) + if res then -- time to move one item? + if src:get_name() == "default:gravel" then -- will we find ore? + if not random_ore(inv, src) then -- no ore found? + add_gravel_to_dst(meta, inv) + end + else + inv:add_item("dst", ItemStack("techage:sieved_gravel")) -- add to dest + end + inv:remove_item("src", src) + end + return true -- process finished + end + return false -- process still running +end + +-- timer callback, alternatively called by on_punch +local function sieve_node_timer(pos, elapsed) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local gravel = ItemStack("default:gravel") + local gravel_sieved = ItemStack("techage:sieved_gravel") + + if move_src2dst(meta, pos, inv, gravel) then + return true + elseif move_src2dst(meta, pos, inv, gravel_sieved) then + return true + else + minetest.get_node_timer(pos):stop() + return false + end +end + + +for idx = 0,4 do + local nodebox_data = { + { -8/16, -8/16, -8/16, 8/16, 4/16, -6/16 }, + { -8/16, -8/16, 6/16, 8/16, 4/16, 8/16 }, + { -8/16, -8/16, -8/16, -6/16, 4/16, 8/16 }, + { 6/16, -8/16, -8/16, 8/16, 4/16, 8/16 }, + { -6/16, -2/16, -6/16, 6/16, 8/16, 6/16 }, + } + nodebox_data[5][5] = (8 - 2*idx) / 16 + + local node_name + local description + local tiles_data + local tube_info + local not_in_creative_inventory + node_name = "techage:sieve" + description = "Gravel Sieve" + tiles_data = { + -- up, down, right, left, back, front + "techage_handsieve_gravel.png", + "techage_handsieve_gravel.png", + "techage_handsieve_sieve.png", + "techage_handsieve_sieve.png", + "techage_handsieve_sieve.png", + "techage_handsieve_sieve.png", + } + + if idx == 3 then + tiles_data[1] = "techage_handsieve_top.png" + not_in_creative_inventory = 0 + else + not_in_creative_inventory = 1 + end + + + minetest.register_node(node_name..idx, { + description = description, + tiles = tiles_data, + drawtype = "nodebox", + drop = node_name, + + tube = tube_info, -- NEW + + node_box = { + type = "fixed", + fixed = nodebox_data, + }, + selection_box = { + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, 4/16, 8/16 }, + }, + + on_timer = sieve_node_timer, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_int("idx", idx) -- for the 4 sieve phases + meta:set_int("gravel_cnt", 0) -- counter to switch between gravel and sieved gravel + meta:set_string("node_name", node_name) + meta:set_string("formspec", sieve_formspec) + local inv = meta:get_inventory() + inv:set_size('src', 1) + inv:set_size('dst', 16) + end, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", I("TA1 Gravel Sieve")) + end, + + on_metadata_inventory_move = function(pos) + local meta = minetest.get_meta(pos) + swap_node(pos, meta, true) + end, + + on_metadata_inventory_take = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if inv:is_empty("src") then + -- sieve should be empty + meta:set_int("idx", 2) + swap_node(pos, meta, false) + meta:set_int("gravel_cnt", 0) + end + end, + + on_metadata_inventory_put = function(pos) + local meta = minetest.get_meta(pos) + swap_node(pos, meta, true) + end, + + on_punch = function(pos, node, puncher, pointed_thing) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if inv:is_empty("dst") and inv:is_empty("src") then + minetest.node_punch(pos, node, puncher, pointed_thing) + else + sieve_node_timer(pos, 0) + end + end, + + on_dig = function(pos, node, puncher, pointed_thing) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if inv:is_empty("dst") and inv:is_empty("src") then + minetest.node_dig(pos, node, puncher, pointed_thing) + end + end, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, + + paramtype = "light", + sounds = default.node_sound_wood_defaults(), + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy=2, cracky=1, not_in_creative_inventory=not_in_creative_inventory}, + drop = node_name.."3", + }) +end + +minetest.register_node("techage:sieved_gravel", { + description = I("Sieved Gravel"), + tiles = {"default_gravel.png"}, + groups = {crumbly=2, falling_node=1, not_in_creative_inventory=1}, + sounds = default.node_sound_gravel_defaults(), +}) + +minetest.register_node("techage:compressed_gravel", { + description = I("Compressed Gravel"), + tiles = {"techage_compressed_gravel.png"}, + groups = {cracky=2, crumbly = 2, cracky = 2}, + sounds = default.node_sound_gravel_defaults(), +}) + +minetest.register_craft({ + output = "techage:sieve", + recipe = { + {"group:wood", "", "group:wood"}, + {"group:wood", "default:steel_ingot", "group:wood"}, + {"group:wood", "", "group:wood"}, + }, +}) + +minetest.register_craft({ + output = "techage:auto_sieve", + type = "shapeless", + recipe = { + "techage:sieve", "default:mese_crystal", "default:mese_crystal", + }, +}) + +minetest.register_craft({ + output = "techage:compressed_gravel", + recipe = { + {"techage:sieved_gravel", "techage:sieved_gravel"}, + {"techage:sieved_gravel", "techage:sieved_gravel"}, + }, +}) + +minetest.register_craft({ + type = "cooking", + output = "default:cobble", + recipe = "techage:compressed_gravel", + cooktime = 10, +}) + +minetest.register_alias("techage:sieve", "techage:sieve3") +minetest.register_alias("techage:auto_sieve", "techage:auto_sieve3") + +-- adaption to Circular Saw +--if minetest.get_modpath("moreblocks") then + +-- stairsplus:register_all("techage", "compressed_gravel", "techage:compressed_gravel", { +-- description= I("Compressed Gravel"), +-- groups={cracky=2, crumbly=2, choppy=2, not_in_creative_inventory=1}, +-- tiles = {"techage_compressed_gravel.png"}, +-- sounds = default.node_sound_stone_defaults(), +-- }) +--end + + diff --git a/iron_age/hammer.lua b/iron_age/hammer.lua new file mode 100644 index 0000000..62a12a6 --- /dev/null +++ b/iron_age/hammer.lua @@ -0,0 +1,141 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + Hammer to convert stone into gravel + +]]-- + +-- Load support for intllib. +local MP = minetest.get_modpath("techage") +local I,_ = dofile(MP.."/intllib.lua") + +local function handler(player_name, node, itemstack, digparams) + local pos = techage.dug_node[player_name] + if not pos then return end + + if minetest.is_protected(pos, player_name) then + minetest.record_protection_violation(pos, player_name) + return + end + + if minetest.get_item_group(node.name, "stone") > 0 then + node.name = "default:gravel" + minetest.swap_node(pos, node) + end +end + +minetest.register_tool("techage:hammer_bronze", { + description = I("Bronze Hammer (converts stone into gravel)"), + inventory_image = "techage_tool_hammer_bronze.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + cracky = {times={[1]=5.00, [2]=2.0, [3]=1.0}, uses=30, maxlevel=2}, + }, + damage_groups = {fleshy=4}, + }, + sound = {breaks = "default_tool_breaks"}, + after_use = function(itemstack, user, node, digparams) + minetest.after(0.05, handler, user:get_player_name(), node) + itemstack:add_wear(digparams.wear) + return itemstack + end, +}) + +minetest.register_tool("techage:hammer_steel", { + description = I("Steel Hammer (converts stone into gravel)"), + inventory_image = "techage_tool_hammer_steel.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + cracky = {times={[1]=4.00, [2]=1.60, [3]=0.80}, uses=30, maxlevel=2}, + }, + damage_groups = {fleshy=4}, + }, + sound = {breaks = "default_tool_breaks"}, + after_use = function(itemstack, user, node, digparams) + minetest.after(0.05, handler, user:get_player_name(), node) + itemstack:add_wear(digparams.wear) + return itemstack + end, +}) + +minetest.register_tool("techage:hammer_mese", { + description = I("Mese Hammer (converts stone into gravel)"), + inventory_image = "techage_tool_hammer_mese.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=3, + groupcaps={ + cracky = {times={[1]=2.4, [2]=1.2, [3]=0.60}, uses=40, maxlevel=3}, + }, + damage_groups = {fleshy=5}, + }, + sound = {breaks = "default_tool_breaks"}, + after_use = function(itemstack, user, node, digparams) + minetest.after(0.05, handler, user:get_player_name(), node) + itemstack:add_wear(digparams.wear) + return itemstack + end, +}) + +minetest.register_tool("techage:hammer_diamond", { + description = I("Diamond Hammer (converts stone into gravel)"), + inventory_image = "techage_tool_hammer_diamond.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=3, + groupcaps={ + cracky = {times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=40, maxlevel=3}, + }, + damage_groups = {fleshy=5}, + }, + sound = {breaks = "default_tool_breaks"}, + after_use = function(itemstack, user, node, digparams) + minetest.after(0.05, handler, user:get_player_name(), node) + itemstack:add_wear(digparams.wear) + return itemstack + end, +}) + +minetest.register_craft({ + output = "techage:hammer_bronze", + recipe = { + {"default:bronze_ingot", "group:stick", "default:bronze_ingot"}, + {"default:bronze_ingot", "group:stick", "default:bronze_ingot"}, + {"", "group:stick", ""}, + } +}) +minetest.register_craft({ + output = "techage:hammer_steel", + recipe = { + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"", "group:stick", ""}, + } +}) +minetest.register_craft({ + output = "techage:hammer_mese", + recipe = { + {"default:mese_crystal", "group:stick", "default:mese_crystal"}, + {"default:mese_crystal", "group:stick", "default:mese_crystal"}, + {"", "group:stick", ""}, + } +}) +minetest.register_craft({ + output = "techage:hammer_diamond", + recipe = { + {"default:diamond", "group:stick", "default:diamond"}, + {"default:diamond", "group:stick", "default:diamond"}, + {"", "group:stick", ""}, + } +}) diff --git a/mod.conf b/mod.conf index 6f5624b..95386aa 100644 --- a/mod.conf +++ b/mod.conf @@ -1 +1,3 @@ -name = techage \ No newline at end of file +name = techage +depends = default, tubelib2, basic_materials +description = Hello World! \ No newline at end of file diff --git a/steam_engine/battery.lua b/steam_engine/battery.lua index 5a194d1..8feac0e 100644 --- a/steam_engine/battery.lua +++ b/steam_engine/battery.lua @@ -4,7 +4,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local STANDBY_TICKS = 4 diff --git a/steam_engine/boiler.lua b/steam_engine/boiler.lua index d01e2ec..c3e669c 100644 --- a/steam_engine/boiler.lua +++ b/steam_engine/boiler.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local CYCLE_TIME = 4 diff --git a/steam_engine/cylinder.lua b/steam_engine/cylinder.lua index f0edf35..72e0334 100644 --- a/steam_engine/cylinder.lua +++ b/steam_engine/cylinder.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local POWER_CONSUMPTION = 8 diff --git a/steam_engine/drive_axle.lua b/steam_engine/drive_axle.lua index c7d4cd3..3530330 100644 --- a/steam_engine/drive_axle.lua +++ b/steam_engine/drive_axle.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") diff --git a/steam_engine/firebox.lua b/steam_engine/firebox.lua index 0554ae6..6f88ee1 100644 --- a/steam_engine/firebox.lua +++ b/steam_engine/firebox.lua @@ -20,7 +20,7 @@ local M = minetest.get_meta 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 MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local CYCLE_TIME = 2 diff --git a/steam_engine/flywheel.lua b/steam_engine/flywheel.lua index d47d5e8..74bf475 100644 --- a/steam_engine/flywheel.lua +++ b/steam_engine/flywheel.lua @@ -20,7 +20,7 @@ local M = minetest.get_meta 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 MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local STANDBY_TICKS = 4 diff --git a/steam_engine/gearbox.lua b/steam_engine/gearbox.lua index 79b583c..027c660 100644 --- a/steam_engine/gearbox.lua +++ b/steam_engine/gearbox.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") local POWER_CONSUMPTION = 1 diff --git a/steam_engine/steam_pipe.lua b/steam_engine/steam_pipe.lua index 6be9892..adb2ea4 100644 --- a/steam_engine/steam_pipe.lua +++ b/steam_engine/steam_pipe.lua @@ -18,7 +18,7 @@ local P = minetest.string_to_pos local M = minetest.get_meta -- Load support for intllib. -local MP = minetest.get_modpath("tubelib2") +local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") diff --git a/textures/techage_appl_sieve.png b/textures/techage_appl_sieve.png new file mode 100644 index 0000000000000000000000000000000000000000..c0d6515d56d898159f528c8fe6d0485200e455e2 GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*HqnfCnqN$FEKH3kLpED zAd9gi$S;_|;n|He5GTpo-G!lpRn`N@;VkfoEM{Qf76xHPhFNnYfP(BLp1!W^kD0ke z#RYd(|6T+XD)n@643W5;9Kp)U)5DYSpdq2fiBU{*4bK9_1h(s|Lb(s{tPNcq)*zX{ z-N2(Ju$b|L0P9TYrZW%z|F<_WVK|Y%W+>yZ%YkP@+3)`gfm(!x*{`hY>to|s?9F^A w;Zab7(F~IXSyL>4Smc3UuEM3}4GD}4`K>FVdQ&MBb@0E_)g&j0`b literal 0 HcmV?d00001 diff --git a/textures/techage_appl_sieve4.png b/textures/techage_appl_sieve4.png index 242b85e1f4c79a4c939b837eaba700e49d1e2bea..deaa6f7a6a1f11fb5cd0de5da6fe53d57c28ffbf 100644 GIT binary patch delta 319 zcmV-F0l@y}0^z>%&`Cr=R5;7U zlCciLAP|NTm!^x8d&5MSd;>c>Ig}Vj7oUSLHQn7Cr-t|G^B^2oG!c!VCcWuPfII## zM+_EO5vckJ5-V|(1lI(hG^Pg-#tZ;3zybB39Bh5x<`p*9N_lj!_E7s*9^m=jdCCTW z(gJ6-tqRcb0JN+SD91ajz&ospUsXQ_j9UKaCxRFPI2|f&EZ0w~F<`H81e;-ODL-$b z;%ZICa{Vw7lVZcJ%QxmmU(aI*$aV|(`DiTHkLFWk+yr``VNA-?;d1-BKM&4a$Zv4Y RmnQ%K002ovPDHLkV1mEPe?i#p8)FR=Ae)JV8 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 literal 0 HcmV?d00001 diff --git a/textures/techage_appl_sieve_top.png b/textures/techage_appl_sieve_top.png new file mode 100644 index 0000000000000000000000000000000000000000..d54fe6385c16b2f5be694347728e8b2542cee93d GIT binary patch literal 920 zcmV;J184k+P)I_&ND=&p6xyZQgQ-=ph1eXqXXqr3JDd;QscyI|ki;T6g1 z$q$##P;V`x-3rxU!1sHn?e6X_cfa-Zb?)c=&1X}|>dB4IU&AC3j^CoOG-m7fC+xkK z-~aQm$#u!<$@ZsjkcNHy#z{mpm%iS&W&HWw`-QVBlGT%IAHINJZ=$rzG|}uFK3?hs zPX6(gWc6g{v)4(Y2&E0J6~#9I8yYTauOPxTs|E(CS(30TPSCQ)8PN^Pv=lNtFM2qIYqvIXPf^Xp*cx%HKKk(3Q1yOqO99SFtA|{#QFrFC$Q0&cC%PEEZUdP uhIu^|MPo*jh$N0kqfy~(c-#z`*ZU6z=f^Z|0reaJ0000t`6oBEqoWi?&|@5%XjFQ@lg zx-0^D9h1~dfx-QGiE_tSmTbd5=uq%OlEn-qgprP3kZXJ4Aw{4C|I=BIOJvLqDxxz} z&iJ6Gj&-RH;2)N5#FMEX4&hk7pR)w>#=n?)v&oyXSrRBnXA)97aXFuL>Why2rE*$3 z&*(|-JPx~;7Q^WlH|o;henL^&U0mN{))oZijQrO->Ijjj6v`X$)bPk8Arfcw-+U*= ziV2b@!%2Indr7pa+FE|GM~tc<7_6x*)#sqUt7v$HX`~fUeGdAdru+y2rXO}P?Di}~ zIv(0-PTXf#&G^tV+bw$j`@9uoqx-Ib@%ohml7kPV8UtQc>BT!(_T*W+`j%H9smb$- zmL3bqEc;`u#?_#=49tl)Adi{j)Qs0qjQ#3q@Yu)V1D~K9m57U>oR?-WtJ?*^WuX$M zg_&c&m1&1~@K@hy0&Hr8+{NR##wRl%zuPs~Hs0|CQ_5~4K49{@gkR={tktpXf jPs0`IbpH}Zk?cPK);A4q)&$uI00000NkvXXu0mjfy*X6m?RK_=y0002(Nkle)J8y(A5QOKq_;I9O8$xYtpyrXI=8#Bz5S03KC*@}c zlx9t~^CxR|b_VpIpbFa>6Qmv*hs#RYqGn4om0zJ;k=#r*hK<6OUPqsdFytgjA+_^P zIU(?Tg3U0X^BnXw6mighba)>*NG4<}2iXGUIM6NjMQq+0kmaBgC(-?N5?x_52dajQ zfrBqN$Qzhwi&3bi$oePBg@emCd}Lj9(2;fBLq>V*hy2gue#%2eqQ*f)AT;=iYRCtW zAnl~FP7n#@j&9Rz>E^VZ^N;&qw?%aen-!bCPW{oXm8#gk*RNg|9P$?y>5gs5QHahki5d$K2om@ zM{R7N<|jwZA(8qZD0Os^^4JNA6xk?Kep=0rX22ipWno&ay--7AaauWBxa%jl93nyp|#LRn{}CBprVK*NB}Jv{yCv9BRHe*{g3^B96;Lbiq=TOe%+ zR12aIJU3tyf{qTR=kaK|LaPwS8X^W3t_VTiKu2G+L^VaxUr{b0IK9I~(Pak}MOQsU z)CZe?`nVnX5Rs|2pa}Q|U(pQt047#eXk&?)q}{hov!$EUcFtdJzuOko)o+G2cbWQq jTO(xgb6$V;7qsgei4jU*etVA500000NkvXXu0mjfHA#zo diff --git a/textures/techage_handsieve_gravel.png b/textures/techage_handsieve_gravel.png new file mode 100644 index 0000000000000000000000000000000000000000..8b0597aafe32f33b4f97f69c680fb33eb8004d72 GIT binary patch literal 2253 zcmV;;2r~DHP)%kWyVgJcQzLkw7o zV<(0qOWjSf$>LD+TzP0&k=X{)@N3}*PJsoU@B6gBefr0)Z5s?jA$5Z=+M|?%W!V&Y zh3oam_Djsc94Tt{>kV$-MQd}iN+(PThOU9*jUIFd@IFuMlZstjVJH)6m}GfNU6r(T zfn_V|vc&2SX!3xzF6sLdG)>ZW0*#KQX=vN#!FR_z-E&PeIuJVEFe6VKbVDKA7-0-( zn+zchEYH7t`=+Lo60M1_-4W-uO;r{M**@sb6Wxz^!ZvD@-a)w~Nk`C@bX^DL6irC{ zsi3GOnkMmvDUQ8IDhs`T!NAYaq=D3p2j3m@^iEg^O(K+yCIo+Z;SeV=yTbyn?=ti} zOcRP?!R`=ImKD8Tie;LNeUH2-sTx7|MNQAu34+%&ZHo{(yZt{g44upKGZw2`%Btqi zfAD|A6G@byNrfhKEMr4nmOOv{45buVRxq86*aQJe8Au^eN}&v$+fBe?wINP2Zf=&i zj?L-(oV+Lj4d_rxQ8yin)ta_#acqZUo)}IiXp{)4qa25!*Fy-&$;79ln zR5iA3Q&$y5S)u{U+YOebIOd7sus~NfZ55NIF=<{Rgp3NxB5`W;aJH!-ag{HxLHbEIW zNsd7CEkC;q_gTG$+e4k~kqRN}fLX2+Oj$TC8a5iZn^+=-4L}P1A6G(npg& zVZyQRadopo*LCJ66NZBxwq>Jf8sEKo!{T;LRaNv{8^<mfb_dWj#v>okH5qyKI}zP8;nimuZqH@AKhSd=T-QZvuv%|<{OFu8ilOTO z2&0tcI>2~j;5rT$7Z097!5pnu0ObwqD+g`dW)_b^eUe$ zv`tH1RJ?j~P1iQKmch5Lu9zG`o_zcPFTeUXmSr;V`uykhg2i%!kdooFJ7|Uhn&u)><$sr z$=g1$SRj$i=X0FFjLBK=z6ajrxodN~*^%W1+e63)m*;3g62~!N6p@z|mSvNdHU6MS zlw=&DgfuIVQZSp0P^RMSbb^$Ub+D(doB!X49$j8ApN$C*2OP&?etLqGI?%D*ZfQD= z$z;m+S2tYWESdNNf?dS<>6DA}IdPIP@_p99mMDrbm7-}{s`{=^9P{+zu)yjMXsei_ zmb`uw|1ZyNhwJ5_u;!dUvIW7Z`TaG0sr{wYfMwIKZJbt z`RBZR`I3?EadmTxZs^QUrVIyt9NR_{cYWfRr~UQQKXsO^kcNpSB*E?L2W`VJ3V+sy z>`=VV6F-QdO&2s(@!)Ovb2sEMPtWs=x+-zq9$lF-8a!+pKJ@N*8y@q-u^1k@4S(*2 bJm&ouLYk5MNRut700000NkvXXu0mjfJl-Zr literal 0 HcmV?d00001 diff --git a/textures/techage_handsieve_sieve.png b/textures/techage_handsieve_sieve.png new file mode 100644 index 0000000000000000000000000000000000000000..dbf785c07725735abe4d5d57d737ffe610694ed1 GIT binary patch literal 1562 zcmV+#2IcvQP)?r7%{UzV#|U(OLj;+02>|$v1P%E2jBsa zcz~G^JBCb>PN&;;`=ea0x>dLCWsyvV?t~;l_`j@kbk0w8ESKQk{rXqG^!;9s=_IE- zRCLa9yWS8;$*`Ysy;u=N5dfzr6ZTb&4i%fthBWJOI8>bEL)P0JQVPOQ^Yr-@C*vV; zr1{fd{wn^nPu>T3^k7C9hWzX4B~PEf;F~AU&|wI`wkQ!&QPl?TJ?mXT94flb@!;YD z=^du7xw+jCh9R3>Nj@6z>2bk&QGUAQG_uy>urIx zmR>I6*tQjSJzASWyOmZFUit`^Vyu*G=Km+T5D|Qxw>B9oFh%r z4+D$_J){gcJIV2QzWMe!S2rt!40!zMW3&z__6Mfp5m(nsgn%@OxxBjO>#x2hi6gQs z#XCn31kBH;jPoIn9zH-y`C)+0TE6`1D{ePCW@o3YH#?@2oVIPbdU3^mUvP1LifJs9 ze1P{*>`RPk7!F@e(zcc)Nw95;X&MCZ@@7dK>kk7Q>V`l{PERIit(l#jpn`zKYK^s) zVZYCIR}iQG6^5+VTLPu{{3oCAg%9^=8YXhZjg0ydU6?zxnKE zMOiZ+#nhXZ6vdu63b9>B+qMk)8EG1m#vxJ$jD`cI;}JRxsf^)Aj~?=ahjV7rF}vN4 zG)FzlDBoF-3TF*; zmLQ%G2Qf&AlmX5jP*I8%64AD3S8zHn*|#87^iEw$3E>21?W>&s;)wn#b06wlH9 zDQ35zSZ_$O1mT`ytYTj^oSitT?HcJyZl1j$$r6(I8q+F7SR#CnL-8qX@sdUjF}nq( zI*|1kD4n2Z7x=EhSqWAUW)-c?h@uK-Ve&?=5O{7^ zioDlhn})bQ{5~f>dFAu+j!%t;DJs+iZjTIyxUND5A@Lvwz;zZM1c zXYbVKNkZEgWZ>SL^Tvm3@ZLi-MaY1BDls-dh=9T9K$>g_bd2ghV3^m4Abhps2lS84 zQMZL9ODa1W!n9zC_9qbrRDydpr=RB{$m&+k$6-cP)#3fe0hY z)=^g>S-(fMUDH+xo&?{makiqk72NK2m= zA+q!IdSHw|Ne9`Wk5CbKb98|3`b^`9dlIQajWsp4Y0+tZbb#;rvf+TvX;eSYsrDtk zd`uiJjt162Ex zY&d+=rv}q=T-V}U_xjU$+`Hc=54#c}BsfRc9F7ifzfXdv*?x=bY6hc!a{Rm7CtYih z=^351G-h`6`ulxSCmP>b@ExMvA06O+pV}@L^!f_#6&1(-Bf8)BZ$;F54i)%rCIA2c M07*qoM6N<$f-MT>)Bpeg literal 0 HcmV?d00001 diff --git a/textures/techage_handsieve_top.png b/textures/techage_handsieve_top.png new file mode 100644 index 0000000000000000000000000000000000000000..32f615904119d9073747c5a7f5a836bd2690a22b GIT binary patch literal 934 zcmV;X16lluP)X?Xq{u*4$89W@AYt;8lLA9M=AASiec|2ZgU1DGkSmjL%mT)=!juz(I3RL>Nd5Y zQ%VO=^pm|o%I>Wc+i_90%P`VpX@bsTJl`Qp61+x}Jla8L35|9aAr#t31cp4%(K;`! z8~3wW5At8NJV>E5@!k_6hSMb=J!yJht-&+*^Us(Mp<@g-MF86 z>Ezr6sT`EoLRvN}y*cE} z;-2}^x@NpV(NBDF@q}r#yC~bG=J)t~W1h9OHEur(3k!Gj{PGhyML%)<{pXF&5-hJx z&ZfJls!@LK=TN;lxI zFO%mvM-Fum%0^s1f5H?8Z-2R4X$HzpsJj8eJoHoV5)f=;wZlJrhJPM+55}x}osx$-V zpKFhTXwoFSZ*YASMB^m9a$}~_47~PaHVUFibKw4Pl_K~i&Vg4JJv`q**)Bq=$#dXn z?^|>hV-fCOdM3?*Gm92knozITFvd)t1MRKL3?ogaSp%I+o&$IPji_o4-2FGA*FWf2 znt?Z;?T&)z>!s7C2!@@%wn}xw{$Bq;9n#>8fJnNYO`b;RaGN}hOLxPAcF1u*D~g8y zgJBAjgmjwax?x$}csCsPlSvXX7$#(CLY@ptcf*5r$Z@~_08@U$y;6DE-~a#s07*qo IM6N<$g1yVQT>t<8 literal 0 HcmV?d00001 diff --git a/textures/techage_tool_hammer_bronze.png b/textures/techage_tool_hammer_bronze.png new file mode 100644 index 0000000000000000000000000000000000000000..3c48e9f64cd93a56cd4e52083f66360f0c95f80b GIT binary patch literal 1454 zcmV;f1yTBmP)61}g)3`f30G03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00k0BL_t(|+U=W9Xk$ej z$GsK4<3^-GL?K00DJV!$gOe`CcZKqBJrW4n9*;=+et3||<-`H?ZK z%w||GIDl1)x#q+4@+J<~7ytjo{w{v_=~n>2RB^-VMgd�Pvu3fGb~YHASGfcefU) z2#KiSA2bdC0K=&>s1|cb7D}!Uk56Q=wLHTBob3h&cvfB(d^$w!hD6-(y5QU(jfE`O zLKf^K3Lv$;SOe%)mI`&p7Dc!!!e2ZOyp$S5J0c{afFDks@d!ch(W@9E>5R(>hwF=9 zQoAI002m$GZ%c%Z7C|1KhZP+`&%6uB0es}s&*Nd~auc3nbZGy?6hY&>pI+W{J+IAA z0s!X9+tPw47RR5z-*CORvj;d0V6_&E$?7z`=mG*KU|GmSs5`bREqD=j_KrUnRD^-B z;YDC^)p_vW|9XNKpL@phxwZMpW;&?cFg}q508}?OVsC@4l^5YvVgQiBlQ3)ZlP)2| zs5>^s&OM9i+zbHVF$QBx0R{km_7_(_NT})prNzCwHQczf5g0x!2UrA1`OS~Jsud0r zGAHmgVSFNsci)_ewF@v>A(drSt50I6(jll5f{xCib^%@cN)}4m6p$4}*?WE+BB%(F z9Ej8%8;9$Qm@97wDu^bo;HSpAWBcwOIw^pqn&kNYZ4$Z~p{fV`_dIQpXX9{yrK$nc z({(P;%?3IVWCCw3&otsn0V`Q3DOX(-L0oNF9gscioIt5ya@N?%!v1u*%GL*TcTFfE)Nd=nXdo^+g@Ta%{aOJDxlOAzC;CGa|9i$9?uDlKL{!tX?yB{C9 zTwp~FFB3s0gkMUK7<1)q+~(kXv<0Qjx3&%E5J!jM0_=KP)!oXin?ZJ^g=p`=U$KX@Rdo1u{4n+uXGlsrO+T|(A1gnNh-fJYra z5mLeL>;;Awg|L!^5=^$!{5`}#!ZL<$+W|6o5xNC_%1P!uv&s| zxd=uK4^^>Tna$92XSJhj+kHM__;62ZdKuoh2+|)QsV2PB3UB0qAU*!H!TSo(?eJOw zdI4T3K(D|{1?VMsj{v;}FCB$@3Em^XY7N%6zjRlh5A1+f-@6W8gf_Ocr?(4yx-`#r zD`kksTiph)odZ64dy4&C-)f4`jqt`BpmzT)r62w1$BB*q0I;ewm-#Ucy#N3J07*qo IM6N<$f(r?bSpWb4 literal 0 HcmV?d00001 diff --git a/textures/techage_tool_hammer_diamond.png b/textures/techage_tool_hammer_diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..5be814e55afe80ab02e4afb2f680c3b66101c4d9 GIT binary patch literal 1466 zcmV;r1x5OaP)62MoVxen0>K03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00kaNL_t(|+U;9UXdG1- z|Gi}o(hvkwZR$a-T}`dK-3T_&qur8&S`65t9s(XLhJr##j6!m3Kx+1)2oW#B9;!5l zRji0L@l*=iOO}acS8}KzwlUdS3@IsUpBKOBn>X*hd9#0JlHL6-lbH+*zu)_PzwdkB zOMq^4qoadG{lOQ%UF7sLzxOZrJ&x~3hFM$$BqIJEzx(GceE0HEJoETtIJj>gp56Z> z1}CR^Cn$jD3iIyG!srQ%J1YQy+TZ`+w`v6d@Z%dJtQ`sPfCqp(H*es|d+)d;P?VRK zBPAgbHTXL>ZvX&x_3uTlFpqpD<#{=qPUG15A_wqLJ1D@n@~RNiA!;=w;s$RDK@G|n z%Yu((!M7s;O4-XEKvz{NIF+hQ!f6@&3r_%#_Vu6<5)x5>-_^g@M+7~is~njF10E%e zJ1d`3xg_uaFwnc%5D6_cK@q$NR#pVviz*-mi1EnbBRGEPvJ0MKpm%fIn4opuFN~h> z+z-vn0su-=6G}sr&GFQiBc5lg8^E<1Fjo$TiM1NMtO5c~fK{O)!KqX|X(5uZx^e%# zup}g!4PIq`nPQk8VfeyDE#V7=FR*m(EQ`YgnM$U#N;c_W8zzt0{oM1hRso+Ugf+w?x0ui*zAjuD$O4XBUbpLe!9so$k)&~#?qDk4BVo*OI{w{N1 zz@sqnesFTyiIV_h8Vp~!=#pUD{Ma^N6uHqimAygKXL1d-%RxN@k*KN)PNj-Ju3qs~ zgvb;ymIeRn6`-C*N!J;w)RHUA-IK2(DPlg$ijZX=X7yV}fGzlI|L@o4 z$_P9Qko`f->w3YrBn522-$oCCXF)YwP75MSH;9$xuLIw70>-l72m6A-1HkXKO%c3t zj-Vq#9>R)2eqaLM)D$4_dwPSx8|L?%z^N1=dIMeanUppSg1`enavOnn7bKra`G}CK zgsN&t=Ma4WZnb41~$Su$x2zF`HZ!0XQH>N&PDDWaZyZ>j+7Z0<2B^`0OX)^8y0LBJKZAlb UPw=vZ!vFvP07*qoM6N<$g5nyJEC2ui literal 0 HcmV?d00001 diff --git a/textures/techage_tool_hammer_mese.png b/textures/techage_tool_hammer_mese.png new file mode 100644 index 0000000000000000000000000000000000000000..a87072939916436cefab54299b6c8cc32493a36e GIT binary patch literal 1418 zcmV;51$Fv~P)61~`YuyR-lR03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00izyL_t(|+U;90Xd71; z{+=SLoYgG#P}0TCB14dnUFhH?P{`gar5ZXGVr*#X(kWxdLg=92?j6+4*+a5LL!q+J zVbD!Agb0Tygos4-V80IXyS{t(zjyD>r#oAxAB?0(LH@q?ec%7T_Yz=P%PMrStiSNZ zixn=OpPm9|XTYsnA6QWc=e?f80dUT@{GWEa!i%5)-s?I3i_Og`INv&d^%Ac83INb( zOxYq55C9JVM@Jm@?)@u~Fe}$R$drUq*5HqhW@=wsW9ao9FxCxxxL)7DVBl~7pDcm` zLMu;I&<@$Ep_DgxQ%PzdYr6@)-2}gk1dy^ZKuolXS+&}yATD#3LRaQGnj_m3yQ;TW-1z~&8JRe=C508>Sg z;CX%2YE6=a2MkiVuD?qCeZ|RKQp_6pU(zxc!S00H37FX|KE* za=Oq1fSWhz_eLY`lf+n;w1nsNQLkSEesl2b$0^<-SrDdS0S*9B@)xV0q;$C;Y~i{G zXn!}&tqU*#Q21LOcXcZqr-UVRnNY89VD}Fv`7fV_3d9QOe5+f1L59u_ag`8vbWXJk znA#U(U84m?BOW4w`m?AG5toE4c7yP|J~-b(t92495N%Wezz07IM)Uq*o&+%6Bq#T8 zn=)mDE)V4Isn<7PyPZy30nF69qg0@ieG~~4!GnP_&dUOfv95O2RT9+IrgDIKZBl}; zg3VduJP#WJp{S0sQK1-TMi>rPw1kTtWF8^ND4B{?vay40nKI_iol>q{Ae0Gl12HNf zA3pp@YXuRA<8hVebtV`&BiLBM6pZ3MVFgNUwOSL5bsGTOT;>3w1UaN^LosR|kl(A- zngNB$uiNd)Ah$s%%Cp1aicf;=@MAlGiQ3uuf}9PqzLUGqxEy5-K_b-^Jg<)@PfkM} zAu|PRH^Kk>8b~rI=_W%;Exn$D_4N-hgzrw~3Q$jRzkLjUL!-_I@{ZE9gQUQ>S|?EN zA60UmKR*kopqw>$01!&xd@GRH;<>!Frbv*%%Uxi9|9S{;o|7O6Uexgf_~GdcETsZd zE>PaLIgmY9#VUX|b0;7Qyr>xoAH(y`0)CZAk^QWap#x8qD*w3=U<>~6e80BWN90|A znh$Ygt^+@pE?^7(Evf=Mi|XNOrx0Z6WG_FOz^6{Yb`$*eYBYEN>Jhf_96?8fdI&3* z@V*Irsssq|pWcWDuerTp@?{7$$f%Ek1nU0L27GF5Fa_{|Ok%9d<#tFBLUj%09wLzT zb8CY-@YI!6g3HSg5mYGd?_c+Um&-t-VF&)g7NEc%Pf`Of7KlaN6Uu%+KN5dq`vs-6 z!BdqGypagGOO(rYeoxH;8H3kaqurhjMM;1sCV=Ym8G}#vq^8K=t=pjZS6I3U@2Y~g zQb3#@f7QT860qptjRX_{yq18XfF}tk68I1SMFUTc!bJifB4Do%_Uxa<>hrM`u<`w` zkV%NSpTGJc2mlX$y3b!f{T=G@)}nzo&H+Dv^Cf@h{pFLeh~TX^Ko|XQDa%^cvMz1? Y2Z;SZ=TJZ3=Kufz07*qoM6N<$f-|6q(EtDd literal 0 HcmV?d00001 diff --git a/textures/techage_tool_hammer_steel.png b/textures/techage_tool_hammer_steel.png new file mode 100644 index 0000000000000000000000000000000000000000..680717e73f52ab024dfc771b5f08a0a21ce60913 GIT binary patch literal 1426 zcmV;D1#S9?P)61u{%O0cijL03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00j0)L_t(|+U;90Ya>S# z{zj-XZsH;+jp9avV;5(OG%gGY?&Bt~MaqL184}W@y7I~clfW9MPoZ@B1$UjB6pLAL zpsgY>Ck)x+h;eC83j4{kqc^*=@@m(X^gu|v5-i_0-}~O1H#V@2b*yxVsvmf9aUtpR z&CLyNZ*Q@^y)9OSa2bZ71R&K2fuB7umgl7vRp;K$=J0HED&BMd_bk;dvc4x%WM06tp=10r~-Vu-JT(W?$Ns*olYmE zgu7~aS1t)W0CYF6A4S4KO;81|g4Gp4*QyFg0cz~;?;}Z)DR_$R=Jk^?LF>HtJTGcrG-ku<<-OQijvSM z8$4%tD)@fCKLtOTOxWM``+W!@W{gp<5HDUwDe&_|v+R}EP0eI-0MKf+*!z>oWJ;0{ zf=!7yj^Q{C@LPm;KfCyZ4SYzhYe@kK0D1DK)t@I!zCdX)91aou;1&j7Rtg9LNcpX{ zyQUQ`5|k1qPjDOuM}J1ORsl&XWXfC9>Ju5JbSSEXqOEgTCMXEFl#+eSoLawaBFiI8exN?baU9rgr^{A= z$dYKD3J84O%IhR>1V>Sn)Rh842w_}xodkWgb@2N4be*LHN(Gx)<06L*Qgv*-l@&tF z-52PUVKf>U2|qbG!O_u?sKW#WCsSG_n{=>^ERWgS+pDz-%y>dkL(DVC(kc~HW8@5y{9rU1v1+@&b^r`(=>td!s!7?JVqQO>e%I-AQVLVA zgCK}%YlQN0b~GAINw95xY#T6&Ua!aY22~Ouy4|jkkaJHnBM5?|HUbWJ zApiOfn5R)Pb%vZ;!Z1X)+eL=?_9`bpo#N^w=)+GUK_w!uIpRp5QM>xu-Q7hH1VN=$ zKm|`hBuFV!j!mD{tuHp5pQf`04E(SiMWs%Et@|`hLOp zeb@|S?*}(q06s2U0eRp7;P-DIl%Ve(i4^J;RI{@I&rPJx&d#8MUzh@Hzyo(9Yydbt zNA6jGs)(X8C-B^!pivk2PuL*vBCm$)CP`$OWUszwfiIna!yU*MTlwGt=p*dRIf97@ zeF)3RKMQ=R1Q7VoH}k<8PH%*I7^0h^-bT}y&GS6={Luz{X(m_#_>?CJA*5OkIYPLq zp`Al)>4vwEGH3$N9a+tBcsWA^XNrTtU<$n1Y{GS2EAWp_0S^4-RcYX9fkfUpp_=da z=K>#XAJ8ZpJQs6<&m=;v63u4QD&I>>fr`N!Q-j+2d4SJN09WTL24C(TeU-smmqGdi zBvXg?T)|r@ph%5>Zs2nXSa$H41grvhBLS-do+V(Fz|Rn{YT(&cc$L7<5O8`9@$R4H zs`G^v@YTyVP)R7bpMU-)2mr5s`BDD+_7CXetz`qB*$4dk{nzrp`0ptR%Lv|j1N7K` gOIgP{*70QHe^zBn8kfc7=l}o!07*qoM6N<$g1pdq&j0`b literal 0 HcmV?d00001