Version 1.1.0
[minetest_spawnbuilder.git] / init.lua
blobe198e58155b0324b897936d9d307ff82e82ff434
1 local storage_ref = minetest.get_mod_storage()
2 local stored_centerpos = {}
3 local check = storage_ref:get_string("spawnbuilder_centerpos_x")
4 if check ~= "" then
5 stored_centerpos.x = storage_ref:get_int("spawnbuilder_centerpos_x")
6 stored_centerpos.y = storage_ref:get_int("spawnbuilder_centerpos_y")
7 stored_centerpos.z = storage_ref:get_int("spawnbuilder_centerpos_z")
8 minetest.log("action", "[spawnbuilder] Spawn platform position loaded: "..minetest.pos_to_string(stored_centerpos))
9 else
10 stored_centerpos = minetest.setting_get_pos("static_spawnpoint")
11 -- Default position
12 if not stored_centerpos then
13 stored_centerpos = { x=0, y=-1, z=0 }
14 end
15 storage_ref:set_int("spawnbuilder_centerpos_x", stored_centerpos.x)
16 storage_ref:set_int("spawnbuilder_centerpos_y", stored_centerpos.y)
17 storage_ref:set_int("spawnbuilder_centerpos_z", stored_centerpos.z)
18 minetest.log("action", "[spawnbuilder] Initial spawn platform position registered and saved: "..minetest.pos_to_string(stored_centerpos))
19 end
21 -- Width of the stored_centerpos platform
22 local WIDTH
23 check = storage_ref:get_string("spawnbuilder_width")
24 if check ~= "" then
25 WIDTH = check
26 else
27 WIDTH = tonumber(minetest.settings:get("spawnbuilder_width"))
28 if type(WIDTH) == "number" then
29 WIDTH = math.floor(WIDTH)
30 else
31 WIDTH = 33
32 end
33 end
34 minetest.log("action", "[spawnbuilder] Using spawn platform width of "..WIDTH..".")
36 -- Height of the platform
37 local HEIGHT = 2
39 -- Number of air layers above the platform
40 local AIRSPACE = 3
42 -- Generates the platform or platform piece within minp and maxp with the center at centerpos
43 local function generate_platform(minp, maxp, centerpos)
44 -- Get stone and cobble nodes, based on the mapgen aliases. This allows for great compability with practically
45 -- all subgames!
46 local c_stone = minetest.get_content_id("mapgen_stone")
47 local c_cobble
48 if minetest.registered_aliases["mapgen_cobble"] == "air" or minetest.registered_aliases["mapgen_cobble"] == nil then
49 -- Fallback option: If cobble mapgen alias is inappropriate or missing, use stone instead.
50 c_cobble = c_stone
51 else
52 c_cobble = minetest.get_content_id("mapgen_cobble")
53 end
55 local w_neg, w_pos
56 w_pos = math.floor(WIDTH / 2)
57 if math.fmod(WIDTH, 2) == 0 then
58 w_neg = -w_pos + 1
59 else
60 w_neg = -w_pos
61 end
63 local xmin = math.max(centerpos.x + w_neg, minp.x)
64 local xmax = math.min(centerpos.x + w_pos, maxp.x)
65 local zmin = math.max(centerpos.z + w_neg, minp.z)
66 local zmax = math.min(centerpos.z + w_pos, maxp.z)
67 local ymin = math.max(centerpos.y - (HEIGHT-1), minp.y)
68 local ymax = math.min(centerpos.y + AIRSPACE, maxp.y)
70 if maxp.x >= xmin and minp.x <= xmax and maxp.y >= ymin and minp.y <= ymax and maxp.z >= zmin and minp.z <= zmax then
71 local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
72 local data = vm:get_data()
73 local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
75 for x = xmin, xmax do
76 for y = ymin, ymax do
77 for z = zmin, zmax do
78 local p_pos = area:index(x, y, z)
79 local pos = {x=x,y=y,z=z}
80 if minetest.registered_nodes[minetest.get_node(pos).name].is_ground_content == true then
81 if y <= centerpos.y then
82 if x == centerpos.x and y == centerpos.y and z == centerpos.z then
83 data[p_pos] = c_cobble
84 minetest.log("action", "[spawnbuilder] Spawn platform center generated at "..minetest.pos_to_string(pos)..".")
85 else
86 data[p_pos] = c_stone
87 end
88 elseif y >= centerpos.y + 1 and y <= ymax then
89 data[p_pos] = core.CONTENT_AIR
90 end
91 end
92 end
93 end
94 end
96 vm:set_data(data)
97 vm:calc_lighting()
98 vm:write_to_map()
99 end
102 minetest.register_on_generated(function(minp, maxp, seed)
103 local centerpos = table.copy(stored_centerpos)
105 if minp.x <= centerpos.x and maxp.x >= centerpos.x and minp.y <= centerpos.y and maxp.y >= centerpos.y and minp.z <= centerpos.z and maxp.z >= centerpos.z then
106 if not WIDTH or WIDTH <= 0 then
107 minetest.log("warning", "[spawnbuilder] Invalid spawnbuilder_width. Spawn platform will NOT be generated.")
108 return
111 local ground = false
112 local air = true
113 -- Check for solid ground
114 for y = 3, -6, -1 do
115 local nn = minetest.get_node({x=centerpos.x, y=centerpos.y+y, centerpos.z}).name
116 local walkable = minetest.registered_nodes[nn].walkable
117 if y >= 0 and nn ~= "air" then
118 air = false
119 elseif y < 0 and walkable then
120 ground = true
123 -- Player has enough space and ground to spawn safely. No change required
124 if air and ground then
125 minetest.log("action", "[spawnbuilder] Safe player spawn detected. Spawn platform will NOT be generated.")
126 return
130 generate_platform(minp, maxp, centerpos)
131 end)