2022-04-09 20:42:52 +02:00
|
|
|
|
-- If true, the Perlin test nodes will support color
|
|
|
|
|
-- (set to false in case of performance problems)
|
|
|
|
|
local COLORIZE_NODES = true
|
2022-04-15 21:43:23 +02:00
|
|
|
|
-- The number of available test node colors is divided by this number.
|
|
|
|
|
-- A number between 1 to 256
|
|
|
|
|
-- * 1 = Full 256 palette.
|
|
|
|
|
-- * 2 = 128 colors.
|
|
|
|
|
-- * 4 = 64 colors.
|
|
|
|
|
-- etc.
|
|
|
|
|
-- Higher values lead to less colors but increased performance.
|
|
|
|
|
-- This value is only used for performance reason, because Minetest
|
|
|
|
|
-- has a sharp performance drop when there are many different node colors on screen.
|
|
|
|
|
-- Consider removing this one when Minetest's performance problem has been solved.
|
|
|
|
|
local COLOR_PRECISION = 4
|
2022-04-09 20:42:52 +02:00
|
|
|
|
|
2022-04-15 22:30:02 +02:00
|
|
|
|
-- Time to wait in seconds before checking and generating new nodes in autobuild mode.
|
2022-04-16 15:10:49 +02:00
|
|
|
|
local AUTOBUILD_UPDATE_TIME = 0.1
|
2022-04-15 22:30:02 +02:00
|
|
|
|
|
|
|
|
|
-- x/y/z size of chunks to generate in autobuild mode.
|
2022-04-16 15:10:49 +02:00
|
|
|
|
local AUTOBUILD_SIZE = 24
|
2022-04-16 01:33:59 +02:00
|
|
|
|
-- Amount of chunks to generate around player
|
|
|
|
|
local AUTOBUILD_CHUNKDIST = 2
|
2022-04-15 22:30:02 +02:00
|
|
|
|
|
|
|
|
|
|
2022-04-15 05:55:17 +02:00
|
|
|
|
-- Color of the formspec box[] element
|
|
|
|
|
local FORMSPEC_BOX_COLOR = "#00000080"
|
2022-04-16 00:25:00 +02:00
|
|
|
|
-- Color for the section titles in the formspec
|
|
|
|
|
local FORMSPEC_HEADER_COLOR = "#000000FF"
|
2022-04-15 05:55:17 +02:00
|
|
|
|
|
2022-04-09 18:25:27 +02:00
|
|
|
|
local S = minetest.get_translator("perlin_explorer")
|
2022-04-10 01:45:19 +02:00
|
|
|
|
local F = minetest.formspec_escape
|
2022-04-09 18:23:01 +02:00
|
|
|
|
|
2022-04-15 05:55:17 +02:00
|
|
|
|
-- Per-player formspec states (mostly for remembering checkbox states)
|
2022-04-14 04:47:05 +02:00
|
|
|
|
local formspec_states = {}
|
|
|
|
|
|
2022-04-15 05:55:17 +02:00
|
|
|
|
-- List of noise parameters profiles
|
|
|
|
|
local np_profiles = {}
|
|
|
|
|
|
|
|
|
|
local default_noiseparams = {
|
2022-04-10 01:54:20 +02:00
|
|
|
|
offset = 0.0,
|
|
|
|
|
scale = 1.0,
|
|
|
|
|
spread = vector.new(10, 10, 10),
|
|
|
|
|
seed = 0,
|
|
|
|
|
octaves = 2,
|
2022-04-14 05:14:00 +02:00
|
|
|
|
persistence = 0.5,
|
2022-04-10 01:54:20 +02:00
|
|
|
|
lacunarity = 2.0,
|
2022-04-14 04:47:05 +02:00
|
|
|
|
flags = "noeased,noabsvalue",
|
2022-04-10 01:54:20 +02:00
|
|
|
|
}
|
2022-04-15 05:55:17 +02:00
|
|
|
|
|
|
|
|
|
-- Holds the currently used Perlin noise
|
|
|
|
|
local current_perlin = {}
|
|
|
|
|
-- holds the current PerlinNoise object
|
|
|
|
|
current_perlin.noise = nil
|
|
|
|
|
current_perlin.noiseparams = table.copy(default_noiseparams)
|
|
|
|
|
table.insert(np_profiles, current_perlin.noiseparams)
|
2022-04-10 00:33:16 +02:00
|
|
|
|
-- Side length of calculated perlin area
|
2022-04-11 02:21:07 +02:00
|
|
|
|
current_perlin.size = 64
|
2022-04-09 18:23:01 +02:00
|
|
|
|
-- Theoretical min and max values for Perlin noise (for colorization)
|
|
|
|
|
current_perlin.min = -1
|
2022-04-11 02:21:07 +02:00
|
|
|
|
current_perlin.max = 1
|
2022-04-16 03:24:41 +02:00
|
|
|
|
current_perlin.nodetype = 1
|
2022-04-09 18:23:01 +02:00
|
|
|
|
|
2022-04-09 21:43:33 +02:00
|
|
|
|
-- dimensions of current Perlin noise (2 or 3)
|
|
|
|
|
current_perlin.dimensions = 2
|
|
|
|
|
-- If greater than 1, the Perlin noise values are "pixelized". Noise values at
|
|
|
|
|
-- coordinates not divisible by sidelen will be set equal to the noise value
|
|
|
|
|
-- of the nearest number (counting downwards) that is divisible by sidelen.
|
|
|
|
|
-- This is (kind of) analogous to the "sidelen" parameter of mapgen decorations.
|
|
|
|
|
current_perlin.sidelen = 1
|
2022-04-16 04:44:05 +02:00
|
|
|
|
-- Place position of current perlin (relevant for single placing)
|
2022-04-16 13:25:21 +02:00
|
|
|
|
current_perlin.pos = nil
|
2022-04-09 20:42:52 +02:00
|
|
|
|
|
2022-04-16 04:44:05 +02:00
|
|
|
|
-- If enabled, automatically generate nodes around player
|
|
|
|
|
current_perlin.autogen = false
|
|
|
|
|
|
|
|
|
|
-- Remember which areas have been loaded by the autogen so far
|
|
|
|
|
-- Index: Hash of node position, value: true if loaded
|
2022-04-16 13:01:48 +02:00
|
|
|
|
local loaded_areas = {}
|
2022-04-14 03:07:42 +02:00
|
|
|
|
|
2022-04-09 20:42:52 +02:00
|
|
|
|
------------
|
|
|
|
|
|
2022-04-09 21:43:33 +02:00
|
|
|
|
-- Helper functions
|
|
|
|
|
-- Reduce the pos coordinates down to the closest numbers divisible by sidelen
|
|
|
|
|
local sidelen_pos = function(pos, sidelen)
|
|
|
|
|
local newpos = table.copy(pos)
|
|
|
|
|
if sidelen <= 1 then
|
|
|
|
|
return newpos
|
|
|
|
|
end
|
2022-04-09 23:11:58 +02:00
|
|
|
|
newpos.x = newpos.x - newpos.x % sidelen
|
|
|
|
|
newpos.y = newpos.y - newpos.y % sidelen
|
|
|
|
|
newpos.z = newpos.z - newpos.z % sidelen
|
2022-04-09 21:43:33 +02:00
|
|
|
|
return newpos
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-16 06:20:08 +02:00
|
|
|
|
local build_flags_string = function(eased, absvalue)
|
|
|
|
|
local flags = ""
|
|
|
|
|
if eased then
|
|
|
|
|
flags = "eased"
|
|
|
|
|
else
|
|
|
|
|
flags = "noeased"
|
|
|
|
|
end
|
|
|
|
|
if absvalue then
|
|
|
|
|
flags = flags .. ",absvalue"
|
|
|
|
|
else
|
|
|
|
|
flags = flags .. ",noabsvalue"
|
|
|
|
|
end
|
|
|
|
|
return flags
|
|
|
|
|
end
|
|
|
|
|
local parse_flags_string = function(flags)
|
|
|
|
|
local ftable = string.split(flags, ",")
|
|
|
|
|
local eased, absvalue = false, false
|
|
|
|
|
for f=1, #ftable do
|
|
|
|
|
local s = string.trim(ftable[f])
|
|
|
|
|
if s == "eased" then
|
|
|
|
|
eased = true
|
|
|
|
|
elseif s == "absvalue" then
|
|
|
|
|
absvalue = true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return { eased = eased, absvalue = absvalue }
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-15 22:11:32 +02:00
|
|
|
|
-- Sets the currently active Perlin noise.
|
|
|
|
|
-- * noiseparams: NoiseParams table (see Minetest's Lua API documentation)
|
|
|
|
|
local set_perlin_noise = function(noiseparams)
|
|
|
|
|
current_perlin.noise = PerlinNoise(noiseparams)
|
|
|
|
|
current_perlin.noiseparams = noiseparams
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-09 18:23:01 +02:00
|
|
|
|
-- Test nodes to generate a map based on a perlin noise
|
2022-04-09 20:42:52 +02:00
|
|
|
|
local paramtype2
|
|
|
|
|
if COLORIZE_NODES then
|
|
|
|
|
paramtype2 = "color"
|
|
|
|
|
end
|
2022-04-16 03:24:41 +02:00
|
|
|
|
|
2022-04-16 03:37:31 +02:00
|
|
|
|
-- Register list of node types for test mapgen
|
2022-04-16 03:24:41 +02:00
|
|
|
|
local nodetypes = {
|
2022-04-16 03:37:31 +02:00
|
|
|
|
-- { Entry name for sformspec, positive node, negative node, supports color? }
|
|
|
|
|
{ S("Solid Nodes"), "perlin_explorer:node", "perlin_explorer:node_negative", true },
|
|
|
|
|
{ S("Grid Nodes"), "perlin_explorer:grid", "perlin_explorer:grid_negative", true },
|
|
|
|
|
{ S("Minibox Nodes"), "perlin_explorer:mini", "perlin_explorer:mini_negative", true },
|
2022-04-16 03:24:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-16 06:20:08 +02:00
|
|
|
|
-- Analyze the given noiseparams for interesting properties.
|
|
|
|
|
-- Returns: <min>, <max>, <waves>
|
|
|
|
|
-- min = minimum possible value
|
|
|
|
|
-- max = maximum possible value
|
|
|
|
|
-- waves = table with x/y/z indices, each containing a list of effective "wavelengths" for each of the axes
|
|
|
|
|
local analyze_noiseparams = function(noiseparams)
|
|
|
|
|
local np = noiseparams
|
|
|
|
|
|
|
|
|
|
local flags = parse_flags_string(noiseparams.flags)
|
|
|
|
|
local is_absolute = flags.absvalue == true
|
|
|
|
|
-- Calculate min. and max. possible values
|
|
|
|
|
-- Octaves
|
|
|
|
|
local o_min, o_max = 0, 0
|
|
|
|
|
for o=1, np.octaves do
|
|
|
|
|
local exp = o-1
|
|
|
|
|
o_max = o_max + (1 * np.persistence ^ exp)
|
|
|
|
|
if not is_absolute then
|
|
|
|
|
o_min = o_min + (- 1 * np.persistence ^ exp)
|
|
|
|
|
-- Note: If absvalue flag is set, the sum of the octaves
|
|
|
|
|
-- is always 0, so we don't need to calculate it
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
-- Offset and scale
|
|
|
|
|
local min_value = np.offset + np.scale * o_min
|
|
|
|
|
local max_value = np.offset + np.scale * o_max
|
|
|
|
|
|
|
|
|
|
-- Calculate "wavelengths"
|
|
|
|
|
local axes = { "x", "y", "z" }
|
|
|
|
|
local waves = {}
|
|
|
|
|
for a=1, #axes do
|
|
|
|
|
local w = axes[a]
|
|
|
|
|
waves[w] = {}
|
|
|
|
|
local wave = np.spread[w]
|
|
|
|
|
for o=1, np.octaves do
|
|
|
|
|
table.insert(waves[w], wave)
|
|
|
|
|
wave = wave * (1 / np.lacunarity)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return min_value, max_value, waves
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-16 03:37:31 +02:00
|
|
|
|
-- Add stone node to nodetypes, if present
|
|
|
|
|
minetest.register_on_mods_loaded(function()
|
|
|
|
|
local stone = minetest.registered_aliases["mapgen_stone"]
|
|
|
|
|
if stone then
|
|
|
|
|
local desc = minetest.registered_nodes[stone].description
|
|
|
|
|
if not desc then
|
|
|
|
|
desc = stone
|
|
|
|
|
end
|
|
|
|
|
table.insert(nodetypes, { desc, stone, "air", false})
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
2022-04-09 18:25:27 +02:00
|
|
|
|
minetest.register_node("perlin_explorer:node", {
|
2022-04-16 02:55:36 +02:00
|
|
|
|
description = S("Solid Perlin Test Node"),
|
2022-04-10 01:54:20 +02:00
|
|
|
|
paramtype = "light",
|
|
|
|
|
sunlight_propagates = true,
|
2022-04-09 20:42:52 +02:00
|
|
|
|
paramtype2 = paramtype2,
|
2022-04-09 18:25:27 +02:00
|
|
|
|
tiles = {"perlin_explorer_node.png"},
|
|
|
|
|
palette = "perlin_explorer_node_palette.png",
|
2022-04-09 18:23:01 +02:00
|
|
|
|
groups = { dig_immediate = 3 },
|
|
|
|
|
-- Force-drop without metadata to avoid spamming the inventory
|
2022-04-09 18:25:27 +02:00
|
|
|
|
drop = "perlin_explorer:node",
|
2022-04-09 18:23:01 +02:00
|
|
|
|
})
|
2022-04-09 18:25:27 +02:00
|
|
|
|
minetest.register_node("perlin_explorer:node_negative", {
|
2022-04-16 02:55:36 +02:00
|
|
|
|
description = S("Solid Negative Perlin Test Node"),
|
2022-04-10 01:54:20 +02:00
|
|
|
|
paramtype = "light",
|
|
|
|
|
sunlight_propagates = true,
|
2022-04-09 20:42:52 +02:00
|
|
|
|
paramtype2 = paramtype2,
|
2022-04-09 18:25:27 +02:00
|
|
|
|
tiles = {"perlin_explorer_node_neg.png"},
|
|
|
|
|
palette = "perlin_explorer_node_palette_neg.png",
|
2022-04-09 18:23:01 +02:00
|
|
|
|
groups = { dig_immediate = 3 },
|
|
|
|
|
-- Force-drop without metadata to avoid spamming the inventory
|
2022-04-09 18:25:27 +02:00
|
|
|
|
drop = "perlin_explorer:node_negative",
|
2022-04-09 18:23:01 +02:00
|
|
|
|
})
|
2022-04-16 02:20:53 +02:00
|
|
|
|
|
2022-04-16 02:55:36 +02:00
|
|
|
|
minetest.register_node("perlin_explorer:grid", {
|
|
|
|
|
description = S("Grid Perlin Test Node"),
|
2022-04-16 02:20:53 +02:00
|
|
|
|
paramtype = "light",
|
|
|
|
|
drawtype = "allfaces",
|
2022-04-16 02:55:36 +02:00
|
|
|
|
use_texture_alpha = "clip",
|
2022-04-16 02:20:53 +02:00
|
|
|
|
sunlight_propagates = true,
|
|
|
|
|
paramtype2 = paramtype2,
|
2022-04-16 02:55:36 +02:00
|
|
|
|
tiles = {"perlin_explorer_grid.png"},
|
2022-04-16 02:20:53 +02:00
|
|
|
|
palette = "perlin_explorer_node_palette.png",
|
|
|
|
|
groups = { dig_immediate = 3 },
|
2022-04-16 02:55:36 +02:00
|
|
|
|
drop = "perlin_explorer:grid",
|
2022-04-16 02:20:53 +02:00
|
|
|
|
})
|
2022-04-16 02:55:36 +02:00
|
|
|
|
minetest.register_node("perlin_explorer:grid_negative", {
|
|
|
|
|
description = S("Grid Negative Perlin Test Node"),
|
2022-04-16 02:20:53 +02:00
|
|
|
|
paramtype = "light",
|
|
|
|
|
sunlight_propagates = true,
|
|
|
|
|
paramtype2 = paramtype2,
|
2022-04-16 02:55:36 +02:00
|
|
|
|
tiles = {"perlin_explorer_grid_neg.png"},
|
|
|
|
|
use_texture_alpha = "clip",
|
|
|
|
|
palette = "perlin_explorer_node_palette_neg.png",
|
|
|
|
|
groups = { dig_immediate = 3 },
|
|
|
|
|
drop = "perlin_explorer:grid_negative",
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
minetest.register_node("perlin_explorer:mini", {
|
|
|
|
|
description = S("Minibox Perlin Test Node"),
|
|
|
|
|
paramtype = "light",
|
|
|
|
|
drawtype = "nodebox",
|
|
|
|
|
climbable = true,
|
|
|
|
|
walkable = false,
|
|
|
|
|
node_box = {
|
|
|
|
|
type = "fixed",
|
|
|
|
|
fixed = { -2/16, -2/16, -2/16, 2/16, 2/16, 2/16 },
|
|
|
|
|
},
|
|
|
|
|
use_texture_alpha = "clip",
|
|
|
|
|
sunlight_propagates = true,
|
|
|
|
|
paramtype2 = paramtype2,
|
|
|
|
|
tiles = {"perlin_explorer_mini.png"},
|
|
|
|
|
palette = "perlin_explorer_node_palette.png",
|
|
|
|
|
groups = { dig_immediate = 3 },
|
|
|
|
|
drop = "perlin_explorer:mini",
|
|
|
|
|
})
|
|
|
|
|
minetest.register_node("perlin_explorer:mini_negative", {
|
|
|
|
|
description = S("Minibox Negative Perlin Test Node"),
|
|
|
|
|
paramtype = "light",
|
|
|
|
|
drawtype = "nodebox",
|
|
|
|
|
climbable = true,
|
|
|
|
|
walkable = false,
|
|
|
|
|
node_box = {
|
|
|
|
|
type = "fixed",
|
|
|
|
|
fixed = { -2/16, -2/16, -2/16, 2/16, 2/16, 2/16 },
|
|
|
|
|
},
|
|
|
|
|
sunlight_propagates = true,
|
|
|
|
|
paramtype2 = paramtype2,
|
|
|
|
|
tiles = {"perlin_explorer_mini_neg.png"},
|
|
|
|
|
use_texture_alpha = "clip",
|
2022-04-16 02:20:53 +02:00
|
|
|
|
palette = "perlin_explorer_node_palette_neg.png",
|
|
|
|
|
groups = { dig_immediate = 3 },
|
2022-04-16 02:55:36 +02:00
|
|
|
|
drop = "perlin_explorer:mini_negative",
|
2022-04-16 02:20:53 +02:00
|
|
|
|
})
|
|
|
|
|
|
2022-04-09 20:39:15 +02:00
|
|
|
|
minetest.register_tool("perlin_explorer:getter", {
|
|
|
|
|
description = S("Perlin Value Getter"),
|
|
|
|
|
_tt_help = S("Punch a node to display the Perlin noise value at this position"),
|
|
|
|
|
inventory_image = "perlin_explorer_getter.png",
|
|
|
|
|
wield_image = "perlin_explorer_getter.png",
|
|
|
|
|
groups = { disable_repair = 1 },
|
|
|
|
|
on_use = function(itemstack, user, pointed_thing)
|
2022-04-10 01:45:19 +02:00
|
|
|
|
if not user then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
local privs = minetest.get_player_privs(user:get_player_name())
|
|
|
|
|
if not privs.server then
|
2022-04-10 01:54:20 +02:00
|
|
|
|
minetest.chat_send_player(user:get_player_name(), S("Insufficient privileges! You need the @1 privilege to use this tool.", "server"))
|
|
|
|
|
return
|
2022-04-10 01:45:19 +02:00
|
|
|
|
end
|
2022-04-09 20:39:15 +02:00
|
|
|
|
if current_perlin.noise then
|
|
|
|
|
if pointed_thing.type ~= "node" then
|
|
|
|
|
-- No-op for non-nodes
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
local pos = pointed_thing.under
|
2022-04-09 21:43:33 +02:00
|
|
|
|
local getpos = sidelen_pos(pos, current_perlin.sidelen)
|
2022-04-09 20:39:15 +02:00
|
|
|
|
local val
|
|
|
|
|
if current_perlin.dimensions == 2 then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
val = current_perlin.noise:get_2d({x=getpos.x, y=getpos.z})
|
2022-04-09 21:00:12 +02:00
|
|
|
|
elseif current_perlin.dimensions == 3 then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
val = current_perlin.noise:get_3d(getpos)
|
2022-04-09 21:00:12 +02:00
|
|
|
|
else
|
2022-04-09 21:43:33 +02:00
|
|
|
|
minetest.chat_send_player(user:get_player_name(), S("Unknown/invalid number of Perlin noise dimensions. Use /generate_perlin first!"))
|
2022-04-09 20:39:15 +02:00
|
|
|
|
end
|
|
|
|
|
minetest.chat_send_player(user:get_player_name(), S("pos=@1, value=@2", minetest.pos_to_string(pos), val))
|
|
|
|
|
else
|
2022-04-15 21:44:49 +02:00
|
|
|
|
local msg = S("No Perlin noise set. Set one first!")
|
2022-04-09 20:39:15 +02:00
|
|
|
|
minetest.chat_send_player(user:get_player_name(), msg)
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
2022-04-09 23:17:35 +02:00
|
|
|
|
local update_map = function(pos, set_nodes)
|
2022-04-09 18:23:01 +02:00
|
|
|
|
local stats
|
|
|
|
|
if not current_perlin.noise then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-10 00:33:16 +02:00
|
|
|
|
local size_v = vector.new(current_perlin.size, current_perlin.size, current_perlin.size)
|
2022-04-09 18:23:01 +02:00
|
|
|
|
|
|
|
|
|
local startpos = pos
|
2022-04-10 00:33:16 +02:00
|
|
|
|
local endpos = vector.add(startpos, current_perlin.size-1)
|
2022-04-09 18:23:01 +02:00
|
|
|
|
|
|
|
|
|
local y_max = endpos.y - startpos.y
|
|
|
|
|
if current_perlin.dimensions == 2 then
|
|
|
|
|
y_max = 0
|
|
|
|
|
startpos.y = pos.y
|
|
|
|
|
endpos.y = pos.y
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-09 23:17:35 +02:00
|
|
|
|
local vmanip, emin, emax, vdata, vdata2, varea
|
|
|
|
|
if set_nodes then
|
|
|
|
|
vmanip = VoxelManip(startpos, endpos)
|
|
|
|
|
emin, emax = vmanip:get_emerged_area()
|
|
|
|
|
vdata = vmanip:get_data()
|
|
|
|
|
vdata2 = vmanip:get_param2_data()
|
|
|
|
|
varea = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
|
|
|
end
|
2022-04-09 21:43:33 +02:00
|
|
|
|
|
2022-04-16 03:24:41 +02:00
|
|
|
|
local content_test_node = minetest.get_content_id(nodetypes[current_perlin.nodetype][2])
|
|
|
|
|
local content_test_node_negative = minetest.get_content_id(nodetypes[current_perlin.nodetype][3])
|
2022-04-16 03:37:31 +02:00
|
|
|
|
local needs_color = nodetypes[current_perlin.nodetype][4]
|
2022-04-16 03:24:41 +02:00
|
|
|
|
|
2022-04-09 18:23:01 +02:00
|
|
|
|
stats = {}
|
|
|
|
|
stats.avg = 0
|
|
|
|
|
local sum_of_values = 0
|
|
|
|
|
local value_count = 0
|
|
|
|
|
for x=0, endpos.x - startpos.x do
|
|
|
|
|
for y=0, y_max do
|
|
|
|
|
for z=0, endpos.z - startpos.z do
|
|
|
|
|
-- Get Perlin value at current pos
|
|
|
|
|
local relpos = vector.new(x,y,z)
|
|
|
|
|
local abspos = vector.add(startpos, relpos)
|
2022-04-09 21:43:33 +02:00
|
|
|
|
local abspos_get = sidelen_pos(abspos, current_perlin.sidelen)
|
2022-04-09 18:23:01 +02:00
|
|
|
|
local perlin_value
|
|
|
|
|
if current_perlin.dimensions == 2 then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
perlin_value = current_perlin.noise:get_2d({x=abspos_get.x, y=abspos_get.z})
|
2022-04-09 18:23:01 +02:00
|
|
|
|
elseif current_perlin.dimensions == 3 then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
perlin_value = current_perlin.noise:get_3d(abspos_get)
|
2022-04-09 18:23:01 +02:00
|
|
|
|
else
|
2022-04-09 18:25:27 +02:00
|
|
|
|
error("[perlin_explorer] Unknown/invalid number of Perlin noise dimensions!")
|
2022-04-09 18:23:01 +02:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Statistics
|
|
|
|
|
if not stats.min then
|
|
|
|
|
stats.min = perlin_value
|
|
|
|
|
elseif perlin_value < stats.min then
|
|
|
|
|
stats.min = perlin_value
|
|
|
|
|
end
|
|
|
|
|
if not stats.max then
|
|
|
|
|
stats.max = perlin_value
|
|
|
|
|
elseif perlin_value > stats.max then
|
|
|
|
|
stats.max = perlin_value
|
|
|
|
|
end
|
|
|
|
|
sum_of_values = sum_of_values + perlin_value
|
|
|
|
|
value_count = value_count + 1
|
|
|
|
|
|
|
|
|
|
-- Calculate color (param2) for node
|
2022-04-09 22:48:27 +02:00
|
|
|
|
local zeropoint = 0
|
|
|
|
|
local min_size = zeropoint - current_perlin.min
|
|
|
|
|
local max_size = current_perlin.max - zeropoint
|
2022-04-16 03:37:31 +02:00
|
|
|
|
local node_param2 = 0
|
|
|
|
|
if needs_color then
|
|
|
|
|
if perlin_value >= zeropoint then
|
|
|
|
|
node_param2 = (math.abs(perlin_value) / max_size) * 255
|
|
|
|
|
else
|
|
|
|
|
node_param2 = (math.abs(perlin_value) / min_size) * 255
|
|
|
|
|
end
|
|
|
|
|
node_param2 = math.floor(math.abs(node_param2))
|
|
|
|
|
node_param2 = math.max(0, math.min(255, node_param2))
|
|
|
|
|
if node_param2 < 255 then
|
|
|
|
|
node_param2 = node_param2 - (node_param2 % COLOR_PRECISION)
|
|
|
|
|
end
|
2022-04-15 21:43:23 +02:00
|
|
|
|
end
|
2022-04-09 18:23:01 +02:00
|
|
|
|
|
2022-04-09 23:17:35 +02:00
|
|
|
|
if set_nodes then
|
|
|
|
|
-- Get vmanip index
|
|
|
|
|
local index = varea:indexp(abspos)
|
|
|
|
|
if not index then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-09 18:23:01 +02:00
|
|
|
|
|
2022-04-09 23:17:35 +02:00
|
|
|
|
-- Set node and param2
|
|
|
|
|
if perlin_value >= zeropoint then
|
2022-04-16 03:24:41 +02:00
|
|
|
|
vdata[index] = content_test_node
|
2022-04-09 18:23:01 +02:00
|
|
|
|
vdata2[index] = node_param2
|
|
|
|
|
else
|
2022-04-09 23:17:35 +02:00
|
|
|
|
if current_perlin.show_negative == true then
|
2022-04-16 03:24:41 +02:00
|
|
|
|
vdata[index] = content_test_node_negative
|
2022-04-09 23:17:35 +02:00
|
|
|
|
vdata2[index] = node_param2
|
|
|
|
|
else
|
|
|
|
|
vdata[index] = minetest.CONTENT_AIR
|
|
|
|
|
vdata2[index] = 0
|
|
|
|
|
end
|
2022-04-09 18:23:01 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
stats.avg = sum_of_values / value_count
|
|
|
|
|
|
2022-04-09 23:17:35 +02:00
|
|
|
|
if set_nodes then
|
|
|
|
|
-- Set vmanip, return stats
|
|
|
|
|
vmanip:set_data(vdata)
|
|
|
|
|
vmanip:set_param2_data(vdata2)
|
|
|
|
|
vmanip:write_to_map()
|
|
|
|
|
end
|
2022-04-09 18:23:01 +02:00
|
|
|
|
return stats
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Creates and demonstrates a Perlin noise.
|
|
|
|
|
-- * pos: Where the Perlin noise starts
|
|
|
|
|
-- * options: table with:
|
|
|
|
|
-- * dimensions: number of Perlin noise dimensions (2 or 3)
|
2022-04-10 00:33:16 +02:00
|
|
|
|
-- * size: side length of area/volume to calculate)
|
2022-04-09 19:44:15 +02:00
|
|
|
|
-- * show_negative: if true, places nodes for negative Perlin values (default: true for 2 dimensions and false for 3 dimensions)
|
2022-04-09 23:17:35 +02:00
|
|
|
|
-- * set_nodes: if true, will set nodes, otherwise it's a "dry run"
|
|
|
|
|
local create_perlin = function(pos, options)
|
2022-04-09 19:44:15 +02:00
|
|
|
|
if not current_perlin.noise then
|
|
|
|
|
return false
|
|
|
|
|
end
|
2022-04-09 18:23:01 +02:00
|
|
|
|
current_perlin.dimensions = options.dimensions
|
2022-04-10 00:33:16 +02:00
|
|
|
|
current_perlin.size = options.size
|
2022-04-09 18:23:01 +02:00
|
|
|
|
current_perlin.show_negative = options.show_negative
|
|
|
|
|
if current_perlin.show_negative == nil then
|
2022-04-09 19:44:15 +02:00
|
|
|
|
if current_perlin.dimensions == 2 then
|
2022-04-09 20:39:15 +02:00
|
|
|
|
current_perlin.show_negative = true
|
2022-04-09 19:44:15 +02:00
|
|
|
|
elseif current_perlin.dimensions == 3 then
|
2022-04-09 20:39:15 +02:00
|
|
|
|
current_perlin.show_negative = false
|
2022-04-09 19:44:15 +02:00
|
|
|
|
end
|
2022-04-09 18:23:01 +02:00
|
|
|
|
end
|
2022-04-15 22:41:31 +02:00
|
|
|
|
local cpos = table.copy(pos)
|
|
|
|
|
local mpos = vector.round(cpos)
|
2022-04-11 02:21:07 +02:00
|
|
|
|
current_perlin.pos = mpos
|
2022-04-09 23:17:35 +02:00
|
|
|
|
local set_nodes = options.set_nodes ~= false
|
|
|
|
|
local stats = update_map(mpos, set_nodes)
|
2022-04-16 02:05:51 +02:00
|
|
|
|
|
|
|
|
|
-- Show a particle in the center of the newly generated area
|
|
|
|
|
local center = vector.new()
|
|
|
|
|
center.x = mpos.x + options.size/2
|
2022-04-16 13:58:45 +02:00
|
|
|
|
if current_perlin.dimensions == 2 then
|
|
|
|
|
center.y = mpos.y + 3
|
|
|
|
|
else
|
|
|
|
|
center.y = mpos.y + options.size/2
|
|
|
|
|
end
|
2022-04-16 02:05:51 +02:00
|
|
|
|
center.z = mpos.z + options.size/2
|
|
|
|
|
minetest.add_particle({
|
|
|
|
|
pos = center,
|
|
|
|
|
expirationtime = 4,
|
|
|
|
|
size = 16,
|
|
|
|
|
texture = "perlin_explorer_new_chunk_particle.png",
|
|
|
|
|
glow = minetest.LIGHT_MAX,
|
|
|
|
|
})
|
2022-04-09 18:23:01 +02:00
|
|
|
|
if stats then
|
2022-04-16 04:52:29 +02:00
|
|
|
|
minetest.log("info", "[perlin_explorer] Perlin noise generated at %s! Stats: min. value=%.3f, max. value=%.3f, avg. value=%.3f", minetest.pos_to_string(mpos), stats.min, stats.max, stats.avg)
|
|
|
|
|
local fo = function(str)
|
|
|
|
|
return string.format("%.3f", str)
|
|
|
|
|
end
|
|
|
|
|
return S("Perlin noise generated at @1! Stats: min. value=@2, max. value=@3, avg. value=@4", minetest.pos_to_string(mpos), fo(stats.min), fo(stats.max), fo(stats.avg))
|
|
|
|
|
else
|
|
|
|
|
minetest.log("error", "[perlin_explorer] Could not get stats!")
|
|
|
|
|
return false
|
2022-04-09 18:23:01 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-16 13:25:21 +02:00
|
|
|
|
local seeder_reseed = function(player, regen)
|
|
|
|
|
local msg
|
|
|
|
|
if regen and (not current_perlin.autogen and current_perlin.pos) then
|
|
|
|
|
msg = S("New random seed set, starting to regenerate nodes ...")
|
|
|
|
|
minetest.chat_send_player(player:get_player_name(), msg)
|
|
|
|
|
msg = create_perlin(current_perlin.pos, {dimensions = current_perlin.dimensions, size = current_perlin.size})
|
|
|
|
|
if msg ~= false then
|
|
|
|
|
minetest.chat_send_player(player:get_player_name(), msg)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
msg = S("New random seed set!")
|
|
|
|
|
minetest.chat_send_player(player:get_player_name(), msg)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function seeder_use(reseed)
|
|
|
|
|
return function(itemstack, user, pointed_thing)
|
|
|
|
|
if not user then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
local privs = minetest.get_player_privs(user:get_player_name())
|
|
|
|
|
if not privs.server then
|
|
|
|
|
minetest.chat_send_player(user:get_player_name(), S("Insufficient privileges! You need the @1 privilege to use this tool.", "server"))
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
if current_perlin.noise then
|
|
|
|
|
local noiseparams = table.copy(current_perlin.noiseparams)
|
|
|
|
|
noiseparams.seed = math.random(0, 2^32-1)
|
|
|
|
|
set_perlin_noise(noiseparams)
|
|
|
|
|
loaded_areas = {}
|
|
|
|
|
seeder_reseed(user, reseed)
|
|
|
|
|
else
|
|
|
|
|
local msg = S("No Perlin noise set. Set one first!")
|
|
|
|
|
minetest.chat_send_player(user:get_player_name(), msg)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
minetest.register_tool("perlin_explorer:seeder", {
|
|
|
|
|
description = S("Random Perlin seed setter"),
|
|
|
|
|
_tt_help = S("Punch: Set a random seed for the current Perlin noise params").."\n"..
|
|
|
|
|
S("Place: Set a random seed and regenerate nodes (if applicable)"),
|
|
|
|
|
inventory_image = "perlin_explorer_seeder.png",
|
|
|
|
|
wield_image = "perlin_explorer_seeder.png",
|
|
|
|
|
groups = { disable_repair = 1 },
|
|
|
|
|
on_use = seeder_use(false),
|
|
|
|
|
on_secondary_use = seeder_use(true),
|
|
|
|
|
on_place = seeder_use(true),
|
|
|
|
|
})
|
|
|
|
|
|
2022-04-09 21:43:33 +02:00
|
|
|
|
minetest.register_chatcommand("perlin_set_options", {
|
|
|
|
|
privs = { server = true },
|
2022-04-16 13:53:00 +02:00
|
|
|
|
description = S("Set Perlin map generation options"),
|
2022-04-09 22:48:27 +02:00
|
|
|
|
params = S("<dimensions> <sidelen> <minval> <maxval>"),
|
2022-04-09 21:43:33 +02:00
|
|
|
|
func = function(name, param)
|
2022-04-09 22:48:27 +02:00
|
|
|
|
local dimensions, sidelen, min, max = string.match(param, "([23]) ([0-9]+) ([0-9.-]+) ([0-9.-]+)")
|
|
|
|
|
if not dimensions then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
dimensions = tonumber(dimensions)
|
|
|
|
|
sidelen = tonumber(sidelen)
|
2022-04-09 22:48:27 +02:00
|
|
|
|
min = tonumber(min)
|
|
|
|
|
max = tonumber(max)
|
|
|
|
|
if not dimensions or not sidelen or not min or not max then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
return false, S("Invalid parameter type.")
|
|
|
|
|
end
|
|
|
|
|
current_perlin.dimensions = dimensions
|
|
|
|
|
current_perlin.sidelen = sidelen
|
2022-04-09 22:48:27 +02:00
|
|
|
|
current_perlin.min = min
|
|
|
|
|
current_perlin.max = max
|
2022-04-16 13:01:48 +02:00
|
|
|
|
loaded_areas = {}
|
2022-04-16 13:53:00 +02:00
|
|
|
|
return true, S("Perlin map generation options set!")
|
2022-04-09 21:43:33 +02:00
|
|
|
|
end,
|
|
|
|
|
})
|
2022-04-09 23:17:35 +02:00
|
|
|
|
|
2022-04-09 21:43:33 +02:00
|
|
|
|
minetest.register_chatcommand("perlin_set_noise", {
|
2022-04-09 19:44:15 +02:00
|
|
|
|
privs = { server = true },
|
2022-04-16 13:53:00 +02:00
|
|
|
|
description = S("Set active Perlin noise parameters"),
|
|
|
|
|
params = S("<offset> <scale> <seed> <spread_x> <spread_y> <spread_z> <octaves> <persistence> <lacunarity> [<flags>]"),
|
2022-04-09 19:44:15 +02:00
|
|
|
|
func = function(name, param)
|
2022-04-16 13:53:00 +02:00
|
|
|
|
local offset, scale, seed, sx, sy, sz, octaves, persistence, lacunarity, flags = string.match(param, string.rep("([0-9.-]+) ", 9) .. "([a-zA-Z, ]+)")
|
|
|
|
|
if not offset then
|
|
|
|
|
offset, scale, seed, sx, sy, sz, octaves, persistence, lacunarity = string.match(param, string.rep("([0-9.-]+) ", 8) .. "([0-9.-]+)")
|
|
|
|
|
if not offset then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if not flags then
|
|
|
|
|
flags = ""
|
2022-04-09 19:44:15 +02:00
|
|
|
|
end
|
|
|
|
|
octaves = tonumber(octaves)
|
|
|
|
|
offset = tonumber(offset)
|
|
|
|
|
sx = tonumber(sx)
|
|
|
|
|
sy = tonumber(sy)
|
|
|
|
|
sz = tonumber(sz)
|
|
|
|
|
persistence = tonumber(persistence)
|
|
|
|
|
lacunarity = tonumber(lacunarity)
|
|
|
|
|
seed = tonumber(seed)
|
|
|
|
|
if not octaves or not offset or not sx or not sy or not sz or not persistence or not lacunarity or not seed then
|
2022-04-09 21:43:33 +02:00
|
|
|
|
return false, S("Invalid parameter type.")
|
2022-04-09 19:44:15 +02:00
|
|
|
|
end
|
|
|
|
|
set_perlin_noise({
|
|
|
|
|
octaves = octaves,
|
|
|
|
|
offset = offset,
|
|
|
|
|
scale = scale,
|
|
|
|
|
spread = { x = sx, y = sy, z = sz },
|
|
|
|
|
persistence = persistence,
|
|
|
|
|
lacunarity = lacunarity,
|
|
|
|
|
seed = seed,
|
2022-04-16 13:53:00 +02:00
|
|
|
|
flags = flags,
|
2022-04-09 19:44:15 +02:00
|
|
|
|
})
|
2022-04-16 13:01:48 +02:00
|
|
|
|
loaded_areas = {}
|
2022-04-16 13:53:00 +02:00
|
|
|
|
return true, S("Active Perlin noise parameters set!")
|
2022-04-09 19:44:15 +02:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
minetest.register_chatcommand("perlin_generate", {
|
|
|
|
|
privs = { server = true },
|
|
|
|
|
description = S("Generate Perlin noise"),
|
2022-04-10 00:33:16 +02:00
|
|
|
|
params = S("<pos> <size>"),
|
2022-04-09 19:44:15 +02:00
|
|
|
|
func = function(name, param)
|
2022-04-10 00:33:16 +02:00
|
|
|
|
local x, y, z, size = string.match(param, "([0-9.-]+) ([0-9.-]+) ([0-9.-]+) ([0-9]+)")
|
2022-04-09 20:39:15 +02:00
|
|
|
|
if not x then
|
2022-04-09 19:44:15 +02:00
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
x = tonumber(x)
|
|
|
|
|
y = tonumber(y)
|
|
|
|
|
z = tonumber(z)
|
2022-04-10 00:33:16 +02:00
|
|
|
|
size = tonumber(size)
|
|
|
|
|
if not x or not y or not z or not size then
|
2022-04-09 19:44:15 +02:00
|
|
|
|
return false
|
|
|
|
|
end
|
2022-04-10 00:33:16 +02:00
|
|
|
|
if not x or not y or not z or not size then
|
2022-04-09 19:44:15 +02:00
|
|
|
|
return false, S("Invalid parameter type.")
|
|
|
|
|
end
|
|
|
|
|
local pos = vector.new(x, y, z)
|
|
|
|
|
|
|
|
|
|
minetest.chat_send_player(name, S("Creating Perlin noise, please wait …"))
|
2022-04-10 00:33:16 +02:00
|
|
|
|
local msg = create_perlin(pos, {dimensions=current_perlin.dimensions, size=size})
|
2022-04-09 19:44:15 +02:00
|
|
|
|
if msg == false then
|
2022-04-16 04:52:29 +02:00
|
|
|
|
return false, S("No Perlin noise set. Set one first!")
|
2022-04-09 19:44:15 +02:00
|
|
|
|
end
|
|
|
|
|
return true, msg
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
2022-04-16 06:20:08 +02:00
|
|
|
|
-- Analyzes the given noise params and shows the result in a pretty-printed formspec to player
|
|
|
|
|
local analyze_noiseparams_and_show_formspec = function(player, noiseparams)
|
|
|
|
|
local min, max, waves = analyze_noiseparams(noiseparams)
|
|
|
|
|
local print_waves = function(waves_a)
|
|
|
|
|
local stringified_waves = {}
|
|
|
|
|
for w=1, #waves_a do
|
|
|
|
|
local strwave
|
|
|
|
|
local is_bad = false
|
|
|
|
|
if minetest.is_nan(waves_a[w]) or waves_a[w] == math.huge or waves_a[w] == -math.huge then
|
|
|
|
|
strwave = minetest.colorize("#FF0000FF", waves_a[w])
|
|
|
|
|
elseif waves_a[w] < 1 then
|
|
|
|
|
strwave = minetest.colorize("#FF0000FF", "0")
|
|
|
|
|
else
|
|
|
|
|
strwave = string.format("%.0f", waves_a[w])
|
|
|
|
|
end
|
|
|
|
|
table.insert(stringified_waves, strwave)
|
2022-04-14 04:47:05 +02:00
|
|
|
|
end
|
2022-04-16 06:20:08 +02:00
|
|
|
|
return table.concat(stringified_waves, ", ")
|
2022-04-14 04:47:05 +02:00
|
|
|
|
end
|
2022-04-16 06:20:08 +02:00
|
|
|
|
local form = [[
|
|
|
|
|
formspec_version[4]size[10,5]
|
|
|
|
|
container[0.25,0.25]
|
|
|
|
|
box[0,0;9.5,3.5;]]..FORMSPEC_BOX_COLOR..[[]
|
|
|
|
|
box[0,0;9.5,0.4;]]..FORMSPEC_HEADER_COLOR..[[]
|
|
|
|
|
label[0.25,0.2;]]..F(S("Noise Parameters Analysis"))..[[]
|
|
|
|
|
|
|
|
|
|
label[0.25,1;]]..F(S("Minimum possible value: @1", min))..[[]
|
|
|
|
|
label[0.25,1.5;]]..F(S("Maximum possible value: @1", max))..[[]
|
|
|
|
|
|
|
|
|
|
label[0.25,2;]]..F(S("X wavelengths: @1", print_waves(waves.x)))..[[]
|
|
|
|
|
label[0.25,2.5;]]..F(S("Y wavelengths: @1", print_waves(waves.y)))..[[]
|
|
|
|
|
label[0.25,3;]]..F(S("Z wavelengths: @1", print_waves(waves.z)))..[[]
|
|
|
|
|
|
|
|
|
|
button_exit[3,3.75;3,0.75;close;]]..F(S("Close"))..[[]
|
|
|
|
|
|
|
|
|
|
container_end[]
|
|
|
|
|
--]]
|
|
|
|
|
minetest.show_formspec(player:get_player_name(), "perlin_explorer:analyze", form)
|
2022-04-14 04:47:05 +02:00
|
|
|
|
end
|
|
|
|
|
|
2022-04-15 21:00:37 +02:00
|
|
|
|
local show_formspec = function(player, noiseparams, profile_id)
|
2022-04-15 20:49:01 +02:00
|
|
|
|
local np
|
2022-04-15 21:00:37 +02:00
|
|
|
|
if noiseparams then
|
|
|
|
|
np = noiseparams
|
2022-04-15 20:49:01 +02:00
|
|
|
|
else
|
|
|
|
|
np = current_perlin.noiseparams
|
2022-04-15 21:00:37 +02:00
|
|
|
|
end
|
|
|
|
|
if not profile_id then
|
2022-04-15 20:49:01 +02:00
|
|
|
|
profile_id = 1
|
|
|
|
|
end
|
2022-04-15 06:55:11 +02:00
|
|
|
|
local offset = tostring(np.offset or "")
|
|
|
|
|
local scale = tostring(np.scale or "")
|
|
|
|
|
local seed = tostring(np.seed or "")
|
2022-04-10 01:45:19 +02:00
|
|
|
|
local sx, sy, sz = "", "", ""
|
2022-04-15 06:55:11 +02:00
|
|
|
|
if np.spread then
|
|
|
|
|
sx = tostring(np.spread.x or "")
|
|
|
|
|
sy = tostring(np.spread.y or "")
|
|
|
|
|
sz = tostring(np.spread.z or "")
|
2022-04-10 01:45:19 +02:00
|
|
|
|
end
|
2022-04-15 06:55:11 +02:00
|
|
|
|
local octaves = tostring(np.octaves or "")
|
|
|
|
|
local persistence = tostring(np.persistence or "")
|
|
|
|
|
local lacunarity = tostring(np.lacunarity or "")
|
2022-04-11 02:21:07 +02:00
|
|
|
|
|
|
|
|
|
local size = tostring(current_perlin.size or "")
|
|
|
|
|
local sidelen = tostring(current_perlin.sidelen or "")
|
2022-04-16 13:25:21 +02:00
|
|
|
|
local pos_x, pos_y, pos_z = "", "", ""
|
|
|
|
|
if current_perlin.pos then
|
|
|
|
|
pos_x = tostring(current_perlin.pos.x or "")
|
|
|
|
|
pos_y = tostring(current_perlin.pos.y or "")
|
|
|
|
|
pos_z = tostring(current_perlin.pos.z or "")
|
|
|
|
|
end
|
2022-04-11 02:21:07 +02:00
|
|
|
|
local value_min = tostring(current_perlin.min or "")
|
|
|
|
|
local value_max = tostring(current_perlin.max or "")
|
|
|
|
|
|
2022-04-15 06:55:11 +02:00
|
|
|
|
local flags = np.flags
|
2022-04-14 04:47:05 +02:00
|
|
|
|
local flags_table = parse_flags_string(flags)
|
|
|
|
|
local eased = tostring(flags_table.eased)
|
|
|
|
|
local absvalue = tostring(flags_table.absvalue)
|
|
|
|
|
|
2022-04-15 05:55:17 +02:00
|
|
|
|
local noiseparams_list = {}
|
|
|
|
|
for i=1, #np_profiles do
|
|
|
|
|
table.insert(noiseparams_list, S("Profile @1", i))
|
|
|
|
|
end
|
|
|
|
|
local noiseparams_list_str = table.concat(noiseparams_list, ",")
|
|
|
|
|
|
2022-04-10 23:41:41 +02:00
|
|
|
|
local dimensions_index = (current_perlin.dimensions or 2) - 1
|
2022-04-16 03:24:41 +02:00
|
|
|
|
local nodetype_index = (current_perlin.nodetype)
|
|
|
|
|
|
|
|
|
|
local nodetypes_list = {}
|
|
|
|
|
for i=1, #nodetypes do
|
|
|
|
|
table.insert(nodetypes_list, F(nodetypes[i][1]))
|
|
|
|
|
end
|
|
|
|
|
local nodetypes_list_str = table.concat(nodetypes_list, ",")
|
2022-04-15 20:49:01 +02:00
|
|
|
|
|
|
|
|
|
local delete_btn = ""
|
|
|
|
|
if #np_profiles > 1 then
|
2022-04-16 05:07:15 +02:00
|
|
|
|
delete_btn = "button[7.25,0;2.0,0.5;delete_np_profile;"..F(S("Delete")).."]"
|
2022-04-15 20:49:01 +02:00
|
|
|
|
end
|
2022-04-16 04:44:05 +02:00
|
|
|
|
local autogen_label
|
|
|
|
|
local create_btn = ""
|
2022-04-16 13:35:33 +02:00
|
|
|
|
local xyzsize = ""
|
2022-04-16 04:44:05 +02:00
|
|
|
|
if current_perlin.autogen then
|
|
|
|
|
autogen_label = S("Disable mapgen")
|
|
|
|
|
else
|
|
|
|
|
autogen_label = S("Enable mapgen")
|
|
|
|
|
create_btn = "button[3.5,0;3,1;create;"..F(S("Apply and create")).."]"
|
2022-04-16 13:35:33 +02:00
|
|
|
|
xyzsize = [[
|
|
|
|
|
field[0.25,1.95;2,0.75;pos_x;]]..F(S("X"))..[[;]]..pos_x..[[]
|
|
|
|
|
field[2.35,1.95;2,0.75;pos_y;]]..F(S("Y"))..[[;]]..pos_y..[[]
|
|
|
|
|
field[4.45,1.95;2,0.75;pos_z;]]..F(S("Z"))..[[;]]..pos_z..[[]
|
|
|
|
|
field[6.55,1.95;2,0.75;size;]]..F(S("Size"))..[[;]]..size..[[]
|
|
|
|
|
field_close_on_enter[pos_x;false]
|
|
|
|
|
field_close_on_enter[pos_y;false]
|
|
|
|
|
field_close_on_enter[pos_z;false]
|
|
|
|
|
field_close_on_enter[value_min;false]
|
|
|
|
|
field_close_on_enter[value_max;false]
|
|
|
|
|
]]
|
2022-04-16 04:44:05 +02:00
|
|
|
|
end
|
2022-04-10 01:45:19 +02:00
|
|
|
|
local form = [[
|
2022-04-16 00:18:50 +02:00
|
|
|
|
formspec_version[4]size[10,12.5]
|
2022-04-15 03:17:19 +02:00
|
|
|
|
container[0.25,0.25]
|
2022-04-15 05:55:17 +02:00
|
|
|
|
box[0,0;9.5,5.5;]]..FORMSPEC_BOX_COLOR..[[]
|
2022-04-16 00:25:00 +02:00
|
|
|
|
box[0,0;9.5,0.4;]]..FORMSPEC_HEADER_COLOR..[[]
|
|
|
|
|
label[0.15,0.2;]]..F(S("Noise parameters"))..[[]
|
2022-04-16 00:36:34 +02:00
|
|
|
|
container[0.0,0.5]
|
|
|
|
|
dropdown[0.25,0;2,0.5;np_profiles;]]..noiseparams_list_str..[[;]]..profile_id..[[;true]
|
|
|
|
|
button[3.25,0;2.0,0.5;add_np_profile;]]..F(S("Add"))..[[]
|
|
|
|
|
button[5.25,0;2.0,0.5;load_np_profile;]]..F(S("Load"))..[[]
|
2022-04-15 20:49:01 +02:00
|
|
|
|
]]..delete_btn..[[
|
2022-04-16 00:36:34 +02:00
|
|
|
|
container_end[]
|
|
|
|
|
container[0.0,1.5]
|
|
|
|
|
field[0.25,0;2,0.75;offset;]]..F(S("Offset"))..[[;]]..offset..[[]
|
|
|
|
|
field[3.25,0;2,0.75;scale;]]..F(S("Scale"))..[[;]]..scale..[[]
|
|
|
|
|
field[6.25,0;2,0.75;seed;]]..F(S("Seed"))..[[;]]..seed..[[]
|
|
|
|
|
image_button[8.35,0.0;0.75,0.75;perlin_explorer_seeder.png;set_random_seed;]
|
|
|
|
|
field[0.25,1.2;2,0.75;spread_x;]]..F(S("X Spread"))..[[;]]..sx..[[]
|
|
|
|
|
field[3.25,1.2;2,0.75;spread_y;]]..F(S("Y Spread"))..[[;]]..sy..[[]
|
|
|
|
|
field[6.25,1.2;2,0.75;spread_z;]]..F(S("Z Spread"))..[[;]]..sz..[[]
|
|
|
|
|
field[0.25,2.4;2,0.75;octaves;]]..F(S("Octaves"))..[[;]]..octaves..[[]
|
|
|
|
|
field[3.25,2.4;2,0.75;persistence;]]..F(S("Persistence"))..[[;]]..persistence..[[]
|
|
|
|
|
field[6.25,2.4;2,0.75;lacunarity;]]..F(S("Lacunarity"))..[[;]]..lacunarity..[[]
|
|
|
|
|
checkbox[0.25,3.55;eased;]]..F(S("eased"))..[[;]]..eased..[[]
|
|
|
|
|
checkbox[3.25,3.55;absvalue;]]..F(S("absvalue"))..[[;]]..absvalue..[[]
|
2022-04-16 06:20:08 +02:00
|
|
|
|
button[6.25,3.35;2.0,0.5;analyze;]]..F(S("Analyze"))..[[]
|
2022-04-16 00:36:34 +02:00
|
|
|
|
container_end[]
|
2022-04-15 22:18:53 +02:00
|
|
|
|
|
2022-04-10 01:45:19 +02:00
|
|
|
|
field_close_on_enter[offset;false]
|
|
|
|
|
field_close_on_enter[scale;false]
|
|
|
|
|
field_close_on_enter[seed;false]
|
|
|
|
|
field_close_on_enter[spread_x;false]
|
|
|
|
|
field_close_on_enter[spread_y;false]
|
|
|
|
|
field_close_on_enter[spread_z;false]
|
|
|
|
|
field_close_on_enter[octaves;false]
|
|
|
|
|
field_close_on_enter[persistence;false]
|
|
|
|
|
field_close_on_enter[lacunarity;false]
|
2022-04-11 02:21:07 +02:00
|
|
|
|
field_close_on_enter[sidelen;false]
|
2022-04-10 01:45:19 +02:00
|
|
|
|
|
2022-04-16 00:18:50 +02:00
|
|
|
|
tooltip[set_random_seed;]]..F(S("Random seed"))..[[]
|
|
|
|
|
container_end[]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
container[0.25,6.0]
|
2022-04-16 00:25:00 +02:00
|
|
|
|
box[0,0;9.5,1.6;]]..FORMSPEC_BOX_COLOR..[[]
|
|
|
|
|
box[0,0;9.5,0.4;]]..FORMSPEC_HEADER_COLOR..[[]
|
|
|
|
|
label[0.15,0.2;]]..F(S("Noise options"))..[[]
|
|
|
|
|
dropdown[0.25,0.7;1,0.75;dimensions;]]..F(S("2D"))..[[,]]..F(S("3D"))..[[;]]..dimensions_index..[[;true]
|
|
|
|
|
field[2.25,0.7;2,0.75;sidelen;]]..F(S("Pixelization"))..[[;]]..sidelen..[[]
|
2022-04-16 00:18:50 +02:00
|
|
|
|
tooltip[sidelen;]]..F(S("If higher than 1, Perlin values will be repeated along all axes every x nodes, for a ‘pixelized’ effect."))..[[]
|
|
|
|
|
container_end[]
|
|
|
|
|
|
|
|
|
|
|
2022-04-16 00:25:00 +02:00
|
|
|
|
container[0.25,7.85]
|
2022-04-16 00:18:50 +02:00
|
|
|
|
box[0,0;9.5,2.9;]]..FORMSPEC_BOX_COLOR..[[]
|
2022-04-16 00:25:00 +02:00
|
|
|
|
box[0,0;9.5,0.4;]]..FORMSPEC_HEADER_COLOR..[[]
|
2022-04-16 00:28:27 +02:00
|
|
|
|
label[0.15,0.2;]]..F(S("Node generation"))..[[]
|
2022-04-16 00:18:50 +02:00
|
|
|
|
field[0.25,0.75;2,0.75;value_min;]]..F(S("Min. color at"))..[[;]]..value_min..[[]
|
|
|
|
|
field[2.35,0.75;2,0.75;value_max;]]..F(S("Max. color at"))..[[;]]..value_max..[[]
|
2022-04-16 03:24:41 +02:00
|
|
|
|
dropdown[6.55,0.75;2,0.75;nodetype;]]..nodetypes_list_str..[[;]]..nodetype_index..[[;true]
|
2022-04-16 13:35:33 +02:00
|
|
|
|
]]..xyzsize..[[
|
2022-04-16 00:18:50 +02:00
|
|
|
|
tooltip[value_min;]]..F(S("The Perlin value at which the node color gradient begins. Must be lower than 0."))..[[]
|
|
|
|
|
tooltip[value_max;]]..F(S("The Perlin value at which the node color gradient ends. Must be higher than 0."))..[[]
|
|
|
|
|
container_end[]
|
|
|
|
|
|
|
|
|
|
|
2022-04-16 00:25:00 +02:00
|
|
|
|
container[0,10.95]
|
2022-04-15 03:17:19 +02:00
|
|
|
|
button[0.5,0;3,1;apply;]]..F(S("Apply"))..[[]
|
2022-04-16 04:44:05 +02:00
|
|
|
|
]]..create_btn..[[
|
|
|
|
|
button[6.5,0;3,1;toggle_autogen;]]..F(autogen_label)..[[]
|
2022-04-15 03:17:19 +02:00
|
|
|
|
container_end[]
|
2022-04-10 01:45:19 +02:00
|
|
|
|
]]
|
|
|
|
|
minetest.show_formspec(player:get_player_name(), "perlin_explorer:creator", form)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
|
|
|
if formname ~= "perlin_explorer:creator" then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-10 01:46:30 +02:00
|
|
|
|
-- Require 'server' priv
|
|
|
|
|
local privs = minetest.get_player_privs(player:get_player_name())
|
|
|
|
|
if not privs.server then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-14 04:47:05 +02:00
|
|
|
|
|
|
|
|
|
-- Handle checkboxes
|
|
|
|
|
local name = player:get_player_name()
|
2022-04-15 06:55:11 +02:00
|
|
|
|
local flags_touched = false
|
2022-04-14 04:47:05 +02:00
|
|
|
|
if fields.eased == "true" then
|
|
|
|
|
formspec_states[name].eased = true
|
2022-04-15 21:45:32 +02:00
|
|
|
|
return
|
2022-04-14 04:47:05 +02:00
|
|
|
|
elseif fields.eased == "false" then
|
|
|
|
|
formspec_states[name].eased = false
|
2022-04-15 21:45:32 +02:00
|
|
|
|
return
|
2022-04-14 04:47:05 +02:00
|
|
|
|
end
|
|
|
|
|
if fields.absvalue == "true" then
|
|
|
|
|
formspec_states[name].absvalue = true
|
2022-04-15 21:45:32 +02:00
|
|
|
|
return
|
2022-04-14 04:47:05 +02:00
|
|
|
|
elseif fields.absvalue == "false" then
|
|
|
|
|
formspec_states[name].absvalue = false
|
2022-04-15 21:45:32 +02:00
|
|
|
|
return
|
2022-04-14 04:47:05 +02:00
|
|
|
|
end
|
|
|
|
|
|
2022-04-15 05:55:17 +02:00
|
|
|
|
-- Deleting a profile does not require any other field
|
|
|
|
|
if fields.delete_np_profile then
|
|
|
|
|
if #np_profiles <= 1 then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-15 21:00:37 +02:00
|
|
|
|
local profile_to_delete = tonumber(fields.np_profiles)
|
|
|
|
|
table.remove(np_profiles, profile_to_delete)
|
|
|
|
|
local new_id = math.max(1, profile_to_delete - 1)
|
2022-04-16 00:28:27 +02:00
|
|
|
|
show_formspec(player, default_noiseparams, new_id)
|
2022-04-15 05:55:17 +02:00
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-14 04:47:05 +02:00
|
|
|
|
-- Handle other fields
|
2022-04-16 04:44:05 +02:00
|
|
|
|
local do_apply = fields.apply ~= nil or fields.toggle_autogen ~= nil
|
2022-04-10 01:45:19 +02:00
|
|
|
|
local do_create = fields.create ~= nil or fields.key_enter_field ~= nil
|
2022-04-16 06:20:08 +02:00
|
|
|
|
local do_analyze = fields.analyze ~= nil
|
|
|
|
|
if (do_create or do_apply or do_analyze or fields.add_np_profile or fields.np_profiles) then
|
2022-04-10 01:45:19 +02:00
|
|
|
|
if fields.offset and fields.scale and fields.seed and fields.spread_x and fields.spread_y and fields.spread_z and fields.octaves and fields.persistence and fields.lacunarity then
|
2022-04-15 05:55:17 +02:00
|
|
|
|
|
2022-04-16 13:01:48 +02:00
|
|
|
|
loaded_areas = {}
|
2022-04-10 01:45:19 +02:00
|
|
|
|
local offset = tonumber(fields.offset)
|
|
|
|
|
local scale = tonumber(fields.scale)
|
|
|
|
|
local seed = tonumber(fields.seed)
|
|
|
|
|
local sx = tonumber(fields.spread_x)
|
|
|
|
|
local sy = tonumber(fields.spread_y)
|
|
|
|
|
local sz = tonumber(fields.spread_z)
|
2022-04-10 03:33:22 +02:00
|
|
|
|
if not sx or not sy or not sz then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-10 01:45:19 +02:00
|
|
|
|
local spread = vector.new(sx, sy, sz)
|
|
|
|
|
local octaves = tonumber(fields.octaves)
|
|
|
|
|
local persistence = tonumber(fields.persistence)
|
|
|
|
|
local lacunarity = tonumber(fields.lacunarity)
|
2022-04-10 23:41:41 +02:00
|
|
|
|
local dimensions = tonumber(fields.dimensions)
|
2022-04-11 02:21:07 +02:00
|
|
|
|
local sidelen = tonumber(fields.sidelen)
|
|
|
|
|
local px = tonumber(fields.pos_x)
|
|
|
|
|
local py = tonumber(fields.pos_y)
|
|
|
|
|
local pz = tonumber(fields.pos_z)
|
|
|
|
|
local size = tonumber(fields.size)
|
|
|
|
|
local value_min = tonumber(fields.value_min)
|
|
|
|
|
local value_max = tonumber(fields.value_max)
|
2022-04-16 03:24:41 +02:00
|
|
|
|
local nodetype = tonumber(fields.nodetype)
|
2022-04-15 05:55:17 +02:00
|
|
|
|
if (offset and scale and spread and octaves and persistence) then
|
2022-04-14 04:47:05 +02:00
|
|
|
|
local eased = formspec_states[name].eased
|
|
|
|
|
local absvalue = formspec_states[name].absvalue
|
2022-04-15 05:55:17 +02:00
|
|
|
|
local noiseparams = {
|
2022-04-10 01:45:19 +02:00
|
|
|
|
offset = offset,
|
|
|
|
|
scale = scale,
|
|
|
|
|
seed = seed,
|
|
|
|
|
spread = spread,
|
|
|
|
|
octaves = octaves,
|
|
|
|
|
persistence = persistence,
|
|
|
|
|
lacunarity = lacunarity,
|
2022-04-14 04:47:05 +02:00
|
|
|
|
flags = build_flags_string(eased, absvalue),
|
2022-04-15 05:55:17 +02:00
|
|
|
|
}
|
2022-04-16 06:20:08 +02:00
|
|
|
|
-- Open analyze window
|
|
|
|
|
if do_analyze then
|
|
|
|
|
analyze_noiseparams_and_show_formspec(player, noiseparams)
|
|
|
|
|
return
|
2022-04-15 05:55:17 +02:00
|
|
|
|
-- Change NP profile selection
|
2022-04-16 06:20:08 +02:00
|
|
|
|
elseif fields.load_np_profile and fields.np_profiles then
|
2022-04-15 20:49:01 +02:00
|
|
|
|
local profile = tonumber(fields.np_profiles)
|
2022-04-15 21:00:37 +02:00
|
|
|
|
local loaded_np = np_profiles[profile]
|
2022-04-15 20:49:01 +02:00
|
|
|
|
-- Load new profile
|
2022-04-15 21:00:37 +02:00
|
|
|
|
show_formspec(player, loaded_np, profile)
|
2022-04-15 20:49:01 +02:00
|
|
|
|
minetest.log("action", "[perlin_explorer] Loaded perlin noise profile "..profile)
|
|
|
|
|
return
|
2022-04-15 20:53:11 +02:00
|
|
|
|
-- Add new profile and save current noiseparams to it
|
2022-04-15 20:49:01 +02:00
|
|
|
|
elseif fields.add_np_profile then
|
2022-04-15 05:55:17 +02:00
|
|
|
|
table.insert(np_profiles, noiseparams)
|
2022-04-15 20:49:01 +02:00
|
|
|
|
local new_profile = #np_profiles
|
|
|
|
|
minetest.log("action", "[perlin_explorer] Perlin noise profile "..new_profile.." added!")
|
2022-04-15 21:00:37 +02:00
|
|
|
|
show_formspec(player, noiseparams, new_profile)
|
2022-04-15 05:55:17 +02:00
|
|
|
|
return
|
2022-04-15 22:18:53 +02:00
|
|
|
|
elseif fields.set_random_seed then
|
|
|
|
|
-- Randomize seed
|
|
|
|
|
local profile = tonumber(fields.np_profiles)
|
|
|
|
|
noiseparams.seed = math.random(0, 2^32-1)
|
|
|
|
|
show_formspec(player, noiseparams, profile)
|
|
|
|
|
return
|
2022-04-15 05:55:17 +02:00
|
|
|
|
end
|
2022-04-15 22:18:53 +02:00
|
|
|
|
|
2022-04-16 13:35:33 +02:00
|
|
|
|
if not (dimensions and sidelen and value_min and value_max and nodetype) then
|
2022-04-15 05:55:17 +02:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
-- Convert dropdown index to actual dimensions number
|
|
|
|
|
dimensions = dimensions + 1
|
|
|
|
|
-- Spread is used differently in 2D
|
|
|
|
|
if dimensions == 2 then
|
|
|
|
|
spread.y = spread.z
|
|
|
|
|
end
|
|
|
|
|
set_perlin_noise(noiseparams)
|
|
|
|
|
minetest.log("action", "[perlin_explorer] Perlin noise set!")
|
2022-04-11 02:21:07 +02:00
|
|
|
|
current_perlin.dimensions = dimensions
|
|
|
|
|
current_perlin.sidelen = sidelen
|
|
|
|
|
current_perlin.min = value_min
|
|
|
|
|
current_perlin.max = value_max
|
2022-04-16 03:24:41 +02:00
|
|
|
|
current_perlin.nodetype = nodetype
|
2022-04-16 13:35:33 +02:00
|
|
|
|
if fields.toggle_autogen then
|
|
|
|
|
current_perlin.autogen = not current_perlin.autogen
|
|
|
|
|
if current_perlin.autogen then
|
|
|
|
|
loaded_areas = {}
|
|
|
|
|
end
|
|
|
|
|
local profile = tonumber(fields.np_profiles)
|
|
|
|
|
show_formspec(player, noiseparams, profile)
|
|
|
|
|
minetest.log("action", "[perlin_explorer] Autogen state is now: "..tostring(current_perlin.autogen))
|
|
|
|
|
elseif do_create then
|
|
|
|
|
if not px or not py or not pz or not size then
|
2022-04-15 05:55:17 +02:00
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-16 13:35:33 +02:00
|
|
|
|
current_perlin.size = size
|
2022-04-15 05:55:17 +02:00
|
|
|
|
local place_pos = vector.new(px, py, pz)
|
2022-04-13 22:35:29 +02:00
|
|
|
|
local msg = S("Creating Perlin noise, please wait …")
|
2022-04-14 04:47:05 +02:00
|
|
|
|
minetest.chat_send_player(name, msg)
|
2022-04-13 22:35:29 +02:00
|
|
|
|
msg = create_perlin(place_pos, {dimensions=dimensions, size=size})
|
2022-04-11 02:21:07 +02:00
|
|
|
|
if msg then
|
2022-04-14 04:47:05 +02:00
|
|
|
|
minetest.chat_send_player(name, msg)
|
2022-04-11 02:21:07 +02:00
|
|
|
|
elseif msg == false then
|
2022-04-10 01:45:19 +02:00
|
|
|
|
minetest.log("error", "[perlin_explorer] Error generating Perlin noise nodes!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
minetest.register_tool("perlin_explorer:creator", {
|
|
|
|
|
description = S("Perlin Noise Creator"),
|
|
|
|
|
_tt_help = S("Punch to open the Perlin noise creation menu"),
|
|
|
|
|
inventory_image = "perlin_explorer_creator.png",
|
|
|
|
|
wield_image = "perlin_explorer_creator.png",
|
|
|
|
|
groups = { disable_repair = 1 },
|
|
|
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
|
|
|
if not user then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
local privs = minetest.get_player_privs(user:get_player_name())
|
|
|
|
|
if not privs.server then
|
2022-04-10 01:54:20 +02:00
|
|
|
|
minetest.chat_send_player(user:get_player_name(), S("Insufficient privileges! You need the @1 privilege to use this tool.", "server"))
|
|
|
|
|
return
|
2022-04-10 01:45:19 +02:00
|
|
|
|
end
|
|
|
|
|
show_formspec(user)
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
2022-04-14 03:07:42 +02:00
|
|
|
|
local timer = 0
|
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
|
timer = timer + dtime
|
2022-04-15 22:30:02 +02:00
|
|
|
|
if timer < AUTOBUILD_UPDATE_TIME then
|
2022-04-14 03:07:42 +02:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
timer = 0
|
2022-04-16 04:44:05 +02:00
|
|
|
|
if current_perlin.noise and current_perlin.autogen then
|
2022-04-14 03:07:42 +02:00
|
|
|
|
local player = minetest.get_player_by_name("singleplayer")
|
|
|
|
|
if not player then
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-16 15:31:35 +02:00
|
|
|
|
local build = function(pos, pos_hash, player_name)
|
2022-04-15 22:36:25 +02:00
|
|
|
|
if not pos or not pos.x or not pos.y or not pos.z then
|
|
|
|
|
minetest.log("error", "[perlin_explorer] build(): Invalid pos!")
|
|
|
|
|
return
|
|
|
|
|
end
|
2022-04-16 15:31:35 +02:00
|
|
|
|
if not pos_hash then
|
|
|
|
|
minetest.log("error", "[perlin_explorer] build(): Invalid pos_hash!")
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
if not loaded_areas[pos_hash] then
|
2022-04-16 04:52:29 +02:00
|
|
|
|
create_perlin(pos, {
|
2022-04-14 03:07:42 +02:00
|
|
|
|
dimensions = current_perlin.dimensions,
|
|
|
|
|
size = AUTOBUILD_SIZE,
|
|
|
|
|
})
|
2022-04-16 15:31:35 +02:00
|
|
|
|
loaded_areas[pos_hash] = true
|
2022-04-14 03:07:42 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2022-04-09 19:44:15 +02:00
|
|
|
|
|
2022-04-14 03:07:42 +02:00
|
|
|
|
local pos = vector.round(player:get_pos())
|
|
|
|
|
pos = sidelen_pos(pos, AUTOBUILD_SIZE)
|
2022-04-16 01:33:59 +02:00
|
|
|
|
local neighbors = { vector.new(0, 0, 0) }
|
|
|
|
|
local c = AUTOBUILD_CHUNKDIST
|
|
|
|
|
local cc = c
|
|
|
|
|
if current_perlin.dimensions == 2 then
|
|
|
|
|
cc = 0
|
|
|
|
|
end
|
|
|
|
|
for cx=-c, c do
|
|
|
|
|
for cy=-cc, cc do
|
|
|
|
|
for cz=-c, c do
|
|
|
|
|
table.insert(neighbors, vector.new(cx, cy, cz))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-04-16 15:31:35 +02:00
|
|
|
|
local chunks = {}
|
2022-04-14 03:07:42 +02:00
|
|
|
|
for n=1, #neighbors do
|
2022-04-16 01:33:59 +02:00
|
|
|
|
local offset = vector.multiply(neighbors[n], AUTOBUILD_SIZE)
|
|
|
|
|
local npos = vector.add(pos, offset)
|
2022-04-16 15:31:35 +02:00
|
|
|
|
local hash = minetest.hash_node_position(npos)
|
|
|
|
|
if not loaded_areas[hash] then
|
|
|
|
|
table.insert(chunks, {npos, hash})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if #chunks > 0 then
|
|
|
|
|
minetest.log("verbose", "[perlin_explorer] Started building "..#chunks.." chunk(s)")
|
|
|
|
|
end
|
|
|
|
|
for c=1, #chunks do
|
|
|
|
|
local npos = chunks[c][1]
|
|
|
|
|
local nhash = chunks[c][2]
|
|
|
|
|
build(npos, nhash, player:get_player_name())
|
|
|
|
|
end
|
|
|
|
|
if #chunks > 0 then
|
|
|
|
|
minetest.log("verbose", "[perlin_explorer] Done building "..#chunks.." chunk(s)")
|
2022-04-14 03:07:42 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
2022-04-14 04:47:05 +02:00
|
|
|
|
|
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
|
|
|
local name = player:get_player_name()
|
|
|
|
|
formspec_states[name] = {
|
|
|
|
|
eased = false,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
|
|
|
local name = player:get_player_name()
|
|
|
|
|
formspec_states[name] = nil
|
|
|
|
|
end)
|