1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Dehardcode the death formspec (#15155)

Co-authored-by: Paul Ouellette <oue.paul18@gmail.com>
This commit is contained in:
grorp 2024-09-24 22:37:44 +02:00 committed by GitHub
parent 3c48671076
commit 526a2f7b8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
79 changed files with 242 additions and 172 deletions

View file

@ -1,15 +0,0 @@
-- CSM death formspec. Only used when clientside modding is enabled, otherwise
-- handled by the engine.
core.register_on_death(function()
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
"label[4.85,1.35;" .. fgettext("You died") ..
"]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]"
core.show_formspec("bultin:death", formspec)
end)
core.register_on_formspec_input(function(formname, fields)
if formname == "bultin:death" then
core.send_respawn()
end
end)

View file

@ -9,6 +9,5 @@ dofile(commonpath .. "mod_storage.lua")
dofile(commonpath .. "chatcommands.lua") dofile(commonpath .. "chatcommands.lua")
dofile(commonpath .. "information_formspecs.lua") dofile(commonpath .. "information_formspecs.lua")
dofile(clientpath .. "chatcommands.lua") dofile(clientpath .. "chatcommands.lua")
dofile(clientpath .. "death_formspec.lua")
dofile(clientpath .. "misc.lua") dofile(clientpath .. "misc.lua")
assert(loadfile(commonpath .. "item_s.lua"))({}) -- Just for push/read node functions assert(loadfile(commonpath .. "item_s.lua"))({}) -- Just for push/read node functions

View file

@ -0,0 +1,31 @@
local F = core.formspec_escape
local S = core.get_translator("__builtin")
function core.show_death_screen(player, _reason)
local fs = {
"formspec_version[1]",
"size[11,5.5,true]",
"bgcolor[#320000b4;true]",
"label[4.85,1.35;", F(S("You died")), "]",
"button_exit[4,3;3,0.5;btn_respawn;", F(S("Respawn")), "]",
}
core.show_formspec(player:get_player_name(), "__builtin:death", table.concat(fs, ""))
end
core.register_on_dieplayer(function(player, reason)
core.show_death_screen(player, reason)
end)
core.register_on_joinplayer(function(player)
if player:get_hp() == 0 then
core.show_death_screen(player, nil)
end
end)
core.register_on_player_receive_fields(function(player, formname, fields)
if formname == "__builtin:death" and fields.quit and player:get_hp() == 0 then
player:respawn()
core.log("action", player:get_player_name() .. " respawns at " ..
player:get_pos():to_string())
end
end)

View file

@ -38,6 +38,7 @@ dofile(gamepath .. "forceloading.lua")
dofile(gamepath .. "hud.lua") dofile(gamepath .. "hud.lua")
dofile(gamepath .. "knockback.lua") dofile(gamepath .. "knockback.lua")
dofile(gamepath .. "async.lua") dofile(gamepath .. "async.lua")
dofile(gamepath .. "death_screen.lua")
core.after(0, builtin_shared.cache_content_ids) core.after(0, builtin_shared.cache_content_ids)

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Вы загінулі
Respawn=Адрадзіцца

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Умряхте
Respawn=Прераждане

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Has mort
Respawn=Reaparèixer

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Zemřel jsi
Respawn=Oživit

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Buest ti farw
Respawn=Atgyfodi

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Du døde
Respawn=Genopstå

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Es wurden insgesamt @1 Datenpunkt(e) aufgeze
The output is limited to '@1'.=Die Ausgabe ist beschränkt auf „@1“. The output is limited to '@1'.=Die Ausgabe ist beschränkt auf „@1“.
Saving of profile failed: @1=Speichern des Profils fehlgeschlagen: @1 Saving of profile failed: @1=Speichern des Profils fehlgeschlagen: @1
Profile saved to @1=Profil abgespeichert nach @1 Profile saved to @1=Profil abgespeichert nach @1
You died=Sie sind gestorben
Respawn=Wiederbeleben

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Πέθανες
Respawn=Επανεμφάνηση

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Sume @1 ekzemplero(j) konserviĝis.
The output is limited to '@1'.=La eligo estas limigita al «@1». The output is limited to '@1'.=La eligo estas limigita al «@1».
Saving of profile failed: @1=Konservado de profilo malsukcesis: @1 Saving of profile failed: @1=Konservado de profilo malsukcesis: @1
Profile saved to @1=Profilo konservita al @1 Profile saved to @1=Profilo konservita al @1
You died=Vi mortis
Respawn=Renaskiĝi

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Has muerto
Respawn=Reaparecer

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Said surma
Respawn=Ärka ellu

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Hil zara
Respawn=Birsortu

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Kuolit
Respawn=Synny uudelleen

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Namatay ka
Respawn=Mag-respawn

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=@1 échantillons ont été collectés.
The output is limited to '@1'.=La sortie est limitée à '@1'. The output is limited to '@1'.=La sortie est limitée à '@1'.
Saving of profile failed: @1=La sauvegarde du profil a échoué : @1 Saving of profile failed: @1=La sauvegarde du profil a échoué : @1
Profile saved to @1=Le profil a été sauvegardé dans @1 Profile saved to @1=Le profil a été sauvegardé dans @1
You died=Vous êtes mort
Respawn=Réapparaître

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Fuair tú bás
Respawn=Athsceith

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Morreches
Respawn=Reaparecer

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Meghaltál
Respawn=Újraéledés

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Total @1 sampel yang diambil.
The output is limited to '@1'.=Keluaran dibatasi ke '@1'. The output is limited to '@1'.=Keluaran dibatasi ke '@1'.
Saving of profile failed: @1=Penyimpanan profil gagal: @1 Saving of profile failed: @1=Penyimpanan profil gagal: @1
Profile saved to @1=Profil disimpan ke @1 Profile saved to @1=Profil disimpan ke @1
You died=Anda mati
Respawn=Bangkit kembali

View file

@ -245,3 +245,5 @@ A total of @1 sample(s) were taken.=Son stati ottenuti campioni per un totale di
The output is limited to '@1'.=L'output è limitato a '@1'. The output is limited to '@1'.=L'output è limitato a '@1'.
Saving of profile failed: @1=Errore nel salvare il profilo: @1 Saving of profile failed: @1=Errore nel salvare il profilo: @1
Profile saved to @1=Profilo salvato in @1 Profile saved to @1=Profilo salvato in @1
You died=Sei morto
Respawn=Rinasci

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=死んでしまった
Respawn=リスポーン

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=.i do morsi
Respawn=tolcanci

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Panjenengan pejah
Respawn=Bangkit Malilh

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=사망했습니다
Respawn=리스폰

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Кулінныд
Respawn=Ловзьыны

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Сиз өлдүңүз.
Respawn=Кайтадан жаралуу

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Jūs numirėte
Respawn=Prisikelti

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Jūs nomirāt
Respawn=Atdzīvoties

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=尔死矣
Respawn=复生

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Та үхсэн
Respawn=Дахин төрөх

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=तू मेलास
Respawn=पुनर्जन्म

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Sebanyak @1 sampel telah diambil secara kese
The output is limited to '@1'.=Output dihadkan kepada '@1'. The output is limited to '@1'.=Output dihadkan kepada '@1'.
Saving of profile failed: @1=Penyimpanan profil telah gagal: @1 Saving of profile failed: @1=Penyimpanan profil telah gagal: @1
Profile saved to @1=Profil telah disimpan ke @1 Profile saved to @1=Profil telah disimpan ke @1
You died=Anda telah meninggal
Respawn=Jelma semula

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Du døde
Respawn=Gjenoppstå

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Je bent gestorven
Respawn=Herboren worden

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Du døydde
Respawn=Kom opp att

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Setz mòrt·a
Respawn=Tornar

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Nie żyjesz
Respawn=Wróć do gry

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Você morreu
Respawn=Renascer

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Um total de @1 amostra(s) foi coletada.
The output is limited to '@1'.=A saída é limitada a '@1'. The output is limited to '@1'.=A saída é limitada a '@1'.
Saving of profile failed: @1=Falha ao salvar o perfil: @1 Saving of profile failed: @1=Falha ao salvar o perfil: @1
Profile saved to @1=Perfil salvo em @1 Profile saved to @1=Perfil salvo em @1
You died=Você morreu
Respawn=Reviver

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Ai murit
Respawn=Reînviere

View file

@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Всего было взято @1 образ
The output is limited to '@1'.=Вывод ограничен значением '@1'. The output is limited to '@1'.=Вывод ограничен значением '@1'.
Saving of profile failed: @1=Не удалось сохранить данные профилирования: @1 Saving of profile failed: @1=Не удалось сохранить данные профилирования: @1
Profile saved to @1=Данные профилирования сохранены в @1 Profile saved to @1=Данные профилирования сохранены в @1
You died=Вы умерли
Respawn=Возродиться

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Zomrel si
Respawn=Oživiť

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Umrl si
Respawn=Ponovno oživi

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Умро си
Respawn=Врати се у живот

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Umro/la si.
Respawn=Vrati se u zivot

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Du dog
Respawn=Återuppstå

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Umekufa.
Respawn=Respawn

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=sina moli
Respawn=o kama sin

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Öldün
Respawn=Yeniden Canlan

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Сез үлдегез
Respawn=Тергезелергә

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Ви загинули
Respawn=Відродитися

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=Bạn đã bị chết
Respawn=Hồi sinh

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=您已死亡
Respawn=重生

View file

@ -0,0 +1,3 @@
# textdomain: __builtin
You died=您已死亡
Respawn=重生

View file

@ -338,8 +338,6 @@ Call these functions only at load time!
is checked to see if the command exists, but after the input is parsed. is checked to see if the command exists, but after the input is parsed.
* Return `true` to mark the command as handled, which means that the default * Return `true` to mark the command as handled, which means that the default
handlers will be prevented. handlers will be prevented.
* `minetest.register_on_death(function())`
* Called when the local player dies
* `minetest.register_on_hp_modification(function(hp))` * `minetest.register_on_hp_modification(function(hp))`
* Called when server modified player's HP * Called when server modified player's HP
* `minetest.register_on_damage_taken(function(hp))` * `minetest.register_on_damage_taken(function(hp))`
@ -487,8 +485,6 @@ Call these functions only at load time!
* Returns `false` if the client is already disconnecting otherwise returns `true`. * Returns `false` if the client is already disconnecting otherwise returns `true`.
* `minetest.get_server_info()` * `minetest.get_server_info()`
* Returns [server info](#server-info). * Returns [server info](#server-info).
* `minetest.send_respawn()`
* Sends a respawn request to the server.
### Storage API ### Storage API
* `minetest.get_mod_storage()`: * `minetest.get_mod_storage()`:

View file

@ -5869,6 +5869,7 @@ Call these functions only at load time!
* `minetest.register_on_dieplayer(function(ObjectRef, reason))` * `minetest.register_on_dieplayer(function(ObjectRef, reason))`
* Called when a player dies * Called when a player dies
* `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange * `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange
* For customizing the death screen, see `minetest.show_death_screen`.
* `minetest.register_on_respawnplayer(function(ObjectRef))` * `minetest.register_on_respawnplayer(function(ObjectRef))`
* Called when player is to be respawned * Called when player is to be respawned
* Called _before_ repositioning of player occurs * Called _before_ repositioning of player occurs
@ -6573,6 +6574,13 @@ Formspec
* `"INV"`: something failed * `"INV"`: something failed
* `"CHG"`: has been changed * `"CHG"`: has been changed
* `"VAL"`: not changed * `"VAL"`: not changed
* `minetest.show_death_screen(player, reason)`
* Called when the death screen should be shown.
* `player` is an ObjectRef, `reason` is a PlayerHPChangeReason table or nil.
* By default, this shows a simple formspec with the option to respawn.
Respawning is done via `ObjectRef:respawn`.
* You can override this to show a custom death screen.
* For general death handling, use `minetest.register_on_dieplayer` instead.
Item handling Item handling
------------- -------------

View file

@ -1359,9 +1359,9 @@ void Client::sendDamage(u16 damage)
Send(&pkt); Send(&pkt);
} }
void Client::sendRespawn() void Client::sendRespawnLegacy()
{ {
NetworkPacket pkt(TOSERVER_RESPAWN, 0); NetworkPacket pkt(TOSERVER_RESPAWN_LEGACY, 0);
Send(&pkt); Send(&pkt);
} }

