forked from Mirrorlandia_minetest/minetest
Handle death and respawn better
This commit is contained in:
parent
857fe0551c
commit
74febd5c31
@ -152,6 +152,7 @@ set(minetest_SRCS
|
||||
guiInventoryMenu.cpp
|
||||
guiPauseMenu.cpp
|
||||
guiPasswordChange.cpp
|
||||
guiDeathScreen.cpp
|
||||
client.cpp
|
||||
tile.cpp
|
||||
game.cpp
|
||||
|
@ -431,7 +431,7 @@ void Client::step(float dtime)
|
||||
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
|
||||
|
||||
// This should be incremented in each version
|
||||
writeU16(&data[51], 2);
|
||||
writeU16(&data[51], 3);
|
||||
|
||||
// Send as unreliable
|
||||
Send(0, data, false);
|
||||
@ -1477,6 +1477,22 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(command == TOCLIENT_DEATHSCREEN)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
bool set_camera_point_target = readU8(is);
|
||||
v3f camera_point_target = readV3F1000(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_DEATHSCREEN;
|
||||
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_back(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
|
||||
@ -1712,6 +1728,20 @@ void Client::sendDamage(u8 damage)
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendRespawn()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
||||
writeU16(os, TOSERVER_RESPAWN);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendPlayerPos()
|
||||
{
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
10
src/client.h
10
src/client.h
@ -113,7 +113,8 @@ enum ClientEventType
|
||||
{
|
||||
CE_NONE,
|
||||
CE_PLAYER_DAMAGE,
|
||||
CE_PLAYER_FORCE_MOVE
|
||||
CE_PLAYER_FORCE_MOVE,
|
||||
CE_DEATHSCREEN,
|
||||
};
|
||||
|
||||
struct ClientEvent
|
||||
@ -129,6 +130,12 @@ struct ClientEvent
|
||||
f32 pitch;
|
||||
f32 yaw;
|
||||
} player_force_move;
|
||||
struct{
|
||||
bool set_camera_point_target;
|
||||
f32 camera_point_target_x;
|
||||
f32 camera_point_target_y;
|
||||
f32 camera_point_target_z;
|
||||
} deathscreen;
|
||||
};
|
||||
};
|
||||
|
||||
@ -191,6 +198,7 @@ public:
|
||||
void sendChangePassword(const std::wstring oldpassword,
|
||||
const std::wstring newpassword);
|
||||
void sendDamage(u8 damage);
|
||||
void sendRespawn();
|
||||
|
||||
// locks envlock
|
||||
void removeNode(v3s16 p);
|
||||
|
@ -172,6 +172,13 @@ enum ToClientCommand
|
||||
string serialized item
|
||||
}
|
||||
*/
|
||||
|
||||
TOCLIENT_DEATHSCREEN = 0x37,
|
||||
/*
|
||||
u16 command
|
||||
u8 bool set camera point target
|
||||
v3f1000 camera point target (to point the death cause or whatever)
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
@ -321,6 +328,10 @@ enum ToServerCommand
|
||||
[2] u16 item
|
||||
*/
|
||||
|
||||
TOSERVER_RESPAWN=0x38,
|
||||
/*
|
||||
u16 TOSERVER_RESPAWN
|
||||
*/
|
||||
};
|
||||
|
||||
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
|
||||
|
77
src/game.cpp
77
src/game.cpp
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "guiPasswordChange.h"
|
||||
#include "guiInventoryMenu.h"
|
||||
#include "guiTextInputMenu.h"
|
||||
#include "guiDeathScreen.h"
|
||||
#include "materials.h"
|
||||
#include "config.h"
|
||||
#include "clouds.h"
|
||||
@ -39,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "mainmenumanager.h"
|
||||
#include "gettext.h"
|
||||
|
||||
/*
|
||||
TODO: Move content-aware stuff to separate file by adding properties
|
||||
@ -129,6 +131,26 @@ struct TextDestSignNode : public TextDest
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
/* Respawn menu callback */
|
||||
|
||||
class MainRespawnInitiator: public IRespawnInitiator
|
||||
{
|
||||
public:
|
||||
MainRespawnInitiator(bool *active, Client *client):
|
||||
m_active(active), m_client(client)
|
||||
{
|
||||
*m_active = true;
|
||||
}
|
||||
void respawn()
|
||||
{
|
||||
*m_active = false;
|
||||
m_client->sendRespawn();
|
||||
}
|
||||
private:
|
||||
bool *m_active;
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
/*
|
||||
Hotbar draw routine
|
||||
*/
|
||||
@ -916,6 +938,8 @@ void the_game(
|
||||
|
||||
bool invert_mouse = g_settings->getBool("invert_mouse");
|
||||
|
||||
bool respawn_menu_active = false;
|
||||
|
||||
/*
|
||||
Main loop
|
||||
*/
|
||||
@ -1388,9 +1412,24 @@ void the_game(
|
||||
|
||||
/*
|
||||
Player speed control
|
||||
TODO: Cache the keycodes from getKeySetting
|
||||
*/
|
||||
|
||||
if(!noMenuActive() || !device->isWindowActive())
|
||||
{
|
||||
PlayerControl control(
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
camera_pitch,
|
||||
camera_yaw
|
||||
);
|
||||
client.setPlayerControl(control);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*bool a_up,
|
||||
bool a_down,
|
||||
@ -1435,6 +1474,7 @@ void the_game(
|
||||
//client.step(dtime_avg1);
|
||||
}
|
||||
|
||||
{
|
||||
// Read client events
|
||||
for(;;)
|
||||
{
|
||||
@ -1448,12 +1488,43 @@ void the_game(
|
||||
//u16 damage = event.player_damage.amount;
|
||||
//dstream<<"Player damage: "<<damage<<std::endl;
|
||||
damage_flash_timer = 0.05;
|
||||
if(event.player_damage.amount >= 2){
|
||||
damage_flash_timer += 0.05 * event.player_damage.amount;
|
||||
}
|
||||
}
|
||||
else if(event.type == CE_PLAYER_FORCE_MOVE)
|
||||
{
|
||||
camera_yaw = event.player_force_move.yaw;
|
||||
camera_pitch = event.player_force_move.pitch;
|
||||
}
|
||||
else if(event.type == CE_DEATHSCREEN)
|
||||
{
|
||||
if(respawn_menu_active)
|
||||
continue;
|
||||
|
||||
/*bool set_camera_point_target =
|
||||
event.deathscreen.set_camera_point_target;
|
||||
v3f camera_point_target;
|
||||
camera_point_target.X = event.deathscreen.camera_point_target_x;
|
||||
camera_point_target.Y = event.deathscreen.camera_point_target_y;
|
||||
camera_point_target.Z = event.deathscreen.camera_point_target_z;*/
|
||||
MainRespawnInitiator *respawner =
|
||||
new MainRespawnInitiator(
|
||||
&respawn_menu_active, &client);
|
||||
GUIDeathScreen *menu =
|
||||
new GUIDeathScreen(guienv, guiroot, -1,
|
||||
&g_menumgr, respawner);
|
||||
menu->drop();
|
||||
|
||||
/* Handle visualization */
|
||||
|
||||
damage_flash_timer = 0;
|
||||
|
||||
/*LocalPlayer* player = client.getLocalPlayer();
|
||||
player->setPosition(player->getPosition() + v3f(0,-BS,0));
|
||||
camera.update(player, busytime, screensize);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TimeTaker //timer2("//timer2");
|
||||
@ -1468,14 +1539,10 @@ void the_game(
|
||||
f32 camera_fov = camera.getFovMax();
|
||||
|
||||
if(FIELD_OF_VIEW_TEST)
|
||||
{
|
||||
client.updateCamera(v3f(0,0,0), v3f(0,0,1), camera_fov);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.updateCamera(camera_position,
|
||||
camera_direction, camera_fov);
|
||||
}
|
||||
|
||||
//timer2.stop();
|
||||
//TimeTaker //timer3("//timer3");
|
||||
|
179
src/guiDeathScreen.cpp
Normal file
179
src/guiDeathScreen.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "guiDeathScreen.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "gettext.h"
|
||||
#include "client.h"
|
||||
|
||||
GUIDeathScreen::GUIDeathScreen(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr, IRespawnInitiator *respawner
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_respawner(respawner),
|
||||
m_screensize(1,1)
|
||||
{
|
||||
}
|
||||
|
||||
GUIDeathScreen::~GUIDeathScreen()
|
||||
{
|
||||
removeChildren();
|
||||
delete m_respawner;
|
||||
}
|
||||
|
||||
void GUIDeathScreen::removeChildren()
|
||||
{
|
||||
const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for(core::list<gui::IGUIElement*>::ConstIterator
|
||||
i = children.begin(); i != children.end(); i++)
|
||||
{
|
||||
children_copy.push_back(*i);
|
||||
}
|
||||
for(core::list<gui::IGUIElement*>::Iterator
|
||||
i = children_copy.begin();
|
||||
i != children_copy.end(); i++)
|
||||
{
|
||||
(*i)->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIDeathScreen::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
m_screensize = screensize;
|
||||
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
core::rect<s32> rect(
|
||||
screensize.X/2 - 500/2,
|
||||
screensize.Y/2 - 200/2,
|
||||
screensize.X/2 + 500/2,
|
||||
screensize.Y/2 + 200/2
|
||||
);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = rect.getSize();
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
changeCtype("");
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 400, 50);
|
||||
rect = rect + v2s32(size.X/2-400/2, size.Y/2-50/2-25);
|
||||
Environment->addStaticText(wgettext("You died."), rect, false,
|
||||
true, this, 256);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, 30);
|
||||
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
|
||||
gui::IGUIElement *e =
|
||||
Environment->addButton(rect, this, 257,
|
||||
wgettext("Respawn"));
|
||||
Environment->setFocus(e);
|
||||
}
|
||||
changeCtype("C");
|
||||
}
|
||||
|
||||
void GUIDeathScreen::drawMenu()
|
||||
{
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
{
|
||||
video::SColor color(180,50,0,0);
|
||||
driver->draw2DRectangle(color,
|
||||
core::rect<s32>(0,0,m_screensize.X,m_screensize.Y), NULL);
|
||||
}
|
||||
{
|
||||
video::SColor bgcolor(50,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIDeathScreen::OnEvent(const SEvent& event)
|
||||
{
|
||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
||||
{
|
||||
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
|
||||
{
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
|
||||
{
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.EventType==EET_GUI_EVENT)
|
||||
{
|
||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
||||
&& isVisible())
|
||||
{
|
||||
if(!canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
dstream<<"GUIDeathScreen: Not allowing focus change."
|
||||
<<std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
||||
{
|
||||
switch(event.GUIEvent.Caller->getID())
|
||||
{
|
||||
case 257:
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
void GUIDeathScreen::respawn()
|
||||
{
|
||||
m_respawner->respawn();
|
||||
}
|
||||
|
60
src/guiDeathScreen.h
Normal file
60
src/guiDeathScreen.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GUIMESSAGEMENU_HEADER
|
||||
#define GUIMESSAGEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
class IRespawnInitiator
|
||||
{
|
||||
public:
|
||||
virtual void respawn() = 0;
|
||||
};
|
||||
|
||||
class GUIDeathScreen : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIDeathScreen(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr, IRespawnInitiator *respawner);
|
||||
~GUIDeathScreen();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent& event);
|
||||
|
||||
void respawn();
|
||||
|
||||
private:
|
||||
IRespawnInitiator *m_respawner;
|
||||
v2u32 m_screensize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
142
src/server.cpp
142
src/server.cpp
@ -2026,16 +2026,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
// Get player
|
||||
Player *player = emergePlayer(playername, password, peer_id);
|
||||
|
||||
/*{
|
||||
// DEBUG: Test serialization
|
||||
std::ostringstream test_os;
|
||||
player->serialize(test_os);
|
||||
dstream<<"Player serialization test: \""<<test_os.str()
|
||||
<<"\""<<std::endl;
|
||||
std::istringstream test_is(test_os.str());
|
||||
player->deSerialize(test_is);
|
||||
}*/
|
||||
|
||||
// If failed, cancel
|
||||
if(player == NULL)
|
||||
{
|
||||
@ -2044,32 +2034,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// If a client is already connected to the player, cancel
|
||||
if(player->peer_id != 0)
|
||||
{
|
||||
derr_server<<DTIME<<"Server: peer_id="<<peer_id
|
||||
<<" tried to connect to "
|
||||
"an already connected player (peer_id="
|
||||
<<player->peer_id<<")"<<std::endl;
|
||||
return;
|
||||
}
|
||||
// Set client of player
|
||||
player->peer_id = peer_id;
|
||||
*/
|
||||
|
||||
// Check if player doesn't exist
|
||||
if(player == NULL)
|
||||
throw con::InvalidIncomingDataException
|
||||
("Server::ProcessData(): INIT: Player doesn't exist");
|
||||
|
||||
/*// update name if it was supplied
|
||||
if(datasize >= 20+3)
|
||||
{
|
||||
data[20+3-1] = 0;
|
||||
player->updateName((const char*)&data[3]);
|
||||
}*/
|
||||
|
||||
/*
|
||||
Answer with a TOCLIENT_INIT
|
||||
*/
|
||||
@ -2146,10 +2110,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
|
||||
// Warnings about protocol version can be issued here
|
||||
/*if(getClient(peer->id)->net_proto_version == 0)
|
||||
if(getClient(peer->id)->net_proto_version < 3)
|
||||
{
|
||||
SendChatMessage(peer_id, L"# Server: NOTE: YOUR CLIENT IS OLD AND DOES NOT WORK PROPERLY WITH THIS SERVER");
|
||||
}*/
|
||||
SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND DOES NOT WORK PROPERLY WITH THIS SERVER");
|
||||
}
|
||||
|
||||
/*
|
||||
Check HP, respawn if necessary
|
||||
*/
|
||||
{
|
||||
Player *player = m_env.getPlayer(peer_id);
|
||||
HandlePlayerHP(player, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -3207,35 +3179,20 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
}
|
||||
else if(command == TOSERVER_DAMAGE)
|
||||
{
|
||||
if(g_settings->getBool("enable_damage"))
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
u8 damage = readU8(is);
|
||||
if(player->hp > damage)
|
||||
|
||||
if(g_settings->getBool("enable_damage"))
|
||||
{
|
||||
player->hp -= damage;
|
||||
HandlePlayerHP(player, damage);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->hp = 0;
|
||||
|
||||
dstream<<"TODO: Server: TOSERVER_HP_DECREMENT: Player dies"
|
||||
<<std::endl;
|
||||
|
||||
v3f pos = findSpawnPos(m_env.getServerMap());
|
||||
player->setPosition(pos);
|
||||
player->hp = 20;
|
||||
SendMovePlayer(player);
|
||||
SendPlayerHP(player);
|
||||
|
||||
//TODO: Throw items around
|
||||
}
|
||||
}
|
||||
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
else if(command == TOSERVER_PASSWORD)
|
||||
{
|
||||
/*
|
||||
@ -3296,7 +3253,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
<<std::endl;
|
||||
SendChatMessage(peer_id, L"Password change successful");
|
||||
}
|
||||
else if (command == TOSERVER_PLAYERITEM)
|
||||
else if(command == TOSERVER_PLAYERITEM)
|
||||
{
|
||||
if (datasize < 2+2)
|
||||
return;
|
||||
@ -3305,6 +3262,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
player->wieldItem(item);
|
||||
SendWieldedItem(player);
|
||||
}
|
||||
else if(command == TOSERVER_RESPAWN)
|
||||
{
|
||||
if(player->hp != 0)
|
||||
return;
|
||||
|
||||
RespawnPlayer(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
derr_server<<"WARNING: Server::ProcessData(): Ignoring "
|
||||
@ -3501,6 +3465,23 @@ void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
|
||||
con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
|
||||
bool set_camera_point_target, v3f camera_point_target)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
||||
writeU16(os, TOCLIENT_DEATHSCREEN);
|
||||
writeU8(os, set_camera_point_target);
|
||||
writeV3F1000(os, camera_point_target);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
/*
|
||||
Non-static send methods
|
||||
*/
|
||||
@ -3955,6 +3936,51 @@ void Server::SendBlocks(float dtime)
|
||||
Something random
|
||||
*/
|
||||
|
||||
void Server::HandlePlayerHP(Player *player, s16 damage)
|
||||
{
|
||||
if(player->hp > damage)
|
||||
{
|
||||
player->hp -= damage;
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
dstream<<"Server::HandlePlayerHP(): Player "
|
||||
<<player->getName()<<" dies"<<std::endl;
|
||||
|
||||
player->hp = 0;
|
||||
|
||||
//TODO: Throw items around
|
||||
|
||||
// Handle players that are not connected
|
||||
if(player->peer_id == PEER_ID_INEXISTENT){
|
||||
RespawnPlayer(player);
|
||||
return;
|
||||
}
|
||||
|
||||
SendPlayerHP(player);
|
||||
|
||||
RemoteClient *client = getClient(player->peer_id);
|
||||
if(client->net_proto_version >= 3)
|
||||
{
|
||||
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
|
||||
}
|
||||
else
|
||||
{
|
||||
RespawnPlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::RespawnPlayer(Player *player)
|
||||
{
|
||||
v3f pos = findSpawnPos(m_env.getServerMap());
|
||||
player->setPosition(pos);
|
||||
player->hp = 20;
|
||||
SendMovePlayer(player);
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
|
||||
void Server::UpdateCrafting(u16 peer_id)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
@ -488,6 +488,8 @@ private:
|
||||
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
|
||||
static void SendAccessDenied(con::Connection &con, u16 peer_id,
|
||||
const std::wstring &reason);
|
||||
static void SendDeathscreen(con::Connection &con, u16 peer_id,
|
||||
bool set_camera_point_target, v3f camera_point_target);
|
||||
|
||||
/*
|
||||
Non-static send methods
|
||||
@ -526,6 +528,9 @@ private:
|
||||
Something random
|
||||
*/
|
||||
|
||||
void HandlePlayerHP(Player *player, s16 damage);
|
||||
void RespawnPlayer(Player *player);
|
||||
|
||||
void UpdateCrafting(u16 peer_id);
|
||||
|
||||
// When called, connection mutex should be locked
|
||||
|
Loading…
Reference in New Issue
Block a user