Cranks, shafts, and spruce trees.
This commit is contained in:
parent
4659a008ac
commit
9011835cf4
40 changed files with 1496 additions and 104 deletions
|
|
@ -4,4 +4,104 @@ rgt_machines = {
|
|||
}
|
||||
local ns = rgt_machines
|
||||
|
||||
-- Recursively propagate a network reassignment to all connected nodes (ignoring positions in `ignore`).
|
||||
local function propagate_network_update(pos, net, net_type, ignore)
|
||||
ignore[minetest.hash_node_position(pos)] = true
|
||||
-- Store the network to the target node.
|
||||
local m = minetest.get_meta(pos)
|
||||
m:set_string("network", net)
|
||||
m:set_string("network_type", net_type)
|
||||
-- Check each neighboring node for further propagation.
|
||||
for _, x in ipairs(rgt.adjacent_neighbor_offests) do
|
||||
-- If we already checked this node, we shouldn't consider it to avoid infinite recursion.
|
||||
if not ignore[minetest.hash_node_position(pos +x)] then
|
||||
local ncid, _, nparam2 = minetest.get_node_raw(pos.x +x.x, pos.y +x.y, pos.z +x.z)
|
||||
local ndef = minetest.registered_nodes[rgt.content_ids_to_nodes[ncid]]
|
||||
-- Ensure that this node can belong to a network and thus is a valid propagation target.
|
||||
if ndef._network_can_accept and ndef._network_can_accept(pos, nparam2) then
|
||||
propagate_network_update(pos +x, net, ignore)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Called when a pos is added to or removed from a network.
|
||||
-- Whether an addition or deletion is being performed depends on whether the node at `pos` belongs to the `network_component` group.
|
||||
function ns.update_network(pos, net_type)
|
||||
local cid, _, param2 = minetest.get_node_raw(pos.x, pos.y, pos.z)
|
||||
local def = minetest.registered_nodes[rgt.content_ids_to_nodes[cid]]
|
||||
-- We're adding a node.
|
||||
if def._network_neighbors then
|
||||
-- Find all adjacent networks.
|
||||
local net
|
||||
local nets = {}
|
||||
local num_nets = 0
|
||||
for _, x in ipairs(def._network_neighbors(pos, param2)) do
|
||||
local ncid, _, nparam2 = minetest.get_node_raw(pos.x +x.x, pos.y +x.y, pos.z +x.z)
|
||||
local ndef = minetest.registered_nodes[rgt.content_ids_to_nodes[ncid]]
|
||||
-- Ensure that this node can accept a network propagation from this position.
|
||||
if ndef._network_can_accept and ndef._network_can_accept(pos, nparam2) then
|
||||
local m = minetest.get_meta(pos +x)
|
||||
local n = m:get("network")
|
||||
local nt = m:get("network_type")
|
||||
-- If the node doesn't have a network for some reason, we should give it one.
|
||||
if nt == net_type and not n or table.indexof(nets, n) == -1 then
|
||||
-- Set our network to the first one we find.
|
||||
if not net then
|
||||
net = n
|
||||
-- Store the positions of any other adjacent networks, so we can merge them with ours.
|
||||
elseif net ~= n then
|
||||
nets[#nets +1] = x
|
||||
end
|
||||
num_nets = num_nets +1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Propagate our chosen network to adjacent networks with different IDs.
|
||||
-- If we didn't find any adjacent networks, this will just do nothing.
|
||||
local ignore = {[minetest.hash_node_position(pos)] = true}
|
||||
for _, x in ipairs(nets) do
|
||||
propagate_network_update(pos +x, net, net_type, ignore)
|
||||
end
|
||||
|
||||
-- Create a new unique network ID if none of our neighbors have one.
|
||||
if not net then
|
||||
net = string.format("net_%d_%06d", minetest.get_us_time(), math.random(100000, 999999))
|
||||
end
|
||||
|
||||
-- Save our chosen network ID.
|
||||
local m = minetest.get_meta(pos)
|
||||
m:set_string("network", net)
|
||||
m:set_string("network_type", net_type)
|
||||
-- We're removing a node.
|
||||
else
|
||||
-- Find all adjacent networks.
|
||||
local net
|
||||
local nets = {}
|
||||
for _, x in ipairs(rgt.adjacent_neighbor_offests) do
|
||||
local ncid, _, nparam2 = minetest.get_node_raw(pos.x +x.x, pos.y +x.y, pos.z +x.z)
|
||||
local ndef = minetest.registered_nodes[rgt.content_ids_to_nodes[ncid]]
|
||||
-- Ensure that this node can accept a network propagation from this position.
|
||||
if ndef._network_can_accept and ndef._network_can_accept(pos, nparam2) then
|
||||
local m = minetest.get_meta(pos +x)
|
||||
local n = m:get("network")
|
||||
local nt = m:get("network_type")
|
||||
if nt == net_type then
|
||||
nets[#nets +1] = x
|
||||
end
|
||||
end
|
||||
end
|
||||
-- We only need to ensure that these networks are unique, thus one of them can keep its original ID.
|
||||
if #nets > 1 then table.remove(nets, 1) end
|
||||
|
||||
-- Create a new ID for each network and propagate it.
|
||||
local pos_hash = minetest.hash_node_position(pos)
|
||||
for _, x in ipairs(nets) do
|
||||
net = string.format("net_%d_%06d", minetest.get_us_time(), math.random(100000, 999999))
|
||||
-- Provide a different ignore table each time, to ensure that when the same network abuts this node on multiple edges, all touching nodes get the same network in the end.
|
||||
propagate_network_update(pos +x, net, net_type, {[pos_hash] = true})
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ end
|
|||
|
||||
-- Called when a pos is added to or removed from a network.
|
||||
-- Whether an addition or deletion is being performed depends on whether the node at `pos` belongs to the `network_component` group.
|
||||
function ns.update_network(pos)
|
||||
function ns.update_network_(pos)
|
||||
-- We're adding a node.
|
||||
if minetest.get_item_group(minetest.get_node(pos).name, "network_component") > 0 then
|
||||
-- Find all adjacent networks.
|
||||
|
|
|
|||
|
|
@ -1,22 +1,631 @@
|
|||
local ns = rgt_machines
|
||||
|
||||
ns.components = {}
|
||||
local db = minetest.get_mod_storage()
|
||||
|
||||
--[[
|
||||
{
|
||||
name = "...", -- The component's name.
|
||||
attach_points
|
||||
local shaft_networks = {}
|
||||
|
||||
local shafts = {}
|
||||
|
||||
local ShaftNetwork
|
||||
ShaftNetwork = {
|
||||
init = function(id)
|
||||
local e = {
|
||||
id = id,
|
||||
torque = ModifierStack(),
|
||||
load = ModifierStack(),
|
||||
inertia = ModifierStack(),
|
||||
alpha = 0,
|
||||
omega = 0,
|
||||
angle = 0,
|
||||
}
|
||||
setmetatable(e, {__index = ShaftNetwork})
|
||||
local saved = minetest.deserialize(db:get(id))
|
||||
if saved then
|
||||
e:read(saved)
|
||||
end
|
||||
function e._update() e:update() end
|
||||
e.torque:listen("change", e._update)
|
||||
e.inertia:listen("change", e._update)
|
||||
function e._tick(...) e:tick(...) end
|
||||
rgt.clock:listen("tick", e._tick)
|
||||
return e
|
||||
end,
|
||||
deinit = function(e)
|
||||
e:save()
|
||||
rgt.clock:unlisten("tick", e._tick)
|
||||
end,
|
||||
read = function(e, saved)
|
||||
for k, v in pairs(saved.torque) do
|
||||
e.torque:set(k, v)
|
||||
end
|
||||
for k, v in pairs(saved.load) do
|
||||
e.load:set(k, v)
|
||||
end
|
||||
for k, v in pairs(saved.inertia) do
|
||||
e.inertia:set(k, v)
|
||||
end
|
||||
e.alpha = saved.alpha
|
||||
e.omega = saved.omega
|
||||
end,
|
||||
store = function(e)
|
||||
local out = {
|
||||
torque = {},
|
||||
load = {},
|
||||
inertia = {},
|
||||
alpha = e.alpha,
|
||||
omega = e.omega,
|
||||
angle = e.angle,
|
||||
}
|
||||
for k, v in pairs(e.torque) do
|
||||
if k ~= "value" and k ~= "mode" and k ~= "listeners" then out.torque[k] = v end
|
||||
end
|
||||
for k, v in pairs(e.load) do
|
||||
if k ~= "value" and k ~= "mode" and k ~= "listeners" then out.load[k] = v end
|
||||
end
|
||||
for k, v in pairs(e.inertia) do
|
||||
if k ~= "value" and k ~= "mode" and k ~= "listeners" then out.inertia[k] = v end
|
||||
end
|
||||
return out
|
||||
end,
|
||||
save = function(e)
|
||||
db:set_string(e.id, minetest.serialize(e:store()))
|
||||
end,
|
||||
tick = function(e, dtime)
|
||||
local constant_load = math.max(0, math.abs(e.torque.value) -e.load.value) *math.sign(e.torque.value)
|
||||
local net_torque = constant_load -(5 *e.omega)
|
||||
e.alpha = net_torque /e.inertia.value
|
||||
e.omega = e.omega +(e.alpha *dtime)
|
||||
|
||||
if math.abs(e.omega) < 0.05 then
|
||||
e.alpha = 0
|
||||
e.omega = 0
|
||||
end
|
||||
|
||||
e.angle = (e.angle +(e.omega *dtime)) %(math.pi *200)
|
||||
|
||||
for i = 1, #e do
|
||||
e[i]:set_angle(e.angle)
|
||||
end
|
||||
end,
|
||||
update = function(e, dtime)
|
||||
end,
|
||||
}
|
||||
setmetatable(ShaftNetwork, {
|
||||
__call = function(_, ...)
|
||||
return ShaftNetwork.init(...)
|
||||
end
|
||||
})
|
||||
|
||||
local function propagate_shaft_update(pos, net, ignore)
|
||||
local cid, _, param2 = minetest.get_node_raw(pos.x, pos.y, pos.z)
|
||||
local def = minetest.registered_nodes[rgt.content_ids_to_nodes[cid]]
|
||||
local hashed_pos = minetest.hash_node_position(pos)
|
||||
ignore[hashed_pos] = true
|
||||
-- Store the network to the target node.
|
||||
local m = minetest.get_meta(pos)
|
||||
local old_net = m:get("network")
|
||||
if shaft_networks[old_net] then
|
||||
for i = 1, #shaft_networks[old_net] do
|
||||
local e = shaft_networks[old_net][i]
|
||||
if e and e.pos == pos then
|
||||
if not shaft_networks[net] then
|
||||
shaft_networks[net] = ShaftNetwork(net)
|
||||
shaft_networks[net]:read(shaft_networks[old_net]:store())
|
||||
end
|
||||
e:change_network(net)
|
||||
end
|
||||
end
|
||||
end
|
||||
m:set_string("network", net)
|
||||
-- Check each neighboring node for further propagation.
|
||||
for _, x in ipairs(def._network_neighbors(pos, param2)) do
|
||||
-- If we already checked this node, we shouldn't consider it to avoid infinite recursion.
|
||||
if not ignore[minetest.hash_node_position(x)] then
|
||||
local ncid, _, nparam2 = minetest.get_node_raw(x.x, x.y, x.z)
|
||||
local ndef = minetest.registered_nodes[rgt.content_ids_to_nodes[ncid]]
|
||||
-- Ensure that this node can belong to a network and thus is a valid propagation target.
|
||||
if ndef and minetest.get_item_group(ndef.name, "shaft") > 0 and ndef._network_can_accept and ndef._network_can_accept(x, pos, nparam2) then
|
||||
propagate_shaft_update(x, net, ignore)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ns.update_shaft(pos, removing, ignore)
|
||||
local cid, _, param2 = minetest.get_node_raw(pos.x, pos.y, pos.z)
|
||||
local def = minetest.registered_nodes[rgt.content_ids_to_nodes[cid]]
|
||||
|
||||
if not removing then
|
||||
-- Find all adjacent networks.
|
||||
local net
|
||||
local nets = {}
|
||||
local num_nets = 0
|
||||
for _, x in ipairs(def._network_neighbors(pos, param2)) do
|
||||
local ncid, _, nparam2 = minetest.get_node_raw(x.x, x.y, x.z)
|
||||
local ndef = minetest.registered_nodes[rgt.content_ids_to_nodes[ncid]]
|
||||
-- Ensure that this node can accept a network propagation from this position.
|
||||
if ndef and minetest.get_item_group(ndef.name, "shaft") > 0 and ndef._network_can_accept and ndef._network_can_accept(x, pos, nparam2) then
|
||||
local m = minetest.get_meta(x)
|
||||
local n = m:get("network")
|
||||
-- If the node doesn't have a network for some reason, we should give it one.
|
||||
if not n or table.indexof(nets, n) == -1 then
|
||||
-- Set our network to the first one we find.
|
||||
if not net then
|
||||
net = n
|
||||
-- Store the positions of any other adjacent networks, so we can merge them with ours.
|
||||
elseif net ~= n then
|
||||
nets[#nets +1] = x
|
||||
end
|
||||
num_nets = num_nets +1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a new unique network ID if none of our neighbors have one.
|
||||
if not net then
|
||||
net = string.format("net_%d_%06d", minetest.get_us_time(), math.random(100000, 999999))
|
||||
end
|
||||
|
||||
-- Propagate our chosen network to adjacent networks with different IDs.
|
||||
-- If we didn't find any adjacent networks, this will just do nothing.
|
||||
local ignore = {[minetest.hash_node_position(pos)] = true}
|
||||
for _, x in ipairs(nets) do
|
||||
propagate_shaft_update(x, net, ignore)
|
||||
end
|
||||
|
||||
-- Save our chosen network ID.
|
||||
local m = minetest.get_meta(pos)
|
||||
m:set_string("network", net)
|
||||
return net
|
||||
else
|
||||
-- Find all adjacent networks.
|
||||
local net
|
||||
local nets = {}
|
||||
for _, x in ipairs(def._network_neighbors(pos, param2)) do
|
||||
local ncid, _, nparam2 = minetest.get_node_raw(x.x, x.y, x.z)
|
||||
local ndef = minetest.registered_nodes[rgt.content_ids_to_nodes[ncid]]
|
||||
-- Ensure that this node can accept a network propagation from this position.
|
||||
if ndef and minetest.get_item_group(ndef.name, "shaft") > 0 and ndef._network_can_accept and ndef._network_can_accept(x, pos, nparam2) then
|
||||
local m = minetest.get_meta(x)
|
||||
local n = m:get("network")
|
||||
nets[#nets +1] = x
|
||||
end
|
||||
end
|
||||
-- We only need to ensure that these networks are unique, thus one of them can keep its original ID.
|
||||
-- if #nets > 0 then table.remove(nets, 1) end
|
||||
|
||||
-- Create a new ID for each network and propagate it.
|
||||
local pos_hash = minetest.hash_node_position(pos)
|
||||
for i, x in ipairs(nets) do
|
||||
net = string.format("net_%d_%06d", minetest.get_us_time(), math.random(100000, 999999))
|
||||
-- Provide a different ignore table each time, to ensure that when the same network abuts this node on multiple edges, all touching nodes get the same network in the end.
|
||||
propagate_shaft_update(x, net, {[pos_hash] = true, color = i == 1 and "red" or "blue"})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rgt.register_entity("shaft", {
|
||||
initial_properties = {
|
||||
visual = "mesh",
|
||||
mesh = "rgt_shaft.gltf",
|
||||
textures = {"rgt_shaft.png"},
|
||||
pointable = false,
|
||||
},
|
||||
on_activate = function(e, data)
|
||||
e.pos = e.object:get_pos():round()
|
||||
|
||||
if shafts[minetest.hash_node_position(e.pos)] or not minetest.get_node(e.pos).name:find "shaft" then
|
||||
e.object:remove()
|
||||
return
|
||||
end
|
||||
extend(e, minetest.deserialize(data or "return {}"))
|
||||
|
||||
e.omega = 0
|
||||
e.angle = e.angle or 0
|
||||
|
||||
e.object:set_armor_groups{immortal = 1}
|
||||
|
||||
e.object:set_rotation(e.rotation)
|
||||
|
||||
shafts[minetest.hash_node_position(e.pos)] = e
|
||||
if not shaft_networks[e.net] then
|
||||
shaft_networks[e.net] = ShaftNetwork(e.net)
|
||||
end
|
||||
e:set_angle(shaft_networks[e.net].angle)
|
||||
shaft_networks[e.net].inertia:set(e.pos:to_string(), 1)
|
||||
table.insert(shaft_networks[e.net], e)
|
||||
end,
|
||||
on_deactivate = function(e)
|
||||
shafts[minetest.hash_node_position(e.pos)] = nil
|
||||
if not shaft_networks[e.net][1] then
|
||||
table.remove(shaft_networks[e.net], table.indexof(shaft_networks[e.net], e))
|
||||
shaft_networks[e.net]:deinit()
|
||||
shaft_networks[e.net] = nil
|
||||
end
|
||||
end,
|
||||
get_staticdata = function(e)
|
||||
return minetest.serialize{rotation = e.rotation, invert = e.invert, net = e.net}
|
||||
end,
|
||||
|
||||
change_network = function(e, new_net)
|
||||
say("Changed network at "..e.pos:to_string().." from "..e.net.." to "..new_net)
|
||||
local net = shaft_networks[e.net]
|
||||
net.inertia:set(e.pos:to_string(), nil)
|
||||
table.remove(net, table.indexof(net, e))
|
||||
e.net = new_net
|
||||
if not shaft_networks[e.net] then
|
||||
shaft_networks[e.net] = ShaftNetwork(e.net)
|
||||
end
|
||||
table.insert(shaft_networks[e.net], e)
|
||||
shaft_networks[e.net].inertia:set(e.pos:to_string(), 1)
|
||||
end,
|
||||
set_angle = function(e, angle)
|
||||
-- e.object:set_properties {
|
||||
-- nametag = e.net
|
||||
-- }
|
||||
e.object:set_bone_override("root", {
|
||||
rotation = {
|
||||
vec = vector.new(0, 0, e.invert and angle or -angle),
|
||||
interpolation = 0.1,
|
||||
absolute = true
|
||||
}
|
||||
})
|
||||
end
|
||||
})
|
||||
|
||||
local shaft_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
-3/16, -3/16, -0.5,
|
||||
3/16, 3/16, 0.5
|
||||
}
|
||||
--]]
|
||||
function ns.register_component(def)
|
||||
ns.components[def.name] = def
|
||||
end
|
||||
}
|
||||
|
||||
function ns.register_plate(name, def)
|
||||
rgt.register_item(name, def)
|
||||
end
|
||||
rgt.register_node("shaft", {
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
selection_box = shaft_box,
|
||||
collision_box = shaft_box,
|
||||
groups = {shaft = 1, dig_immediate = 3},
|
||||
entities = shafts,
|
||||
|
||||
on_place = function(s, p, pt)
|
||||
local under = minetest.get_node(pt.under)
|
||||
if under.name == "red_glazed_terracotta:shaft" then
|
||||
return minetest.item_place_node(s, p, pt, under.param2)
|
||||
end
|
||||
|
||||
if not p:get_player_control().sneak then
|
||||
local target = minetest.registered_nodes[under.name].buildable_to and pt.under or pt.above
|
||||
for _, neighbor in ipairs(minetest.find_nodes_in_area(target:offset(-1,-1,-1), target:offset(1,1,1), "shaft")) do
|
||||
if neighbor:distance(target) <= 1 then
|
||||
return minetest.item_place_node(s, p, pt, minetest.get_node(neighbor).param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return minetest.item_place_node(s, p, pt)
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
|
||||
local net = ns.update_shaft(pos)
|
||||
minetest.add_entity(pos, "red_glazed_terracotta:shaft", minetest.serialize{rotation = rgt.facedir_to_rotation(param2), invert = dir.x < 0 or dir.z < 0, net = net})
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
local e = shafts[minetest.hash_node_position(pos)]
|
||||
shaft_networks[e.net].inertia:set(pos:to_string(), nil)
|
||||
e.object:remove()
|
||||
shafts[minetest.hash_node_position(pos)] = nil
|
||||
ns.update_shaft(pos, true)
|
||||
end,
|
||||
|
||||
_network_can_accept = function(pos, from, param2)
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
|
||||
return dir:abs() == from:direction(pos):abs()
|
||||
end,
|
||||
_network_neighbors = function(pos, param2)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
|
||||
return {pos +dir, pos -dir}
|
||||
end,
|
||||
})
|
||||
|
||||
local hand_cranks = {}
|
||||
|
||||
rgt.register_entity("hand_crank", {
|
||||
initial_properties = {
|
||||
visual = "mesh",
|
||||
mesh = "rgt_hand_crank.gltf",
|
||||
textures = {"rgt_hand_crank.png"},
|
||||
pointable = false
|
||||
},
|
||||
on_activate = function(e, data)
|
||||
e.pos = e.object:get_pos():round()
|
||||
|
||||
if hand_cranks[minetest.hash_node_position(e.pos)] or not minetest.get_node(e.object:get_pos()).name:find "hand_crank" then
|
||||
e.object:remove()
|
||||
return
|
||||
end
|
||||
extend(e, minetest.deserialize(data or "return {}"))
|
||||
|
||||
e.rotation = vector.new(e.rotation.x, e.rotation.y, e.rotation.z)
|
||||
|
||||
e.torque = 0
|
||||
e.omega = 0
|
||||
e.angle = e.angle or 0
|
||||
|
||||
e.object:set_armor_groups{immortal = 1}
|
||||
|
||||
e.object:set_rotation(e.rotation)
|
||||
|
||||
hand_cranks[minetest.hash_node_position(e.pos)] = e
|
||||
if not shaft_networks[e.net] then
|
||||
shaft_networks[e.net] = ShaftNetwork(e.net)
|
||||
end
|
||||
e:set_angle(shaft_networks[e.net].angle)
|
||||
shaft_networks[e.net].inertia:set(e.pos:to_string(), 1)
|
||||
table.insert(shaft_networks[e.net], e)
|
||||
end,
|
||||
on_deactivate = function(e)
|
||||
hand_cranks[minetest.hash_node_position(e.pos)] = nil
|
||||
table.remove(shaft_networks[e.net], table.indexof(shaft_networks[e.net], e))
|
||||
if not shaft_networks[e.net][1] then
|
||||
db:set_string(e.net, minetest.serialize(shaft_networks[e.net]))
|
||||
shaft_networks[e.net] = nil
|
||||
end
|
||||
end,
|
||||
get_staticdata = function(e)
|
||||
return minetest.serialize{rotation = e.rotation, invert = e.invert, net = e.net}
|
||||
end,
|
||||
on_step = function(e, dtime)
|
||||
if not e.cranking then
|
||||
e:set_torque(math.max(0, e.torque -1))
|
||||
end
|
||||
end,
|
||||
|
||||
change_network = function(e, new_net)
|
||||
local net = shaft_networks[e.net]
|
||||
net.inertia:set(e.pos:to_string(), nil)
|
||||
net.torque:set(e.pos:to_string(), nil)
|
||||
table.remove(net, table.indexof(net, e))
|
||||
e.net = new_net
|
||||
if not shaft_networks[e.net] then
|
||||
shaft_networks[e.net] = ShaftNetwork(e.net)
|
||||
end
|
||||
table.insert(shaft_networks[e.net], e)
|
||||
shaft_networks[e.net].inertia:set(e.pos:to_string(), 1)
|
||||
shaft_networks[e.net].torque:set(e.pos:to_string(), e.torque)
|
||||
end,
|
||||
add_torque = function(e)
|
||||
e:set_torque(math.min(20, e.torque +1))
|
||||
end,
|
||||
set_torque = function(e, torque)
|
||||
if torque ~= e.torque then
|
||||
e.torque = torque
|
||||
local net = shaft_networks[e.net]
|
||||
net.torque:set(e.pos:to_string(), e.torque)
|
||||
end
|
||||
end,
|
||||
set_angle = function(e, angle)
|
||||
-- local net = shaft_networks[e.net]
|
||||
-- e.object:set_properties {
|
||||
-- nametag = string.format("Torque: %s\nLoad: %s\nI: %s\na: %s\nw: %s\nangle: %s", net.torque.value, net.load.value, net.inertia.value, net.alpha, net.omega, net.angle)
|
||||
-- }
|
||||
e.object:set_bone_override("root", {
|
||||
rotation = {
|
||||
vec = vector.new(0, 0, e.invert and angle or -angle),
|
||||
interpolation = 0.1,
|
||||
absolute = true
|
||||
}
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
local function do_crank(m)
|
||||
local crank = hand_cranks[m.cranking]
|
||||
if not crank then return m:unlisten("tick", do_crank) end
|
||||
if not m.ctl.place or not m.pointed_node or m.pointed_node.under ~= crank.pos then
|
||||
m:unlisten("tick", do_crank)
|
||||
crank.cranking = nil
|
||||
m.cranking = nil
|
||||
return
|
||||
end
|
||||
|
||||
crank:add_torque()
|
||||
end
|
||||
|
||||
rgt.register_node("hand_crank", {
|
||||
mesh = "rgt_hand_crank.gltf"
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
-0.5, -0.5, 0.5,
|
||||
0.5, 0.5, 6/16
|
||||
}
|
||||
},
|
||||
groups = {shaft = 2, dig_immediate = 3},
|
||||
entities = hand_cranks,
|
||||
|
||||
on_construct = function(pos)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
local angle
|
||||
|
||||
local back = minetest.get_node(pos +dir)
|
||||
if back.name:find "shaft" then
|
||||
angle = shafts[minetest.hash_node_position(pos +dir)].angle
|
||||
end
|
||||
|
||||
minetest.add_entity(pos, "red_glazed_terracotta:hand_crank", minetest.serialize{rotation = rgt.facedir_to_rotation(minetest.get_node(pos).param2), angle = angle, invert = dir.x < 0 or dir.z < 0, net = ns.update_shaft(pos)})
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
local e = hand_cranks[minetest.hash_node_position(pos)]
|
||||
shaft_networks[e.net].inertia:set(e.pos:to_string(), nil)
|
||||
e.object:remove()
|
||||
hand_cranks[minetest.hash_node_position(pos)] = nil
|
||||
ns.update_shaft(pos)
|
||||
end,
|
||||
on_rightclick = function(pos, node, p, s, pt)
|
||||
local m = rgt.players[p:get_player_name()]
|
||||
if m.cranking then return end
|
||||
m.cranking = minetest.hash_node_position(pos)
|
||||
hand_cranks[m.cranking].cranking = true
|
||||
m:listen("tick", do_crank)
|
||||
end,
|
||||
|
||||
_network_can_accept = function(pos, from, param2)
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
|
||||
return dir == pos:direction(from)
|
||||
end,
|
||||
_network_neighbors = function(pos, param2)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
local angle
|
||||
|
||||
local back = minetest.get_node_raw(pos.x +dir.x, pos.y +dir.y, pos.z +dir.z)
|
||||
if minetest.get_item_group(rgt.content_ids_to_nodes[back], "shaft") > 0 then
|
||||
return {pos +dir}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
})
|
||||
|
||||
local load_testers = {}
|
||||
|
||||
rgt.register_entity("shaft_load_tester", {
|
||||
initial_properties = {
|
||||
visual = "mesh",
|
||||
mesh = "rgt_shaft.gltf",
|
||||
textures = {"rgt_shaft.png"},
|
||||
pointable = false,
|
||||
},
|
||||
on_activate = function(e, data)
|
||||
e.pos = e.object:get_pos():round()
|
||||
|
||||
if load_testers[minetest.hash_node_position(e.pos)] or not minetest.get_node(e.pos).name:find "shaft_load_tester" then
|
||||
e.object:remove()
|
||||
return
|
||||
end
|
||||
extend(e, minetest.deserialize(data or "return {}"))
|
||||
|
||||
e.torque = 0
|
||||
e.omega = 0
|
||||
e.angle = e.angle or 0
|
||||
|
||||
e.object:set_armor_groups{immortal = 1}
|
||||
|
||||
e.object:set_rotation(e.rotation)
|
||||
|
||||
e.object:set_bone_override("root", {
|
||||
rotation = {
|
||||
vec = vector.new(0, 0, -e.angle),
|
||||
interpolation = 0,
|
||||
absolute = true
|
||||
}
|
||||
})
|
||||
|
||||
load_testers[minetest.hash_node_position(e.pos)] = e
|
||||
if not shaft_networks[e.net] then
|
||||
shaft_networks[e.net] = ShaftNetwork(e.net)
|
||||
end
|
||||
shaft_networks[e.net].inertia:set(e.pos:to_string(), 2)
|
||||
shaft_networks[e.net].load:set(e.pos:to_string(), 4)
|
||||
table.insert(shaft_networks[e.net], e)
|
||||
end,
|
||||
on_deactivate = function(e)
|
||||
load_testers[minetest.hash_node_position(e.pos)] = nil
|
||||
if not shaft_networks[e.net][1] then
|
||||
table.remove(shaft_networks[e.net], table.indexof(shaft_networks[e.net], e))
|
||||
shaft_networks[e.net]:save()
|
||||
shaft_networks[e.net] = nil
|
||||
end
|
||||
end,
|
||||
get_staticdata = function(e)
|
||||
return minetest.serialize{rotation = e.rotation, angle = e.angle, net = e.net}
|
||||
end,
|
||||
on_step = function(e, dtime)
|
||||
if e.omega == 0 then return end
|
||||
|
||||
minetest.after(0, function()
|
||||
e.angle = (e.angle +(e.omega *dtime)) %(math.pi *2)
|
||||
e.object:set_bone_override("root", {
|
||||
rotation = {
|
||||
vec = vector.new(0, 0, -e.angle),
|
||||
interpolation = 0.1,
|
||||
absolute = true
|
||||
}
|
||||
})
|
||||
end)
|
||||
end,
|
||||
|
||||
set_angular_velocity = function(e, w)
|
||||
e.omega = w
|
||||
end,
|
||||
})
|
||||
|
||||
rgt.register_node("shaft_load_tester", {
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
-0.5, -0.5, 0.5,
|
||||
0.5, 0.5, 6/16
|
||||
}
|
||||
},
|
||||
groups = {shaft = 2, dig_immediate = 3},
|
||||
entities = load_testers,
|
||||
|
||||
on_construct = function(pos)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
local angle
|
||||
|
||||
local back = minetest.get_node(pos +dir)
|
||||
if back.name:find "shaft" then
|
||||
angle = shafts[minetest.hash_node_position(pos +dir)].angle
|
||||
end
|
||||
|
||||
minetest.add_entity(pos, "red_glazed_terracotta:shaft_load_tester", minetest.serialize{rotation = rgt.facedir_to_rotation(minetest.get_node(pos).param2), angle = angle, invert = dir.z < 0 or dir.z < 0, net = ns.update_shaft(pos)})
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
load_testers[minetest.hash_node_position(pos)].object:remove()
|
||||
load_testers[minetest.hash_node_position(pos)] = nil
|
||||
ns.update_shaft(pos)
|
||||
end,
|
||||
on_rightclick = function(pos, node, p, s, pt)
|
||||
local m = rgt.players[p:get_player_name()]
|
||||
if m.cranking then return end
|
||||
m.cranking = minetest.hash_node_position(pos)
|
||||
load_testers[m.cranking].cranking = true
|
||||
m:listen("tick", do_crank)
|
||||
end,
|
||||
|
||||
_network_can_accept = function(pos, from, param2)
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
|
||||
return dir == pos:direction(from)
|
||||
end,
|
||||
_network_neighbors = function(pos, param2)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
local angle
|
||||
|
||||
local back = minetest.get_node_raw(pos.x +dir.x, pos.y +dir.y, pos.z +dir.z)
|
||||
if minetest.get_item_group(rgt.content_ids_to_nodes[back], "shaft") > 0 then
|
||||
return {pos +dir}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
})
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[2],"name":"blockbench_export"}],"scene":0,"nodes":[{"name":"cube","mesh":0},{"name":"root","children":[0]},{"children":[1]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":840,"byteLength":16},{"buffer":0,"byteOffset":856,"byteLength":64}],"buffers":[{"byteLength":920,"uri":"data:application/octet-stream;base64,AADwPwAA8D8AAKBAAADwPwAA8D8AAKDAAADwPwAA8L8AAKBAAADwPwAA8L8AAKDAAADwvwAA8D8AAKDAAADwvwAA8D8AAKBAAADwvwAA8L8AAKDAAADwvwAA8L8AAKBAAADwvwAA8D8AAKDAAADwPwAA8D8AAKDAAADwvwAA8D8AAKBAAADwPwAA8D8AAKBAAADwvwAA8L8AAKBAAADwPwAA8L8AAKBAAADwvwAA8L8AAKDAAADwPwAA8L8AAKDAAADwvwAA8D8AAKBAAADwPwAA8D8AAKBAAADwvwAA8L8AAKBAAADwPwAA8L8AAKBAAADwPwAA8D8AAKDAAADwvwAA8D8AAKDAAADwPwAA8L8AAKDAAADwvwAA8L8AAKDAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAAA/AAAAAAAAAAAAAEA+AAAAPwAAQD4AAAAAAABAPgAAAD8AAEA+AAAAAAAAwD4AAAA/AADAPgAAQD4AAGA/AAAAAAAAYD8AAEA+AADAPgAAAAAAAMA+AADAPgAAwD4AAEA+AADAPgAAwD4AAGA/AABAPgAAYD8AAAA/AAAAAAAAMD8AAAAAAAAAPwAAQD4AADA/AABAPgAAwD4AAMA+AAAQPwAAwD4AAMA+AAAQPwAAED8AABA/AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUAAAAAAKuqqj6rqio/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAANezXb8AAAA/AAAAAAAAAIDXs12/AAAAvwAAAAAAAACAMjENpQAAgL8="}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1.875,1.875,5],"min":[-1.875,-1.875,-5],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0.6875,0.875],"min":[0,0],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"},{"bufferView":4,"componentType":5126,"count":4,"max":[1],"min":[0],"type":"SCALAR"},{"bufferView":5,"componentType":5126,"count":4,"max":[0,0,0,1],"min":[0,0,-0.8660253882408142,-1],"type":"VEC4"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"rgt_shaft"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png","name":"rgt_shaft.png","uri":"rgt_shaft.png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]}],"animations":[{"name":"animation","samplers":[{"input":4,"output":5,"interpolation":"LINEAR"}],"channels":[{"sampler":0,"target":{"node":1,"path":"rotation"}}]}]}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 820 B |
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
Loading…
Add table
Add a link
Reference in a new issue