View file

@ -194,7 +194,7 @@ public:
void handleCommand_Breath(NetworkPacket* pkt); void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_MovePlayer(NetworkPacket* pkt); void handleCommand_MovePlayer(NetworkPacket* pkt);
void handleCommand_MovePlayerRel(NetworkPacket* pkt); void handleCommand_MovePlayerRel(NetworkPacket* pkt);
void handleCommand_DeathScreen(NetworkPacket* pkt); void handleCommand_DeathScreenLegacy(NetworkPacket* pkt);
void handleCommand_AnnounceMedia(NetworkPacket* pkt); void handleCommand_AnnounceMedia(NetworkPacket* pkt);
void handleCommand_Media(NetworkPacket* pkt); void handleCommand_Media(NetworkPacket* pkt);
void handleCommand_NodeDef(NetworkPacket* pkt); void handleCommand_NodeDef(NetworkPacket* pkt);
@ -249,7 +249,7 @@ public:
void sendChangePassword(const std::string &oldpassword, void sendChangePassword(const std::string &oldpassword,
const std::string &newpassword); const std::string &newpassword);
void sendDamage(u16 damage); void sendDamage(u16 damage);
void sendRespawn(); void sendRespawnLegacy();
void sendReady(); void sendReady();
void sendHaveMedia(const std::vector<u32> &tokens); void sendHaveMedia(const std::vector<u32> &tokens);
void sendUpdateClientInfo(const ClientDynamicInfo &info); void sendUpdateClientInfo(const ClientDynamicInfo &info);

