Cranks, shafts, and spruce trees.

This commit is contained in:
Signal 2026-05-09 16:01:10 -04:00
parent 4659a008ac
commit 9011835cf4
40 changed files with 1496 additions and 104 deletions

View file

@ -9,6 +9,8 @@ function extend(dst, src)
return dst
end
table.merge = extend
-- PHP-style helper verb
function include(file)
return dofile(minetest.get_modpath(minetest.get_current_modname()).."/"..file)
@ -59,7 +61,7 @@ EventTarget = {
local l = e.listeners[channel]
if not l then return end
for i = 1, #l do
l[i](...)
if l[i] then l[i](...) end
end
end
}
@ -70,15 +72,22 @@ setmetatable(EventTarget, {
StateMachine = {
init = function(obj, states)
local super = EventTarget()
local e = {
local e = table.merge(super, {
states = states,
active_states = {},
obj = obj
}
return setmetatable(e, {__index = super})
})
return setmetatable(e, {__index = StateMachine})
end,
add_state = function(e, state)
if e.active_states[state] then return false end
if e.states[state].excludes then
for i = 1, #e.states[state].excludes do
if e.active_states[e.states[state].excludes[i]] then
e:remove_state(e.states[state].excludes[i])
end
end
end
e.states[state]:add(e.obj)
e.active_states[state] = true
return true
@ -100,6 +109,40 @@ setmetatable(StateMachine, {
__index = EventTarget()
})
ModifierStack = {
init = function(mode)
local e = EventTarget()
extend(e, {
mode = mode or "add",
value = 0
})
return setmetatable(e, {__index = ModifierStack})
end,
set = function(e, key, value)
if key == "value" then return end
if e[key] then
if e.mode == "multiply" then
e.value = e.value /e[key]
else
e.value = e.value -e[key]
end
end
e[key] = value
if e[key] then
if e.mode == "multiply" then
e.value = e.value *e[key]
else
e.value = e.value +e[key]
end
end
e:dispatch("change")
end,
}
setmetatable(ModifierStack, {
__call = function(_, ...) return ModifierStack.init(...) end,
__index = EventTarget
})
rgt = {
adjacent_neighbor_offests = {
vector.new(0,0,1),
@ -117,6 +160,14 @@ rgt = {
vector.new(1,0,0),
vector.new(-1,0,0),
},
abutting_neighbor_offests = {
vector.new(0,0,1),
vector.new(0,0,-1),
vector.new(1,0,0),
vector.new(-1,0,0),
vector.new(0,1,0),
vector.new(0,-1,0),
},
nodes_to_content_ids = {},
content_ids_to_nodes = {},
vm_data = {},
@ -182,7 +233,11 @@ function ns.register_tool(name, def)
end
function ns.register_entity(name, def)
minetest.register_entity(name, def)
def._name = name
if not name:find(":") then
name = "red_glazed_terracotta:"..name
end
minetest.register_entity(":"..name, def)
end
-- Make node dig particles denser.
@ -207,6 +262,46 @@ minetest.register_on_dignode(function(pos, node, digger)
})
end)
-- HACK: Lookup table for getting a rotation from a
-- facedir (because Minetest doesn't have any way
-- to get this information normally)
local facedir_rotations = {
-- +Y
[0] = vector.new(0, 0, 0),
[1] = vector.new(0, math.pi * 1.5, 0),
[2] = vector.new(0, math.pi * 1.0, 0),
[3] = vector.new(0, math.pi * 0.5, 0),
-- +Z
[4] = vector.new(math.pi * 1.5, 0, 0),
[5] = vector.new(0, math.pi * 1.5, math.pi * 1.5),
[6] = vector.new(math.pi * 0.5, math.pi * 1.0, 0),
[7] = vector.new(0, math.pi * 0.5, math.pi * 0.5),
-- -Z
[8] = vector.new(math.pi * 0.5, 0, 0),
[9] = vector.new(0, math.pi * 1.5, math.pi * 0.5),
[10] = vector.new(math.pi * 1.5, math.pi * 1.0, 0),
[11] = vector.new(0, math.pi * 0.5, math.pi * 1.5),
-- +X
[12] = vector.new(0, 0, math.pi * 0.5),
[13] = vector.new(math.pi * 1.5, math.pi * 1.5, 0),
[14] = vector.new(0, math.pi * 1.0, math.pi * 1.5),
[15] = vector.new(math.pi * 0.5, math.pi * 0.5, 0),
-- -X
[16] = vector.new(0, 0, math.pi * 1.5),
[17] = vector.new(math.pi * 0.5, math.pi * 1.5, 0),
[18] = vector.new(0, math.pi * 1.0, math.pi * 0.5),
[19] = vector.new(math.pi * 1.5, math.pi * 0.5, 0),
-- -Y
[20] = vector.new(0, 0, math.pi * 1.0),
[21] = vector.new(0, math.pi * 0.5, math.pi * 1.0),
[22] = vector.new(0, math.pi * 1.0, math.pi * 1.0),
[23] = vector.new(0, math.pi * 1.5, math.pi * 1.0),
}
function ns.facedir_to_rotation(facedir)
return facedir_rotations[facedir] or minetest.facedir_to_dir(facedir):dir_to_rotation()
end
-- Fills the area from pos1 to pos2 with the node named `node`.
function ns.fill_area(pos1, pos2, node)
local minp = vector.new(math.min(pos1.x, pos2.x), math.min(pos1.y, pos2.y), math.min(pos1.z, pos2.z))
@ -255,6 +350,18 @@ function ns.get_node_meta(pos)
return setmetatable({_pos = tostring(minetest.hash_node_position(pos))}, NodeMetaRef)
end
ns.clock = EventTarget()
local seconds = minetest.get_us_time()
minetest.register_globalstep(function(dtime)
ns.clock:dispatch("tick", dtime)
local time = minetest.get_us_time()
if time - seconds >= 1000000 then
ns.clock:dispatch("every_second", dtime)
seconds = time
end
end)
-- Allow nodes to provide a callback to run on activation without
-- needing to register a bunch of mostly identical LBMs.
minetest.register_lbm {