update metadata handling, add HUD waypoints

This commit is contained in:
FaceDeer 2019-12-27 20:03:17 -07:00
parent 23e3517c4a
commit d56a93cb61
4 changed files with 102 additions and 50 deletions

View File

@ -1,4 +0,0 @@
default?
doc?
intllib?
loot?

View File

@ -1 +0,0 @@
Path marker signs for use when exploring a twisty maze of passages that are all alike.

141
init.lua
View File

@ -47,6 +47,39 @@ if particles then
end end
marker_usagehelp = marker_usagehelp .. " " .. S("If you place a marker incorrectly you can \"undo\" the placement by clicking on it with the stack you used to place it. Otherwise, markers can only be removed with an axe. Labeled markers can be turned back into blank markers via the crafting grid.") marker_usagehelp = marker_usagehelp .. " " .. S("If you place a marker incorrectly you can \"undo\" the placement by clicking on it with the stack you used to place it. Otherwise, markers can only be removed with an axe. Labeled markers can be turned back into blank markers via the crafting grid.")
-----------------------------------------------------------------
-- HUD markers
local MARKER_DURATION = 60
local hud_markers = {}
local add_hud_marker = function(player, pos, label)
local hud_id = player:hud_add({
hud_elem_type = "waypoint",
name = label,
text = "m",
number = 0xFFFFFF,
world_pos = pos})
table.insert(hud_markers, {player=player, hud_id=hud_id, duration=0})
end
minetest.register_globalstep(function(dtime)
for i=#hud_markers,1,-1 do
local marker = hud_markers[i]
marker.duration = marker.duration + dtime
if marker.duration > MARKER_DURATION then
marker.player:hud_remove(marker.hud_id)
table.remove(hud_markers, i)
end
end
end)
minetest.register_on_leaveplayer(function(player, timed_out)
for i=#hud_markers,1,-1 do
local marker = hud_markers[i]
if marker.player == player then
table.remove(hud_markers, i)
end
end
end)
--------------------------------------------------------------------
local label_text = S("Label:") local label_text = S("Label:")
local save_text = S("Save") local save_text = S("Save")
@ -61,21 +94,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local stack = player:get_wielded_item() local stack = player:get_wielded_item()
if fields.save and fields.label ~= "" then if fields.save and fields.label ~= "" then
local data = {} local new_stack = ItemStack({name="breadcrumbs:marker", count=stack:get_count(), wear=0})
data.label = fields.label local meta = new_stack:get_meta()
data.number = 1 meta:set_string("label", fields.label)
local new_stack = ItemStack({name="breadcrumbs:marker", count=stack:get_count(), wear=0, metadata=minetest.serialize(data)}) meta:set_int("number", 1)
player:set_wielded_item(new_stack) player:set_wielded_item(new_stack)
end end
end) end)
local tag_to_itemstack = function(pos, count) local tag_to_itemstack = function(pos, count)
local meta = minetest.get_meta(pos) local node_meta = minetest.get_meta(pos)
local data = {} local new_stack = ItemStack({name="breadcrumbs:marker", count=count, wear=0})
data.label = meta:get_string("label") local item_meta = new_stack:get_meta()
data.number = meta:get_int("number") + 1 item_meta:set_string("label", node_meta:get_string("label"))
data.previous_pos = pos item_meta:set_int("number", node_meta:get_int("number") + 1)
local new_stack = ItemStack({name="breadcrumbs:marker", count=count, wear=0, metadata=minetest.serialize(data)}) item_meta:set_string("previous_pos", minetest.pos_to_string(pos))
return new_stack return new_stack
end end
@ -150,10 +183,11 @@ minetest.register_node("breadcrumbs:marker", {
local playername = placer:get_player_name() local playername = placer:get_player_name()
if minetest.is_protected(pos, playername) then return itemstack end if minetest.is_protected(pos, playername) then return itemstack end
local meta = itemstack:get_metadata() local item_meta = itemstack:get_meta()
local data = minetest.deserialize(meta) local label = item_meta:get_string("label")
if label == "" then return itemstack end -- don't place if there's no data
if not data then return itemstack end local number = item_meta:get_int("number")
local previous_pos_string = item_meta:get_string("previous_pos")
local success local success
itemstack, success = minetest.item_place(itemstack, placer, pointed_thing) itemstack, success = minetest.item_place(itemstack, placer, pointed_thing)
@ -161,25 +195,24 @@ minetest.register_node("breadcrumbs:marker", {
if not success then return itemstack end if not success then return itemstack end
local node_meta = minetest.get_meta(pos) local node_meta = minetest.get_meta(pos)
node_meta:set_string("label", data.label) node_meta:set_string("label", label)
node_meta:set_int("number", data.number) node_meta:set_int("number", number)
if data.number > 1 and data.previous_pos then if number > 1 and previous_pos_string ~= "" then
node_meta:set_int("previous_pos_x", data.previous_pos.x) local previous_pos = minetest.string_to_pos(previous_pos_string)
node_meta:set_int("previous_pos_y", data.previous_pos.y) node_meta:set_string("previous_pos", previous_pos_string)
node_meta:set_int("previous_pos_z", data.previous_pos.z) local dist = vector.distance(pos, previous_pos)
local dist = vector.distance(pos, data.previous_pos)
node_meta:set_string("infotext", node_meta:set_string("infotext",
string.format(placed_by_text .. "\n" .. distance_from_text, data.label, data.number, playername, dist)) string.format(placed_by_text .. "\n" .. distance_from_text, label, number, playername, dist))
else else
node_meta:set_string("infotext", node_meta:set_string("infotext",
string.format(placed_by_text, data.label, data.number, playername)) string.format(placed_by_text, label, number, playername))
end end
data.number = data.number + 1 local item_meta = itemstack:get_meta()
data.previous_pos = pos item_meta:set_string("label", label)
itemstack:set_metadata(minetest.serialize(data)) item_meta:set_int("number", number + 1)
item_meta:set_string("previous_pos", minetest.pos_to_string(pos))
return itemstack return itemstack
end, end,
@ -194,15 +227,14 @@ minetest.register_node("breadcrumbs:marker", {
if node.name ~= "breadcrumbs:marker" then return itemstack end if node.name ~= "breadcrumbs:marker" then return itemstack end
local node_meta = minetest.get_meta(pos) local node_meta = minetest.get_meta(pos)
local item_data = minetest.deserialize(itemstack:get_metadata()) local item_meta = itemstack:get_meta()
if node_meta:get_string("label") == item_data.label and local item_label = item_meta:get_string("label")
node_meta:get_int("number") == item_data.number - 1 then local item_number = item_meta:get_int("number")
item_data.number = item_data.number - 1
item_data.previous_pos.x = node_meta:get_int("previous_pos_x") if node_meta:get_string("label") == item_label and node_meta:get_int("number") == item_number - 1 then
item_data.previous_pos.y = node_meta:get_int("previous_pos_y") item_meta:set_int("number", item_number - 1)
item_data.previous_pos.z = node_meta:get_int("previous_pos_z") item_meta:set_string("previous_pos", node_meta:get_string("previous_pos"))
itemstack:set_metadata(minetest.serialize(item_data))
itemstack:set_count(itemstack:get_count() + 1) itemstack:set_count(itemstack:get_count() + 1)
minetest.remove_node(pos) minetest.remove_node(pos)
end end
@ -216,17 +248,20 @@ minetest.register_node("breadcrumbs:marker", {
return tag_to_itemstack(pos, itemstack:get_count()) return tag_to_itemstack(pos, itemstack:get_count())
end end
local meta = minetest.get_meta(pos) local node_meta = minetest.get_meta(pos)
local previous_pos = {} local previous_pos_string = node_meta:get_string("previous_pos")
previous_pos.x = meta:get_int("previous_pos_x")
previous_pos.y = meta:get_int("previous_pos_y")
previous_pos.z = meta:get_int("previous_pos_z")
if meta:get_int("number") > 1 and previous_pos.x and previous_pos.y and previous_pos.z and particles then if node_meta:get_int("number") > 1 and previous_pos_string ~= "" and particles then
local dir = vector.multiply(vector.direction(pos, previous_pos), 2) local previous_pos = minetest.string_to_pos(previous_pos_string)
local label = node_meta:get_string("label")
local number = node_meta:get_int("number") - 1
local distance = math.min(vector.distance(pos, previous_pos), 60) -- Particle stream extends no more than 60 meters
local dir = vector.multiply(vector.direction(pos, previous_pos), distance/10) -- divide distance by exptime
add_hud_marker(player, previous_pos, label .. " #" .. tostring(number))
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = 100, amount = 100,
time = 10, time = MARKER_DURATION,
minpos = pos, minpos = pos,
maxpos = pos, maxpos = pos,
minvel = dir, minvel = dir,
@ -290,3 +325,23 @@ if minetest.get_modpath("loot") then
}) })
end end
minetest.register_lbm({
label = "Upgrade legacy breadcrumb previous_pos",
name = "breadcrumbs:upgrade_previous_pos",
nodenames = {"breadcrumbs:marker"},
run_at_every_load = false,
action = function(pos, node)
local node_meta = minetest.get_meta(pos)
-- The previous_pos used to be stored as a set of three integer metadatas instead of one string
local previous_pos_x = tonumber(node_meta:get_string("previous_pos_x"))
if previous_pos_x ~= nil then
local previous_pos_y = node_meta:get_int("previous_pos_y")
local previous_pos_z = node_meta:get_int("previous_pos_z")
previous_pos_string = minetest.pos_to_string({x=previous_pos_x, y=previous_pos_y, z=previous_pos_z})
node_meta:set_string("previous_pos", previous_pos_string)
node_meta:set_string("previous_pos_x", "")
node_meta:set_string("previous_pos_y", "")
node_meta:set_string("previous_pos_z", "")
end
end,
})

View File

@ -1 +1,3 @@
name = breadcrumbs name = breadcrumbs
description = Path marker signs for use when exploring a twisty maze of passages that are all alike.
optional_depends = default, doc, intllib, loot