guiInventoryMenu.cpp
guiPauseMenu.cpp
guiPasswordChange.cpp
+ guiDeathScreen.cpp
client.cpp
tile.cpp
game.cpp
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);
}
}
}
+ 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 "
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
{
CE_NONE,
CE_PLAYER_DAMAGE,
- CE_PLAYER_FORCE_MOVE
+ CE_PLAYER_FORCE_MOVE,
+ CE_DEATHSCREEN,
};
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;
};
};
void sendChangePassword(const std::wstring oldpassword,
const std::wstring newpassword);
void sendDamage(u8 damage);
+ void sendRespawn();
// locks envlock
void removeNode(v3s16 p);
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
[0] u16 TOSERVER_PLAYERITEM
[2] u16 item
*/
-
+
+ TOSERVER_RESPAWN=0x38,
+ /*
+ u16 TOSERVER_RESPAWN
+ */
};
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
#include "guiPasswordChange.h"
#include "guiInventoryMenu.h"
#include "guiTextInputMenu.h"
+#include "guiDeathScreen.h"
#include "materials.h"
#include "config.h"
#include "clouds.h"
#include "settings.h"
#include "profiler.h"
#include "mainmenumanager.h"
+#include "gettext.h"
/*
TODO: Move content-aware stuff to separate file by adding properties
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
*/
bool invert_mouse = g_settings->getBool("invert_mouse");
+ bool respawn_menu_active = false;
+
/*
Main loop
*/
/*
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,
//client.step(dtime_avg1);
}
- // Read client events
- for(;;)
{
- ClientEvent event = client.getClientEvent();
- if(event.type == CE_NONE)
- {
- break;
- }
- else if(event.type == CE_PLAYER_DAMAGE)
+ // Read client events
+ for(;;)
{
- //u16 damage = event.player_damage.amount;
- //dstream<<"Player damage: "<<damage<<std::endl;
- damage_flash_timer = 0.05;
- }
- else if(event.type == CE_PLAYER_FORCE_MOVE)
- {
- camera_yaw = event.player_force_move.yaw;
- camera_pitch = event.player_force_move.pitch;
+ ClientEvent event = client.getClientEvent();
+ if(event.type == CE_NONE)
+ {
+ break;
+ }
+ else if(event.type == CE_PLAYER_DAMAGE)
+ {
+ //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);*/
+ }
}
}
v3f camera_position = camera.getPosition();
v3f camera_direction = camera.getDirection();
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");
--- /dev/null
+/*
+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();
+}
+
--- /dev/null
+/*
+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
+
// 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)
{
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
*/
}
// 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;
}
}
else if(command == TOSERVER_DAMAGE)
{
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+ u8 damage = readU8(is);
+
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)
- {
- player->hp -= 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
- }
+ HandlePlayerHP(player, damage);
+ }
+ else
+ {
+ SendPlayerHP(player);
}
-
- SendPlayerHP(player);
}
else if(command == TOSERVER_PASSWORD)
{
<<std::endl;
SendChatMessage(peer_id, L"Password change successful");
}
- else if (command == TOSERVER_PLAYERITEM)
+ else if(command == TOSERVER_PLAYERITEM)
{
if (datasize < 2+2)
return;
player->wieldItem(item);
SendWieldedItem(player);
}
+ else if(command == TOSERVER_RESPAWN)
+ {
+ if(player->hp != 0)
+ return;
+
+ RespawnPlayer(player);
+ }
else
{
derr_server<<"WARNING: Server::ProcessData(): Ignoring "
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
*/
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);
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
Something random
*/
+ void HandlePlayerHP(Player *player, s16 damage);
+ void RespawnPlayer(Player *player);
+
void UpdateCrafting(u16 peer_id);
// When called, connection mutex should be locked