View file

@ -35,7 +35,7 @@ enum ClientEventType : u8
CE_NONE, CE_NONE,
CE_PLAYER_DAMAGE, CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE, CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN, CE_DEATHSCREEN_LEGACY,
CE_SHOW_FORMSPEC, CE_SHOW_FORMSPEC,
CE_SHOW_LOCAL_FORMSPEC, CE_SHOW_LOCAL_FORMSPEC,
CE_SPAWN_PARTICLE, CE_SPAWN_PARTICLE,
@ -96,13 +96,6 @@ struct ClientEvent
f32 yaw; f32 yaw;
} player_force_move; } player_force_move;
struct struct
{
bool set_camera_point_target;
f32 camera_point_target_x;
f32 camera_point_target_y;
f32 camera_point_target_z;
} deathscreen;
struct
{ {
std::string *formspec; std::string *formspec;
std::string *formname; std::string *formname;

View file

@ -186,7 +186,7 @@ struct LocalFormspecHandler : public TextDest
assert(m_client != nullptr); assert(m_client != nullptr);
if (fields.find("quit") != fields.end()) if (fields.find("quit") != fields.end())
m_client->sendRespawn(); m_client->sendRespawnLegacy();
return; return;
} }
@ -837,7 +837,7 @@ private:
bool disable_camera_update = false; bool disable_camera_update = false;
}; };
void showDeathFormspec(); void showDeathFormspecLegacy();
void showPauseMenu(); void showPauseMenu();
void pauseAnimation(); void pauseAnimation();
@ -847,7 +847,7 @@ private:
void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_DeathscreenLegacy(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HandleParticleEvent(ClientEvent *event, void handleClientEvent_HandleParticleEvent(ClientEvent *event,
@ -2854,7 +2854,7 @@ const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
{&Game::handleClientEvent_None}, {&Game::handleClientEvent_None},
{&Game::handleClientEvent_PlayerDamage}, {&Game::handleClientEvent_PlayerDamage},
{&Game::handleClientEvent_PlayerForceMove}, {&Game::handleClientEvent_PlayerForceMove},
{&Game::handleClientEvent_Deathscreen}, {&Game::handleClientEvent_DeathscreenLegacy},
{&Game::handleClientEvent_ShowFormSpec}, {&Game::handleClientEvent_ShowFormSpec},
{&Game::handleClientEvent_ShowLocalFormSpec}, {&Game::handleClientEvent_ShowLocalFormSpec},
{&Game::handleClientEvent_HandleParticleEvent}, {&Game::handleClientEvent_HandleParticleEvent},
@ -2910,20 +2910,9 @@ void Game::handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientati
cam->camera_pitch = event->player_force_move.pitch; cam->camera_pitch = event->player_force_move.pitch;
} }
void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam) void Game::handleClientEvent_DeathscreenLegacy(ClientEvent *event, CameraOrientation *cam)
{ {
// If client scripting is enabled, deathscreen is handled by CSM code in showDeathFormspecLegacy();
// builtin/client/init.lua
if (client->modsLoaded())
client->getScript()->on_death();
else
showDeathFormspec();
/* Handle visualization */
LocalPlayer *player = client->getEnv().getLocalPlayer();
runData.damage_flash = 0;
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
} }
void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam) void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam)
@ -4468,7 +4457,7 @@ void Game::readSettings()
****************************************************************************/ ****************************************************************************/
/****************************************************************************/ /****************************************************************************/
void Game::showDeathFormspec() void Game::showDeathFormspecLegacy()
{ {
static std::string formspec_str = static std::string formspec_str =
std::string("formspec_version[1]") + std::string("formspec_version[1]") +

View file

@ -81,7 +81,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_MOVE_PLAYER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayer }, // 0x34 { "TOCLIENT_MOVE_PLAYER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayer }, // 0x34
{ "TOCLIENT_ACCESS_DENIED_LEGACY", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_AccessDenied }, // 0x35 { "TOCLIENT_ACCESS_DENIED_LEGACY", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_AccessDenied }, // 0x35
{ "TOCLIENT_FOV", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Fov }, // 0x36 { "TOCLIENT_FOV", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Fov }, // 0x36
{ "TOCLIENT_DEATHSCREEN", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreen }, // 0x37 { "TOCLIENT_DEATHSCREEN_LEGACY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreenLegacy }, // 0x37
{ "TOCLIENT_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Media }, // 0x38 { "TOCLIENT_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Media }, // 0x38
null_command_handler, null_command_handler,
{ "TOCLIENT_NODEDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_NodeDef }, // 0x3a { "TOCLIENT_NODEDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_NodeDef }, // 0x3a
@ -198,7 +198,7 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
{ "TOSERVER_DAMAGE", 0, true }, // 0x35 { "TOSERVER_DAMAGE", 0, true }, // 0x35
null_command_factory, // 0x36 null_command_factory, // 0x36
{ "TOSERVER_PLAYERITEM", 0, true }, // 0x37 { "TOSERVER_PLAYERITEM", 0, true }, // 0x37
{ "TOSERVER_RESPAWN", 0, true }, // 0x38 { "TOSERVER_RESPAWN_LEGACY", 0, true }, // 0x38
{ "TOSERVER_INTERACT", 0, true }, // 0x39 { "TOSERVER_INTERACT", 0, true }, // 0x39
{ "TOSERVER_REMOVED_SOUNDS", 2, true }, // 0x3a { "TOSERVER_REMOVED_SOUNDS", 2, true }, // 0x3a
{ "TOSERVER_NODEMETA_FIELDS", 0, true }, // 0x3b { "TOSERVER_NODEMETA_FIELDS", 0, true }, // 0x3b

View file

@ -653,20 +653,10 @@ void Client::handleCommand_MovePlayerRel(NetworkPacket *pkt)
player->addPosition(added_pos); player->addPosition(added_pos);
} }
void Client::handleCommand_DeathScreen(NetworkPacket* pkt) void Client::handleCommand_DeathScreenLegacy(NetworkPacket* pkt)
{ {
bool set_camera_point_target;
v3f camera_point_target;
*pkt >> set_camera_point_target;
*pkt >> camera_point_target;
ClientEvent *event = new ClientEvent(); ClientEvent *event = new ClientEvent();
event->type = CE_DEATHSCREEN; event->type = CE_DEATHSCREEN_LEGACY;
event->deathscreen.set_camera_point_target = set_camera_point_target;
event->deathscreen.camera_point_target_x = camera_point_target.X;
event->deathscreen.camera_point_target_y = camera_point_target.Y;
event->deathscreen.camera_point_target_z = camera_point_target.Z;
m_client_event_queue.push(event); m_client_event_queue.push(event);
} }

