mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Optional reconnect functionality
Enable the server to request the client to reconnect. This can be done with the now extended minetest.request_shutdown([reason], [reconnect]) setting.
This commit is contained in:
parent
1e0e85f82e
commit
3b50b2766a
@ -54,29 +54,42 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local function wordwrap_quickhack(str)
|
||||||
|
local res = ""
|
||||||
|
local ar = str:split("\n")
|
||||||
|
for i = 1, #ar do
|
||||||
|
local text = ar[i]
|
||||||
|
-- Hack to add word wrapping.
|
||||||
|
-- TODO: Add engine support for wrapping in formspecs
|
||||||
|
while #text > 80 do
|
||||||
|
if res ~= "" then
|
||||||
|
res = res .. ","
|
||||||
|
end
|
||||||
|
res = res .. core.formspec_escape(string.sub(text, 1, 79))
|
||||||
|
text = string.sub(text, 80, #text)
|
||||||
|
end
|
||||||
|
if res ~= "" then
|
||||||
|
res = res .. ","
|
||||||
|
end
|
||||||
|
res = res .. core.formspec_escape(text)
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function ui.update()
|
function ui.update()
|
||||||
local formspec = ""
|
local formspec = ""
|
||||||
|
|
||||||
-- handle errors
|
-- handle errors
|
||||||
if gamedata ~= nil and gamedata.errormessage ~= nil then
|
if gamedata ~= nil and gamedata.reconnect_requested then
|
||||||
local ar = gamedata.errormessage:split("\n")
|
formspec = wordwrap_quickhack(gamedata.errormessage or "")
|
||||||
for i = 1, #ar do
|
formspec = "size[12,5]" ..
|
||||||
local text = ar[i]
|
"label[0.5,0;" .. fgettext("The server has requested a reconnect:") ..
|
||||||
-- Hack to add word wrapping.
|
"]textlist[0.2,0.8;11.5,3.5;;" .. formspec ..
|
||||||
-- TODO: Add engine support for wrapping in formspecs
|
"]button[6,4.6;3,0.5;btn_reconnect_no;" .. fgettext("Main menu") .. "]" ..
|
||||||
while #text > 80 do
|
"button[3,4.6;3,0.5;btn_reconnect_yes;" .. fgettext("Reconnect") .. "]"
|
||||||
if formspec ~= "" then
|
elseif gamedata ~= nil and gamedata.errormessage ~= nil then
|
||||||
formspec = formspec .. ","
|
formspec = wordwrap_quickhack(gamedata.errormessage)
|
||||||
end
|
|
||||||
formspec = formspec .. core.formspec_escape(string.sub(text, 1, 79))
|
|
||||||
text = string.sub(text, 80, #text)
|
|
||||||
end
|
|
||||||
if formspec ~= "" then
|
|
||||||
formspec = formspec .. ","
|
|
||||||
end
|
|
||||||
formspec = formspec .. core.formspec_escape(text)
|
|
||||||
end
|
|
||||||
local error_title
|
local error_title
|
||||||
if string.find(gamedata.errormessage, "ModError") then
|
if string.find(gamedata.errormessage, "ModError") then
|
||||||
error_title = fgettext("An error occured in a Lua script, such as a mod:")
|
error_title = fgettext("An error occured in a Lua script, such as a mod:")
|
||||||
@ -128,13 +141,6 @@ end
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function ui.handle_buttons(fields)
|
function ui.handle_buttons(fields)
|
||||||
|
|
||||||
if fields["btn_error_confirm"] then
|
|
||||||
gamedata.errormessage = nil
|
|
||||||
update_menu()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for key,value in pairs(ui.childlist) do
|
for key,value in pairs(ui.childlist) do
|
||||||
|
|
||||||
local retval = value:handle_buttons(fields)
|
local retval = value:handle_buttons(fields)
|
||||||
@ -168,8 +174,15 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
core.button_handler = function(fields)
|
core.button_handler = function(fields)
|
||||||
if fields["btn_error_confirm"] then
|
if fields["btn_reconnect_yes"] then
|
||||||
|
gamedata.reconnect_requested = false
|
||||||
gamedata.errormessage = nil
|
gamedata.errormessage = nil
|
||||||
|
gamedata.do_reconnect = true
|
||||||
|
core.start()
|
||||||
|
return
|
||||||
|
elseif fields["btn_reconnect_no"] or fields["btn_error_confirm"] then
|
||||||
|
gamedata.errormessage = nil
|
||||||
|
gamedata.reconnect_requested = false
|
||||||
ui.update()
|
ui.update()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -2174,7 +2174,8 @@ These functions return the leftover itemstack.
|
|||||||
* Optional: Variable number of arguments that are passed to `func`
|
* Optional: Variable number of arguments that are passed to `func`
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
* `minetest.request_shutdown()`: request for server shutdown
|
* `minetest.request_shutdown([message],[reconnect])`: request for server shutdown. Will display `message` to clients,
|
||||||
|
and `reconnect` == true displays a reconnect button.
|
||||||
* `minetest.get_server_status()`: returns server status string
|
* `minetest.get_server_status()`: returns server status string
|
||||||
|
|
||||||
### Bans
|
### Bans
|
||||||
|
@ -393,6 +393,9 @@
|
|||||||
# A message to be displayed to all clients when the server shuts down
|
# A message to be displayed to all clients when the server shuts down
|
||||||
#kick_msg_crash = This server has experienced an internal error. You will now be disconnected.
|
#kick_msg_crash = This server has experienced an internal error. You will now be disconnected.
|
||||||
# A message to be displayed to all clients when the server crashes
|
# A message to be displayed to all clients when the server crashes
|
||||||
|
#ask_reconnect_on_crash = false
|
||||||
|
# Whether to ask clients to reconnect after a (lua) crash.
|
||||||
|
# Set this to true if your server is set up to restart automatically.
|
||||||
|
|
||||||
# Mod profiler
|
# Mod profiler
|
||||||
#mod_profiling = false
|
#mod_profiling = false
|
||||||
|
@ -244,6 +244,7 @@ Client::Client(
|
|||||||
m_chosen_auth_mech(AUTH_MECHANISM_NONE),
|
m_chosen_auth_mech(AUTH_MECHANISM_NONE),
|
||||||
m_auth_data(NULL),
|
m_auth_data(NULL),
|
||||||
m_access_denied(false),
|
m_access_denied(false),
|
||||||
|
m_access_denied_reconnect(false),
|
||||||
m_itemdef_received(false),
|
m_itemdef_received(false),
|
||||||
m_nodedef_received(false),
|
m_nodedef_received(false),
|
||||||
m_media_downloader(new ClientMediaDownloader()),
|
m_media_downloader(new ClientMediaDownloader()),
|
||||||
|
@ -489,6 +489,8 @@ public:
|
|||||||
bool accessDenied()
|
bool accessDenied()
|
||||||
{ return m_access_denied; }
|
{ return m_access_denied; }
|
||||||
|
|
||||||
|
bool reconnectRequested() { return m_access_denied_reconnect; }
|
||||||
|
|
||||||
std::string accessDeniedReason()
|
std::string accessDeniedReason()
|
||||||
{ return m_access_denied_reason; }
|
{ return m_access_denied_reason; }
|
||||||
|
|
||||||
@ -636,6 +638,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
bool m_access_denied;
|
bool m_access_denied;
|
||||||
|
bool m_access_denied_reconnect;
|
||||||
std::string m_access_denied_reason;
|
std::string m_access_denied_reason;
|
||||||
std::queue<ClientEvent> m_client_event_queue;
|
std::queue<ClientEvent> m_client_event_queue;
|
||||||
bool m_itemdef_received;
|
bool m_itemdef_received;
|
||||||
|
@ -168,8 +168,9 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
|
|||||||
ChatBackend chat_backend;
|
ChatBackend chat_backend;
|
||||||
|
|
||||||
// If an error occurs, this is set to something by menu().
|
// If an error occurs, this is set to something by menu().
|
||||||
// It is then displayed before the menu shows on the next call to menu()
|
// It is then displayed before the menu shows on the next call to menu()
|
||||||
std::string error_message;
|
std::string error_message;
|
||||||
|
bool reconnect_requested = false;
|
||||||
|
|
||||||
bool first_loop = true;
|
bool first_loop = true;
|
||||||
|
|
||||||
@ -197,7 +198,8 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
|
|||||||
*/
|
*/
|
||||||
guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000));
|
guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000));
|
||||||
|
|
||||||
bool game_has_run = launch_game(error_message, game_params, cmd_args);
|
bool game_has_run = launch_game(error_message, reconnect_requested,
|
||||||
|
game_params, cmd_args);
|
||||||
|
|
||||||
// If skip_main_menu, we only want to startup once
|
// If skip_main_menu, we only want to startup once
|
||||||
if (skip_main_menu && !first_loop)
|
if (skip_main_menu && !first_loop)
|
||||||
@ -233,6 +235,7 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
|
|||||||
receiver->m_touchscreengui = new TouchScreenGUI(device, receiver);
|
receiver->m_touchscreengui = new TouchScreenGUI(device, receiver);
|
||||||
g_touchscreengui = receiver->m_touchscreengui;
|
g_touchscreengui = receiver->m_touchscreengui;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
the_game(
|
the_game(
|
||||||
kill,
|
kill,
|
||||||
random_input,
|
random_input,
|
||||||
@ -245,6 +248,7 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
|
|||||||
current_port,
|
current_port,
|
||||||
error_message,
|
error_message,
|
||||||
chat_backend,
|
chat_backend,
|
||||||
|
&reconnect_requested,
|
||||||
gamespec,
|
gamespec,
|
||||||
simple_singleplayer_mode
|
simple_singleplayer_mode
|
||||||
);
|
);
|
||||||
@ -325,14 +329,16 @@ bool ClientLauncher::init_engine(int log_level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ClientLauncher::launch_game(std::string &error_message,
|
bool ClientLauncher::launch_game(std::string &error_message,
|
||||||
GameParams &game_params, const Settings &cmd_args)
|
bool reconnect_requested, GameParams &game_params,
|
||||||
|
const Settings &cmd_args)
|
||||||
{
|
{
|
||||||
// Initialize menu data
|
// Initialize menu data
|
||||||
MainMenuData menudata;
|
MainMenuData menudata;
|
||||||
menudata.address = address;
|
menudata.address = address;
|
||||||
menudata.name = playername;
|
menudata.name = playername;
|
||||||
menudata.port = itos(game_params.socket_port);
|
menudata.port = itos(game_params.socket_port);
|
||||||
menudata.errormessage = error_message;
|
menudata.script_data.errormessage = error_message;
|
||||||
|
menudata.script_data.reconnect_requested = reconnect_requested;
|
||||||
|
|
||||||
error_message.clear();
|
error_message.clear();
|
||||||
|
|
||||||
@ -379,11 +385,11 @@ bool ClientLauncher::launch_game(std::string &error_message,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!menudata.errormessage.empty()) {
|
if (!menudata.script_data.errormessage.empty()) {
|
||||||
/* The calling function will pass this back into this function upon the
|
/* The calling function will pass this back into this function upon the
|
||||||
* next iteration (if any) causing it to be displayed by the GUI
|
* next iteration (if any) causing it to be displayed by the GUI
|
||||||
*/
|
*/
|
||||||
error_message = menudata.errormessage;
|
error_message = menudata.script_data.errormessage;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ protected:
|
|||||||
void init_args(GameParams &game_params, const Settings &cmd_args);
|
void init_args(GameParams &game_params, const Settings &cmd_args);
|
||||||
bool init_engine(int log_level);
|
bool init_engine(int log_level);
|
||||||
|
|
||||||
bool launch_game(std::string &error_message, GameParams &game_params,
|
bool launch_game(std::string &error_message, bool reconnect_requested,
|
||||||
const Settings &cmd_args);
|
GameParams &game_params, const Settings &cmd_args);
|
||||||
|
|
||||||
void main_menu(MainMenuData *menudata);
|
void main_menu(MainMenuData *menudata);
|
||||||
bool create_engine_device(int log_level);
|
bool create_engine_device(int log_level);
|
||||||
|
@ -254,6 +254,7 @@ void set_default_settings(Settings *settings)
|
|||||||
|
|
||||||
settings->setDefault("kick_msg_shutdown", "Server shutting down.");
|
settings->setDefault("kick_msg_shutdown", "Server shutting down.");
|
||||||
settings->setDefault("kick_msg_crash", "This server has experienced an internal error. You will now be disconnected.");
|
settings->setDefault("kick_msg_crash", "This server has experienced an internal error. You will now be disconnected.");
|
||||||
|
settings->setDefault("ask_reconnect_on_crash", "false");
|
||||||
|
|
||||||
settings->setDefault("profiler_print_interval", "0");
|
settings->setDefault("profiler_print_interval", "0");
|
||||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||||
|
@ -426,13 +426,15 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerEnvironment::kickAllPlayers(const std::string &reason)
|
void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason,
|
||||||
|
const std::string &str_reason, bool reconnect)
|
||||||
{
|
{
|
||||||
std::wstring wreason = utf8_to_wide(reason);
|
|
||||||
for (std::vector<Player*>::iterator it = m_players.begin();
|
for (std::vector<Player*>::iterator it = m_players.begin();
|
||||||
it != m_players.end();
|
it != m_players.end();
|
||||||
++it) {
|
++it) {
|
||||||
((Server*)m_gamedef)->DenyAccess_Legacy((*it)->peer_id, wreason);
|
((Server*)m_gamedef)->DenyAccessVerCompliant((*it)->peer_id,
|
||||||
|
(*it)->protocol_version, (AccessDeniedCode)reason,
|
||||||
|
str_reason, reconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "mapnode.h"
|
#include "mapnode.h"
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "jthread/jmutex.h"
|
#include "jthread/jmutex.h"
|
||||||
|
#include "network/networkprotocol.h" // for AccessDeniedCode
|
||||||
|
|
||||||
class ServerEnvironment;
|
class ServerEnvironment;
|
||||||
class ActiveBlockModifier;
|
class ActiveBlockModifier;
|
||||||
@ -221,7 +222,8 @@ public:
|
|||||||
float getSendRecommendedInterval()
|
float getSendRecommendedInterval()
|
||||||
{ return m_recommended_send_interval; }
|
{ return m_recommended_send_interval; }
|
||||||
|
|
||||||
void kickAllPlayers(const std::string &reason);
|
void kickAllPlayers(AccessDeniedCode reason,
|
||||||
|
const std::string &str_reason, bool reconnect);
|
||||||
// Save players
|
// Save players
|
||||||
void saveLoadedPlayers();
|
void saveLoadedPlayers();
|
||||||
void savePlayer(const std::string &playername);
|
void savePlayer(const std::string &playername);
|
||||||
|
26
src/game.cpp
26
src/game.cpp
@ -1417,8 +1417,7 @@ struct VolatileRunFlags {
|
|||||||
* hides most of the stuff in this class (nothing in this class is required
|
* hides most of the stuff in this class (nothing in this class is required
|
||||||
* by any other file) but exposes the public methods/data only.
|
* by any other file) but exposes the public methods/data only.
|
||||||
*/
|
*/
|
||||||
class Game
|
class Game {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
~Game();
|
~Game();
|
||||||
@ -1434,6 +1433,7 @@ public:
|
|||||||
std::string *address,
|
std::string *address,
|
||||||
u16 port,
|
u16 port,
|
||||||
std::string &error_message,
|
std::string &error_message,
|
||||||
|
bool *reconnect,
|
||||||
ChatBackend *chat_backend,
|
ChatBackend *chat_backend,
|
||||||
const SubgameSpec &gamespec, // Used for local game
|
const SubgameSpec &gamespec, // Used for local game
|
||||||
bool simple_singleplayer_mode);
|
bool simple_singleplayer_mode);
|
||||||
@ -1588,6 +1588,7 @@ private:
|
|||||||
scene::ISceneManager *smgr;
|
scene::ISceneManager *smgr;
|
||||||
bool *kill;
|
bool *kill;
|
||||||
std::string *error_message;
|
std::string *error_message;
|
||||||
|
bool *reconnect_requested;
|
||||||
IGameDef *gamedef; // Convenience (same as *client)
|
IGameDef *gamedef; // Convenience (same as *client)
|
||||||
scene::ISceneNode *skybox;
|
scene::ISceneNode *skybox;
|
||||||
|
|
||||||
@ -1716,17 +1717,19 @@ bool Game::startup(bool *kill,
|
|||||||
std::string *address, // can change if simple_singleplayer_mode
|
std::string *address, // can change if simple_singleplayer_mode
|
||||||
u16 port,
|
u16 port,
|
||||||
std::string &error_message,
|
std::string &error_message,
|
||||||
|
bool *reconnect,
|
||||||
ChatBackend *chat_backend,
|
ChatBackend *chat_backend,
|
||||||
const SubgameSpec &gamespec,
|
const SubgameSpec &gamespec,
|
||||||
bool simple_singleplayer_mode)
|
bool simple_singleplayer_mode)
|
||||||
{
|
{
|
||||||
// "cache"
|
// "cache"
|
||||||
this->device = device;
|
this->device = device;
|
||||||
this->kill = kill;
|
this->kill = kill;
|
||||||
this->error_message = &error_message;
|
this->error_message = &error_message;
|
||||||
this->random_input = random_input;
|
this->reconnect_requested = reconnect;
|
||||||
this->input = input;
|
this->random_input = random_input;
|
||||||
this->chat_backend = chat_backend;
|
this->input = input;
|
||||||
|
this->chat_backend = chat_backend;
|
||||||
this->simple_singleplayer_mode = simple_singleplayer_mode;
|
this->simple_singleplayer_mode = simple_singleplayer_mode;
|
||||||
|
|
||||||
driver = device->getVideoDriver();
|
driver = device->getVideoDriver();
|
||||||
@ -2239,6 +2242,7 @@ bool Game::connectToServer(const std::string &playername,
|
|||||||
if (client->accessDenied()) {
|
if (client->accessDenied()) {
|
||||||
*error_message = "Access denied. Reason: "
|
*error_message = "Access denied. Reason: "
|
||||||
+ client->accessDeniedReason();
|
+ client->accessDeniedReason();
|
||||||
|
*reconnect_requested = client->reconnectRequested();
|
||||||
errorstream << *error_message << std::endl;
|
errorstream << *error_message << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2376,6 +2380,7 @@ inline bool Game::checkConnection()
|
|||||||
if (client->accessDenied()) {
|
if (client->accessDenied()) {
|
||||||
*error_message = "Access denied. Reason: "
|
*error_message = "Access denied. Reason: "
|
||||||
+ client->accessDeniedReason();
|
+ client->accessDeniedReason();
|
||||||
|
*reconnect_requested = client->reconnectRequested();
|
||||||
errorstream << *error_message << std::endl;
|
errorstream << *error_message << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -4330,6 +4335,7 @@ void the_game(bool *kill,
|
|||||||
|
|
||||||
std::string &error_message,
|
std::string &error_message,
|
||||||
ChatBackend &chat_backend,
|
ChatBackend &chat_backend,
|
||||||
|
bool *reconnect_requested,
|
||||||
const SubgameSpec &gamespec, // Used for local game
|
const SubgameSpec &gamespec, // Used for local game
|
||||||
bool simple_singleplayer_mode)
|
bool simple_singleplayer_mode)
|
||||||
{
|
{
|
||||||
@ -4344,8 +4350,8 @@ void the_game(bool *kill,
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
if (game.startup(kill, random_input, input, device, map_dir,
|
if (game.startup(kill, random_input, input, device, map_dir,
|
||||||
playername, password, &server_address, port,
|
playername, password, &server_address, port, error_message,
|
||||||
error_message, &chat_backend, gamespec,
|
reconnect_requested, &chat_backend, gamespec,
|
||||||
simple_singleplayer_mode)) {
|
simple_singleplayer_mode)) {
|
||||||
game.run();
|
game.run();
|
||||||
game.shutdown();
|
game.shutdown();
|
||||||
|
@ -147,6 +147,7 @@ void the_game(bool *kill,
|
|||||||
u16 port,
|
u16 port,
|
||||||
std::string &error_message,
|
std::string &error_message,
|
||||||
ChatBackend &chat_backend,
|
ChatBackend &chat_backend,
|
||||||
|
bool *reconnect_requested,
|
||||||
const SubgameSpec &gamespec, // Used for local game
|
const SubgameSpec &gamespec, // Used for local game
|
||||||
bool simple_singleplayer_mode);
|
bool simple_singleplayer_mode);
|
||||||
|
|
||||||
|
@ -208,10 +208,8 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
|
|||||||
m_script = new MainMenuScripting(this);
|
m_script = new MainMenuScripting(this);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (m_data->errormessage != "") {
|
m_script->setMainMenuData(&m_data->script_data);
|
||||||
m_script->setMainMenuErrorMessage(m_data->errormessage);
|
m_data->script_data.errormessage = "";
|
||||||
m_data->errormessage = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loadMainMenuScript()) {
|
if (!loadMainMenuScript()) {
|
||||||
errorstream << "No future without mainmenu" << std::endl;
|
errorstream << "No future without mainmenu" << std::endl;
|
||||||
@ -219,10 +217,9 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
}
|
} catch (LuaError &e) {
|
||||||
catch(LuaError &e) {
|
|
||||||
errorstream << "MAINMENU ERROR: " << e.what() << std::endl;
|
errorstream << "MAINMENU ERROR: " << e.what() << std::endl;
|
||||||
m_data->errormessage = e.what();
|
m_data->script_data.errormessage = e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_menu->quitMenu();
|
m_menu->quitMenu();
|
||||||
|
@ -25,17 +25,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
enum
|
struct MainMenuDataForScript {
|
||||||
{
|
|
||||||
TAB_SINGLEPLAYER=0,
|
MainMenuDataForScript() :
|
||||||
TAB_MULTIPLAYER,
|
reconnect_requested(false)
|
||||||
TAB_ADVANCED,
|
{}
|
||||||
TAB_SETTINGS,
|
|
||||||
TAB_CREDITS
|
// Whether the server has requested a reconnect
|
||||||
|
bool reconnect_requested;
|
||||||
|
|
||||||
|
std::string errormessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MainMenuData
|
struct MainMenuData {
|
||||||
{
|
|
||||||
// Client options
|
// Client options
|
||||||
std::string servername;
|
std::string servername;
|
||||||
std::string serverdescription;
|
std::string serverdescription;
|
||||||
@ -43,19 +45,22 @@ struct MainMenuData
|
|||||||
std::string port;
|
std::string port;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string password;
|
std::string password;
|
||||||
|
// Whether to reconnect
|
||||||
|
bool do_reconnect;
|
||||||
|
|
||||||
// Server options
|
// Server options
|
||||||
bool enable_public;
|
bool enable_public;
|
||||||
int selected_world;
|
int selected_world;
|
||||||
bool simple_singleplayer_mode;
|
bool simple_singleplayer_mode;
|
||||||
|
|
||||||
//error handling
|
// Data to be passed to the script
|
||||||
std::string errormessage;
|
MainMenuDataForScript script_data;
|
||||||
|
|
||||||
MainMenuData():
|
MainMenuData():
|
||||||
|
do_reconnect(false),
|
||||||
enable_public(false),
|
enable_public(false),
|
||||||
selected_world(0),
|
selected_world(0),
|
||||||
simple_singleplayer_mode(false),
|
simple_singleplayer_mode(false)
|
||||||
errormessage("")
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,11 +215,28 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
|
|||||||
|
|
||||||
u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA;
|
u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA;
|
||||||
*pkt >> denyCode;
|
*pkt >> denyCode;
|
||||||
if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
|
if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN ||
|
||||||
|
denyCode == SERVER_ACCESSDENIED_CRASH) {
|
||||||
*pkt >> m_access_denied_reason;
|
*pkt >> m_access_denied_reason;
|
||||||
}
|
if (m_access_denied_reason == "") {
|
||||||
else if (denyCode < SERVER_ACCESSDENIED_MAX) {
|
m_access_denied_reason = accessDeniedStrings[denyCode];
|
||||||
|
}
|
||||||
|
u8 reconnect;
|
||||||
|
*pkt >> reconnect;
|
||||||
|
m_access_denied_reconnect = reconnect & 1;
|
||||||
|
} else if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
|
||||||
|
*pkt >> m_access_denied_reason;
|
||||||
|
} else if (denyCode < SERVER_ACCESSDENIED_MAX) {
|
||||||
m_access_denied_reason = accessDeniedStrings[denyCode];
|
m_access_denied_reason = accessDeniedStrings[denyCode];
|
||||||
|
} else {
|
||||||
|
// Allow us to add new error messages to the
|
||||||
|
// protocol without raising the protocol version, if we want to.
|
||||||
|
// Until then (which may be never), this is outside
|
||||||
|
// of the defined protocol.
|
||||||
|
*pkt >> m_access_denied_reason;
|
||||||
|
if (m_access_denied_reason == "") {
|
||||||
|
m_access_denied_reason = "Unknown";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 13/03/15 Legacy code from 0.4.12 and lesser. must stay 1 year
|
// 13/03/15 Legacy code from 0.4.12 and lesser. must stay 1 year
|
||||||
|
@ -202,7 +202,8 @@ enum ToClientCommand
|
|||||||
TOCLIENT_ACCESS_DENIED = 0x0A,
|
TOCLIENT_ACCESS_DENIED = 0x0A,
|
||||||
/*
|
/*
|
||||||
u8 reason
|
u8 reason
|
||||||
std::string custom reason (if reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
|
std::string custom reason (if needed, otherwise "")
|
||||||
|
u8 (bool) reconnect
|
||||||
*/
|
*/
|
||||||
TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks
|
TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks
|
||||||
TOCLIENT_ADDNODE = 0x21,
|
TOCLIENT_ADDNODE = 0x21,
|
||||||
@ -937,6 +938,8 @@ enum AccessDeniedCode {
|
|||||||
SERVER_ACCESSDENIED_ALREADY_CONNECTED,
|
SERVER_ACCESSDENIED_ALREADY_CONNECTED,
|
||||||
SERVER_ACCESSDENIED_SERVER_FAIL,
|
SERVER_ACCESSDENIED_SERVER_FAIL,
|
||||||
SERVER_ACCESSDENIED_CUSTOM_STRING,
|
SERVER_ACCESSDENIED_CUSTOM_STRING,
|
||||||
|
SERVER_ACCESSDENIED_SHUTDOWN,
|
||||||
|
SERVER_ACCESSDENIED_CRASH,
|
||||||
SERVER_ACCESSDENIED_MAX,
|
SERVER_ACCESSDENIED_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -954,8 +957,10 @@ const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
|
|||||||
"Too many users.",
|
"Too many users.",
|
||||||
"Empty passwords are disallowed. Set a password and try again.",
|
"Empty passwords are disallowed. Set a password and try again.",
|
||||||
"Another client is connected with this name. If your client closed unexpectedly, try again in a minute.",
|
"Another client is connected with this name. If your client closed unexpectedly, try again in a minute.",
|
||||||
"Server authention failed. This is likely a server error."
|
"Server authentication failed. This is likely a server error.",
|
||||||
"",
|
"",
|
||||||
|
"Server shutting down.",
|
||||||
|
"This server has experienced an internal error. You will now be disconnected."
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,6 +44,7 @@ Player::Player(IGameDef *gamedef, const char *name):
|
|||||||
hp(PLAYER_MAX_HP),
|
hp(PLAYER_MAX_HP),
|
||||||
hurt_tilt_timer(0),
|
hurt_tilt_timer(0),
|
||||||
hurt_tilt_strength(0),
|
hurt_tilt_strength(0),
|
||||||
|
protocol_version(0),
|
||||||
peer_id(PEER_ID_INEXISTENT),
|
peer_id(PEER_ID_INEXISTENT),
|
||||||
keyPressed(0),
|
keyPressed(0),
|
||||||
// protected
|
// protected
|
||||||
|
@ -362,6 +362,7 @@ public:
|
|||||||
float hurt_tilt_timer;
|
float hurt_tilt_timer;
|
||||||
float hurt_tilt_strength;
|
float hurt_tilt_strength;
|
||||||
|
|
||||||
|
u16 protocol_version;
|
||||||
u16 peer_id;
|
u16 peer_id;
|
||||||
|
|
||||||
std::string inventory_formspec;
|
std::string inventory_formspec;
|
||||||
|
@ -21,15 +21,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "cpp_api/s_internal.h"
|
#include "cpp_api/s_internal.h"
|
||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
|
|
||||||
void ScriptApiMainMenu::setMainMenuErrorMessage(std::string errormessage)
|
void ScriptApiMainMenu::setMainMenuData(MainMenuDataForScript *data)
|
||||||
{
|
{
|
||||||
SCRIPTAPI_PRECHECKHEADER
|
SCRIPTAPI_PRECHECKHEADER
|
||||||
|
|
||||||
lua_getglobal(L, "gamedata");
|
lua_getglobal(L, "gamedata");
|
||||||
int gamedata_idx = lua_gettop(L);
|
int gamedata_idx = lua_gettop(L);
|
||||||
lua_pushstring(L, "errormessage");
|
lua_pushstring(L, "errormessage");
|
||||||
lua_pushstring(L, errormessage.c_str());
|
if (!data->errormessage.empty()) {
|
||||||
|
lua_pushstring(L, data->errormessage.c_str());
|
||||||
|
} else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
lua_settable(L, gamedata_idx);
|
lua_settable(L, gamedata_idx);
|
||||||
|
setboolfield(L, gamedata_idx, "reconnect_requested",
|
||||||
|
data->reconnect_requested);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,16 +22,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "cpp_api/s_base.h"
|
#include "cpp_api/s_base.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
#include "../guiMainMenu.h"
|
||||||
|
|
||||||
class ScriptApiMainMenu
|
class ScriptApiMainMenu : virtual public ScriptApiBase {
|
||||||
: virtual public ScriptApiBase
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* set gamedata.errormessage to inform lua of an error
|
* Hand over MainMenuDataForScript to lua to inform lua of the content
|
||||||
* @param errormessage the error message
|
* @param data the data
|
||||||
*/
|
*/
|
||||||
void setMainMenuErrorMessage(std::string errormessage);
|
void setMainMenuData(MainMenuDataForScript *data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process events received from formspec
|
* process events received from formspec
|
||||||
|
@ -114,15 +114,19 @@ int ModApiMainMenu::l_start(lua_State *L)
|
|||||||
|
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
|
MainMenuData *data = engine->m_data;
|
||||||
|
|
||||||
engine->m_data->selected_world = getIntegerData(L, "selected_world",valid) -1;
|
data->selected_world = getIntegerData(L, "selected_world",valid) -1;
|
||||||
engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
|
data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
|
||||||
engine->m_data->name = getTextData(L,"playername");
|
data->do_reconnect = getBoolData(L, "do_reconnect", valid);
|
||||||
engine->m_data->password = getTextData(L,"password");
|
if (!data->do_reconnect) {
|
||||||
engine->m_data->address = getTextData(L,"address");
|
data->name = getTextData(L,"playername");
|
||||||
engine->m_data->port = getTextData(L,"port");
|
data->password = getTextData(L,"password");
|
||||||
engine->m_data->serverdescription = getTextData(L,"serverdescription");
|
data->address = getTextData(L,"address");
|
||||||
engine->m_data->servername = getTextData(L,"servername");
|
data->port = getTextData(L,"port");
|
||||||
|
}
|
||||||
|
data->serverdescription = getTextData(L,"serverdescription");
|
||||||
|
data->servername = getTextData(L,"servername");
|
||||||
|
|
||||||
//close menu next time
|
//close menu next time
|
||||||
engine->m_startgame = true;
|
engine->m_startgame = true;
|
||||||
|
@ -30,7 +30,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
// request_shutdown()
|
// request_shutdown()
|
||||||
int ModApiServer::l_request_shutdown(lua_State *L)
|
int ModApiServer::l_request_shutdown(lua_State *L)
|
||||||
{
|
{
|
||||||
getServer(L)->requestShutdown();
|
const char *msg = lua_tolstring(L, 1, NULL);
|
||||||
|
bool reconnect = lua_toboolean(L, 2);
|
||||||
|
getServer(L)->requestShutdown(msg ? msg : "", reconnect);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
class ModApiServer : public ModApiBase {
|
class ModApiServer : public ModApiBase {
|
||||||
private:
|
private:
|
||||||
// request_shutdown()
|
// request_shutdown([message], [reconnect])
|
||||||
static int l_request_shutdown(lua_State *L);
|
static int l_request_shutdown(lua_State *L);
|
||||||
|
|
||||||
// get_server_status()
|
// get_server_status()
|
||||||
|
@ -191,6 +191,7 @@ Server::Server(
|
|||||||
m_uptime(0),
|
m_uptime(0),
|
||||||
m_clients(&m_con),
|
m_clients(&m_con),
|
||||||
m_shutdown_requested(false),
|
m_shutdown_requested(false),
|
||||||
|
m_shutdown_ask_reconnect(false),
|
||||||
m_ignore_map_edit_events(false),
|
m_ignore_map_edit_events(false),
|
||||||
m_ignore_map_edit_events_peer_id(0),
|
m_ignore_map_edit_events_peer_id(0),
|
||||||
m_next_sound_id(0)
|
m_next_sound_id(0)
|
||||||
@ -398,7 +399,17 @@ Server::~Server()
|
|||||||
m_env->saveLoadedPlayers();
|
m_env->saveLoadedPlayers();
|
||||||
|
|
||||||
infostream << "Server: Kicking players" << std::endl;
|
infostream << "Server: Kicking players" << std::endl;
|
||||||
m_env->kickAllPlayers(g_settings->get("kick_msg_shutdown"));
|
std::string kick_msg;
|
||||||
|
bool reconnect = false;
|
||||||
|
if (getShutdownRequested()) {
|
||||||
|
reconnect = m_shutdown_ask_reconnect;
|
||||||
|
kick_msg = m_shutdown_msg;
|
||||||
|
}
|
||||||
|
if (kick_msg == "") {
|
||||||
|
kick_msg = g_settings->get("kick_msg_shutdown");
|
||||||
|
}
|
||||||
|
m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
|
||||||
|
kick_msg, reconnect);
|
||||||
|
|
||||||
infostream << "Server: Saving environment metadata" << std::endl;
|
infostream << "Server: Saving environment metadata" << std::endl;
|
||||||
m_env->saveMeta();
|
m_env->saveMeta();
|
||||||
@ -502,7 +513,9 @@ void Server::step(float dtime)
|
|||||||
throw ServerError(async_err);
|
throw ServerError(async_err);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_env->kickAllPlayers(g_settings->get("kick_msg_crash"));
|
m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
|
||||||
|
g_settings->get("kick_msg_crash"),
|
||||||
|
g_settings->getBool("ask_reconnect_on_crash"));
|
||||||
errorstream << "UNRECOVERABLE error occurred. Stopping server. "
|
errorstream << "UNRECOVERABLE error occurred. Stopping server. "
|
||||||
<< "Please fix the following error:" << std::endl
|
<< "Please fix the following error:" << std::endl
|
||||||
<< async_err << std::endl;
|
<< async_err << std::endl;
|
||||||
@ -1070,7 +1083,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
|
|||||||
RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
|
RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
|
||||||
if (client != NULL) {
|
if (client != NULL) {
|
||||||
playername = client->getName();
|
playername = client->getName();
|
||||||
playersao = emergePlayer(playername.c_str(), peer_id);
|
playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
|
||||||
}
|
}
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
m_clients.Unlock();
|
m_clients.Unlock();
|
||||||
@ -1523,16 +1536,18 @@ void Server::SendBreath(u16 peer_id, u16 breath)
|
|||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
|
void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
|
||||||
|
const std::string &custom_reason, bool reconnect)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
assert(reason < SERVER_ACCESSDENIED_MAX);
|
||||||
|
|
||||||
NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
|
NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
|
||||||
pkt << (u8) reason;
|
pkt << (u8)reason;
|
||||||
|
if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
|
||||||
if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING) {
|
|
||||||
pkt << custom_reason;
|
pkt << custom_reason;
|
||||||
}
|
else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
|
||||||
|
reason == SERVER_ACCESSDENIED_CRASH)
|
||||||
|
pkt << custom_reason << (u8)reconnect;
|
||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2567,6 +2582,8 @@ void Server::RespawnPlayer(u16 peer_id)
|
|||||||
playersao->setPos(pos);
|
playersao->setPos(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Server::DenySudoAccess(u16 peer_id)
|
void Server::DenySudoAccess(u16 peer_id)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
@ -2575,6 +2592,24 @@ void Server::DenySudoAccess(u16 peer_id)
|
|||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
|
||||||
|
const std::string &str_reason, bool reconnect)
|
||||||
|
{
|
||||||
|
if (proto_ver >= 25) {
|
||||||
|
SendAccessDenied(peer_id, reason, str_reason);
|
||||||
|
} else {
|
||||||
|
std::wstring wreason = utf8_to_wide(
|
||||||
|
reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
|
||||||
|
accessDeniedStrings[(u8)reason]);
|
||||||
|
SendAccessDenied_Legacy(peer_id, wreason);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_clients.event(peer_id, CSE_SetDenied);
|
||||||
|
m_con.DisconnectPeer(peer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
|
void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
@ -3330,7 +3365,7 @@ v3f Server::findSpawnPos()
|
|||||||
return intToFloat(nodepos, BS);
|
return intToFloat(nodepos, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
|
PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
|
||||||
{
|
{
|
||||||
bool newplayer = false;
|
bool newplayer = false;
|
||||||
|
|
||||||
@ -3383,6 +3418,8 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
|
|||||||
getPlayerEffectivePrivs(player->getName()),
|
getPlayerEffectivePrivs(player->getName()),
|
||||||
isSingleplayer());
|
isSingleplayer());
|
||||||
|
|
||||||
|
player->protocol_version = proto_version;
|
||||||
|
|
||||||
/* Clean up old HUD elements from previous sessions */
|
/* Clean up old HUD elements from previous sessions */
|
||||||
player->clearHud();
|
player->clearHud();
|
||||||
|
|
||||||
|
18
src/server.h
18
src/server.h
@ -244,8 +244,13 @@ public:
|
|||||||
{ return m_shutdown_requested; }
|
{ return m_shutdown_requested; }
|
||||||
|
|
||||||
// request server to shutdown
|
// request server to shutdown
|
||||||
inline void requestShutdown(void)
|
inline void requestShutdown() { m_shutdown_requested = true; }
|
||||||
{ m_shutdown_requested = true; }
|
void requestShutdown(const std::string &msg, bool reconnect)
|
||||||
|
{
|
||||||
|
m_shutdown_requested = true;
|
||||||
|
m_shutdown_msg = msg;
|
||||||
|
m_shutdown_ask_reconnect = reconnect;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns -1 if failed, sound handle on success
|
// Returns -1 if failed, sound handle on success
|
||||||
// Envlock
|
// Envlock
|
||||||
@ -366,6 +371,8 @@ public:
|
|||||||
void deletingPeer(con::Peer *peer, bool timeout);
|
void deletingPeer(con::Peer *peer, bool timeout);
|
||||||
|
|
||||||
void DenySudoAccess(u16 peer_id);
|
void DenySudoAccess(u16 peer_id);
|
||||||
|
void DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
|
||||||
|
const std::string &str_reason = "", bool reconnect = false);
|
||||||
void DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason="");
|
void DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason="");
|
||||||
void acceptAuth(u16 peer_id, bool forSudoMode);
|
void acceptAuth(u16 peer_id, bool forSudoMode);
|
||||||
void DenyAccess_Legacy(u16 peer_id, const std::wstring &reason);
|
void DenyAccess_Legacy(u16 peer_id, const std::wstring &reason);
|
||||||
@ -390,7 +397,8 @@ private:
|
|||||||
void SendMovement(u16 peer_id);
|
void SendMovement(u16 peer_id);
|
||||||
void SendHP(u16 peer_id, u8 hp);
|
void SendHP(u16 peer_id, u8 hp);
|
||||||
void SendBreath(u16 peer_id, u16 breath);
|
void SendBreath(u16 peer_id, u16 breath);
|
||||||
void SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason);
|
void SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
|
||||||
|
const std::string &custom_reason, bool reconnect = false);
|
||||||
void SendAccessDenied_Legacy(u16 peer_id, const std::wstring &reason);
|
void SendAccessDenied_Legacy(u16 peer_id, const std::wstring &reason);
|
||||||
void SendDeathscreen(u16 peer_id,bool set_camera_point_target, v3f camera_point_target);
|
void SendDeathscreen(u16 peer_id,bool set_camera_point_target, v3f camera_point_target);
|
||||||
void SendItemDef(u16 peer_id,IItemDefManager *itemdef, u16 protocol_version);
|
void SendItemDef(u16 peer_id,IItemDefManager *itemdef, u16 protocol_version);
|
||||||
@ -490,7 +498,7 @@ private:
|
|||||||
|
|
||||||
Call with env and con locked.
|
Call with env and con locked.
|
||||||
*/
|
*/
|
||||||
PlayerSAO *emergePlayer(const char *name, u16 peer_id);
|
PlayerSAO *emergePlayer(const char *name, u16 peer_id, u16 proto_version);
|
||||||
|
|
||||||
void handlePeerChanges();
|
void handlePeerChanges();
|
||||||
|
|
||||||
@ -596,6 +604,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool m_shutdown_requested;
|
bool m_shutdown_requested;
|
||||||
|
std::string m_shutdown_msg;
|
||||||
|
bool m_shutdown_ask_reconnect;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Map edit event queue. Automatically receives all map edits.
|
Map edit event queue. Automatically receives all map edits.
|
||||||
|
Loading…
Reference in New Issue
Block a user