mirror of
https://github.com/minetest/minetest_game.git
synced 2024-12-22 06:50:18 +01:00
Add API to control respawn logic and behavior
This commit is contained in:
parent
d1ba7c3db3
commit
c60d8e4da0
28
game_api.txt
28
game_api.txt
@ -632,6 +632,34 @@ set a players home position and teleport a player to home position.
|
||||
* `name` Player you wish to teleport to their home position
|
||||
* return value: false if player cannot be sent home, otherwise true
|
||||
|
||||
Spawn API
|
||||
---------
|
||||
|
||||
The spawn mod takes care of deciding the position of new and respawning players
|
||||
in the world and has an API to modify its behavior.
|
||||
|
||||
`spawn.get_default_pos()`
|
||||
* Gets the default spawn position as decided by a biome-dependent algorithm.
|
||||
* This is not influenced by settings like "static_spawnpoint" or "engine_spawn".
|
||||
* return value: a vector or `nil` on failure
|
||||
|
||||
`spawn.add_suitable_biome(biome)`:
|
||||
* Adds a biome to the list of allowed biomes for the above algorithm.
|
||||
* `biome`: Name of a registered biome
|
||||
|
||||
`spawn.register_on_spawn(func)`:
|
||||
* Registers a callback to be called when a player (re-)spawns. This can be used
|
||||
to intercept the normal logic to e.g. respawn a player at his bed.
|
||||
* `func`: `function(player, is_new)` with arguments
|
||||
- `player`: ObjectRef
|
||||
- `is_new`: true if the player is joining the server for the first time
|
||||
- return value: true to skip all other spawn logic, false or nil otherwise
|
||||
|
||||
When a player (re-)spawns the following order is executed:
|
||||
1. All spawn callbacks in order of registration.
|
||||
2. If no result, teleport player to `spawn.get_default_pos()`.
|
||||
3. If that fails, spawning is left up to engine.
|
||||
|
||||
|
||||
Sfinv API
|
||||
---------
|
||||
|
@ -244,10 +244,9 @@ end
|
||||
-- Callbacks
|
||||
-- Only register respawn callback if respawn enabled
|
||||
if enable_respawn then
|
||||
-- respawn player at bed if enabled and valid position is found
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
local pos = beds.spawn[name]
|
||||
-- Respawn player at bed if valid position is found
|
||||
spawn.register_on_spawn(function(player, is_new)
|
||||
local pos = beds.spawn[player:get_player_name()]
|
||||
if pos then
|
||||
player:set_pos(pos)
|
||||
return true
|
||||
|
@ -1,3 +1,3 @@
|
||||
name = beds
|
||||
description = Minetest Game mod: beds
|
||||
depends = default, wool
|
||||
depends = default, wool, spawn
|
||||
|
49
mods/spawn/api.lua
Normal file
49
mods/spawn/api.lua
Normal file
@ -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)
|
@ -1,12 +1,12 @@
|
||||
-- spawn/init.lua
|
||||
-- Always load the API
|
||||
----------------------
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/api.lua")
|
||||
|
||||
-- Disable by mapgen, setting or if 'static_spawnpoint' is set
|
||||
--------------------------------------------------------------
|
||||
-- Disable biome-search implementation on unsuitable mapgens
|
||||
------------------------------------------------------------
|
||||
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
if mg_name == "v6" or mg_name == "singlenode" or
|
||||
minetest.settings:get("static_spawnpoint") or
|
||||
minetest.settings:get_bool("engine_spawn") then
|
||||
if mg_name == "v6" or mg_name == "singlenode" then
|
||||
return
|
||||
end
|
||||
|
||||
@ -23,27 +23,32 @@ local checks = 128 * 128
|
||||
local pos = {x = 0, y = 8, z = 0}
|
||||
|
||||
|
||||
-- Table of suitable biomes
|
||||
-- Table of suitable biomes and matching API function
|
||||
|
||||
local biome_ids = {
|
||||
minetest.get_biome_id("taiga"),
|
||||
minetest.get_biome_id("coniferous_forest"),
|
||||
minetest.get_biome_id("deciduous_forest"),
|
||||
minetest.get_biome_id("grassland"),
|
||||
minetest.get_biome_id("savanna"),
|
||||
}
|
||||
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
|
||||
spawn.add_suitable_biome(name)
|
||||
end
|
||||
|
||||
-- End of parameters
|
||||
--------------------
|
||||
|
||||
|
||||
-- Direction table
|
||||
|
||||
local dirs = {
|
||||
{x = 0, y = 0, z = 1},
|
||||
{x = -1, y = 0, z = 0},
|
||||
{x = 0, y = 0, z = -1},
|
||||
{x = 1, y = 0, z = 0},
|
||||
vector.new(0, 0, 1),
|
||||
vector.new(-1, 0, 0),
|
||||
vector.new(0, 0, -1),
|
||||
vector.new(1, 0, 0),
|
||||
}
|
||||
|
||||
|
||||
@ -67,8 +72,8 @@ local chunksize = tonumber(minetest.get_mapgen_setting("chunksize"))
|
||||
local spawn_limit = math.max(mapgen_limit - (chunksize + 1) * 16, 0)
|
||||
|
||||
|
||||
--Functions
|
||||
-----------
|
||||
-- Functions
|
||||
------------
|
||||
|
||||
-- Get next position on square search spiral
|
||||
|
||||
@ -98,15 +103,11 @@ local function search()
|
||||
for iter = 1, checks do
|
||||
local biome_data = minetest.get_biome_data(pos)
|
||||
-- Sometimes biome_data is nil
|
||||
local biome = biome_data and biome_data.biome
|
||||
for id_ind = 1, #biome_ids do
|
||||
local biome_id = biome_ids[id_ind]
|
||||
if biome == biome_id then
|
||||
local spawn_y = minetest.get_spawn_level(pos.x, pos.z)
|
||||
if spawn_y then
|
||||
spawn_pos = {x = pos.x, y = spawn_y, z = pos.z}
|
||||
return true
|
||||
end
|
||||
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
|
||||
|
||||
@ -121,38 +122,11 @@ local function search()
|
||||
end
|
||||
|
||||
|
||||
-- On new player spawn and player respawn
|
||||
|
||||
-- Search for spawn position once per server session. If successful, store
|
||||
-- position and reposition players, otherwise leave them at engine spawn
|
||||
-- position.
|
||||
|
||||
local function on_spawn(player)
|
||||
function spawn.get_default_pos()
|
||||
-- Search for spawn position once per server session
|
||||
if not searched then
|
||||
success = search()
|
||||
searched = true
|
||||
end
|
||||
if success then
|
||||
player:set_pos(spawn_pos)
|
||||
end
|
||||
return success
|
||||
return success and spawn_pos
|
||||
end
|
||||
|
||||
minetest.register_on_newplayer(function(player)
|
||||
on_spawn(player)
|
||||
end)
|
||||
|
||||
local enable_bed_respawn = minetest.settings:get_bool("enable_bed_respawn")
|
||||
if enable_bed_respawn == nil then
|
||||
enable_bed_respawn = true
|
||||
end
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
-- Avoid respawn conflict with beds mod
|
||||
if beds and enable_bed_respawn and
|
||||
beds.spawn[player:get_player_name()] then
|
||||
return
|
||||
end
|
||||
|
||||
return on_spawn(player)
|
||||
end)
|
||||
|
@ -1,4 +1,3 @@
|
||||
name = spawn
|
||||
description = Minetest Game mod: spawn
|
||||
depends = default
|
||||
optional_depends = beds
|
||||
|
Loading…
Reference in New Issue
Block a user