View file

@ -231,6 +231,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Move default hotbar from client-side C++ to server-side builtin Lua Move default hotbar from client-side C++ to server-side builtin Lua
Add shadow tint to Lighting packets Add shadow tint to Lighting packets
Add shadow color to CloudParam packets Add shadow color to CloudParam packets
Move death screen to server and make it a regular formspec
The server no longer triggers the hardcoded client-side death
formspec, but the client still supports it for compatibility with
old servers.
Rename TOCLIENT_DEATHSCREEN to TOCLIENT_DEATHSCREEN_LEGACY
Rename TOSERVER_RESPAWN to TOSERVER_RESPAWN_LEGACY
[scheduled bump for 5.10.0] [scheduled bump for 5.10.0]
*/ */
@ -391,10 +397,10 @@ enum ToClientCommand : u16
f32 transition_time f32 transition_time
*/ */
TOCLIENT_DEATHSCREEN = 0x37, TOCLIENT_DEATHSCREEN_LEGACY = 0x37,
/* /*
u8 bool set camera point target u8 bool unused
v3f1000 camera point target (to point the death cause or whatever) v3f1000 unused
*/ */
TOCLIENT_MEDIA = 0x38, TOCLIENT_MEDIA = 0x38,
@ -1002,10 +1008,7 @@ enum ToServerCommand : u16
[2] u16 item [2] u16 item
*/ */
TOSERVER_RESPAWN = 0x38, TOSERVER_RESPAWN_LEGACY = 0x38,
/*
u16 TOSERVER_RESPAWN
*/
TOSERVER_INTERACT = 0x39, TOSERVER_INTERACT = 0x39,
/* /*

View file

@ -82,7 +82,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
{ "TOSERVER_DAMAGE", TOSERVER_STATE_INGAME, &Server::handleCommand_Damage }, // 0x35 { "TOSERVER_DAMAGE", TOSERVER_STATE_INGAME, &Server::handleCommand_Damage }, // 0x35
null_command_handler, // 0x36 null_command_handler, // 0x36
{ "TOSERVER_PLAYERITEM", TOSERVER_STATE_INGAME, &Server::handleCommand_PlayerItem }, // 0x37 { "TOSERVER_PLAYERITEM", TOSERVER_STATE_INGAME, &Server::handleCommand_PlayerItem }, // 0x37
{ "TOSERVER_RESPAWN", TOSERVER_STATE_INGAME, &Server::handleCommand_Respawn }, // 0x38 null_command_handler, // 0x38
{ "TOSERVER_INTERACT", TOSERVER_STATE_INGAME, &Server::handleCommand_Interact }, // 0x39 { "TOSERVER_INTERACT", TOSERVER_STATE_INGAME, &Server::handleCommand_Interact }, // 0x39
{ "TOSERVER_REMOVED_SOUNDS", TOSERVER_STATE_INGAME, &Server::handleCommand_RemovedSounds }, // 0x3a { "TOSERVER_REMOVED_SOUNDS", TOSERVER_STATE_INGAME, &Server::handleCommand_RemovedSounds }, // 0x3a
{ "TOSERVER_NODEMETA_FIELDS", TOSERVER_STATE_INGAME, &Server::handleCommand_NodeMetaFields }, // 0x3b { "TOSERVER_NODEMETA_FIELDS", TOSERVER_STATE_INGAME, &Server::handleCommand_NodeMetaFields }, // 0x3b
@ -181,7 +181,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34 { "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34
null_command_factory, // 0x35 null_command_factory, // 0x35
{ "TOCLIENT_FOV", 0, true }, // 0x36 { "TOCLIENT_FOV", 0, true }, // 0x36
{ "TOCLIENT_DEATHSCREEN", 0, true }, // 0x37 null_command_factory, // 0x37
{ "TOCLIENT_MEDIA", 2, true }, // 0x38 { "TOCLIENT_MEDIA", 2, true }, // 0x38
null_command_factory, // 0x39 null_command_factory, // 0x39
{ "TOCLIENT_NODEDEF", 0, true }, // 0x3A { "TOCLIENT_NODEDEF", 0, true }, // 0x3A

View file

@ -858,33 +858,6 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
playersao->getPlayer()->setWieldIndex(item); playersao->getPlayer()->setWieldIndex(item);
} }
void Server::handleCommand_Respawn(NetworkPacket* pkt)
{
session_t peer_id = pkt->getPeerId();
RemotePlayer *player = m_env->getPlayer(peer_id);
if (player == NULL) {
errorstream <<
"Server::ProcessData(): Canceling: No player for peer_id=" <<
peer_id << " disconnecting peer!" << std::endl;
DisconnectPeer(peer_id);
return;
}
PlayerSAO *playersao = player->getPlayerSAO();
assert(playersao);
if (!playersao->isDead())
return;
RespawnPlayer(peer_id);
actionstream << player->getName() << " respawns at "
<< (playersao->getBasePosition() / BS) << std::endl;
// ActiveObject is added to environment in AsyncRunStep after
// the previous addition has been successfully removed
}
bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string &what) bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string &what)
{ {
ItemStack selected_item, hand_item; ItemStack selected_item, hand_item;

View file

@ -125,21 +125,6 @@ void ScriptApiClient::on_hp_modification(int32_t newhp)
} }
} }
void ScriptApiClient::on_death()
{
SCRIPTAPI_PRECHECKHEADER
// Get registered shutdown hooks
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_death");
// Call callbacks
try {
runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
} catch (LuaError &e) {
getClient()->setFatalError(e);
}
}
void ScriptApiClient::environment_step(float dtime) void ScriptApiClient::environment_step(float dtime)
{ {
SCRIPTAPI_PRECHECKHEADER SCRIPTAPI_PRECHECKHEADER

View file

@ -49,7 +49,6 @@ public:
void on_damage_taken(int32_t damage_amount); void on_damage_taken(int32_t damage_amount);
void on_hp_modification(int32_t newhp); void on_hp_modification(int32_t newhp);
void on_death();
void environment_step(float dtime); void environment_step(float dtime);
void on_formspec_input(const std::string &formname, const StringMap &fields); void on_formspec_input(const std::string &formname, const StringMap &fields);

View file

@ -157,13 +157,6 @@ int ModApiClient::l_show_formspec(lua_State *L)
return 1; return 1;
} }
// send_respawn()
int ModApiClient::l_send_respawn(lua_State *L)
{
getClient(L)->sendRespawn();
return 0;
}
// disconnect() // disconnect()
int ModApiClient::l_disconnect(lua_State *L) int ModApiClient::l_disconnect(lua_State *L)
{ {
@ -348,7 +341,6 @@ void ModApiClient::Initialize(lua_State *L, int top)
API_FCT(clear_out_chat_queue); API_FCT(clear_out_chat_queue);
API_FCT(get_player_names); API_FCT(get_player_names);
API_FCT(show_formspec); API_FCT(show_formspec);
API_FCT(send_respawn);
API_FCT(gettext); API_FCT(gettext);
API_FCT(get_node_or_nil); API_FCT(get_node_or_nil);
API_FCT(disconnect); API_FCT(disconnect);

View file

@ -51,9 +51,6 @@ private:
// show_formspec(name, formspec) // show_formspec(name, formspec)
static int l_show_formspec(lua_State *L); static int l_show_formspec(lua_State *L);
// send_respawn()
static int l_send_respawn(lua_State *L);
// disconnect() // disconnect()
static int l_disconnect(lua_State *L); static int l_disconnect(lua_State *L);

View file

@ -2693,11 +2693,11 @@ int ObjectRef::l_respawn(lua_State *L)
{ {
NO_MAP_LOCK_REQUIRED; NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1); ObjectRef *ref = checkObject<ObjectRef>(L, 1);
RemotePlayer *player = getplayer(ref); auto *psao = getplayersao(ref);
if (player == nullptr) if (psao == nullptr)
return 0; return 0;
getServer(L)->RespawnPlayer(player->getPeerId()); psao->respawn();
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;
} }

View file

@ -1159,10 +1159,6 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
// Send HP // Send HP
SendPlayerHP(playersao, false); SendPlayerHP(playersao, false);
// Send death screen
if (playersao->isDead())
SendDeathscreen(peer_id, false, v3f(0,0,0));
// Send Breath // Send Breath
SendPlayerBreath(playersao); SendPlayerBreath(playersao);
@ -1405,14 +1401,6 @@ void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
Send(&pkt); Send(&pkt);
} }
void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
v3f camera_point_target)
{
NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
pkt << set_camera_point_target << camera_point_target;
Send(&pkt);
}
void Server::SendItemDef(session_t peer_id, void Server::SendItemDef(session_t peer_id,
IItemDefManager *itemdef, u16 protocol_version) IItemDefManager *itemdef, u16 protocol_version)
{ {
@ -2803,32 +2791,8 @@ void Server::HandlePlayerDeath(PlayerSAO *playersao, const PlayerHPChangeReason
// Trigger scripted stuff // Trigger scripted stuff
m_script->on_dieplayer(playersao, reason); m_script->on_dieplayer(playersao, reason);
SendDeathscreen(playersao->getPeerID(), false, v3f(0,0,0));
} }
void Server::RespawnPlayer(session_t peer_id)
{
PlayerSAO *playersao = getPlayerSAO(peer_id);
assert(playersao);
infostream << "Server::RespawnPlayer(): Player "
<< playersao->getPlayer()->getName()
<< " respawns" << std::endl;
const auto *prop = playersao->accessObjectProperties();
playersao->setHP(prop->hp_max,
PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
playersao->setBreath(prop->breath_max);
bool repositioned = m_script->on_respawnplayer(playersao);
if (!repositioned) {
// setPos will send the new position to client
playersao->setPos(findSpawnPos());
}
}
void Server::DenySudoAccess(session_t peer_id) void Server::DenySudoAccess(session_t peer_id)
{ {
NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id); NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);

View file

@ -193,7 +193,6 @@ public:
void handleCommand_ChatMessage(NetworkPacket* pkt); void handleCommand_ChatMessage(NetworkPacket* pkt);
void handleCommand_Damage(NetworkPacket* pkt); void handleCommand_Damage(NetworkPacket* pkt);
void handleCommand_PlayerItem(NetworkPacket* pkt); void handleCommand_PlayerItem(NetworkPacket* pkt);
void handleCommand_Respawn(NetworkPacket* pkt);
void handleCommand_Interact(NetworkPacket* pkt); void handleCommand_Interact(NetworkPacket* pkt);
void handleCommand_RemovedSounds(NetworkPacket* pkt); void handleCommand_RemovedSounds(NetworkPacket* pkt);
void handleCommand_NodeMetaFields(NetworkPacket* pkt); void handleCommand_NodeMetaFields(NetworkPacket* pkt);
@ -356,8 +355,6 @@ public:
void setLighting(RemotePlayer *player, const Lighting &lighting); void setLighting(RemotePlayer *player, const Lighting &lighting);
void RespawnPlayer(session_t peer_id);
/* con::PeerHandler implementation. */ /* con::PeerHandler implementation. */
void peerAdded(con::IPeer *peer); void peerAdded(con::IPeer *peer);
void deletingPeer(con::IPeer *peer, bool timeout); void deletingPeer(con::IPeer *peer, bool timeout);
@ -486,8 +483,6 @@ private:
void SendBreath(session_t peer_id, u16 breath); void SendBreath(session_t peer_id, u16 breath);
void SendAccessDenied(session_t peer_id, AccessDeniedCode reason, void SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
std::string_view custom_reason, bool reconnect = false); std::string_view custom_reason, bool reconnect = false);
void SendDeathscreen(session_t peer_id, bool set_camera_point_target,
v3f camera_point_target);
void SendItemDef(session_t peer_id, IItemDefManager *itemdef, u16 protocol_version); void SendItemDef(session_t peer_id, IItemDefManager *itemdef, u16 protocol_version);
void SendNodeDef(session_t peer_id, const NodeDefManager *nodedef, void SendNodeDef(session_t peer_id, const NodeDefManager *nodedef,
u16 protocol_version); u16 protocol_version);

