From 72502028c0a22f01fe6e6f05759b3d7311a047e4 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Mon, 16 Aug 2021 20:22:44 +0200 Subject: [PATCH] built on 16/08/2021 20:22:44 --- minecart/entitylib.lua | 6 +- minecart/monitoring.lua | 4 +- minecart/recording.lua | 4 + minecart/storage.lua | 2 +- networks/init.lua | 1 - networks/networks.lua | 2 +- techage/README.md | 3 + techage/basic_machines/gravelrinser.lua | 15 +- techage/basic_machines/grinder.lua | 130 ++++++-- techage/doc/manual_DE.lua | 18 ++ techage/doc/plans.lua | 58 ++++ techage/init.lua | 11 +- techage/iron_age/hopper.lua | 14 + techage/iron_age/recipes.lua | 2 +- techage/lamps/growlight.lua | 3 + techage/locale/techage.de.tr | 43 ++- techage/locale/template.txt | 42 +++ techage/logic/button.lua | 32 +- techage/logic/logic_block.lua | 12 +- techage/logic/sequencer.lua | 2 + techage/logic/terminal.lua | 17 + techage/manuals/manual_ta1_DE.md | 17 + techage/manuals/toc_DE.md | 2 + techage/sounds/techage_mill.ogg | Bin 0 -> 26619 bytes techage/sounds/techage_watermill.ogg | Bin 0 -> 23079 bytes techage/ta1_watermill/mill.lua | 178 +++++++++++ techage/ta1_watermill/millboard.lua | 91 ++++++ techage/ta1_watermill/sluice.lua | 227 +++++++++++++ techage/ta1_watermill/ta1_axle.lua | 176 ++++++++++ techage/ta1_watermill/water.lua | 117 +++++++ techage/ta1_watermill/watermill.lua | 300 ++++++++++++++++++ techage/ta3_power/tiny_generator.lua | 29 +- techage/textures/techage_axle_bearing.png | Bin 0 -> 154 bytes .../textures/techage_axle_bearing_front.png | Bin 0 -> 127 bytes techage/textures/techage_invisible.png | Bin 0 -> 126 bytes techage/textures/techage_invisible_inv.png | Bin 0 -> 304 bytes techage/textures/techage_junglewood.png | Bin 0 -> 151 bytes techage/textures/techage_junglewood_top.png | Bin 0 -> 110 bytes techage/textures/techage_mill_base.png | Bin 0 -> 394 bytes techage/textures/techage_mill_front.png | Bin 0 -> 146 bytes techage/textures/techage_mill_inv.png | Bin 0 -> 737 bytes techage/textures/techage_mill_side.png | Bin 0 -> 305 bytes techage/textures/techage_sluice1_inv.png | Bin 0 -> 607 bytes techage/textures/techage_sluice2_inv.png | Bin 0 -> 835 bytes techage/textures/techage_water_flowing.png | Bin 0 -> 178 bytes techage/textures/techage_watermill1_inv.png | Bin 0 -> 139 bytes techage/textures/techage_watermill2_inv.png | Bin 0 -> 131 bytes techage/textures/techage_watermill3_inv.png | Bin 0 -> 120 bytes techage/textures/techage_watermill4_inv.png | Bin 0 -> 165 bytes techage/textures/techage_wood50.png | Bin 0 -> 163 bytes 50 files changed, 1511 insertions(+), 47 deletions(-) create mode 100644 techage/sounds/techage_mill.ogg create mode 100644 techage/sounds/techage_watermill.ogg create mode 100644 techage/ta1_watermill/mill.lua create mode 100644 techage/ta1_watermill/millboard.lua create mode 100644 techage/ta1_watermill/sluice.lua create mode 100644 techage/ta1_watermill/ta1_axle.lua create mode 100644 techage/ta1_watermill/water.lua create mode 100644 techage/ta1_watermill/watermill.lua create mode 100644 techage/textures/techage_axle_bearing.png create mode 100644 techage/textures/techage_axle_bearing_front.png create mode 100644 techage/textures/techage_invisible.png create mode 100644 techage/textures/techage_invisible_inv.png create mode 100644 techage/textures/techage_junglewood.png create mode 100644 techage/textures/techage_junglewood_top.png create mode 100644 techage/textures/techage_mill_base.png create mode 100644 techage/textures/techage_mill_front.png create mode 100644 techage/textures/techage_mill_inv.png create mode 100644 techage/textures/techage_mill_side.png create mode 100644 techage/textures/techage_sluice1_inv.png create mode 100644 techage/textures/techage_sluice2_inv.png create mode 100644 techage/textures/techage_water_flowing.png create mode 100644 techage/textures/techage_watermill1_inv.png create mode 100644 techage/textures/techage_watermill2_inv.png create mode 100644 techage/textures/techage_watermill3_inv.png create mode 100644 techage/textures/techage_watermill4_inv.png create mode 100644 techage/textures/techage_wood50.png diff --git a/minecart/entitylib.lua b/minecart/entitylib.lua index b069421..5c48443 100644 --- a/minecart/entitylib.lua +++ b/minecart/entitylib.lua @@ -85,6 +85,10 @@ local function running(self) if self.reenter then -- through monitoring cart_pos = H2P(self.reenter[1]) + -- pos correction on slopes + if not minecart.is_rail(cart_pos) then + cart_pos.y = cart_pos.y - 1 + end wayp_pos = cart_pos is_junction = false self.waypoint = {pos = H2P(self.reenter[2]), power = 0, dot = self.reenter[4]} @@ -162,7 +166,7 @@ local function running(self) -- Got stuck somewhere if new_speed < 0.1 or dist < 0 then - print("Got stuck somewhere", new_speed, dist) + minetest.log("warning", "[Minecart] Got stuck somewhere " .. new_speed .. " " .. dist) stop_cart(self, wayp_pos) return end diff --git a/minecart/monitoring.lua b/minecart/monitoring.lua index 4d66b5e..2377d8e 100644 --- a/minecart/monitoring.lua +++ b/minecart/monitoring.lua @@ -117,7 +117,7 @@ local function monitoring(cycle) cart.last_pos = vector.round(pos) --print("entity card " .. cart.userID .. " at " .. P2S(cart.last_pos)) else - print("entity card without pos!") + minetest.log("warning", "[Minecart] entity card without pos!") end push(cycle, cart) elseif cart.checkpoints then @@ -130,7 +130,7 @@ local function monitoring(cycle) end push(cycle, cart) else - print("zombie got lost") + minetest.log("warning", "[Minecart] zombie got lost") end else local pos = cart.last_pos or cart.pos diff --git a/minecart/recording.lua b/minecart/recording.lua index 78bb36e..d55e30a 100644 --- a/minecart/recording.lua +++ b/minecart/recording.lua @@ -137,6 +137,10 @@ end function minecart.recording_waypoints(self) local pos = vector.round(self.object:get_pos()) + -- pos correction on slopes + if not minecart.is_rail(pos) then + pos.y = pos.y - 1 + end -- hier müsste überprüfung dest_pos rein self.sum_speed = self.sum_speed + self.curr_speed local wp_pos = check_waypoint(self, pos) diff --git a/minecart/storage.lua b/minecart/storage.lua index 96eb7e1..2db6028 100644 --- a/minecart/storage.lua +++ b/minecart/storage.lua @@ -110,7 +110,7 @@ function minecart.get_route(pos) M(pos):set_int("time", 0) return end - return minetest.deserialize(s) + return route end end end diff --git a/networks/init.lua b/networks/init.lua index bed92ef..67db832 100644 --- a/networks/init.lua +++ b/networks/init.lua @@ -30,7 +30,6 @@ dofile(MP .. "/power.lua") dofile(MP .. "/liquid.lua") dofile(MP .. "/control.lua") -print("networks_test_enabled", minetest.settings:get_bool("networks_test_enabled")) if minetest.settings:get_bool("networks_test_enabled") == true then -- Only for testing/demo purposes dofile(MP .. "/test/test_liquid.lua") diff --git a/networks/networks.lua b/networks/networks.lua index 4cca46a..f569773 100644 --- a/networks/networks.lua +++ b/networks/networks.lua @@ -328,7 +328,7 @@ local function remove_outdated_networks() for _,item in ipairs(to_be_deleted) do local net_name, netID = unpack(item) Networks[net_name][netID] = nil - print("Network " .. netw_num(netID) .. " timed out") + --print("Network " .. netw_num(netID) .. " timed out") end minetest.after(60, remove_outdated_networks) end diff --git a/techage/README.md b/techage/README.md index db87c55..554e2aa 100644 --- a/techage/README.md +++ b/techage/README.md @@ -31,6 +31,9 @@ Copyright (C) 2019-2021 Joachim Stolberg Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt Textures: CC BY-SA 3.0 +The TA1 mill sound is from https://freesound.org/people/JustinBW/sounds/70200/ +The TA1 watermill sound is from https://freesound.org/people/bmoreno/sounds/164182/ + Many thanks to Thomas-S and others for their contributions diff --git a/techage/basic_machines/gravelrinser.lua b/techage/basic_machines/gravelrinser.lua index a680fb0..1d91dd9 100644 --- a/techage/basic_machines/gravelrinser.lua +++ b/techage/basic_machines/gravelrinser.lua @@ -150,21 +150,22 @@ local function washing(pos, crd, nvm, inv) local src = ItemStack("techage:sieved_gravel") local dst = ItemStack("default:sand") if inv:contains_item("src", src) then + if not inv:room_for_item("dst", dst) then + crd.State:blocked(pos, nvm) + return + end local ore = get_random_gravel_ore() if ore then add_object({x=pos.x, y=pos.y+1, z=pos.z}, ore) end + inv:add_item("dst", dst) + inv:remove_item("src", src) + crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS) + return else crd.State:idle(pos, nvm) return end - if not inv:room_for_item("dst", dst) then - crd.State:idle(pos, nvm) - return - end - inv:add_item("dst", dst) - inv:remove_item("src", src) - crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS) end local function keep_running(pos, elapsed) diff --git a/techage/basic_machines/grinder.lua b/techage/basic_machines/grinder.lua index 1f38f50..9cf8dcd 100644 --- a/techage/basic_machines/grinder.lua +++ b/techage/basic_machines/grinder.lua @@ -23,8 +23,9 @@ local STANDBY_TICKS = 3 local COUNTDOWN_TICKS = 4 local CYCLE_TIME = 4 - --- Grinder recipes +-- Grinder recipes TA1 +local RecipesTa1 = {} +-- Grinder recipes TA2 - TA4 local Recipes = {} local function formspec(self, pos, nvm) @@ -250,6 +251,79 @@ local node_name_ta2, node_name_ta3, node_name_ta4 = tube_sides = {L=1, R=1, U=1}, }) +------------------------------------------------------------------------------- +-- TA1 Mill (watermill) +------------------------------------------------------------------------------- +local formspecStr = "size[8,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;src;1,1;1,1;]".. + "item_image[1,1;1,1;farming:wheat]".. + "image[1,1;1,1;techage_form_mask.png]".. + "image[3.5,1;1,1;techage_form_arrow.png]".. + "list[context;dst;6,1;1,1;]".. + "item_image[6,1;1,1;farming:flour]".. + "image[6,1;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]".. + default.get_hotbar_bg(0, 4) + +local function node_timer(pos, elapsed) + if techage.ta1_mill_has_power(pos, 2) then + local inv = M(pos):get_inventory() + local stack = inv:get_stack("src", 1) + if not stack:is_empty() then + local name = stack:get_name() + if RecipesTa1[name] then + local recipe = RecipesTa1[name] + src_to_dst(stack, 1, name, 1, recipe.inp_num, inv, recipe.output) + end + end + end + return true +end + +minetest.register_node("techage:ta1_mill_base", { + description = S("TA1 Mill Base"), + tiles = { + "techage_mill_base.png", + "default_stone_brick.png", + }, + after_place_node = function(pos, placer) + M(pos):set_string("formspec", formspecStr) + local inv = M(pos):get_inventory() + inv:set_size('src', 1) + inv:set_size('dst', 1) + minetest.get_node_timer(pos):start(4) + end, + can_dig = can_dig, + on_timer = node_timer, + allow_metadata_inventory_put = allow_metadata_inventory_take, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, + is_ground_content = false, + groups = {cracky = 2, crumbly = 2, choppy = 2}, +}) + +techage.register_node({"techage:ta1_mill_base"}, { + on_node_load = function(pos, node) + minetest.get_node_timer(pos):start(4) + end, +}) + +minetest.register_craft({ + output = "techage:ta1_mill_base", + recipe = { + {"default:stonebrick", "", "default:stonebrick"}, + {"", "techage:iron_ingot", ""}, + {"default:stonebrick", "", "default:stonebrick"}, + }, +}) + minetest.register_craft({ output = node_name_ta2, recipe = { @@ -284,16 +358,34 @@ if minetest.global_exists("unified_inventory") then width = 2, height = 2, }) + unified_inventory.register_craft_type("milling", { + description = S("Milling"), + icon = 'techage_mill_inv.png', + width = 2, + height = 2, + }) end -function techage.add_grinder_recipe(recipe) +function techage.add_grinder_recipe(recipe, ta1_permitted) local name, num = unpack(string.split(recipe.input, " ", false, 1)) - Recipes[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output} - - if minetest.global_exists("unified_inventory") then - recipe.items = {recipe.input} - recipe.type = "grinding" - unified_inventory.register_craft(recipe) + if minetest.registered_items[name] then + if ta1_permitted then + RecipesTa1[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output} + + if minetest.global_exists("unified_inventory") then + recipe.items = {recipe.input} + recipe.type = "milling" + unified_inventory.register_craft(table.copy(recipe)) + end + end + + Recipes[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output} + + if minetest.global_exists("unified_inventory") then + recipe.items = {recipe.input} + recipe.type = "grinding" + unified_inventory.register_craft(recipe) + end end end @@ -326,14 +418,14 @@ techage.add_grinder_recipe({input="default:acacia_tree", output="default:acacia_ techage.add_grinder_recipe({input="default:aspen_tree", output="default:aspen_leaves 8"}) if minetest.global_exists("farming") then - techage.add_grinder_recipe({input="farming:wheat 3", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:seed_wheat 6", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:barley 3", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:seed_barley 6", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:rye 3", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:seed_rye 6", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:rice 3", output="farming:rice_flour"}) - techage.add_grinder_recipe({input="farming:seed_rice 6", output="farming:rice_flour"}) - techage.add_grinder_recipe({input="farming:oat 3", output="farming:flour"}) - techage.add_grinder_recipe({input="farming:seed_oat 6", output="farming:flour"}) + techage.add_grinder_recipe({input="farming:wheat 3", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:seed_wheat 6", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:barley 3", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:seed_barley 6", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:rye 3", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:seed_rye 6", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:rice 3", output="farming:rice_flour"}, true) + techage.add_grinder_recipe({input="farming:seed_rice 6", output="farming:rice_flour"}, true) + techage.add_grinder_recipe({input="farming:oat 3", output="farming:flour"}, true) + techage.add_grinder_recipe({input="farming:seed_oat 6", output="farming:flour"}, true) end diff --git a/techage/doc/manual_DE.lua b/techage/doc/manual_DE.lua index f3dc08a..6262bd7 100644 --- a/techage/doc/manual_DE.lua +++ b/techage/doc/manual_DE.lua @@ -15,6 +15,8 @@ techage.manual_DE.aTitel = { "1,TA1: Eisenzeitalter", "2,Köhler / Coal Pile", "2,Kohlebrenner / Coal Burner", + "2,Wassermühle", + "3,TA1 Mühle", "2,Erze und Werkzeuge", "3,Hammer", "3,Kiessieb / Gravel Sieve", @@ -339,6 +341,18 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", + "Mit der Wassermühle können Weizen und andere Getreide zu Mehl gemahlen und dann im Ofen zu Brot gebacken werden. Die Mühle wird mit\n".. + "Wasserkraft angetrieben. Dazu muss der Mühlbach über ein Kanal zum Wasserrad geführt werden. Für den Mühlbach muss oberhalb des Mühlerades\n".. + "ein Teich angelegt werden. Die Abbilding rechts (auf \"Plan\" klicken) zeigt den Aufbau.\n".. + "\n".. + "\n".. + "\n", + "Mit der Wassermühle können Weizen und andere Getreide zu Mehl gemahlen und dann im Ofen zu Brot gebacken werden. Die Mühle wird mit\n".. + "Wasserkraft angetrieben. Dazu muss der Mühlbach über ein Kanal zum Wasserrad geführt werden. Für den Mühlbach muss oberhalb des Mühlerades\n".. + "ein Teich angelegt werden. Die Abbilding rechts (auf \"Plan\" klicken) zeigt den Aufbau.\n".. + "\n".. + "\n".. + "\n", "TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb\\, aber auch der Minecart Hopper kann genutzt werden.\n".. "\n".. "\n".. @@ -1723,6 +1737,8 @@ techage.manual_DE.aItemName = { "techage_ta1", "", "", + "", + "", "ta1_gravelsieve", "hammer", "ta1_gravelsieve", @@ -1930,6 +1946,8 @@ techage.manual_DE.aPlanTable = { "", "coalpile", "coalburner", + "watermill1", + "watermill2", "", "", "", diff --git a/techage/doc/plans.lua b/techage/doc/plans.lua index 05e2043..da6bdbc 100644 --- a/techage/doc/plans.lua +++ b/techage/doc/plans.lua @@ -81,6 +81,64 @@ techage.ConstructionPlans["hoppersieve"] = { {false, false, HOPPR, CHEST, false}, } +-- +-- TA1: Watermill +-- +local WATR1 = {"default_water.png" , "techage:water_flowing"} +local WATR3 = {"techage_water_flowing.png" , "techage:water_flowing"} +local WMILL = {"default_wood.png" , "techage:ta1_board1_apple"} +local SLUC1 = {"techage_sluice2_inv.png" , "techage:ta1_sluice_closed"} +local SLUC2 = {"techage_sluice1_inv.png" , "techage:ta1_sluice_handle_closed"} +local MIL11 = {"techage_watermill1_inv.png" , "techage:ta1_watermill"} +local MIL12 = {"techage_watermill1_inv.png^[transformR90" , "techage:ta1_watermill"} +local MIL13 = {"techage_watermill1_inv.png^[transformR180" , "techage:ta1_watermill"} +local MIL14 = {"techage_watermill1_inv.png^[transformR270" , "techage:ta1_watermill"} +local MIL21 = {"techage_watermill2_inv.png" , "techage:ta1_watermill"} +local MIL22 = {"techage_watermill2_inv.png^[transformR90" , "techage:ta1_watermill"} +local MIL23 = {"techage_watermill2_inv.png^[transformR180" , "techage:ta1_watermill"} +local MIL24 = {"techage_watermill2_inv.png^[transformR270" , "techage:ta1_watermill"} +local MIL31 = {"techage_watermill3_inv.png" , "techage:ta1_watermill"} +local MIL32 = {"techage_watermill3_inv.png^[transformR90" , "techage:ta1_watermill"} +local MIL33 = {"techage_watermill3_inv.png^[transformR180" , "techage:ta1_watermill"} +local MIL34 = {"techage_watermill3_inv.png^[transformR270" , "techage:ta1_watermill"} +local MIL40 = {"techage_watermill4_inv.png" , "techage:ta1_watermill"} +local BEARG = {"default_stone_brick.png^techage_axle_bearing_front.png", "techage:ta1_axle_bearing2"} +local BRICK = {"default_stone_brick.png", "default:stonebrick"} + + +techage.ConstructionPlans["watermill1"] = { + {false, false, false, false, false, false, false, false, false, false, false}, + {false, SLUC2, false, false, false, false, false, false, false, false, false}, + {WATR1, SLUC1, WMILL, WMILL, WMILL, WMILL, WMILL, WATR3, false, false, false}, + {WATR1, DDIRT, false, false, MIL31, MIL21, MIL11, MIL21, MIL34, false, false}, + {WATR1, DDIRT, false, false, MIL22, MIL40, MIL40, MIL40, MIL24, false, false}, + {DDIRT, DDIRT, DDIRT, false, MIL12, MIL40, BEARG, MIL40, MIL14, false, false}, + {DDIRT, DDIRT, DDIRT, false, MIL22, MIL40, BRICK, MIL40, MIL24, false, false}, + {DDIRT, DDIRT, DDIRT, DDIRT, MIL32, MIL23, BRICK, MIL23, MIL33, false, false}, + {DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, WATR1, WATR1, WATR1, WATR1}, +} + + +local MILLF = {"default_wood.png" , "techage:ta1_watermill"} +local AXLE1 = {"techage_axle_bearing.png", "techage:ta1_axle"} +local MILLG = {"techage_wood50.png^techage_axle_bearing.png", "techage:ta1_mill_gear"} +local MILL_ = {"techage_mill_side.png", "techage:ta1_mill"} +local MILLB = {"default_stone_brick.png", "techage:ta1_mill_base"} +local FURNE = {"default_furnace_front.png", "default:furnace"} +local HOPER = {"techage_hopper.png", "minecart:hopper"} + +techage.ConstructionPlans["watermill2"] = { + {false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, false, false, false, false, false, false, MILLF, false, false, false}, + {false, false, false, false, false, false, false, false, MILLF, false, false, false}, + {false, false, false, false, false, MILLG, AXLE1, BEARG, MILLF, BEARG, false, false}, + {false, false, false, false, false, MILL_, false, BRICK, MILLF, BRICK, false, false}, + {false, CHEST, HOPER, FURNE, HOPER, MILLB, false, BRICK, MILLF, BRICK, false, false}, + {DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, DDIRT, WATR1, DDIRT, DDIRT, DDIRT}, +} + -- -- Steam Engine -- diff --git a/techage/init.lua b/techage/init.lua index f8a7b60..363b9f0 100644 --- a/techage/init.lua +++ b/techage/init.lua @@ -133,8 +133,17 @@ dofile(MP.."/iron_age/meltingpot.lua") if techage.modified_recipes_enabled then dofile(MP.."/iron_age/tools.lua") end + +-- TA1 Watermill +dofile(MP.."/ta1_watermill/ta1_axle.lua") +dofile(MP.."/ta1_watermill/watermill.lua") +dofile(MP.."/ta1_watermill/water.lua") +dofile(MP.."/ta1_watermill/sluice.lua") +dofile(MP.."/ta1_watermill/millboard.lua") +dofile(MP.."/ta1_watermill/mill.lua") + dofile(MP.."/iron_age/recipes.lua") -if minetest.global_exists("wielded_light") then +if minetest.global_exists("wielded_light") or minetest.global_exists("illumination") then dofile(MP.."/iron_age/meridium.lua") end diff --git a/techage/iron_age/hopper.lua b/techage/iron_age/hopper.lua index 188ea80..374eb0f 100644 --- a/techage/iron_age/hopper.lua +++ b/techage/iron_age/hopper.lua @@ -76,3 +76,17 @@ minecart.register_inventory( }, } ) + +minecart.register_inventory( + { + "techage:ta1_mill_base", + }, + { + put = { + listname = "src", + }, + take = { + listname = "dst", + }, + } +) diff --git a/techage/iron_age/recipes.lua b/techage/iron_age/recipes.lua index af1e1ec..c00e7ea 100644 --- a/techage/iron_age/recipes.lua +++ b/techage/iron_age/recipes.lua @@ -119,7 +119,7 @@ local function register_liquid(source, flowing, itemname, inventory_image, name, -------------------------------- Start Modification -- minetest.set_node(lpos, {name = source}) - if source == "default:lava_source" and lpos.y > 0 then + if source == "default:lava_source" and lpos.y > 0 and not minetest.is_singleplayer() then minetest.chat_send_player(user:get_player_name(), S("[Bucket] Lava can only be placed below sea level!")) return else diff --git a/techage/lamps/growlight.lua b/techage/lamps/growlight.lua index 20dc22c..9165875 100644 --- a/techage/lamps/growlight.lua +++ b/techage/lamps/growlight.lua @@ -135,6 +135,8 @@ techage.register_lamp("techage:growlight", { {-8/16, -8/16, -8/16, 8/16, -13/32, 8/16}, }, }, + on_timer = node_timer_off, + on_switch_lamp = on_switch_lamp, high_power = true, },{ description = S("TA4 LED Grow Light"), @@ -156,6 +158,7 @@ techage.register_lamp("techage:growlight", { }, }, on_timer = node_timer_on, + on_switch_lamp = on_switch_lamp, high_power = true, }) diff --git a/techage/locale/techage.de.tr b/techage/locale/techage.de.tr index 16a92b5..694716a 100644 --- a/techage/locale/techage.de.tr +++ b/techage/locale/techage.de.tr @@ -109,6 +109,7 @@ TA3 Booster=TA3 Gebläse ### button.lua ### +Access:=Zugriff: TA3 Button/Switch=TA3 Taster/Schalter TA4 Button/Switch=TA4 Schalter/Taster @@ -446,6 +447,8 @@ TA4 Gravel Sieve=TA4 Kiessieb Grinder=Mühle Grinding=Mahlen +Milling=Mahlen +TA1 Mill Base=Mühlenunterteil ### growlight.lua ### @@ -642,6 +645,24 @@ Meridium Sword=Meridium Schwert TA3 Mesecons Converter=TA3 Mesecons Konverter +### mill.lua ### + +TA1 Mill=TA1 Mühle +TA1 Mill Gear=TA1 Mühlengetriebe + +### millboard.lua ### + +TA1 Acacia Millrace Board=TA1 Akazie Mühlbachbrett +TA1 Acacia Wood Board=TA1 Akazienholzbrett +TA1 Apple Millrace Board=TA1 Apfel Mühlbachbrett +TA1 Apple Wood Board=TA1 Apfelholzbrett +TA1 Aspen Millrace Board=TA1 Espe Mühlbachbrett +TA1 Aspen Wood Board=TA1 Espenholzbrett +TA1 Jungle Millrace Board=TA1 Dschungel Mühlbachbrett +TA1 Jungle Wood Board=TA1 Dschungelholzbrett +TA1 Pine Millrace Board=TA1 Kiefer Mühlbachbrett +TA1 Pine Wood Board=TA1 Kiefernholzbrett + ### minicell.lua ### TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle @@ -877,6 +898,12 @@ TA4 Silo=Silo TA Lamp=TA Lampe +### sluice.lua ### + +TA1 Sluice Gate=TA1 Schleusenschieber +TA1 Sluice Handle=TA1 Schleusengriff +Your pond is too small!=ein Teich ist zu klein! + ### solarcell.lua ### TA4 Solar Carrier Module=TA4 Solar Trägermodul @@ -925,6 +952,11 @@ Cancel=Abbruch Note: You can't change any values while the block is running!=Hinweis: Während der Block läuft, kann kein Wert geändert werden! Refresh=Aktualisieren +### ta1_axle.lua ### + +TA1 Axle=TA1 Achse +TA1 Axle Bearing=TA1 Achsenlager + ### ta2_weight_chest.lua ### TA2 Weight Chest=TA2 Gewichtekiste @@ -1067,13 +1099,23 @@ Usmium Powder=Usmium Pulver TA Valve=TA Ventil TA3 Valve=TA3 Ventil +### water.lua ### + +Flowing Water=Fließendes Wasser +Water Source=Wasserquelle + ### waterinlet.lua ### Error: No natural water!=Fehler: Kein natürliches Wasser! Error: No water available!=Fehler: Kein Wasser verfügbar! Error: Not on sea level!=Fehler: Nicht auf Meereshöhe! +Operational=Betriebsbereit TA4 Water Inlet=TA4 Wasssereinlass +### watermill.lua ### + +TA1 Watermill=TA1 Wasssermühle + ### waterpump.lua ### TA4 Water Pump=Wasserpumpe @@ -1090,4 +1132,3 @@ This is not the surface of the ocean!=Das ist nicht die Meeresoberfläche! [TA4 Wind Turbine]=[TA4 Windkraftanlage] biome and no ocean!=Biom und keine Meer (ocean)! is a suitable place for a wind turbine!=ist ein geeigneter Ort für eine Windkraftanlage! - diff --git a/techage/locale/template.txt b/techage/locale/template.txt index ac33dce..4b9d436 100644 --- a/techage/locale/template.txt +++ b/techage/locale/template.txt @@ -109,6 +109,7 @@ TA3 Booster= ### button.lua ### +Access:= TA3 Button/Switch= TA4 Button/Switch= @@ -446,6 +447,8 @@ TA4 Gravel Sieve= Grinder= Grinding= +Milling= +TA1 Mill Base= ### growlight.lua ### @@ -642,6 +645,24 @@ Meridium Sword= TA3 Mesecons Converter= +### mill.lua ### + +TA1 Mill= +TA1 Mill Gear= + +### millboard.lua ### + +TA1 Acacia Millrace Board= +TA1 Acacia Wood Board= +TA1 Apple Millrace Board= +TA1 Apple Wood Board= +TA1 Aspen Millrace Board= +TA1 Aspen Wood Board= +TA1 Jungle Millrace Board= +TA1 Jungle Wood Board= +TA1 Pine Millrace Board= +TA1 Pine Wood Board= + ### minicell.lua ### TA4 Streetlamp Solar Cell= @@ -877,6 +898,12 @@ TA4 Silo= TA Lamp= +### sluice.lua ### + +TA1 Sluice Gate= +TA1 Sluice Handle= +Your pond is too small!= + ### solarcell.lua ### TA4 Solar Carrier Module= @@ -925,6 +952,11 @@ Cancel= Note: You can't change any values while the block is running!= Refresh= +### ta1_axle.lua ### + +TA1 Axle= +TA1 Axle Bearing= + ### ta2_weight_chest.lua ### TA2 Weight Chest= @@ -1067,13 +1099,23 @@ Usmium Powder= TA Valve= TA3 Valve= +### water.lua ### + +Flowing Water= +Water Source= + ### waterinlet.lua ### Error: No natural water!= Error: No water available!= Error: Not on sea level!= +Operational= TA4 Water Inlet= +### watermill.lua ### + +TA1 Watermill= + ### waterpump.lua ### TA4 Water Pump= diff --git a/techage/logic/button.lua b/techage/logic/button.lua index b08a0a1..eac8d1b 100644 --- a/techage/logic/button.lua +++ b/techage/logic/button.lua @@ -56,10 +56,12 @@ local function formspec(meta) local numbers = meta:get_string("numbers") or "" local idx = meta:get_int("cycle_idx") or 0 if idx == 0 then idx = 1 end + local access_idx = meta:get_string("public") == "true" and 3 or meta:get_string("protected") == "true" and 2 or 1 return "size[7.5,6]".. "dropdown[0.2,0;3;type;switch,button 1s,button 2s,button 4s,button 8s,button 16s,button 32s;"..idx.."]".. "field[0.5,2;7,1;numbers;"..S("Insert destination node number(s)")..";"..numbers.."]" .. - "checkbox[1,3;public;public;false]".. + "label[0.2,3;"..S("Access:").."]".. + "dropdown[3,3;4;access;private,protected,public;"..access_idx.."]".. "button_exit[2,4;3,1;exit;"..S("Save").."]" end @@ -72,8 +74,17 @@ local function on_receive_fields(pos, formname, fields, player) return end meta:set_string("numbers", fields.numbers) - if fields.public then - meta:set_string("public", fields.public) + if fields.access == "protected" then + meta:set_string("protected", "true") + meta:set_string("public", "") + end + if fields.access == "public" then + meta:set_string("public", "true") + meta:set_string("protected", "") + end + if fields.access == "private" then + meta:set_string("public", "") + meta:set_string("protected", "") end local cycle_time = nil if fields.type == "switch" then @@ -110,12 +121,20 @@ local function on_receive_fields(pos, formname, fields, player) end end +local function can_access(pos, player) + local meta = M(pos) + local public = meta:get_string("public") == "true" + local protected = meta:get_string("protected") == "true" + local owner = meta:get_string("owner") + local name = player:get_player_name() + return public or protected and not minetest.is_protected(pos, name) or owner == name +end + local function on_rightclick_on(pos, node, clicker) local meta = M(pos) local fixed = meta:get_string("fixed") if fixed == "true" then - if meta:get_string("public") == "true" or - clicker:get_player_name() == meta:get_string("owner") then + if can_access(pos, clicker) then switch_on(pos) end end @@ -126,8 +145,7 @@ local function on_rightclick_off(pos, node, clicker) local numbers = meta:get_string("numbers") local cycle_time = meta:get_int("cycle_time") or 0 if numbers ~= "" and numbers ~= nil and cycle_time == 0 then - if meta:get_string("public") == "true" or - clicker:get_player_name() == meta:get_string("owner") then + if can_access(pos, clicker) then switch_off(pos) end end diff --git a/techage/logic/logic_block.lua b/techage/logic/logic_block.lua index 942a410..d81d463 100644 --- a/techage/logic/logic_block.lua +++ b/techage/logic/logic_block.lua @@ -106,8 +106,12 @@ end local function get_inputs(pos) local nvm = techage.get_nvm(pos) + local mem = techage.get_mem(pos) -- old data is needed for formspec 'input' values nvm.old_inp_tbl = table.copy(nvm.inp_tbl or {}) + for _, num in ipairs(mem.outp_num or {}) do + nvm.old_inp_tbl[num] = nvm.outp_tbl[num] or "off" + end return nvm.old_inp_tbl end @@ -148,11 +152,12 @@ local function data(nvm) return table.concat(inp, ", "), table.concat(outp, ", ") end -local function get_code(pos, nvm) +local function get_code(pos, nvm, mem) local meta = M(pos) local tbl = {"local inputs = get_inputs(pos) or {}"} local owner = M(pos):get_string("owner") nvm.own_num = nvm.own_num or M(pos):get_string("node_number") + mem.outp_num = {} for i = 1,NUM_RULES do local outp = meta:get_string("outp" .. i) @@ -167,6 +172,7 @@ local function get_code(pos, nvm) expr = string.gsub(expr, 'on', '"on"') expr = string.gsub(expr, 'off', '"off"') tbl[#tbl + 1] = "if "..expr.." then send(pos, '"..outp.."', '"..val.."') end" + table.insert(mem.outp_num, outp) else nvm.error = err return @@ -190,7 +196,7 @@ end local function execute(pos) local nvm = techage.get_nvm(pos) local mem = techage.get_mem(pos) - mem.code = mem.code or get_code(pos, nvm) + mem.code = mem.code or get_code(pos, nvm, mem) if mem.code then local res, _ = pcall(mem.code) if not res then @@ -304,7 +310,7 @@ minetest.register_node("techage:ta3_logic2", { local nvm = techage.get_nvm(pos) local mem = techage.get_mem(pos) mem.code = nil - get_code(pos, nvm) + get_code(pos, nvm, mem) meta:set_string("formspec", formspec(pos, meta)) end end, diff --git a/techage/logic/sequencer.lua b/techage/logic/sequencer.lua index b5abfb7..1ad89bc 100644 --- a/techage/logic/sequencer.lua +++ b/techage/logic/sequencer.lua @@ -268,6 +268,8 @@ techage.register_node({"techage:ta3_sequencer"}, { else nvm.endless = false end + elseif topic == "pause" then + stop_the_sequencer(pos) else return "unsupported" end diff --git a/techage/logic/terminal.lua b/techage/logic/terminal.lua index bae261c..212356c 100644 --- a/techage/logic/terminal.lua +++ b/techage/logic/terminal.lua @@ -156,6 +156,23 @@ local function command(pos, command, player) return end + local cmnd, payload = command:match('^axle%s+([%w_]+)%s*(.*)$') + if cmnd then + if not minetest.check_player_privs(player, "server") then + output(pos, "server privs missing") + return + end + local resp = techage.transfer( + pos, + "B", -- outdir + cmnd, -- topic + payload, -- payload + techage.TA1Axle, -- network + nil) -- valid nodes + output(pos, dump(resp)) + return + end + if command ~= "" then output(pos, CMNDS_TA3) end diff --git a/techage/manuals/manual_ta1_DE.md b/techage/manuals/manual_ta1_DE.md index 487dba5..37463d9 100644 --- a/techage/manuals/manual_ta1_DE.md +++ b/techage/manuals/manual_ta1_DE.md @@ -53,6 +53,23 @@ Der Schmelztiegel hat ein eigenes Menü mit Rezepten und ein Inventar, wo du die [coalburner|plan] +## Wassermühle + +Mit der Wassermühle können Weizen und andere Getreide zu Mehl gemahlen und dann im Ofen zu Brot gebacken werden. Die Mühle wird mit +Wasserkraft angetrieben. Dazu muss der Mühlbach über ein Kanal zum Wasserrad geführt werden. Für den Mühlbach muss oberhalb des Mühlerades +ein Teich angelegt werden. Die Abbilding rechts (auf "Plan" klicken) zeigt den Aufbau. + +[watermill1|plan] + +### TA1 Mühle + +Mit der Wassermühle können Weizen und andere Getreide zu Mehl gemahlen und dann im Ofen zu Brot gebacken werden. Die Mühle wird mit +Wasserkraft angetrieben. Dazu muss der Mühlbach über ein Kanal zum Wasserrad geführt werden. Für den Mühlbach muss oberhalb des Mühlerades +ein Teich angelegt werden. Die Abbilding rechts (auf "Plan" klicken) zeigt den Aufbau. + +[watermill2|plan] + + ## Erze und Werkzeuge TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb, aber auch der Minecart Hopper kann genutzt werden. diff --git a/techage/manuals/toc_DE.md b/techage/manuals/toc_DE.md index 438c601..16e584a 100644 --- a/techage/manuals/toc_DE.md +++ b/techage/manuals/toc_DE.md @@ -14,6 +14,8 @@ - [TA1: Eisenzeitalter](./manual_ta1_DE.md#ta1:-eisenzeitalter) - [Köhler / Coal Pile](./manual_ta1_DE.md#köhler--coal-pile) - [Kohlebrenner / Coal Burner](./manual_ta1_DE.md#kohlebrenner--coal-burner) + - [Wassermühle](./manual_ta1_DE.md#wassermühle) + - [TA1 Mühle](./manual_ta1_DE.md#ta1-mühle) - [Erze und Werkzeuge](./manual_ta1_DE.md#erze-und-werkzeuge) - [Hammer](./manual_ta1_DE.md#hammer) - [Kiessieb / Gravel Sieve](./manual_ta1_DE.md#kiessieb--gravel-sieve) diff --git a/techage/sounds/techage_mill.ogg b/techage/sounds/techage_mill.ogg new file mode 100644 index 0000000000000000000000000000000000000000..de0617b975786b299cbeabb162a8c6ee823ae7ec GIT binary patch literal 26619 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 literal 0 HcmV?d00001 diff --git a/techage/sounds/techage_watermill.ogg b/techage/sounds/techage_watermill.ogg new file mode 100644 index 0000000000000000000000000000000000000000..3e6486a4306442e5024f928d85a668a5557898ea GIT binary patch literal 23079 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 literal 0 HcmV?d00001 diff --git a/techage/ta1_watermill/mill.lua b/techage/ta1_watermill/mill.lua new file mode 100644 index 0000000..35e0450 --- /dev/null +++ b/techage/ta1_watermill/mill.lua @@ -0,0 +1,178 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA1 Mill + +]]-- + +local M = minetest.get_meta +local S = techage.S + +local function start_mill(pos) + local obj = minetest.add_entity(pos, "techage:ta1_mill_entity") + minetest.remove_node(pos) +end + +local function stop_mill(pos, self) + minetest.swap_node(pos, {name = "techage:ta1_mill", param2 = 0}) + minetest.get_node_timer(pos):start(2) + self.object:remove() +end + +local function has_power(pos, y_offs) + local pos1 = {x = pos.x, y = pos.y + y_offs, z = pos.z} + local nvm = techage.get_nvm(pos1) + nvm.watermill_trigger = (nvm.watermill_trigger or 1) - 1 + return nvm.watermill_trigger > 0 +end + +techage.ta1_mill_has_power = has_power + +minetest.register_node("techage:ta1_mill_gear", { + description = S("TA1 Mill Gear"), + tiles = { + "default_wood.png^techage_axle_bearing.png^[transformR90", + "default_wood.png^techage_axle_bearing.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/2, -1/2, -1/2, 1/2, -1/8, 1/2}, + {-1/8, -1/8, -1/2, 1/8, 1/8, 1/2}, + }, + }, + + after_place_node = function(pos, placer) + techage.TA1Axle:after_place_node(pos) + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.TA1Axle:after_dig_node(pos) + end, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 2, crumbly = 2, choppy = 2}, +}) + +techage.register_node({"techage:ta1_mill_gear"}, { + on_transfer = function(pos, in_dir, topic, payload) + local nvm = techage.get_nvm(pos) + if topic == "trigger" then + nvm.watermill_trigger = 4 + return true + end + end, +}) + +minetest.register_node("techage:ta1_mill", { + description = S("TA1 Mill"), + tiles = { + -- up, down, right, left, back, front + "techage_mill_side.png", + "techage_mill_side.png", + "techage_mill_side.png", + "techage_mill_side.png", + "techage_mill_front.png", + "techage_mill_front.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/8, -1/8, -1/8, 1/8, 4/8, 1/8}, + {-3/8, -3/8, -4/8, -1/8, 3/8, 4/8}, + {-3/8, -4/8, -3/8, -1/8, 4/8, 3/8}, + { 1/8, -3/8, -4/8, 3/8, 3/8, 4/8}, + { 1/8, -4/8, -3/8, 3/8, 4/8, 3/8}, + }, + }, + + after_place_node = function(pos, placer) + minetest.get_node_timer(pos):start(2) + end, + + on_rightclick = function(pos, node, clicker) + start_mill(pos) + end, + + on_timer = function(pos, elapsed) + if has_power(pos, 1) then + start_mill(pos) + end + return true + end, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 2, crumbly = 2, choppy = 2}, +}) + +minetest.register_entity("techage:ta1_mill_entity", { + initial_properties = { + physical = true, + visual = "wielditem", + wield_item = "techage:ta1_mill", + visual_size = {x=0.67, y=0.67, z=0.67}, + static_save = true, + automatic_rotate = -math.pi * 0.2, + pointable = false, + }, + + on_step = function(self, dtime) + self.dtime = (self.dtime or 0) + dtime + + if self.dtime > 2 then + local pos = vector.round(self.object:get_pos()) + if not has_power(pos, 1) then + stop_mill(pos, self) + end + self.dtime = 0 + minetest.sound_play("techage_mill", {gain = 0.3, pos = pos, + max_hear_distance = 10}, true) + end + end, + + on_rightclick = function(self, clicker) + local pos = vector.round(self.object:get_pos()) + stop_mill(pos, self) + end, +}) + +techage.register_node({"techage:ta1_mill"}, { + on_node_load = function(pos, node) + minetest.get_node_timer(pos):start(2) + end, +}) + +minetest.register_craft({ + output = "techage:ta1_mill_gear", + recipe = { + {"default:wood", "", "default:wood"}, + {"techage:ta1_axle", "default:wood", "techage:ta1_axle"}, + {"default:wood", "techage:ta1_axle", "default:wood"}, + }, +}) + +minetest.register_craft({ + output = "techage:ta1_mill", + recipe = { + {"", "techage:iron_ingot", ""}, + {"stairs:slab_stone", "techage:iron_ingot", "stairs:slab_stone"}, + {"", "", ""}, + }, +}) diff --git a/techage/ta1_watermill/millboard.lua b/techage/ta1_watermill/millboard.lua new file mode 100644 index 0000000..b70c5c1 --- /dev/null +++ b/techage/ta1_watermill/millboard.lua @@ -0,0 +1,91 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA1 mill boards + +]]-- + +local M = minetest.get_meta +local S = techage.S + +local function register_board1(output, description, tiles, input) + minetest.register_node(output, { + description = description, + tiles = tiles, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/2, -4/8, -1/2, 1/2, -3/8, 1/2}, + }, + }, + paramtype2 = "wallmounted", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), + }) + + minetest.register_craft({ + output = output .. " 3", + recipe = { + {"", "", input}, + {"", "", input}, + {"", "", input}, + }, + }) +end + +local function register_board2(output, description, tiles, input1, input2) + minetest.register_node(output, { + description = description, + tiles = tiles, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/2, 3/8, -1/2, 1/2, 4/8, 1/2}, + {-1/2, 3/16, -2/16, 1/2, 6/16, 2/16}, + {-1/2, -5/16, -1/16, 1/2, -3/16, 1/16}, + }, + }, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), + }) + + minetest.register_craft({ + output = output, + recipe = { + {"", input1, ""}, + {"", input2, ""}, + {"", "", ""}, + }, + }) +end + +register_board1("techage:ta1_board1_apple", S("TA1 Apple Wood Board"), {"default_wood.png"}, "stairs:slab_wood") +register_board1("techage:ta1_board1_jungle", S("TA1 Jungle Wood Board"), {"default_junglewood.png"}, "stairs:slab_junglewood") +register_board1("techage:ta1_board1_pine", S("TA1 Pine Wood Board"), {"default_pine_wood.png"}, "stairs:slab_pine_wood") +register_board1("techage:ta1_board1_acacia", S("TA1 Acacia Wood Board"), {"default_acacia_wood.png"}, "stairs:slab_acacia_wood") +register_board1("techage:ta1_board1_aspen", S("TA1 Aspen Wood Board"), {"default_aspen_wood.png"}, "stairs:slab_aspen_wood") + +register_board2("techage:ta1_board2_apple", S("TA1 Apple Millrace Board"), {"default_wood.png"}, "techage:ta1_board1_apple", "default:fence_rail_wood") +register_board2("techage:ta1_board2_jungle", S("TA1 Jungle Millrace Board"), {"default_junglewood.png"}, "techage:ta1_board1_jungle", "default:fence_rail_junglewood") +register_board2("techage:ta1_board2_pine", S("TA1 Pine Millrace Board"), {"default_pine_wood.png"}, "techage:ta1_board1_pine", "default:fence_rail_pine_wood") +register_board2("techage:ta1_board2_acacia", S("TA1 Acacia Millrace Board"), {"default_acacia_wood.png"}, "techage:ta1_board1_acacia", "default:fence_rail_acacia_wood") +register_board2("techage:ta1_board2_aspen", S("TA1 Aspen Millrace Board"), {"default_aspen_wood.png"}, "techage:ta1_board1_aspen", "default:fence_rail_aspen_wood") diff --git a/techage/ta1_watermill/sluice.lua b/techage/ta1_watermill/sluice.lua new file mode 100644 index 0000000..c4d796f --- /dev/null +++ b/techage/ta1_watermill/sluice.lua @@ -0,0 +1,227 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA1 Sluice Gate + +]]-- + +local M = minetest.get_meta +local S = techage.S + +local RADIUS = 8 +local DEPTH = 2 +local AMOUNT = RADIUS * RADIUS * 1.5 + +local function check_position(pos, facedir) + local dir = minetest.facedir_to_dir(facedir) + local pos_ = vector.add(pos, dir) + local node = minetest.get_node(pos_) + + if node.name ~= "default:water_source" then + return + end + + dir = vector.multiply(dir, RADIUS) + local center = vector.add(pos, dir) + local pos1 = {x = center.x - RADIUS, y = center.y - DEPTH, z = center.z - RADIUS} + local pos2 = {x = center.x + RADIUS, y = center.y + 0, z = center.z + RADIUS} + local _, nodes = minetest.find_nodes_in_area(pos1, pos2, {"default:water_source"}) + return (nodes["default:water_source"] and nodes["default:water_source"] > AMOUNT) or false +end + +-- Function checks if a millpond is avaliable and +-- returns the pos for the new water block, and the type of block. +local function has_water(pos, facedir, player) + local facedir2, res, dir, pos2 + + -- check left side + facedir2 = (facedir + 3) % 4 + res = check_position(pos, facedir2) + facedir2 = (facedir + 1) % 4 + dir = minetest.facedir_to_dir(facedir2) + pos2 = vector.add(pos, dir) + + if res == nil then + return pos2, "air" + elseif res == true then + return pos2, "water" + else + minetest.chat_send_player(player:get_player_name(), S("Your pond is too small!")) + return pos2, "air" + end + + -- check right side + facedir2 = (facedir + 1) % 4 + res = check_position(pos, facedir2) + facedir2 = (facedir + 3) % 4 + dir = minetest.facedir_to_dir(facedir2) + pos2 = vector.add(pos, dir) + + if res == nil then + return pos2, "air" + elseif res == true then + return pos2, "water" + else + minetest.chat_send_player(player:get_player_name(), S("Your pond is too small!")) + return pos2, "air" + end +end + +local function on_rightclick(pos, node, clicker, itemstack, pointed_thing) + local pos2 = vector.add(pos, {x = 0, y = -1, z = 0}) + local node2 = minetest.get_node(pos2) + local pos3, res = has_water(pos2, node2.param2, clicker) + local node3 = minetest.get_node(pos3) + + if node2.name == "techage:ta1_sluice_closed" then + minetest.swap_node(pos, {name = "techage:ta1_sluice_handle_open", param2 = node.param2}) + minetest.swap_node(pos2, {name = "techage:ta1_sluice_open", param2 = node.param2}) + if res == "water" then + if node3.name == "air" or node3.name == "techage:water_flowing" then + minetest.add_node(pos3, {name = "techage:water_source"}) + minetest.get_node_timer(pos3):start(2) + end + else + minetest.add_node(pos3, {name = "air"}) + end + minetest.sound_play("doors_door_open", {gain = 0.5, pos = pos, + max_hear_distance = 10}, true) + elseif node2.name == "techage:ta1_sluice_open" then + minetest.swap_node(pos, {name = "techage:ta1_sluice_handle_closed", param2 = node.param2}) + minetest.swap_node(pos2, {name = "techage:ta1_sluice_closed", param2 = node.param2}) + if res == "water" then + if node3.name == "techage:water_source" then + minetest.add_node(pos3, {name = "techage:water_flowing"}) + end + else + if node3.name == "techage:water_flowing" then + minetest.add_node(pos3, {name = "air"}) + end + end + minetest.sound_play("doors_door_close", {gain = 0.5, pos = pos, + max_hear_distance = 10}, true) + end +end + +minetest.register_node("techage:ta1_sluice_closed", { + description = S("TA1 Sluice Gate"), + tiles = { + "default_wood.png^techage_junglewood_top.png", + "default_wood.png", + "default_wood.png^techage_junglewood.png", + "default_wood.png^techage_junglewood.png", + "default_wood.png", + "default_wood.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, 5/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, 8/16, 8/16, -5/16}, + {-8/16, -8/16, -8/16, 8/16, -5/16, 8/16}, + {-1/16, -5/16, -7/16, 1/16, 8/16, 7/16}, + }, + }, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("techage:ta1_sluice_open", { + description = S("TA1 Sluice Gate"), + tiles = {"default_wood.png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, 5/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, 8/16, 8/16, -5/16}, + {-8/16, -8/16, -8/16, 8/16, -5/16, 8/16}, + }, + }, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_wood_defaults(), + drop = "techage:sluice_closed", +}) + +minetest.register_node("techage:ta1_sluice_handle_closed", { + description = S("TA1 Sluice Handle"), + tiles = {"default_wood.png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, 0/16, 8/16}, + {-1/16, 0/16, -1/16, 1/16, 4/16, 1/16}, + {-1/16, 2/16, -4/16, 1/16, 4/16, 4/16}, + }, + }, + on_rightclick = on_rightclick, + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("techage:ta1_sluice_handle_open", { + description = S("TA1 Sluice Handle"), + tiles = {"default_wood.png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, 0/16, 8/16}, + {-1/16, 0/16, -1/16, 1/16, 14/16, 1/16}, + {-1/16, 14/16, -4/16, 1/16, 16/16, 4/16}, + }, + }, + on_rightclick = on_rightclick, + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_wood_defaults(), + drop = "techage:sluice_handle_closed", +}) + +minetest.register_craft({ + output = "techage:ta1_sluice_closed", + recipe = { + {"", "", ""}, + {"techage:ta1_board1_apple", "techage:ta1_board1_jungle", "techage:ta1_board1_apple"}, + {"", "techage:ta1_board1_apple", ""}, + }, +}) + +minetest.register_craft({ + output = "techage:ta1_sluice_handle_closed", + recipe = { + {"default:stick", "default:stick", "default:stick"}, + {"", "default:stick", ""}, + {"", "stairs:slab_wood", ""}, + }, +}) diff --git a/techage/ta1_watermill/ta1_axle.lua b/techage/ta1_watermill/ta1_axle.lua new file mode 100644 index 0000000..bd22a15 --- /dev/null +++ b/techage/ta1_watermill/ta1_axle.lua @@ -0,0 +1,176 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA1 Axles for the Watermill + +]]-- + +-- for lazy programmers +local P = minetest.string_to_pos +local M = minetest.get_meta +local S = techage.S + +local Axle = tubelib2.Tube:new({ + dirs_to_check = {1,2,3,4,5,6}, + max_tube_length = 5, + show_infotext = false, + tube_type = "axle1", + primary_node_names = {"techage:ta1_axle"}, + secondary_node_names = {"techage:ta1_mill_gear", "techage:ta1_axle_bearing1", "techage:ta1_axle_bearing2"}, + after_place_tube = function(pos, param2, tube_type, num_tubes, state) + minetest.swap_node(pos, {name = "techage:ta1_axle", param2 = param2}) + end, +}) + +Axle:set_valid_sides("techage:ta1_mill_gear", {"F", "B"}) +Axle:set_valid_sides("techage:ta1_axle_bearing1", {"F", "B"}) +Axle:set_valid_sides("techage:ta1_axle_bearing2", {"F", "B"}) + +minetest.register_node("techage:ta1_axle", { + description = S("TA1 Axle"), + tiles = { + "techage_axle_bearing.png^[transformR90", + "techage_axle_bearing.png^[transformR90", + "techage_axle_bearing.png", + "techage_axle_bearing.png", + "techage_axle_bearing.png", + "techage_axle_bearing.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/8, -1/8, -4/8, 1/8, 1/8, 4/8}, + }, + }, + + after_place_node = function(pos, placer, itemstack, pointed_thing) + if not Axle:after_place_tube(pos, placer, pointed_thing) then + minetest.remove_node(pos) + return true + end + return false + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Axle:after_dig_tube(pos, oldnode, oldmetadata) + end, + + paramtype2 = "facedir", -- important! + on_rotate = screwdriver.disallow, -- important! + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {crumbly = 3, cracky = 3, snappy = 3}, + sounds = default.node_sound_wood_defaults(), +}) + +-- Bearings are defined as secondary nodes which forward received 'on_transfer' commands +minetest.register_node("techage:ta1_axle_bearing1", { + description = S("TA1 Axle Bearing"), + tiles = { + "default_stone_brick.png^techage_axle_bearing.png^[transformR90", + "default_stone_brick.png^techage_axle_bearing.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/2, -1/2, -1/2, 1/2, -1/8, 1/2}, + {-1/8, -1/8, -1/2, 1/8, 1/8, 1/2}, + }, + }, + + after_place_node = function(pos, placer) + Axle:after_place_node(pos) + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Axle:after_dig_node(pos) + end, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 2, crumbly = 2, choppy = 2}, +}) + +minetest.register_node("techage:ta1_axle_bearing2", { + description = S("TA1 Axle Bearing"), + tiles = { + -- up, down, right, left, back, front + "default_stone_brick.png", + "default_stone_brick.png", + "default_stone_brick.png", + "default_stone_brick.png", + "default_stone_brick.png^techage_axle_bearing_front.png", + "default_stone_brick.png^techage_axle_bearing_front.png", + }, + + after_place_node = function(pos, placer) + Axle:after_place_node(pos) + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Axle:after_dig_node(pos) + end, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 2, crumbly = 2, choppy = 2}, +}) + +techage.register_node({"techage:ta1_axle_bearing1", "techage:ta1_axle_bearing2"}, { + on_transfer = function(pos, in_dir, topic, payload) + return techage.transfer( + pos, + in_dir, -- outdir + topic, + payload, + Axle, -- network + nil) -- valid nodes + end, +}) + + +minetest.register_craft({ + output = "techage:ta1_axle", + recipe = { + {"", "", ""}, + {"techage:iron_ingot", "dye:black", "techage:iron_ingot"}, + {"", "", ""}, + }, +}) + +minetest.register_craft({ + output = "techage:ta1_axle_bearing1", + recipe = { + {"", "", ""}, + {"", "techage:ta1_axle", ""}, + {"", "stairs:slab_stonebrick", ""}, + }, +}) + +minetest.register_craft({ + output = "techage:ta1_axle_bearing2", + recipe = { + {"", "", ""}, + {"", "techage:ta1_axle", ""}, + {"", "default:stonebrick", ""}, + }, +}) + +techage.TA1Axle = Axle diff --git a/techage/ta1_watermill/water.lua b/techage/ta1_watermill/water.lua new file mode 100644 index 0000000..64670ea --- /dev/null +++ b/techage/ta1_watermill/water.lua @@ -0,0 +1,117 @@ +-- Based on and derived from minetest_game.default +-- License: LGPL v2.1 + +-- support for MT game translation. +local S = default.get_translator + +minetest.register_node("techage:water_flowing", { + description = S("Flowing Water"), + drawtype = "flowingliquid", + waving = 0, + tiles = {"default_water.png"}, + special_tiles = { + { + name = "default_water_flowing_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.5, + }, + }, + { + name = "default_water_flowing_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.5, + }, + }, + }, + use_texture_alpha = "blend", + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "techage:water_flowing", + liquid_alternative_source = "techage:water_source", + liquid_viscosity = 1, + post_effect_color = {a = 103, r = 30, g = 60, b = 90}, + groups = {water = 3, liquid = 3, cools_lava = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("techage:water_source", { + description = S("Water Source"), + drawtype = "flowingliquid", + waving = 0, + tiles = {"default_water.png"}, + special_tiles = { + { + name = "default_water_flowing_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.5, + }, + }, + { + name = "default_water_flowing_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.5, + }, + }, + }, + + use_texture_alpha = "blend", + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "techage:water_flowing", + liquid_alternative_source = "techage:water_source", + liquid_viscosity = 1, + post_effect_color = {a = 103, r = 30, g = 60, b = 90}, + groups = {water = 3, liquid = 3, cools_lava = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("techage:water_stop", { + description = "Water Stop", + drawtype = "glasslike_framed_optional", + tiles = {"techage_invisible.png"}, + inventory_image = 'techage_invisible_inv.png', + + use_texture_alpha = "blend", + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 3, oddly_breakable_by_hand = 3}, + sounds = default.node_sound_glass_defaults(), + drop = "", +}) diff --git a/techage/ta1_watermill/watermill.lua b/techage/ta1_watermill/watermill.lua new file mode 100644 index 0000000..644dfb1 --- /dev/null +++ b/techage/ta1_watermill/watermill.lua @@ -0,0 +1,300 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA1 Watermill + +]]-- + +local M = minetest.get_meta +local S = techage.S + +local function calc_dir(dir, facedir) + if facedir == 1 then + return {x = dir.z, y = dir.y, z = -dir.x} + elseif facedir == 2 then + return {x = -dir.x, y = dir.y, z = -dir.z} + elseif facedir == 3 then + return {x = -dir.z, y = dir.y, z = dir.x} + end + return {x = dir.x, y = dir.y, z = dir.z} +end + +local function add_node(pos, dir, facedir, node_name) + local pos2 = vector.add(pos, calc_dir(dir, facedir)) + local node = minetest.get_node(pos2) + if techage.is_air_like(node.name) then + minetest.swap_node(pos2, {name = node_name}) + end +end + +local function remove_node(pos, dir, facedir, node_name) + local pos2 = vector.add(pos, calc_dir(dir, facedir)) + local node = minetest.get_node(pos2) + if node.name == node_name then + minetest.swap_node(pos2, {name = "air"}) + end +end + +local function water_flowing(pos, facedir, tRes) + facedir = ((facedir or 0) + 1) % 4 + local dir = minetest.facedir_to_dir(facedir) + + local pos2 = vector.add(pos, dir) + pos2.y = pos2.y + 1 + local node = minetest.get_node(pos2) + if node.name == "techage:water_flowing" then + tRes.backward = false + return true + end + + pos2 = vector.subtract(pos, dir) + pos2.y = pos2.y + 1 + node = minetest.get_node(pos2) + if node.name == "techage:water_flowing" then + tRes.backward = true + return true + end +end + +local function enough_space(pos, facedir) + local pos1 = vector.add(pos, calc_dir({x =-1, y =-1, z = 0}, facedir)) + local pos2 = vector.add(pos, calc_dir({x = 1, y = 1, z = 0}, facedir)) + local _, nodes = minetest.find_nodes_in_area(pos1, pos2, {"air"}) + return nodes["air"] and nodes["air"] == 8 +end + +local function remove_nodes(pos, facedir) + remove_node(pos, {x = 0, y = 1, z = 0}, facedir, "techage:water_stop") + remove_node(pos, {x =-1, y = 0, z = 0}, facedir, "techage:water_stop") + remove_node(pos, {x = 1, y = 0, z = 0}, facedir, "techage:water_stop") + remove_node(pos, {x =-1, y = 1, z =-1}, facedir, "techage:water_stop") + remove_node(pos, {x = 1, y = 1, z =-1}, facedir, "techage:water_stop") + remove_node(pos, {x =-1, y = 1, z = 1}, facedir, "techage:water_stop") + remove_node(pos, {x = 1, y = 1, z = 1}, facedir, "techage:water_stop") +end + +local function start_wheel(pos, facedir, backward) + local obj = minetest.add_entity(pos, "techage:ta1_watermill_entity") + local dir = minetest.facedir_to_dir(facedir) + local yaw = minetest.dir_to_yaw(dir) + if backward then + obj:set_rotation({x=-math.pi/2, y=yaw, z=0}) + else + obj:set_rotation({x=math.pi/2, y=yaw, z=0}) + end + local self = obj:get_luaentity() + self.facedir = facedir + + add_node(pos, {x = 0, y = 1, z = 0}, facedir, "techage:water_stop") + add_node(pos, {x =-1, y = 0, z = 0}, facedir, "techage:water_stop") + add_node(pos, {x = 1, y = 0, z = 0}, facedir, "techage:water_stop") + add_node(pos, {x =-1, y = 1, z =-1}, facedir, "techage:water_stop") + add_node(pos, {x = 1, y = 1, z =-1}, facedir, "techage:water_stop") + add_node(pos, {x =-1, y = 1, z = 1}, facedir, "techage:water_stop") + add_node(pos, {x = 1, y = 1, z = 1}, facedir, "techage:water_stop") + minetest.remove_node(pos) +end + +local function stop_wheel(pos, self) + self.facedir = self.facedir or 0 + if self.facedir == 0 or self.facedir == 2 then + minetest.swap_node(pos, {name = "techage:ta1_watermill", param2 = 4}) + M(pos):set_int("facedir", self.facedir) + minetest.get_node_timer(pos):start(2) + elseif self.facedir == 1 or self.facedir == 3 then + minetest.swap_node(pos, {name = "techage:ta1_watermill", param2 = 13}) + M(pos):set_int("facedir", self.facedir) + minetest.get_node_timer(pos):start(2) + end + + remove_nodes(pos, self.facedir) + self.object:remove() +end + +local function trigger_consumer(pos, facedir) + local outdir = facedir + 1 + local resp = techage.transfer( + pos, + outdir, -- outdir + "trigger", -- topic + nil, -- payload + techage.TA1Axle, -- network + nil) -- valid nodes + if not resp then + outdir = tubelib2.Turn180Deg[outdir] + resp = techage.transfer( + pos, + outdir, -- outdir + "trigger", -- topic + nil, -- payload + techage.TA1Axle, -- network + nil) -- valid nodes + end +end + +minetest.register_node("techage:ta1_watermill", { + description = S("TA1 Watermill"), + tiles = { + -- up, down, right, left, back, front + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/2, -1/2, -1/2, 1/2, 1/2, 1/2}, + + {-4.5/2, -1/2, 0.8/2, 4.5/2, 1/2, 1.0/2}, + {-4.5/2, -1/2, -1.0/2, 4.5/2, 1/2, -0.8/2}, + {-3.8/2, -1/2, 2.1/2, 3.8/2, 1/2, 2.3/2}, + {-3.8/2, -1/2, -2.3/2, 3.8/2, 1/2, -2.1/2}, + + { 0.8/2, -1/2, -4.5/2, 1.0/2, 1/2, 4.5/2}, + {-1.0/2, -1/2, -4.5/2, -0.8/2, 1/2, 4.5/2}, + { 2.1/2, -1/2, -3.8/2, 2.3/2, 1/2, 3.8/2}, + {-2.3/2, -1/2, -3.8/2, -2.1/2, 1/2, 3.8/2}, + }, + }, + on_rightclick = function(pos, node, clicker) + start_wheel(pos, M(pos):get_int("facedir")) + end, + + on_timer = function(pos, elapsed) + local tRes = {} + if water_flowing(pos, M(pos):get_int("facedir"), tRes) then + start_wheel(pos, M(pos):get_int("facedir"), tRes.backward) + end + return true + end, + + paramtype2 = "facedir", + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 2, crumbly = 2, choppy = 2, not_in_creative_inventory = 1}, + node_placement_prediction = "", + drop = "techage:ta1_watermill_inv", +}) + +-- A smaller one for the inventory +minetest.register_node("techage:ta1_watermill_inv", { + description = S("TA1 Watermill"), + --inventory_image = "techage_waterwheel_inv.png", + --wield_image = "techage_waterwheel_inv.png", + tiles = { + -- up, down, right, left, back, front + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1/4, -1/4, -1/4, 1/4, 1/4, 1/4}, + + {-4.5/4, 0.8/4, -1/4, 4.5/4, 1.0/4, 1/4}, + {-4.5/4, -1.0/4, -1/4, 4.5/4, -0.8/4, 1/4}, + {-3.8/4, 2.1/4, -1/4, 3.8/4, 2.3/4, 1/4}, + {-3.8/4, -2.3/4, -1/4, 3.8/4, -2.1/4, 1/4}, + + { 0.8/4, -4.5/4, -1/4, 1.0/4, 4.5/4, 1/4}, + {-1.0/4, -4.5/4, -1/4, -0.8/4, 4.5/4, 1/4}, + { 2.1/4, -3.8/4, -1/4, 2.3/4, 3.8/4, 1/4}, + {-2.3/4, -3.8/4, -1/4, -2.1/4, 3.8/4, 1/4}, + }, + }, + + after_place_node = function(pos, placer) + local node = minetest.get_node(pos) + M(pos):set_int("facedir", node.param2) + remove_nodes(pos, node.param2) + if (node.param2 == 0 or node.param2 == 2) and enough_space(pos, node.param2) then + minetest.swap_node(pos, {name = "techage:ta1_watermill", param2 = 4}) + minetest.get_node_timer(pos):start(2) + elseif (node.param2 == 1 or node.param2 == 3) and enough_space(pos, node.param2) then + minetest.swap_node(pos, {name = "techage:ta1_watermill", param2 = 13}) + minetest.get_node_timer(pos):start(2) + else + minetest.remove_node(pos) + return true + end + end, + + paramtype2 = "facedir", + node_placement_prediction = "", + diggable = false, +}) + +techage.register_node({"techage:ta1_watermill"}, { + on_node_load = function(pos, node) + minetest.get_node_timer(pos):start(2) + end, +}) + + +minetest.register_entity("techage:ta1_watermill_entity", { + initial_properties = { + physical = true, + collisionbox = {-0.5, -1.5, -1.5, 0.5, 1.5, 1.5}, + visual = "wielditem", + wield_item = "techage:ta1_watermill", + visual_size = {x=0.67, y=0.67, z=0.67}, + static_save = true, + automatic_rotate = -math.pi * 0.2, + pointable = false, + }, + + on_step = function(self, dtime) + self.dtime = (self.dtime or 0) + dtime + + if self.dtime > 2 then + self.dtime = 0 + local pos = vector.round(self.object:get_pos()) + if not water_flowing(pos, self.facedir, {}) then + stop_wheel(pos, self) + end + trigger_consumer(pos, self.facedir) + minetest.sound_play("techage_watermill", {gain = 0.3, pos = pos, + max_hear_distance = 10}, true) + end + end, + + on_rightclick = function(self, clicker) + local pos = vector.round(self.object:get_pos()) + stop_wheel(pos, self) + end, + + on_activate = function(self, staticdata) + self.facedir = tonumber(staticdata) or 0 + end, + + get_staticdata = function(self) + return self.facedir + end, +}) + +minetest.register_craft({ + output = "techage:ta1_watermill_inv", + recipe = { + {"techage:ta1_board1_apple", "techage:ta1_board1_apple", "techage:ta1_board1_apple"}, + {"techage:ta1_board1_apple", "default:wood", "techage:ta1_board1_apple"}, + {"techage:ta1_board1_apple", "techage:ta1_board1_apple", "techage:ta1_board1_apple"}, + }, +}) diff --git a/techage/ta3_power/tiny_generator.lua b/techage/ta3_power/tiny_generator.lua index 8a21e6d..ee98127 100644 --- a/techage/ta3_power/tiny_generator.lua +++ b/techage/ta3_power/tiny_generator.lua @@ -187,11 +187,24 @@ minetest.register_node("techage:tiny_generator", { on_rotate = screwdriver.disallow, is_ground_content = false, - after_place_node = function(pos) + after_place_node = function(pos, placer, itemstack) local nvm = techage.get_nvm(pos) local number = techage.add_node(pos, "techage:tiny_generator") nvm.running = false nvm.burn_cycles = 0 + if itemstack then + local stack_meta = itemstack:get_meta() + if stack_meta then + local liquid_name = stack_meta:get_string("liquid_name") + local liquid_amount = stack_meta:get_int("liquid_amount") + if liquid_name ~= "" and fuel.burntime(liquid.name) and + liquid_amount >= 0 and liquid_amount <= fuel.CAPACITY then + nvm.liquid = nvm.liquid or {} + nvm.liquid.name = liquid_name + nvm.liquid.amount = liquid_amount + end + end + end State:node_init(pos, nvm, number) M(pos):set_string("formspec", formspec(State, pos, nvm)) M(pos):set_int("outdir", networks.side_to_outdir(pos, "R")) @@ -205,13 +218,25 @@ minetest.register_node("techage:tiny_generator", { techage.del_mem(pos) end, + preserve_metadata = function(pos, oldnode, oldmetadata, drops) + local nvm = techage.get_nvm(pos) + if nvm.liquid and nvm.liquid.name and nvm.liquid.amount > 0 then + -- generator tank is not empty + local meta = drops[1]:get_meta() + meta:set_string("liquid_name", nvm.liquid.name) + meta:set_int("liquid_amount", nvm.liquid.amount) + meta:set_string("description", S("TA3 Tiny Power Generator") .. " (fuel: " .. + tostring(nvm.liquid and nvm.liquid.amount or 0) .. "/" .. + tostring(fuel.CAPACITY) .. ")") + end + end, + get_generator_data = get_generator_data, ta3_formspec = techage.generator_settings("ta3", PWR_PERF), on_receive_fields = on_receive_fields, on_rightclick = on_rightclick, on_punch = fuel.on_punch, on_timer = node_timer, - can_dig = fuel.can_dig, }) minetest.register_node("techage:tiny_generator_on", { diff --git a/techage/textures/techage_axle_bearing.png b/techage/textures/techage_axle_bearing.png new file mode 100644 index 0000000000000000000000000000000000000000..61be451bdad12ea1efe842b83c8b4467af80a43b GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$efSN8%RAX8ac*IMt@QSB57vmN5>@|q?04M-?yHYwUyAAdzYa8t!PC{xWt~$(6963OE@%J% literal 0 HcmV?d00001 diff --git a/techage/textures/techage_axle_bearing_front.png b/techage/textures/techage_axle_bearing_front.png new file mode 100644 index 0000000000000000000000000000000000000000..175fb565ff4e455c7f8ab5a9c85d803bda4c133f GIT binary patch literal 127 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$efSN8%RWo2a`Z}C=bejvqI z666=m;PC858jz#n>Eak7aXC3*fxZB5qmj~dC&^6Xg*|Jg2DquUdE5#rdHaQl;r%3b U=9^h8AS)O=UHx3vIVCg!0CXlG8UO$Q literal 0 HcmV?d00001 diff --git a/techage/textures/techage_invisible.png b/techage/textures/techage_invisible.png new file mode 100644 index 0000000000000000000000000000000000000000..b5501901058238bb6b4593e78ed5846e55493522 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;OS+@4BLl<6e(pbstUx|vage(c z!@6@aFM%B90G|+7_X3}$UzaX{@jRv7|ftIx;Y9?C1WI$O_~$76-XI zF|0c$^AgBm3-AeXbuaMY;AC+4owooaT@vIM%;50sMjDW_+tbA{MC1I`iyH--4R}~D zy#Flw?hKPmu|+x0WI+v0*Qu&TJ?@2O2`w+YwSrO@WA;8$ewhE@xeDhL!HDPwD+DEP zI=entDEi?7V@N;4&T5t&HcUBkjA{K5D}HQfqddyP4l0wd$2%~ ztM4AqRO?QiT@42=Ol{l7`bzXczf{HdXvh1G6Ro_1H*9y?u*7S_HXYANqLz~?w(53% w?U;3BmaEds7V13SrlPWfj32*# zn*tPPED7=pW^j0RBMr#0^mK6y;kcfh5VQ4CW8=^N|CxDu7B1xD=~=0uWU`u3>DZR6 vP-d5=%xn#xSdoC9%v2GNq)KLHEe3|)YeXjdsW~y9XCZe2rn=FBX zj3q&S!3+-1ZlnP@!k#XUAsp9}6BwA)*nOHNrZ90Z^qys&98`a{6DZB#>FVdQ&MBb@ E0F2)m4*&oF literal 0 HcmV?d00001 diff --git a/techage/textures/techage_mill_base.png b/techage/textures/techage_mill_base.png new file mode 100644 index 0000000000000000000000000000000000000000..50b5d3303d75635dab753e5194c7beb1d180077b GIT binary patch literal 394 zcmV;50d@X~P)aBp-i+PgO7(hhMaSXI}@J*L&DW`O|;=;Bp6X90AR3_ ztgeYojmW~dbBR{I_fXXi0eLQj_U8TkH4UB(0HL1aWi~PsSRv6i#$`ZYa|o#%V+?Zw zID0_=F2p25BUofQ^#`_+BBjOas2%llVK{z!9mPi^Ul3gozX5ZD$1d3_M}Hylz<~4- zd_rXN7!VpSG$uZwv^k&;W(O$h83DZ8y|#j>4*;tD8GIgAE^K?%ws6Q?d)EfQR@r+i owZ9#>m(8Dzi*5h^SHM@uf5kvFz(ct}djJ3c07*qoM6N<$f=uwBO8@`> literal 0 HcmV?d00001 diff --git a/techage/textures/techage_mill_front.png b/techage/textures/techage_mill_front.png new file mode 100644 index 0000000000000000000000000000000000000000..97351d4cee7ea3823a1ecf88091fb0419adcba8c GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{SN8&+dGqI4Yw@pLw^mw! z!P8V!bM3t=Kv~9;AirP+hi5m^fE+zf7sn8d^T`Pb25d~~R~1AB&N48yH8mYlU=*;` qa#+*AEwF$?;j*&_!!#ZR69&8WIuokcZyEq~GI+ZBxvXm32-qJPNEw_BTl*05>UrcNydkaZgYCoHV3)Lh%DpqA^CvM$^@bG2`FZX= z$I&rLpN%B?8YGFIBj@-rLK;aFKSrYYVzv^0x0e zAux`)npEAw6>9Sjz6G76d=!aRgO!z2qNS1STKLc#bF)LKrOpI;y~g ztz?lxO#sT5$!8?s9FYpi*F!$ADnX%&8mK9szBdS)K(enbJr*)OsZLMwaNSEwfnisu2(^g3LKfOIBS$8m3B=?gOd%b} zX%cb0K9irF5gvy9?vJ3CDF%9f&p>=oX9u-4A_iiJDXL=lEurP&h z+9T{kqSu-=JuZjRzC3PonLz%kDdtSyAn8wfdQjb{u;4AVs`!>vOg_V72K@1mtl_IF zG|dJ>_SKy2R#jQ&vUpoRQZ(KK;veItylaPJp(>*jbzPlDishn`?Sty^Z0{+^4UE5X2>>Q^ZoK4*Z@`8 T7xUD200000NkvXXu0mjfR*_Z! literal 0 HcmV?d00001 diff --git a/techage/textures/techage_mill_side.png b/techage/textures/techage_mill_side.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ee649d808e1676651dd262cbb1e77439755129 GIT binary patch literal 305 zcmV-10nYx3P)3K~yNuT~bjF!ypLd z3f6c4A>F_B3TFQ{=>@i>_dmiwoZ@JT@&ulM01zBYt-MqRB8~{<%ZRlB8(|Y(q5`tT zENW*n)Dv?Sg#W}@0(C=z2pxDi?*N}9&X9-M0FTyYo{bubD$D}V^dO3o!-R;3Ztq)H z1u{NLc^LqYPbp6epaQKtW$7N17J8TR2@v zD{NFUPd+A?Blh|L000YgQchC(;9l2-p9A>xO_`K&ohVhC zm2?Y!L>sQaPHzaj_tx6j2k)ccr(19)0S*GJ2;jBW_8r0Dl(+@KdcW(>gN+3O)8|~I z!RcoSBv)V%UIaLZLj}$;yFeK@RG>9afSHITHBxXh2G^yrsmvA7!pspUHCn*#0yZ~e zXTe%tCSo;u;h6&OdBw!r7Z%!?MhY+!k#7hN*9T7F>q6&)Yn%MMa>VDX8$f5QaJZ1W zV1sidfJ$KB65z@gwo#xDVg-hv^iv9fCj@=G=%W%)(`4!6_!vRr69LV)DhAE0FDTAj z4+0~BC-@)&137C5Ak8WMl;Ien7BoTzNyof89Ege3B`|3~UJ5X1(?ZJBCA`Mejt_xw z1yBe=$66_G&-Npsm|(1ib~N8|+1~qV%M0o#$O| zNrga^h1S@^5=BSCyV75mavG~ArL%Lz;uePv;^e8E9f8^xsAqyady1mK(9>Uak~OxV td#zO2;3zIxC;I;i<|XISWT}WPe*tS8S^T5JYMcN7002ovPDHLkV1hp41xx?{ literal 0 HcmV?d00001 diff --git a/techage/textures/techage_sluice2_inv.png b/techage/textures/techage_sluice2_inv.png new file mode 100644 index 0000000000000000000000000000000000000000..80a4cb1efbdd11d3db5f416f7ff4ac740efe8f96 GIT binary patch literal 835 zcmV-J1HAl+P)P)t-sM{rDo zWgYQ9mYmT{UV{HBde!Ur8%mM=NJfEpk~nR6!_KLn&%gG-OOGg=axUH6eat zJyk*{KQJA0SvO8RBwI!+ns`VWSrz#J000hjQchCAT6rrTLwD0~xOC-LRwPd}vF zdDiV{Xjg`w*8nq%KJ@t?RE9PHCmrzF0E8lYRTn_Z$n|P(!{9^%ot60)Lj%k4tp>P> zFeKZx0Vm^lwp_ar036b#HUCN>56tsxfXxzwYXZ773<=vOqZVINkFUt*2Eau%0~bj{dB#q-{9}P_lSZ>0}$r-v(|ts1Nsb5 zBOo%q1t3Jg#}E`JcA*K#36g!3G(aM9Y1XX*lw=xQQmwq`x{YAYrleVUShBGKn8?S- z2k8y~sT7n7P<93T{9kv{GLcJMy|PehPffD3YivXWNT-xeogLe&GO{Kzd!2h2UtxeZ`y zH&FW&PN@k<98=1nS=$B>JJC#6^=fh_b|+{63|K1C4!|4%xSFc~&PAg|Kp6nXz%^Td z_<$>OrvR+sjLklH0AwekGN-QXM2o)CHvmy0ppfqG4Sfb8zaN1-=E8_{G^QVMc_Vu^ zvcYj|=w?^~RvIlYq}~H5X89CM-r{i_O$f}5ejNLhBJSM$uuukUPhkN>nGJ;u00JSv zV51QD!47~+i3qhlA8532W~qMxpDywSYawa!6~H|s$(N#k1`Jg$ZUCp!Z?KBI75N7t z$EF$*X!V^7Re-x)Ni3E7l=lEcX&H8-7QjrVmiYyM!!yA1D=|Ujxc~c5?q5!0!T%BKXs<>I)XVb9|!U67#f!QPGfY}@S$+wu| z)y*9=E!~}j7PH-9?#X6OVRSKiXx;U}sw8mk>xKRMgr-P8jBlI2?0k4m!0a0i?zN2j XZ8^@H9d}9v8qVP9>gTe~DWM4fzE?a+ literal 0 HcmV?d00001 diff --git a/techage/textures/techage_watermill1_inv.png b/techage/textures/techage_watermill1_inv.png new file mode 100644 index 0000000000000000000000000000000000000000..b7f26fcfd31787bdf3ee07d9e0dc5d01dd2ea11b GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPE^3h)VWbuaK)+ThumX;YtQ5bmrR zWUs7KxLFG*%UBZR7tG-B>_!@pqweYA7{YNqSs;OdS&eNDPZ}F5NApCDHb%DQ4Wd3g hhx*#iooYPg$k4o;+3TH1W7cWHK47|z7 Y5O<8};TOdVra;vUp00i_>zopr0RF}!jsO4v literal 0 HcmV?d00001 diff --git a/techage/textures/techage_watermill3_inv.png b/techage/textures/techage_watermill3_inv.png new file mode 100644 index 0000000000000000000000000000000000000000..e58e307c114d871f4b715780d4d174c2a5284a18 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9JOMr-uI>dsOB=l!l8nNgRa@4$ z^aI5iOM?7@862M7NCR@DJY5_^IIbrrD99N!a-<0ybP0l+XkKb>|>4 literal 0 HcmV?d00001 diff --git a/techage/textures/techage_watermill4_inv.png b/techage/textures/techage_watermill4_inv.png new file mode 100644 index 0000000000000000000000000000000000000000..8198c86bf7831571baca43fc8c7946f44911a643 GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPE^4e$wZbuaL#OE757v{}~Z72=@0 zu+F1B+xG5qfipk_j3q&S!3+-1ZlnP@cAhSdAsp9}1A=(W%=m(Xk_r+Sn8nx_IhrRr zG9F53>NHTkB5~jf$AXoKM-18}6;m4$`C?ApF!A&ZymCW=q1m3*@N%)dB+w)VPgg&e IbxsLQ06~W^jQ{`u literal 0 HcmV?d00001 diff --git a/techage/textures/techage_wood50.png b/techage/textures/techage_wood50.png new file mode 100644 index 0000000000000000000000000000000000000000..18914f2df86b11f938e6325d54fadbc9d62834dd GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPE^4e$wZbuaK)+Ta=Hq|%mYQ=e!s zx6(D)TkF>=KP{jF#*!evU