Skip to content

Commit

Permalink
Named waypoints (#7)
Browse files Browse the repository at this point in the history
* fix params

* split waypoints out into named_waypoints library mod

* fix bookgen

* update depends.txt

* add option to disable HUD waypoints, make foundation-filling less agressive to preserve caves

* remove deprecated reset_hud_markers call

* disallow 0-sized settlements

* add upgrade path

* upgrader fixes
  • Loading branch information
FaceDeer authored Jan 26, 2020
1 parent 8b9749a commit 910932f
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 454 deletions.
144 changes: 35 additions & 109 deletions settlements/admin_commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,115 +3,51 @@ local S, NS = settlements.S, settlements.NS

local visual_range = tonumber(minetest.settings:get("settlements_visibility_range")) or 600

minetest.register_chatcommand("settlements_list", {
description = S("List the settlements you know about"),
privs = {["server"]=true},
func = function(name, param)
local player = minetest.get_player_by_name(name)
local player_pos = player:get_pos()

local settlement_list = settlements.settlements_in_world:get_areas_in_area(
{x=-32000, y=-32000, z=-32000}, {x=32000, y=32000, z=32000}, true, true, true)

for _, settlement in pairs(settlement_list) do
local data = minetest.deserialize(settlement.data)
if data.discovered_by[name] then
local pos = settlement.min
local distance = math.floor(vector.distance(player_pos, pos))
local settlement_name = data.name or "Town"
minetest.chat_send_player(name, S("@1 is located @2m away at @3",
settlement_name, distance, minetest.pos_to_string(pos)))
end
end
end,
})

local function set_all_discovered(player_name, state)
local settlement_list = settlements.settlements_in_world:get_areas_in_area(
{x=-32000, y=-32000, z=-32000}, {x=32000, y=32000, z=32000}, true, true, true)
for id, settlement in pairs(settlement_list) do
local data = minetest.deserialize(settlement.data)
data.discovered_by[player_name] = state
settlements.settlements_in_world:remove_area(id)
settlements.settlements_in_world:insert_area(settlement.min, settlement.min, minetest.serialize(data), id)
end
settlements.settlements_save()
end

minetest.register_chatcommand("settlements_discover_all", {
description = S("Set all settlements as known"),
param = S("player_name, or nothing for yourself"),
privs = {["server"]=true},
func = function(name, param)
if param ~= "" then
name = param
end
set_all_discovered(name, true)
end,
})

minetest.register_chatcommand("settlements_undiscover_all", {
description = S("Set all settlements as unknown to you or another player"),
param = S("player_name, or nothing for yourself"),
privs = {["server"]=true},
func = function(name, param)
if param ~= "" then
name = param
end
set_all_discovered(name, nil)
end,
})

local function get_nearest_settlement_within_range(pos, range, name)
local min_edge = vector.subtract(pos, range)
local max_edge = vector.add(pos, range)
local settlement_list = settlements.settlements_in_world:get_areas_in_area(min_edge, max_edge, true, true, true)
local settlement_list = named_waypoints.get_waypoints_in_area("settlements", min_edge, max_edge)

local min_dist = range + 1 -- start with number beyond range
local min_id = nil
local min_data = nil
local min_pos = nil
local min_settlement = nil
for id, settlement in pairs(settlement_list) do
local data = minetest.deserialize(settlement.data)
local distance = vector.distance(pos, settlement.min)
if distance < min_dist and data.discovered_by[name] then
local distance = vector.distance(pos, settlement.pos)
if distance < min_dist and settlement.data.discovered_by[name] then
min_dist = distance
min_id = id
min_data = data
min_pos = settlement.min
min_settlement = settlement
end
end

return min_pos, min_id, min_data
return min_settlement
end

minetest.register_chatcommand("settlements_rename_nearest", {
description = S("Change the name of the nearest settlement within visible range"),
param = S("The new name for this settlement, or nothing to generate a new random name"),
description = S("Change the name of the nearest settlement you can see"),
params = S("The new name for this settlement, or nothing to generate a new random name"),
privs = {["server"]=true},
func = function(name, param)
local player = minetest.get_player_by_name(name)
local player_pos = player:get_pos()

local min_pos, min_id, min_data = get_nearest_settlement_within_range(player_pos, visual_range, name)
local settlement = get_nearest_settlement_within_range(player_pos, visual_range, name)

if min_id ~= nil then
if settlement ~= nil then
local data = settlement.data
if param == "" then
local def = settlements.registered_settlements[min_data.settlement_type]
local def
if data.settlement_type then
def = settlements.registered_settlements[data.settlement_type]
end
if not def then
minetest.chat_send_player(name, S("Missing settlement definition for @1", min_data.settlement_type))
minetest.chat_send_player(name, S("Missing settlement definition for @1", data.settlement_type))
return
end
param = def.generate_name(min_pos)
end
local oldname = min_data.name
min_data.name = param
settlements.settlements_in_world:remove_area(min_id)
settlements.settlements_in_world:insert_area(min_pos, min_pos, minetest.serialize(min_data), min_id)
settlements.settlements_save()
minetest.log("action", "[settlements] Renamed " .. oldname .. " to " .. param)
minetest.chat_send_player(name, S("Settlement successfully renamed from @1 to @2.", oldname, param))
settlements.remove_all_hud_markers()
local oldname = data.name
data.name = param
named_waypoints.update_waypoint("settlements", settlement.pos, data)
minetest.chat_send_player(name, S("Renamed @1 to @2.", oldname, param))
return
end

Expand All @@ -121,7 +57,7 @@ minetest.register_chatcommand("settlements_rename_nearest", {

minetest.register_chatcommand("settlements_regenerate_names", {
description = S("Regenerate the names for all settments of a particular type"),
param = S("The settlement type"),
params = S("The settlement type"),
privs = {["server"]=true},
func = function(name, param)
if param == "" then
Expand All @@ -134,49 +70,39 @@ minetest.register_chatcommand("settlements_regenerate_names", {
return
end

local settlement_list = settlements.settlements_in_world:get_areas_in_area(
{x=-32000, y=-32000, z=-32000}, {x=32000, y=32000, z=32000}, true, true, true)
local settlement_list = named_waypoints.get_waypoints_in_area("settlements",
{x=-32000, y=-32000, z=-32000}, {x=32000, y=32000, z=32000})
for id, settlement in pairs(settlement_list) do
local data = minetest.deserialize(settlement.data)
local data = settlement.data
if data.settlement_type == param then
local pos = settlement.min
local pos = settlement.pos
local oldname = data.name
data.name = settlement_def.generate_name(pos)
named_waypoints.update_waypoint("settlements", pos, data)
minetest.chat_send_player(name, S("Renamed @1 to @2", oldname, data.name))
minetest.log("action", "[settlements] Renamed " .. oldname .. " to " .. data.name)
settlements.settlements_in_world:remove_area(id)
settlements.settlements_in_world:insert_area(pos, pos, minetest.serialize(data), id)
end
end
settlements.settlements_save()
settlements.remove_all_hud_markers()
end,
})

minetest.register_chatcommand("settlements_remove_nearest", {
description = S("Remove the nearest settlement within a certain range (default 40)"),
param = S("range"),
params = S("range"),
privs = {["server"] = true},
func = function(name, param)
local range = tonumber(param) or 40
local player = minetest.get_player_by_name(name)
local player_pos = player:get_pos()
local min_pos, min_id, min_data = get_nearest_settlement_within_range(player_pos, range, name)

if min_id ~= nil then
local result = settlements.settlements_in_world:remove_area(min_id)
if result then
settlements.settlements_save()
minetest.log("action", "[settlements] Removed " .. min_data.name)
minetest.chat_send_player(name, S("Settlement @1 successfully removed.", min_data.name))
settlements.remove_all_hud_markers()
return
else
minetest.chat_send_player(name, S("Error removing settlement @1.", min_data.name))
return
end
local settlement = get_nearest_settlement_within_range(player_pos, range, name)

if settlement ~= nil then
named_waypoints.remove_waypoint("settlements", settlement.pos)
minetest.log("action", "[settlements] Removed " .. settlement.data.name)
minetest.chat_send_player(name, S("Settlement @1 successfully removed.", settlement.data.name))
else
minetest.chat_send_player(name, S("No known settlements within @1m found.", range))
end
minetest.chat_send_player(name, S("No known settlements within @1m found.", range))
end,
})

Expand Down
8 changes: 3 additions & 5 deletions settlements/admin_tools.lua
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ minetest.register_craftitem("settlements:mark_location_tool", {

local center_surface = pointed_thing.under
if center_surface then
local existing_area = settlements.settlements_in_world:get_areas_for_pos(center_surface, true, true)
center_surface = vector.add(center_surface, {x=0, y=2, z=0})
local existing_area = named_waypoints.get_waypoints_in_area("settlements", vector.subtract(center_surface, 5), vector.add(center_surface, 5))
if next(existing_area) then
minetest.chat_send_player(placer:get_player_name(), S("There's already a settlement at @1", minetest.pos_to_string(center_surface)))
return
Expand All @@ -153,10 +154,7 @@ minetest.register_craftitem("settlements:mark_location_tool", {
local name = settlement_def.generate_name(center_surface)
minetest.chat_send_player(placer:get_player_name(), S("Marked settlement @1 at @2", name, minetest.pos_to_string(center_surface)))
-- add settlement to list
settlements.settlements_in_world:insert_area(center_surface, center_surface,
minetest.serialize({name=name, discovered_by = {}, settlement_type = settlement_type}))
-- save list to file
settlements.settlements_save()
named_waypoints.add_waypoint("settlements", center_surface, {name=name, settlement_type = settlement_type})
end
end,
})
24 changes: 11 additions & 13 deletions settlements/bookgen.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ local half_map_chunk_size = settlements.half_map_chunk_size
minetest.register_abm({
label = "Settlement book authoring",
nodenames = {"default:bookshelf"},
interval = 86400/2, -- twice daily
interval = 900, -- once per quarter hour
-- Operation interval in seconds
chance = 1,
chance = 100,
-- Chance of triggering `action` per-node per-interval is 1.0 / this value
catch_up = true,
-- If true, catch-up behaviour is enabled: The `chance` value is
Expand All @@ -62,12 +62,12 @@ minetest.register_abm({
-- There's probably only ever going to be one, but might as well do a closeness check to be on the safe side.
local min_edge = vector.subtract(pos, half_map_chunk_size)
local max_edge = vector.add(pos, half_map_chunk_size)
local settlement_list = settlements.settlements_in_world:get_areas_in_area(min_edge, max_edge, true, true, true)
local settlement_list = named_waypoints.get_waypoints_in_area("settlements", min_edge, max_edge)
local closest_settlement
for id, settlement in pairs(settlement_list) do
local target_pos = settlement.min
for _, settlement in pairs(settlement_list) do
local target_pos = settlement.pos
if not closest_settlement or vector.distance(pos, target_pos) < vector.distance(pos, closest_settlement.pos) then
closest_settlement = {pos = target_pos, data = settlement.data}
closest_settlement = settlement
end
end

Expand All @@ -76,7 +76,7 @@ minetest.register_abm({
end

-- Get the settlement def and, if it generate books, generate one
local data = minetest.deserialize(closest_settlement.data)
local data = closest_settlement.data
local town_name = data.name
local town_type = data.settlement_type
local town_def = settlements.registered_settlements[town_type]
Expand Down Expand Up @@ -176,21 +176,19 @@ local get_random_settlement_within_range = function(pos, range_max, range_min)
end
local min_edge = vector.subtract(pos, range_max)
local max_edge = vector.add(pos, range_max)
local settlement_list = settlements.settlements_in_world:get_areas_in_area(min_edge, max_edge, true, true, true)
local settlement_list = named_waypoints.get_waypoints_in_area("settlements", min_edge, max_edge)
local settlements_within_range = {}
for id, settlement in pairs(settlement_list) do
local target_pos = settlement.min
local distance = vector.distance(pos, target_pos)
for _, settlement in pairs(settlement_list) do
local distance = vector.distance(pos, settlement.pos)
if distance < range_max and distance > range_min then
table.insert(settlements_within_range, {pos = target_pos, data = settlement.data})
table.insert(settlements_within_range, settlement)
end
end
if #settlements_within_range == 0 then
return
end

local target = settlements_within_range[math.random(#settlements_within_range)]
target.data = minetest.deserialize(target.data)
return target
end

Expand Down
Loading

0 comments on commit 910932f

Please sign in to comment.