View file

@ -126,7 +126,7 @@ class EmergeManager;
| TOCLIENT_INVENTORY | | | | | TOCLIENT_INVENTORY | | | |
| TOCLIENT_HP (opt) | \-----------------/ | | TOCLIENT_HP (opt) | \-----------------/ |
| TOCLIENT_BREATH | | | TOCLIENT_BREATH | |
| TOCLIENT_DEATHSCREEN | | | TOCLIENT_DEATHSCREEN_LEGACY | |
+-----------------------------+ | +-----------------------------+ |
| | | |
v | v |

View file

@ -558,6 +558,21 @@ void PlayerSAO::setBreath(const u16 breath, bool send)
m_env->getGameDef()->SendPlayerBreath(this); m_env->getGameDef()->SendPlayerBreath(this);
} }
void PlayerSAO::respawn()
{
infostream << "PlayerSAO::respawn(): Player " << m_player->getName()
<< " respawns" << std::endl;
setHP(m_prop.hp_max, PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
setBreath(m_prop.breath_max);
bool repositioned = m_env->getScriptIface()->on_respawnplayer(this);
if (!repositioned) {
// setPos will send the new position to client
setPos(m_env->getGameDef()->findSpawnPos());
}
}
Inventory *PlayerSAO::getInventory() const Inventory *PlayerSAO::getInventory() const
{ {
return m_player ? &m_player->inventory : nullptr; return m_player ? &m_player->inventory : nullptr;

View file

@ -124,6 +124,7 @@ public:
void setHPRaw(u16 hp) { m_hp = hp; } void setHPRaw(u16 hp) { m_hp = hp; }
u16 getBreath() const { return m_breath; } u16 getBreath() const { return m_breath; }
void setBreath(const u16 breath, bool send = true); void setBreath(const u16 breath, bool send = true);
void respawn();
/* /*
Inventory interface Inventory interface