Allow mechanisms to be linked, and allow storing links in schematics.
This commit is contained in:
parent
8f98a7fa2d
commit
8a8fa943c5
9 changed files with 438 additions and 104 deletions
|
|
@ -45,6 +45,26 @@ function Promise(fn)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- HACK: Lookup table for getting a rotation from a
|
||||||
|
-- facedir (because Minetest doesn't have any way
|
||||||
|
-- to get this)
|
||||||
|
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, 0),
|
||||||
|
[3] = vector.new(0, math.pi *0.5, 0),
|
||||||
|
|
||||||
|
-- +Z
|
||||||
|
[4] = vector.new(math.pi *1.5, 0, 0),
|
||||||
|
[5] = vector.new(math.pi *1.5, math.pi *1.5, 0),
|
||||||
|
[6] = vector.new(math.pi *1.5, math.pi, 0),
|
||||||
|
[7] = vector.new(math.pi *1.5, math.pi *0.5, 0),
|
||||||
|
}
|
||||||
|
function artifact.facedir_to_rotation(facedir)
|
||||||
|
return facedir_rotations[facedir] or minetest.facedir_to_dir(facedir):dir_to_rotation()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
minetest.register_lbm{
|
minetest.register_lbm{
|
||||||
name = ":artifact:on_load",
|
name = ":artifact:on_load",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ function ns.apply_key(m)
|
||||||
eye_height = 1.6
|
eye_height = 1.6
|
||||||
}
|
}
|
||||||
m.eye_height = 1.6
|
m.eye_height = 1.6
|
||||||
|
-- Switch hand appearance.
|
||||||
|
m.inv:set_stack("main", 1, ItemStack("input_"..m.character))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ns.apply_vix(m)
|
function ns.apply_vix(m)
|
||||||
|
|
@ -17,6 +19,8 @@ function ns.apply_vix(m)
|
||||||
eye_height = 1.5
|
eye_height = 1.5
|
||||||
}
|
}
|
||||||
m.eye_height = 1.5
|
m.eye_height = 1.5
|
||||||
|
-- Switch hand appearance.
|
||||||
|
m.inv:set_stack("main", 1, ItemStack("input_"..m.character))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ns.swap_character(m)
|
function ns.swap_character(m)
|
||||||
|
|
|
||||||
1
mods/artifact_characters/models/artifact_hand.gltf
Normal file
1
mods/artifact_characters/models/artifact_hand.gltf
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"asset":{"version":"2.0","generator":"Blockbench 4.11.0 glTF exporter"},"scenes":[{"nodes":[3],"name":"blockbench_export"}],"scene":0,"nodes":[{"translation":[-7.341186189470692,-10.221666105894709,3.75],"name":"Right Arm","mesh":0},{"translation":[-7.341186189470692,-10.221666105894709,3.75],"name":"Right Arm Layer","mesh":1},{"rotation":[0.9829629131445342,0.12940952255126037,-0.017037086855465768,0.12940952255126018],"name":"RightArm","children":[0,1]},{"children":[2]}],"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":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":1128,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":1416,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":1608,"byteLength":72,"target":34963}],"buffers":[{"byteLength":1680,"uri":"data:application/octet-stream;base64,AACMQAAAcEEAAHA/AACMQAAAcEEAAHC/AACMQAAA8EAAAHA/AACMQAAA8EAAAHC/AAAgQAAAcEEAAHC/AAAgQAAAcEEAAHA/AAAgQAAA8EAAAHC/AAAgQAAA8EAAAHA/AAAgQAAAcEEAAHC/AACMQAAAcEEAAHC/AAAgQAAAcEEAAHA/AACMQAAAcEEAAHA/AAAgQAAA8EAAAHA/AACMQAAA8EAAAHA/AAAgQAAA8EAAAHC/AACMQAAA8EAAAHC/AAAgQAAAcEEAAHA/AACMQAAAcEEAAHA/AAAgQAAA8EAAAHA/AACMQAAA8EAAAHA/AACMQAAAcEEAAHC/AAAgQAAAcEEAAHC/AACMQAAA8EAAAHC/AAAgQAAA8EAAAHC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/ABAkPwAgoD4A8C8/ACCgPgAQJD8A4P8+APAvPwDg/z4AEDw/ACCgPgDwRz8AIKA+ABA8PwDg/z4A8Ec/AOD/PgDwOz8A4J8+ABAwPwDgnz4A8Ds/ACCIPgAQMD8AIIg+APBHPwAgiD4AEDw/ACCIPgDwRz8A4J8+ABA8PwDgnz4AEEg/ACCgPgDwUz8AIKA+ABBIPwDg/z4A8FM/AOD/PgAQMD8AIKA+APA7PwAgoD4AEDA/AOD/PgDwOz8A4P8+AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUAAACRQACAckEAAIw/AACRQACAckEAAIy/AACRQAAA60AAAIw/AACRQAAA60AAAIy/AAAWQACAckEAAIy/AAAWQACAckEAAIw/AAAWQAAA60AAAIy/AAAWQAAA60AAAIw/AAAWQACAckEAAIy/AACRQACAckEAAIy/AAAWQACAckEAAIw/AACRQACAckEAAIw/AAAWQAAA60AAAIw/AACRQAAA60AAAIw/AAAWQAAA60AAAIy/AACRQAAA60AAAIy/AAAWQACAckEAAIw/AACRQACAckEAAIw/AAAWQAAA60AAAIw/AACRQAAA60AAAIw/AACRQACAckEAAIy/AAAWQACAckEAAIy/AACRQAAA60AAAIy/AAAWQAAA60AAAIy/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAkPwAAED8AADA/AAAQPwAAJD8AAEA/AAAwPwAAQD8AAEA/AAAQPwAATD8AABA/AABAPwAAQD8AAEw/AABAPwAAPD8AABA/AAAwPwAAED8AADw/AAAEPwAAMD8AAAQ/AABIPwAABD8AADw/AAAEPwAASD8AABA/AAA8PwAAED8AAEw/AAAQPwAAWD8AABA/AABMPwAAQD8AAFg/AABAPwAAMD8AABA/AAA8PwAAED8AADA/AABAPwAAPD8AAEA/AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUA"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[4.375,15,0.9375],"min":[2.5,7.5,-0.9375],"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.827880859375,0.499755859375],"min":[0.640869140625,0.265869140625],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"},{"bufferView":4,"componentType":5126,"count":24,"max":[4.53125,15.15625,1.09375],"min":[2.34375,7.34375,-1.09375],"type":"VEC3"},{"bufferView":5,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":6,"componentType":5126,"count":24,"max":[0.84375,0.75],"min":[0.640625,0.515625],"type":"VEC2"},{"bufferView":7,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"artifact_key.png"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]},{"primitives":[{"mode":4,"attributes":{"POSITION":4,"NORMAL":5,"TEXCOORD_0":6},"indices":7,"material":0}]}]}
|
||||||
|
|
@ -21,13 +21,14 @@ minetest.register_entity(":artifact:lever_display", {
|
||||||
end
|
end
|
||||||
e.object:set_armor_groups{immortal = 1}
|
e.object:set_armor_groups{immortal = 1}
|
||||||
extend(e, minetest.deserialize(data) or {})
|
extend(e, minetest.deserialize(data) or {})
|
||||||
|
if not e.rotation then e.rotation = vector.zero() end
|
||||||
levers[e.object:get_pos():round():to_string()] = e
|
levers[e.object:get_pos():round():to_string()] = e
|
||||||
end,
|
end,
|
||||||
on_deactivte = function(e)
|
on_deactivte = function(e)
|
||||||
levers[e.object:get_pos():round():to_string()] = nil
|
levers[e.object:get_pos():round():to_string()] = nil
|
||||||
end,
|
end,
|
||||||
get_staticdata = function(e)
|
get_staticdata = function(e)
|
||||||
return {rotation = e.rotation}
|
return minetest.serialize{rotation = e.rotation}
|
||||||
end,
|
end,
|
||||||
on_interact = function(e)
|
on_interact = function(e)
|
||||||
if e._active then
|
if e._active then
|
||||||
|
|
@ -36,6 +37,7 @@ minetest.register_entity(":artifact:lever_display", {
|
||||||
e.object:set_animation({x=1,y=2}, 2, 0.1, false)
|
e.object:set_animation({x=1,y=2}, 2, 0.1, false)
|
||||||
minetest.after(0.5, function()
|
minetest.after(0.5, function()
|
||||||
e._no_interact = nil
|
e._no_interact = nil
|
||||||
|
e:trigger(false)
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
e._active = true
|
e._active = true
|
||||||
|
|
@ -43,10 +45,21 @@ minetest.register_entity(":artifact:lever_display", {
|
||||||
e.object:set_animation({x=0,y=1}, 2, 0.1, false)
|
e.object:set_animation({x=0,y=1}, 2, 0.1, false)
|
||||||
minetest.after(0.5, function()
|
minetest.after(0.5, function()
|
||||||
e._no_interact = nil
|
e._no_interact = nil
|
||||||
|
e:trigger(true)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
trigger = function(e, state)
|
||||||
|
local receivers = minetest.deserialize(minetest.get_meta(e.object:get_pos():round()):get("receivers") or "return nil")
|
||||||
|
if receivers then
|
||||||
|
artifact.dispatch_event(receivers, {type = state and "on" or "off"})
|
||||||
|
end
|
||||||
|
end,
|
||||||
rotate = function(e, rot)
|
rotate = function(e, rot)
|
||||||
|
if not rot then
|
||||||
|
say "!"
|
||||||
|
return
|
||||||
|
end
|
||||||
e.object:set_rotation(rot)
|
e.object:set_rotation(rot)
|
||||||
e.rotation = rot
|
e.rotation = rot
|
||||||
e.object:set_properties {
|
e.object:set_properties {
|
||||||
|
|
@ -58,6 +71,7 @@ minetest.register_entity(":artifact:lever_display", {
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
artifact.register_node("lever", {
|
artifact.register_node("lever", {
|
||||||
drawtype = "airlike",
|
drawtype = "airlike",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
|
|
@ -66,9 +80,13 @@ artifact.register_node("lever", {
|
||||||
pointable = false,
|
pointable = false,
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
local m = minetest.get_meta(pos)
|
local m = minetest.get_meta(pos)
|
||||||
|
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
|
||||||
|
if m:contains("initialized") then
|
||||||
|
levers[pos:to_string()]:rotate(rot)
|
||||||
|
else
|
||||||
m:set_string("initialized", "true")
|
m:set_string("initialized", "true")
|
||||||
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
|
||||||
minetest.add_entity(pos, "artifact:lever_display", minetest.serialize{type = "wood"}):get_luaentity():rotate(rot)
|
minetest.add_entity(pos, "artifact:lever_display", minetest.serialize{type = "wood"}):get_luaentity():rotate(rot)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
on_destruct = function(pos)
|
on_destruct = function(pos)
|
||||||
levers[pos:to_string()].object:remove()
|
levers[pos:to_string()].object:remove()
|
||||||
|
|
@ -79,15 +97,18 @@ artifact.register_node("lever", {
|
||||||
-- Dynamically initialize doors that were mapgen'd in.
|
-- Dynamically initialize doors that were mapgen'd in.
|
||||||
if not m:contains("initialized") then
|
if not m:contains("initialized") then
|
||||||
m:set_string("initialized", "true")
|
m:set_string("initialized", "true")
|
||||||
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
|
||||||
minetest.add_entity(pos, "artifact:lever_display", minetest.serialize{type = "wood"}):get_luaentity():rotate(rot)
|
minetest.add_entity(pos, "artifact:lever_display", minetest.serialize{type = "wood"}):get_luaentity():rotate(rot)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
on_rightclick = function(pos)
|
||||||
|
local rot = artifact.facedir_to_rotation(minetest.get_node(pos).param2)
|
||||||
|
levers[pos:to_string()]:rotate(rot)
|
||||||
|
end,
|
||||||
on_rotate = function(pos, node, p, click, param2)
|
on_rotate = function(pos, node, p, click, param2)
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
node.param2 = param2
|
node.param2 = param2
|
||||||
minetest.swap_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
local rot = minetest.facedir_to_dir(node.param2):dir_to_rotation()
|
local rot = artifact.facedir_to_rotation(param2)
|
||||||
levers[pos:to_string()]:rotate(rot)
|
levers[pos:to_string()]:rotate(rot)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
||||||
14
mods/artifact_mechanisms/colors.lua
Normal file
14
mods/artifact_mechanisms/colors.lua
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
artifact.register_entity("ccolor_swapper_display", {
|
||||||
|
initial_properties = {
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "artifact_color_swapper.gltf",
|
||||||
|
textures = {"artifact_color_swapper_gold.png"}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
artifact.register_node("color_swapper", {
|
||||||
|
on_construct = function(pos)
|
||||||
|
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
@ -25,14 +25,17 @@ minetest.register_entity(":artifact:door", {
|
||||||
return (e._open and vector.new(-0.5, 0.5, 0) or vector.new(0, 0.5, 0.5)):rotate(e.object:get_rotation())
|
return (e._open and vector.new(-0.5, 0.5, 0) or vector.new(0, 0.5, 0.5)):rotate(e.object:get_rotation())
|
||||||
end,
|
end,
|
||||||
on_activate = function(e, data)
|
on_activate = function(e, data)
|
||||||
if not minetest.get_node(e.object:get_pos()).name:find "door" then
|
local node = minetest.get_node(e.object:get_pos())
|
||||||
|
if not node.name:find "door" then
|
||||||
e.object:remove()
|
e.object:remove()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
e.object:set_armor_groups{immortal = 1}
|
e.object:set_armor_groups{immortal = 1}
|
||||||
extend(e, minetest.deserialize(data) or {})
|
extend(e, minetest.deserialize(data) or {})
|
||||||
if e.type == "iron" and e._locked == nil then
|
if e.type == "iron" then
|
||||||
|
if e._locked == nil then
|
||||||
e._locked = true
|
e._locked = true
|
||||||
|
end
|
||||||
e.object:set_properties {
|
e.object:set_properties {
|
||||||
textures = {"artifact_door_iron.png"},
|
textures = {"artifact_door_iron.png"},
|
||||||
}
|
}
|
||||||
|
|
@ -45,38 +48,32 @@ minetest.register_entity(":artifact:door", {
|
||||||
e._no_interact = true
|
e._no_interact = true
|
||||||
end
|
end
|
||||||
e._name = ""..math.random()
|
e._name = ""..math.random()
|
||||||
|
local nm = minetest.get_meta(e.object:get_pos())
|
||||||
|
if (node.name:find "_open") and not e._open then
|
||||||
|
e:open(true)
|
||||||
|
elseif not (node.name:find "_open") and e._open then
|
||||||
|
e:close(true)
|
||||||
|
end
|
||||||
doors[e.object:get_pos():round():to_string()] = e
|
doors[e.object:get_pos():round():to_string()] = e
|
||||||
end,
|
end,
|
||||||
on_deactivate = function(e)
|
on_deactivate = function(e)
|
||||||
doors[e.object:get_pos():round():to_string()] = nil
|
doors[e.object:get_pos():round():to_string()] = nil
|
||||||
end,
|
end,
|
||||||
on_interact = function(e)
|
on_interact = function(e)
|
||||||
|
if e._locked then return end
|
||||||
if e._open then
|
if e._open then
|
||||||
e._open = nil
|
e:close()
|
||||||
e._no_interact = true
|
|
||||||
e._name = ""..math.random()
|
|
||||||
e.object:set_animation({x=0.5,y=1}, 1.5, 0.1, false)
|
|
||||||
minetest.after(0.1, function()
|
|
||||||
local pos = e.object:get_pos():round()
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
node.name = "door_"..e.type
|
|
||||||
minetest.swap_node(pos, node)
|
|
||||||
e.object:set_properties {
|
|
||||||
selectionbox = artifact.rotate_selectionbox({
|
|
||||||
-0.5, -0.5, -0.5,
|
|
||||||
0.5, 1.5, -6/16
|
|
||||||
}, e.rotation)
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
minetest.after(0.25, function()
|
|
||||||
e._no_interact = nil
|
|
||||||
end)
|
|
||||||
else
|
else
|
||||||
|
e:open()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
open = function(e, snap)
|
||||||
|
if e._open then return end
|
||||||
e._open = true
|
e._open = true
|
||||||
e._no_interact = true
|
e._no_interact = true
|
||||||
e._name = ""..math.random()
|
e._name = ""..math.random()
|
||||||
e.object:set_animation({x=0,y=0.5}, 1.5, 0.1, false)
|
e.object:set_animation({x=snap and 0.5 or 0,y=0.5}, 1.5, 0.1, false)
|
||||||
minetest.after(0.1, function()
|
minetest.after(snap and 0 or 0.1, function()
|
||||||
local pos = e.object:get_pos():round()
|
local pos = e.object:get_pos():round()
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
node.name = "door_"..e.type.."_open"
|
node.name = "door_"..e.type.."_open"
|
||||||
|
|
@ -88,7 +85,32 @@ minetest.register_entity(":artifact:door", {
|
||||||
}, e.rotation)
|
}, e.rotation)
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
minetest.after(0.25, function()
|
if not e._locked then
|
||||||
|
minetest.after(snap and 0 or 0.25, function()
|
||||||
|
e._no_interact = nil
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
close = function(e, snap)
|
||||||
|
if not e._open then return end
|
||||||
|
e._open = nil
|
||||||
|
e._no_interact = true
|
||||||
|
e._name = ""..math.random()
|
||||||
|
e.object:set_animation({x=snap and 1 or 0.5,y=1}, 1.5, 0.1, false)
|
||||||
|
minetest.after(snap and 0 or 0.1, function()
|
||||||
|
local pos = e.object:get_pos():round()
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
node.name = "door_"..e.type
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
e.object:set_properties {
|
||||||
|
selectionbox = artifact.rotate_selectionbox({
|
||||||
|
-0.5, -0.5, -0.5,
|
||||||
|
0.5, 1.5, -6/16
|
||||||
|
}, e.rotation)
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
if not e._locked then
|
||||||
|
minetest.after(snap and 0 or 0.25, function()
|
||||||
e._no_interact = nil
|
e._no_interact = nil
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
@ -113,6 +135,43 @@ minetest.register_entity(":artifact:door", {
|
||||||
})
|
})
|
||||||
|
|
||||||
local function register_basic_door(type)
|
local function register_basic_door(type)
|
||||||
|
local function onload(pos)
|
||||||
|
local m = minetest.get_meta(pos)
|
||||||
|
-- Dynamically initialize doors that were mapgen'd in.
|
||||||
|
if not m:contains("initialized") then
|
||||||
|
m:set_string("initialized", "true")
|
||||||
|
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
||||||
|
rot.y = rot.y -math.pi
|
||||||
|
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function ondestruct(pos, reason)
|
||||||
|
if reason == "whack" then
|
||||||
|
-- TODO: Particles
|
||||||
|
end
|
||||||
|
doors[pos:to_string()].object:remove()
|
||||||
|
doors[pos:to_string()] = nil
|
||||||
|
end
|
||||||
|
local function onsignal(pos, event)
|
||||||
|
local door = doors[vector.to_string(pos)]
|
||||||
|
if event.type == "on" then
|
||||||
|
if door then
|
||||||
|
door:open()
|
||||||
|
else
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
node.name = "door_"..e.type.."_open"
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
end
|
||||||
|
elseif event.type == "off" then
|
||||||
|
if door then
|
||||||
|
door:close()
|
||||||
|
else
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
node.name = "door_"..e.type.."_open"
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
artifact.register_node("door_"..type, {
|
artifact.register_node("door_"..type, {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
node_box = {
|
node_box = {
|
||||||
|
|
@ -128,30 +187,10 @@ local function register_basic_door(type)
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
pointable = false,
|
pointable = false,
|
||||||
groups = {call_on_load = 1, whackable = type == "wood" and 1 or nil},
|
groups = {call_on_load = 1, whackable = type == "wood" and 1 or nil},
|
||||||
on_construct = function(pos)
|
on_construct = onload,
|
||||||
local m = minetest.get_meta(pos)
|
on_destruct = ondestruct,
|
||||||
m:set_string("initialized", "true")
|
on_load = onload,
|
||||||
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
on_signal = onsignal
|
||||||
rot.y = rot.y -math.pi
|
|
||||||
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
|
|
||||||
end,
|
|
||||||
on_destruct = function(pos, reason)
|
|
||||||
if reason == "whack" then
|
|
||||||
-- TODO: Particles
|
|
||||||
end
|
|
||||||
doors[pos:to_string()].object:remove()
|
|
||||||
doors[pos:to_string()] = nil
|
|
||||||
end,
|
|
||||||
on_load = function(pos)
|
|
||||||
local m = minetest.get_meta(pos)
|
|
||||||
-- Dynamically initialize doors that were mapgen'd in.
|
|
||||||
if not m:contains("initialized") then
|
|
||||||
m:set_string("initialized", "true")
|
|
||||||
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
|
||||||
rot.y = rot.y -math.pi
|
|
||||||
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
artifact.register_node("door_"..type.."_open", {
|
artifact.register_node("door_"..type.."_open", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
|
|
@ -168,27 +207,10 @@ local function register_basic_door(type)
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
pointable = false,
|
pointable = false,
|
||||||
groups = {call_on_load = 1, whackable = type == "wood" and 1 or nil},
|
groups = {call_on_load = 1, whackable = type == "wood" and 1 or nil},
|
||||||
on_construct = function(pos)
|
on_construct = onload,
|
||||||
local m = minetest.get_meta(pos)
|
on_destruct = ondestruct,
|
||||||
m:set_string("initialized", "true")
|
on_load = onload,
|
||||||
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
on_signal = onsignal
|
||||||
rot.y = rot.y -math.pi
|
|
||||||
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
|
|
||||||
end,
|
|
||||||
on_destruct = function(pos)
|
|
||||||
doors[pos:to_string()].object:remove()
|
|
||||||
doors[pos:to_string()] = nil
|
|
||||||
end,
|
|
||||||
on_load = function(pos)
|
|
||||||
local m = minetest.get_meta(pos)
|
|
||||||
-- Dynamically initialize doors that were mapgen'd in.
|
|
||||||
if not m:contains("initialized") then
|
|
||||||
m:set_string("initialized", "true")
|
|
||||||
local rot = minetest.facedir_to_dir(minetest.get_node(pos).param2):dir_to_rotation()
|
|
||||||
rot.y = rot.y -math.pi
|
|
||||||
minetest.add_entity(pos, "artifact:door", minetest.serialize{type = type}):get_luaentity():rotate(rot)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,239 @@ artifact.register_craftitem("cancel", {
|
||||||
inventory_image = "artifact_cancel.png"
|
inventory_image = "artifact_cancel.png"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
--- @param receivers: A list of node positions to notify.
|
||||||
|
--- @param event: The event to send.
|
||||||
|
function artifact.dispatch_event(receivers, event)
|
||||||
|
for _, x in ipairs(receivers) do
|
||||||
|
-- Ensure that nodes are available.
|
||||||
|
minetest.load_area(x.pos)
|
||||||
|
local node = minetest.get_node(x.pos)
|
||||||
|
local def = minetest.registered_nodes[node.name]
|
||||||
|
if def.on_signal then
|
||||||
|
def.on_signal(x.pos, event, x.channel or "gold")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
include "basics.lua"
|
include "basics.lua"
|
||||||
include "doors.lua"
|
include "doors.lua"
|
||||||
include "chest.lua"
|
include "chest.lua"
|
||||||
|
|
||||||
|
|
||||||
|
function artifact.load_schematic(dst, path, rot)
|
||||||
|
minetest.place_schematic(dst, path..".mts", rot or "0")
|
||||||
|
local f = io.open(path..".json")
|
||||||
|
local meta = minetest.parse_json(f:read("a"))
|
||||||
|
f:close()
|
||||||
|
-- Load auxiliary metadata.
|
||||||
|
for p, m in pairs(meta or {}) do
|
||||||
|
local pos = dst +vector.from_string(p)
|
||||||
|
-- Transform all position fields back into global space.
|
||||||
|
if m.fields and m.fields.receivers then
|
||||||
|
local receivers = minetest.deserialize(m.fields.receivers)
|
||||||
|
for i, x in ipairs(receivers) do
|
||||||
|
x.pos = vector.add(x.pos, dst)
|
||||||
|
receivers[i] = x
|
||||||
|
end
|
||||||
|
m.fields.receivers = minetest.serialize(receivers)
|
||||||
|
end
|
||||||
|
minetest.get_meta(pos):from_table(m)
|
||||||
|
local def = minetest.registered_nodes[minetest.get_node(pos).name]
|
||||||
|
if def.on_construct then
|
||||||
|
def.on_construct(pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_entity(":test", {
|
||||||
|
initial_properties = {
|
||||||
|
static_save = false,
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "artifact_character.gltf",
|
||||||
|
},
|
||||||
|
on_activate = function(e)
|
||||||
|
-- e.object:set_bone_override("root", {
|
||||||
|
-- position = {vec = vector.new(15,15,15)}
|
||||||
|
-- })
|
||||||
|
end,
|
||||||
|
on_rightclick = function(e, p)
|
||||||
|
local v = vector.new(0, p:get_properties().eye_height *10, 0)
|
||||||
|
p:set_eye_offset(v,v,v)
|
||||||
|
p:set_attach(e.object, "Head")
|
||||||
|
end,
|
||||||
|
on_punch = function(e, p)
|
||||||
|
p:set_detach()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if artifact.debug then
|
||||||
|
|
||||||
|
local link_colors = {
|
||||||
|
"gold",
|
||||||
|
"red",
|
||||||
|
"blue"
|
||||||
|
}
|
||||||
|
|
||||||
|
if minetest.get_modpath("rhotator") then
|
||||||
|
minetest.override_item("rhotator:screwdriver", {
|
||||||
|
pointabilities = {
|
||||||
|
nodes = {
|
||||||
|
-- This gets added to everything in debug mode.
|
||||||
|
["group:dig_immediate"] = true,
|
||||||
|
air = false,
|
||||||
|
},
|
||||||
|
objects = {
|
||||||
|
-- The display entities should all be immortal.
|
||||||
|
["group:immortal"] = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
minetest.override_item("testtools:param2tool", {
|
||||||
|
pointabilities = {
|
||||||
|
nodes = {
|
||||||
|
-- This gets added to everything in debug mode.
|
||||||
|
["group:dig_immediate"] = true,
|
||||||
|
air = false,
|
||||||
|
},
|
||||||
|
objects = {
|
||||||
|
-- The display entities should all be immortal.
|
||||||
|
["group:immortal"] = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
artifact.register_craftitem("linker_tool", {
|
||||||
|
inventory_image = "artifact_linker_tool.png",
|
||||||
|
stack_max = 1,
|
||||||
|
pointabilities = {
|
||||||
|
nodes = {
|
||||||
|
-- This gets added to everything in debug mode.
|
||||||
|
["group:dig_immediate"] = true,
|
||||||
|
air = false,
|
||||||
|
},
|
||||||
|
objects = {
|
||||||
|
-- The display entities should all be immortal.
|
||||||
|
["group:immortal"] = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_secondary_use = function(s, p, pt)
|
||||||
|
local m = s:get_meta()
|
||||||
|
-- Just cycle through the colors list.
|
||||||
|
local color = link_colors[(table.indexof(link_colors, m:get("color") or "gold") +1) %#link_colors +1]
|
||||||
|
m:set_string("color", color)
|
||||||
|
m:set_string("inventory_image", "[fill:16x16:0,0:"..color.."#00^artifact_linker_tool.png")
|
||||||
|
return s
|
||||||
|
end,
|
||||||
|
on_place = function(s, p, pt)
|
||||||
|
local m = artifact.players[p:get_player_name()]
|
||||||
|
if pt.type == "node" and m._linker_target then
|
||||||
|
local color = s:get_meta():get("color") or "gold"
|
||||||
|
local meta = minetest.get_meta(m._linker_target)
|
||||||
|
local receivers = minetest.deserialize(meta:get("receivers") or "return {}")
|
||||||
|
if m.ctl.sneak then
|
||||||
|
local idx = 0
|
||||||
|
for i, x in ipairs(receivers) do
|
||||||
|
if vector.equals(x.pos, pt.under) then idx = i end
|
||||||
|
end
|
||||||
|
if idx > 0 then
|
||||||
|
table.remove(receivers, idx)
|
||||||
|
m.object:hud_remove(m._linker_receivers[idx])
|
||||||
|
table.remove(m._linker_receivers, idx)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local idx = 0
|
||||||
|
for i, x in ipairs(receivers) do
|
||||||
|
if vector.equals(x.pos, pt.under) then idx = i end
|
||||||
|
end
|
||||||
|
-- Ensure we haven't added this pos already.
|
||||||
|
if idx == 0 then
|
||||||
|
table.insert(receivers, {pos = pt.under, channel = color})
|
||||||
|
table.insert(m._linker_receivers, m.object:hud_add {
|
||||||
|
type = "image_waypoint",
|
||||||
|
scale = {x=3, y=3},
|
||||||
|
world_pos = pt.under,
|
||||||
|
text = "artifact_linker_tool.png^[colorize:"..color..":64"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
meta:set_string("receivers", minetest.serialize(receivers))
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_use = function(s, p, pt)
|
||||||
|
local m = artifact.players[p:get_player_name()]
|
||||||
|
if pt.type == "node" then
|
||||||
|
m._linker_target = pt.under
|
||||||
|
if m._linker_target_hud then
|
||||||
|
m.object:hud_remove(m._linker_target_hud)
|
||||||
|
end
|
||||||
|
m._linker_target_hud = m.object:hud_add {
|
||||||
|
type = "image_waypoint",
|
||||||
|
scale = {x=3, y=3},
|
||||||
|
world_pos = pt.under,
|
||||||
|
text = "artifact_linker_tool.png"
|
||||||
|
}
|
||||||
|
if m._linker_receivers then
|
||||||
|
for _, x in ipairs(m._linker_receivers) do
|
||||||
|
m.object:hud_remove(x)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
m._linker_receivers = {}
|
||||||
|
local receivers = minetest.deserialize(minetest.get_meta(m._linker_target):get("receivers") or "return {}")
|
||||||
|
for _, x in ipairs(receivers) do
|
||||||
|
table.insert(m._linker_receivers, m.object:hud_add {
|
||||||
|
type = "image_waypoint",
|
||||||
|
scale = {x=3, y=3},
|
||||||
|
world_pos = x.pos,
|
||||||
|
text = "artifact_linker_tool.png^[colorize:"..x.channel..":64"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
-- To make life easier, simply require worldedit in order to export an area.
|
||||||
|
if minetest.global_exists("worldedit") then
|
||||||
|
minetest.mkdir(minetest.get_worldpath().."/schems")
|
||||||
|
minetest.register_chatcommand("export", {
|
||||||
|
privs = {server = true},
|
||||||
|
params = "<name>",
|
||||||
|
description = "Export the selected region as a schematic, with all node metadata stored in an adjacent JSON file.",
|
||||||
|
func = function(name, args)
|
||||||
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||||
|
print(dump(minetest.create_schematic(pos1, pos2, nil, minetest.get_worldpath().."/schems/"..args..".mts")))
|
||||||
|
local minp = vector.sort(pos1, pos2)
|
||||||
|
local meta = {}
|
||||||
|
for _, pos in pairs(minetest.find_nodes_with_meta(pos1, pos2)) do
|
||||||
|
local mt = minetest.get_meta(pos):to_table()
|
||||||
|
mt.fields.initialized = nil
|
||||||
|
-- Transform all position fields into local coordinate space.
|
||||||
|
if mt.fields.receivers then
|
||||||
|
local receivers = minetest.deserialize(mt.fields.receivers)
|
||||||
|
for i, x in ipairs(receivers) do
|
||||||
|
x.pos = vector.subtract(x.pos, minp)
|
||||||
|
receivers[i] = x
|
||||||
|
end
|
||||||
|
mt.fields.receivers = minetest.serialize(receivers)
|
||||||
|
end
|
||||||
|
meta[(pos -minp):to_string()] = mt
|
||||||
|
end
|
||||||
|
local f = io.open(minetest.get_worldpath().."/schems/"..args..".json", "w")
|
||||||
|
f:write(minetest.write_json(meta))
|
||||||
|
f:flush()
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_chatcommand("load", {
|
||||||
|
privs = {server = true},
|
||||||
|
func = function(name, args)
|
||||||
|
artifact.load_schematic(artifact.players[name].pos:round(), minetest.get_worldpath().."/schems/"..args)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Player = setmetatable({
|
||||||
m.character = m.meta:get("character") or "key"
|
m.character = m.meta:get("character") or "key"
|
||||||
|
|
||||||
m.inv = p:get_inventory()
|
m.inv = p:get_inventory()
|
||||||
m.inv:set_stack("main", 1, ItemStack("input"))
|
m.inv:set_stack("main", 1, ItemStack("input_"..m.character))
|
||||||
|
|
||||||
-- Generic black sky, since the whole game takes place underground.
|
-- Generic black sky, since the whole game takes place underground.
|
||||||
p:set_sky{
|
p:set_sky{
|
||||||
|
|
@ -219,7 +219,7 @@ Player = setmetatable({
|
||||||
|
|
||||||
-- MARK: Radial menu handling
|
-- MARK: Radial menu handling
|
||||||
|
|
||||||
if ctl.place and not m.ctl.place and wi:get_name() == "artifact:input" then
|
if ctl.place and not m.ctl.place and wi:get_name():find "artifact:input" and (not m.pointed_obj or m.pointed_obj._no_interact) then
|
||||||
artifact.show_radial_menu(m, {
|
artifact.show_radial_menu(m, {
|
||||||
name = "construct",
|
name = "construct",
|
||||||
"test",
|
"test",
|
||||||
|
|
@ -228,7 +228,7 @@ Player = setmetatable({
|
||||||
"test4",
|
"test4",
|
||||||
"test5"
|
"test5"
|
||||||
})
|
})
|
||||||
elseif m._menu and not (ctl.place and wi:get_name() == "artifact:input") then
|
elseif m._menu and not (ctl.place and wi:get_name():find "artifact:input") or (m.pointed_obj and not m.pointed_obj._no_interact) then
|
||||||
artifact.dismiss_radial_menu(m, "construct")
|
artifact.dismiss_radial_menu(m, "construct")
|
||||||
elseif m._menu then
|
elseif m._menu then
|
||||||
local dx = m.yaw -yaw
|
local dx = m.yaw -yaw
|
||||||
|
|
@ -324,8 +324,24 @@ Player = setmetatable({
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
artifact.register_craftitem("input", {
|
local _hand = minetest.registered_items[""]
|
||||||
|
|
||||||
|
function artifact.register_input(name)
|
||||||
|
artifact.register_node("input_"..name, {
|
||||||
inventory_image = "artifact_rmb_100.png",
|
inventory_image = "artifact_rmb_100.png",
|
||||||
|
description = "",
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "artifact_hand.gltf",
|
||||||
|
tiles = {"artifact_"..name..".png"},
|
||||||
|
use_texture_alpha = "opaque",
|
||||||
|
visual_scale = 1,
|
||||||
|
wield_scale = vector.new(2,2,2),
|
||||||
|
node_placement_prediction = "",
|
||||||
|
on_construct = function(pos)
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
end,
|
||||||
|
drop = "",
|
||||||
range = 0,
|
range = 0,
|
||||||
on_drop = function(s, p, pos)
|
on_drop = function(s, p, pos)
|
||||||
local m = artifact.players[p:get_player_name()]
|
local m = artifact.players[p:get_player_name()]
|
||||||
|
|
@ -335,6 +351,9 @@ artifact.register_craftitem("input", {
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
end
|
||||||
|
artifact.register_input "key"
|
||||||
|
artifact.register_input "vix"
|
||||||
|
|
||||||
|
|
||||||
minetest.register_globalstep(function()
|
minetest.register_globalstep(function()
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ end
|
||||||
|
|
||||||
function ns.dismiss_radial_menu(m, name)
|
function ns.dismiss_radial_menu(m, name)
|
||||||
-- This is in case we only want to close a specific menu while leaving others intact.
|
-- This is in case we only want to close a specific menu while leaving others intact.
|
||||||
if name and m._menu.name ~= name then return end
|
if name and (not m._menu or m._menu.name ~= name) then return end
|
||||||
for _, x in ipairs(m._menu) do
|
for _, x in ipairs(m._menu) do
|
||||||
x:remove(m)
|
x:remove(m)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue