diff --git a/mods/maps/maps/forest/map.mts b/mods/maps/maps/forest/map.mts index 9f52a1a..2627d04 100644 Binary files a/mods/maps/maps/forest/map.mts and b/mods/maps/maps/forest/map.mts differ diff --git a/mods/mtg/spawn/README.txt b/mods/mtg/spawn/README.txt new file mode 100644 index 0000000..fc16c2a --- /dev/null +++ b/mods/mtg/spawn/README.txt @@ -0,0 +1,7 @@ +Minetest Game mod: spawn +======================== +See license.txt for license information. + +Authors of source code +---------------------- +paramat (MIT) diff --git a/mods/mtg/spawn/api.lua b/mods/mtg/spawn/api.lua new file mode 100644 index 0000000..bffe32a --- /dev/null +++ b/mods/mtg/spawn/api.lua @@ -0,0 +1,49 @@ +spawn = {} + +-- provide empty default implementations + +function spawn.get_default_pos() + return nil +end + +function spawn.add_suitable_biome(biome) +end + +-- Callback registration + +spawn.registered_on_spawn = {} + +function spawn.register_on_spawn(func) + table.insert(spawn.registered_on_spawn, func) +end + +-- Logic run on spawn + +local use_engine_spawn = minetest.settings:get("static_spawnpoint") or + minetest.settings:get_bool("engine_spawn") + +local function on_spawn(player, is_new) + -- Ask all callbacks first + for _, cb in ipairs(spawn.registered_on_spawn) do + if cb(player, is_new) then + return true + end + end + -- Fall back to default spawn + if not use_engine_spawn then + local pos = spawn.get_default_pos() + if pos then + player:set_pos(pos) + return true + end + end + return false +end + +minetest.register_on_newplayer(function(player) + on_spawn(player, true) +end) + +minetest.register_on_respawnplayer(function(player) + return on_spawn(player, false) +end) diff --git a/mods/mtg/spawn/init.lua b/mods/mtg/spawn/init.lua new file mode 100644 index 0000000..9cad5f9 --- /dev/null +++ b/mods/mtg/spawn/init.lua @@ -0,0 +1,127 @@ +-- Always load the API +---------------------- +dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/api.lua") + +-- Disable biome-search implementation on unsuitable mapgens +------------------------------------------------------------ + +local mg_name = minetest.get_mapgen_setting("mg_name") +if mg_name == "v6" or mg_name == "singlenode" then + return +end + + +-- Parameters +------------- + +-- Resolution of search grid in nodes. +local res = 64 +-- Number of points checked in the square search grid (edge * edge). +local checks = 128 * 128 +-- Starting point for biome checks. This also sets the y co-ordinate for all +-- points checked, so the suitable biomes must be active at this y. +local pos = {x = 0, y = 8, z = 0} + + +-- Table of suitable biomes and matching API function + +local biome_ids = {} + +function spawn.add_suitable_biome(biome) + local id = minetest.get_biome_id(biome) + assert(id ~= nil) + biome_ids[id] = true +end + +for _, name in ipairs({ + "taiga", "coniferous_forest", "deciduous_forest", "grassland", "savanna" +}) do + local id = minetest.get_biome_id(name) + if id then + biome_ids[id] = true + end +end + +-- End of parameters +-------------------- + +-- Direction table + +local dirs = { + vector.new(0, 0, 1), + vector.new(-1, 0, 0), + vector.new(0, 0, -1), + vector.new(1, 0, 0), +} + + +-- Initial variables + +local edge_len = 1 +local edge_dist = 0 +local dir_step = 0 +local dir_ind = 1 +local searched = false +local success = false +local spawn_pos = {} + + +-- Functions +------------ + +-- Get next position on square search spiral + +local function next_pos() + if edge_dist == edge_len then + edge_dist = 0 + dir_ind = dir_ind + 1 + if dir_ind == 5 then + dir_ind = 1 + end + dir_step = dir_step + 1 + edge_len = math.floor(dir_step / 2) + 1 + end + + local dir = dirs[dir_ind] + local move = vector.multiply(dir, res) + + edge_dist = edge_dist + 1 + + return vector.add(pos, move) +end + + +-- Spawn position search + +local function search() + local edge1, edge2 = core.get_mapgen_edges() + for iter = 1, checks do + local biome_data = minetest.get_biome_data(pos) + -- Sometimes biome_data is nil + if biome_data and biome_ids[biome_data.biome] then + local spawn_y = minetest.get_spawn_level(pos.x, pos.z) + if spawn_y then + spawn_pos = vector.new(pos.x, spawn_y, pos.z) + return true + end + end + + pos = next_pos() + -- Check for position being outside world edge + if pos.x < edge1.x or pos.z < edge1.z or pos.x > edge2.x or pos.z > edge2.z then + return false + end + end + + return false +end + + +function spawn.get_default_pos() + -- Search for spawn position once per server session + if not searched then + success = search() + searched = true + end + return success and spawn_pos +end diff --git a/mods/mtg/spawn/license.txt b/mods/mtg/spawn/license.txt new file mode 100644 index 0000000..a466aab --- /dev/null +++ b/mods/mtg/spawn/license.txt @@ -0,0 +1,24 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2018 paramat + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT diff --git a/mods/mtg/spawn/mod.conf b/mods/mtg/spawn/mod.conf new file mode 100644 index 0000000..7a09d4a --- /dev/null +++ b/mods/mtg/spawn/mod.conf @@ -0,0 +1,3 @@ +name = spawn +description = Minetest Game mod: spawn +depends = default