techage_modpack/techage/ta1_watermill/watermill.lua
2023-11-05 13:18:27 +01:00

320 lines
9.2 KiB
Lua

--[[
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 == "default:water_flowing" or node.name == "default:river_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 == "default:water_flowing" or node.name == "default:river_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.5, 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_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 = "",
})
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"},
},
})