commit 7daaa15d972bb7d1a4d807c1b3af1c8460532eae Author: Wuzzy Date: Tue Nov 7 22:26:22 2017 +0100 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..d494e04 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Spawn Builder +Version 1.0.0 + +## Description +This mod generates a simple stone platform at the world origin +or the static spawn point. +Ideal for the `singlenode` map generator. + +## Usage +Activate this *before* the spawn area got generated (ideally +in a new world), then just join the world. +Recommended to be used in the `singlenode` mapgen, but it works +in other map generators, too. + +### Settings +With the setting `spawnbuilder_width` you can change the width of +the spawn platform. Note that values below 3 are not recommended. + +If the static spawn point (`static_spawnpoint`) is set on the +first start of the mod, the platform is centered at this +position instead. + +## Behaviour +This mod generates a stone platform of size 33×2×33 with +a single cobblestone in the center. Also, 3 layers +above the platform are turned into air because the +center position might be buried in the ground. + +As a safety measure, nodes with the property +`is_ground_content=false` will never be overwritten. + +Also, no platform is generated if the center position is +already in a safe spawn (in air, a few blocks below solid +ground). + +## Dependencies +This mod works with almost all subgames out of the box. + +The only requirement is that the subgame defines the mapgen +aliases `mapgen_stone` and `mapgen_cobble` which is almost +certainly the case. + +## License of everything in this mod +MIT License. diff --git a/description.txt b/description.txt new file mode 100644 index 0000000..f0e8423 --- /dev/null +++ b/description.txt @@ -0,0 +1 @@ +Generates a stone platform below the world origin or static spawn point. Ideal for the singlenode mapgen. diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..b7e7d8b --- /dev/null +++ b/init.lua @@ -0,0 +1,131 @@ +local storage_ref = minetest.get_mod_storage() +local stored_centerpos = {} +local check = storage_ref:get_string("spawnbuilder_centerpos_x") +if check ~= "" then + stored_centerpos.x = storage_ref:get_int("spawnbuilder_centerpos_x") + stored_centerpos.y = storage_ref:get_int("spawnbuilder_centerpos_y") + stored_centerpos.z = storage_ref:get_int("spawnbuilder_centerpos_z") + minetest.log("action", "[spawnbuilder] Spawn platform position loaded: "..minetest.pos_to_string(stored_centerpos)) +else + stored_centerpos = minetest.setting_get_pos("static_spawnpoint") + -- Default position + if not stored_centerpos then + stored_centerpos = { x=0, y=-1, z=0 } + end + storage_ref:set_int("spawnbuilder_centerpos_x", stored_centerpos.x) + storage_ref:set_int("spawnbuilder_centerpos_y", stored_centerpos.y) + storage_ref:set_int("spawnbuilder_centerpos_z", stored_centerpos.z) + minetest.log("action", "[spawnbuilder] Initial spawn platform position registered and saved: "..minetest.pos_to_string(stored_centerpos)) +end + +-- Width of the stored_centerpos platform +local WIDTH +check = storage_ref:get_string("spawnbuilder_width") +if check ~= "" then + WIDTH = check +else + WIDTH = tonumber(minetest.setting_get("spawnbuilder_width")) + if type(WIDTH) == "number" then + WIDTH = math.floor(WIDTH) + else + WIDTH = 33 + end +end +minetest.log("action", "[spawnbuilder] Using spawn platform width of "..WIDTH..".") + +-- Height of the platform +local HEIGHT = 2 + +-- Number of air layers above the platform +local AIRSPACE = 3 + +-- Generates the platform or platform piece within minp and maxp with the center at centerpos +local function generate_platform(minp, maxp, centerpos) + -- Get stone and cobble nodes, based on the mapgen aliases. This allows for great compability with practically + -- all subgames! + local c_stone = minetest.get_content_id("mapgen_stone") + local c_cobble + if minetest.registered_aliases["mapgen_cobble"] == "air" or minetest.registered_aliases["mapgen_cobble"] == nil then + -- Fallback option: If cobble mapgen alias is inappropriate or missing, use stone instead. + c_cobble = c_stone + else + c_cobble = minetest.get_content_id("mapgen_cobble") + end + + local w_neg, w_pos + w_pos = math.floor(WIDTH / 2) + if math.fmod(WIDTH, 2) == 0 then + w_neg = -w_pos + 1 + else + w_neg = -w_pos + end + + local xmin = math.max(centerpos.x + w_neg, minp.x) + local xmax = math.min(centerpos.x + w_pos, maxp.x) + local zmin = math.max(centerpos.z + w_neg, minp.z) + local zmax = math.min(centerpos.z + w_pos, maxp.z) + local ymin = math.max(centerpos.y - (HEIGHT-1), minp.y) + local ymax = math.min(centerpos.y + AIRSPACE, maxp.y) + + 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 + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local data = vm:get_data() + local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax}) + + for x = xmin, xmax do + for y = ymin, ymax do + for z = zmin, zmax do + local p_pos = area:index(x, y, z) + local pos = {x=x,y=y,z=z} + if minetest.registered_nodes[minetest.get_node(pos).name].is_ground_content == true then + if y <= centerpos.y then + if x == centerpos.x and y == centerpos.y and z == centerpos.z then + data[p_pos] = c_cobble + minetest.log("action", "[spawnbuilder] Spawn platform center generated at "..minetest.pos_to_string(pos)..".") + else + data[p_pos] = c_stone + end + elseif y >= centerpos.y + 1 and y <= ymax then + data[p_pos] = core.CONTENT_AIR + end + end + end + end + end + + vm:set_data(data) + vm:calc_lighting() + vm:write_to_map() + end +end + +minetest.register_on_generated(function(minp, maxp, seed) + local centerpos = table.copy(stored_centerpos) + + 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 + if not WIDTH or WIDTH <= 0 then + minetest.log("warning", "[spawnbuilder] Invalid spawnbuilder_width. Spawn platform will NOT be generated.") + return + end + + local ground = false + local air = true + -- Check for solid ground + for y = 3, -6, -1 do + local nn = minetest.get_node({x=centerpos.x, y=centerpos.y+y, centerpos.z}).name + local walkable = minetest.registered_nodes[nn].walkable + if y >= 0 and nn ~= "air" then + air = false + elseif y < 0 and walkable then + ground = true + end + end + -- Player has enough space and ground to spawn safely. No change required + if air and ground then + minetest.log("action", "[spawnbuilder] Safe player spawn detected. Spawn platform will NOT be generated.") + return + end + end + + generate_platform(minp, maxp, centerpos) +end) diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..f967225 --- /dev/null +++ b/mod.conf @@ -0,0 +1 @@ +name = spawnbuilder diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..a147ec4 Binary files /dev/null and b/screenshot.png differ diff --git a/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..55899bc --- /dev/null +++ b/settingtypes.txt @@ -0,0 +1,4 @@ +#Side length of the surface area of the spawn platform +#If the number is odd, the platform will be centered at spawn. +#Using a width lower than 3 is not recommended. +spawnbuilder_width (Spawn platform width) int 33 1