mirror of
https://github.com/minetest/minetest.git
synced 2024-11-30 03:23:45 +01:00
Server: announce MIN/MAX protocol version supported to serverlist. Client: check serverlist
Client now informs about incompatible servers from the list, this permits to prevent the protocol movements. Server announces its supported protocol versions to master server
This commit is contained in:
parent
8941ea0cc9
commit
5a0ed780f5
@ -564,7 +564,7 @@ if INIT == "mainmenu" then
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function fgettext(text, ...)
|
function fgettext_ne(text, ...)
|
||||||
text = core.gettext(text)
|
text = core.gettext(text)
|
||||||
local arg = {n=select('#', ...), ...}
|
local arg = {n=select('#', ...), ...}
|
||||||
if arg.n >= 1 then
|
if arg.n >= 1 then
|
||||||
@ -586,7 +586,11 @@ if INIT == "mainmenu" then
|
|||||||
end
|
end
|
||||||
text = result
|
text = result
|
||||||
end
|
end
|
||||||
return core.formspec_escape(text)
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
|
function fgettext(text, ...)
|
||||||
|
return core.formspec_escape(fgettext_ne(text, ...))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -16,9 +16,15 @@
|
|||||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Global menu data
|
-- Global menu data
|
||||||
---------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
menudata = {}
|
menudata = {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Local cached values
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local min_supp_proto = core.get_min_supp_proto()
|
||||||
|
local max_supp_proto = core.get_max_supp_proto()
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Menu helper functions
|
-- Menu helper functions
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -42,6 +48,25 @@ function image_column(tooltip, flagname)
|
|||||||
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png")
|
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function order_favorite_list(list)
|
||||||
|
local res = {}
|
||||||
|
--orders the favorite list after support
|
||||||
|
for i=1,#list,1 do
|
||||||
|
local fav = list[i]
|
||||||
|
if is_server_protocol_compat(fav.proto_min, fav.proto_max) then
|
||||||
|
table.insert(res, fav)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i=1,#list,1 do
|
||||||
|
local fav = list[i]
|
||||||
|
if not is_server_protocol_compat(fav.proto_min, fav.proto_max) then
|
||||||
|
table.insert(res, fav)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function render_favorite(spec,render_details)
|
function render_favorite(spec,render_details)
|
||||||
local text = ""
|
local text = ""
|
||||||
@ -68,6 +93,7 @@ function render_favorite(spec,render_details)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local details = ""
|
local details = ""
|
||||||
|
local grey_out = not is_server_protocol_compat(spec.proto_max, spec.proto_min)
|
||||||
|
|
||||||
if spec.clients ~= nil and spec.clients_max ~= nil then
|
if spec.clients ~= nil and spec.clients_max ~= nil then
|
||||||
local clients_color = ''
|
local clients_color = ''
|
||||||
@ -87,11 +113,17 @@ function render_favorite(spec,render_details)
|
|||||||
clients_color = '#ffba97' -- 90-100%: orange
|
clients_color = '#ffba97' -- 90-100%: orange
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if grey_out then
|
||||||
|
clients_color = '#aaaaaa'
|
||||||
|
end
|
||||||
|
|
||||||
details = details ..
|
details = details ..
|
||||||
clients_color .. ',' ..
|
clients_color .. ',' ..
|
||||||
render_client_count(spec.clients) .. ',' ..
|
render_client_count(spec.clients) .. ',' ..
|
||||||
'/,' ..
|
'/,' ..
|
||||||
render_client_count(spec.clients_max) .. ','
|
render_client_count(spec.clients_max) .. ','
|
||||||
|
elseif grey_out then
|
||||||
|
details = details .. '#aaaaaa,?,/,?,'
|
||||||
else
|
else
|
||||||
details = details .. ',?,/,?,'
|
details = details .. ',?,/,?,'
|
||||||
end
|
end
|
||||||
@ -114,7 +146,7 @@ function render_favorite(spec,render_details)
|
|||||||
details = details .. "0,"
|
details = details .. "0,"
|
||||||
end
|
end
|
||||||
|
|
||||||
return details .. text
|
return details .. (grey_out and '#aaaaaa,' or ',') .. text
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -195,7 +227,7 @@ function asyncOnlineFavourites()
|
|||||||
nil,
|
nil,
|
||||||
function(result)
|
function(result)
|
||||||
if core.setting_getbool("public_serverlist") then
|
if core.setting_getbool("public_serverlist") then
|
||||||
menudata.favorites = result
|
menudata.favorites = order_favorite_list(result)
|
||||||
core.event_handler("Refresh")
|
core.event_handler("Refresh")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -225,3 +257,21 @@ function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency)
|
|||||||
|
|
||||||
return retval
|
return retval
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function is_server_protocol_compat(proto_min, proto_max)
|
||||||
|
return not ((min_supp_proto > (proto_max or 24)) or (max_supp_proto < (proto_min or 13)))
|
||||||
|
end
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function is_server_protocol_compat_or_error(proto_min, proto_max)
|
||||||
|
if not is_server_protocol_compat(proto_min, proto_max) then
|
||||||
|
gamedata.errormessage = fgettext_ne("Protocol version mismatch, server " ..
|
||||||
|
((proto_min ~= proto_max) and "supports protocols between $1 and $2" or "enforces protocol version $1") ..
|
||||||
|
", we " ..
|
||||||
|
((min_supp_proto ~= max_supp_proto) and "support protocols between version $3 and $4." or "only support protocol version $3"),
|
||||||
|
proto_min or 13, proto_max or 24, min_supp_proto, max_supp_proto)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
@ -62,6 +62,7 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
|
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
|
||||||
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
|
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
|
||||||
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
|
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
|
||||||
|
"color,span=1;" ..
|
||||||
"text,padding=1]" -- name
|
"text,padding=1]" -- name
|
||||||
else
|
else
|
||||||
retval = retval .. "tablecolumns[text]"
|
retval = retval .. "tablecolumns[text]"
|
||||||
@ -88,7 +89,6 @@ end
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
local function main_button_handler(tabview, fields, name, tabdata)
|
local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
|
|
||||||
if fields["te_name"] ~= nil then
|
if fields["te_name"] ~= nil then
|
||||||
gamedata.playername = fields["te_name"]
|
gamedata.playername = fields["te_name"]
|
||||||
core.setting_set("name", fields["te_name"])
|
core.setting_set("name", fields["te_name"])
|
||||||
@ -98,6 +98,10 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
local event = core.explode_table_event(fields["favourites"])
|
local event = core.explode_table_event(fields["favourites"])
|
||||||
if event.type == "DCL" then
|
if event.type == "DCL" then
|
||||||
if event.row <= #menudata.favorites then
|
if event.row <= #menudata.favorites then
|
||||||
|
if not is_server_protocol_compat_or_error(menudata.favorites[event.row].proto_min,
|
||||||
|
menudata.favorites[event.row].proto_max) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
gamedata.address = menudata.favorites[event.row].address
|
gamedata.address = menudata.favorites[event.row].address
|
||||||
gamedata.port = menudata.favorites[event.row].port
|
gamedata.port = menudata.favorites[event.row].port
|
||||||
gamedata.playername = fields["te_name"]
|
gamedata.playername = fields["te_name"]
|
||||||
@ -189,7 +193,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
local current_favourite = core.get_table_index("favourites")
|
local current_favourite = core.get_table_index("favourites")
|
||||||
if current_favourite == nil then return end
|
if current_favourite == nil then return end
|
||||||
core.delete_favorite(current_favourite)
|
core.delete_favorite(current_favourite)
|
||||||
menudata.favorites = core.get_favorites()
|
menudata.favorites = order_favorite_list(core.get_favorites())
|
||||||
tabdata.fav_selected = nil
|
tabdata.fav_selected = nil
|
||||||
|
|
||||||
core.setting_set("address","")
|
core.setting_set("address","")
|
||||||
@ -215,6 +219,11 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
|
|
||||||
gamedata.servername = menudata.favorites[fav_idx].name
|
gamedata.servername = menudata.favorites[fav_idx].name
|
||||||
gamedata.serverdescription = menudata.favorites[fav_idx].description
|
gamedata.serverdescription = menudata.favorites[fav_idx].description
|
||||||
|
|
||||||
|
if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min,
|
||||||
|
menudata.favorites[fav_idx].proto_max)then
|
||||||
|
return true
|
||||||
|
end
|
||||||
else
|
else
|
||||||
gamedata.servername = ""
|
gamedata.servername = ""
|
||||||
gamedata.serverdescription = ""
|
gamedata.serverdescription = ""
|
||||||
|
@ -45,6 +45,7 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
|
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
|
||||||
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
|
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
|
||||||
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
|
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
|
||||||
|
"color,span=1;" ..
|
||||||
"text,padding=1]" -- name
|
"text,padding=1]" -- name
|
||||||
else
|
else
|
||||||
retval = retval .. "tablecolumns[text]"
|
retval = retval .. "tablecolumns[text]"
|
||||||
@ -87,7 +88,6 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function main_button_handler(tabview, fields, name, tabdata)
|
local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
|
|
||||||
if fields["btn_start_singleplayer"] then
|
if fields["btn_start_singleplayer"] then
|
||||||
@ -159,6 +159,11 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
|
|
||||||
gamedata.servername = menudata.favorites[fav_idx].name
|
gamedata.servername = menudata.favorites[fav_idx].name
|
||||||
gamedata.serverdescription = menudata.favorites[fav_idx].description
|
gamedata.serverdescription = menudata.favorites[fav_idx].description
|
||||||
|
|
||||||
|
if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min,
|
||||||
|
menudata.favorites[fav_idx].proto_max) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
else
|
else
|
||||||
gamedata.servername = ""
|
gamedata.servername = ""
|
||||||
gamedata.serverdescription = ""
|
gamedata.serverdescription = ""
|
||||||
|
@ -197,9 +197,11 @@ core.delete_world(index)
|
|||||||
Helpers:
|
Helpers:
|
||||||
core.gettext(string) -> string
|
core.gettext(string) -> string
|
||||||
^ look up the translation of a string in the gettext message catalog
|
^ look up the translation of a string in the gettext message catalog
|
||||||
fgettext(string, ...) -> string
|
fgettext_ne(string, ...)
|
||||||
^ call core.gettext(string), replace "$1"..."$9" with the given
|
^ call core.gettext(string), replace "$1"..."$9" with the given
|
||||||
^ extra arguments, call core.formspec_escape and return the result
|
^ extra arguments and return the result
|
||||||
|
fgettext(string, ...) -> string
|
||||||
|
^ same as fgettext_ne(), but calls core.formspec_escape before returning result
|
||||||
core.parse_json(string[, nullvalue]) -> something (possible in async calls)
|
core.parse_json(string[, nullvalue]) -> something (possible in async calls)
|
||||||
^ see core.parse_json (lua_api.txt)
|
^ see core.parse_json (lua_api.txt)
|
||||||
dump(obj, dumped={})
|
dump(obj, dumped={})
|
||||||
@ -211,6 +213,12 @@ string:trim()
|
|||||||
core.is_yes(arg) (possible in async calls)
|
core.is_yes(arg) (possible in async calls)
|
||||||
^ returns whether arg can be interpreted as yes
|
^ returns whether arg can be interpreted as yes
|
||||||
|
|
||||||
|
Version compat:
|
||||||
|
core.get_min_supp_proto()
|
||||||
|
^ returns the minimum supported network protocol version
|
||||||
|
core.get_max_supp_proto()
|
||||||
|
^ returns the maximum supported network protocol version
|
||||||
|
|
||||||
Async:
|
Async:
|
||||||
core.handle_async(async_job,parameters,finished)
|
core.handle_async(async_job,parameters,finished)
|
||||||
^ execute a function asynchronously
|
^ execute a function asynchronously
|
||||||
|
@ -472,6 +472,7 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < servers.size(); i++)
|
for (unsigned int i = 0; i < servers.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
lua_pushnumber(L,index);
|
lua_pushnumber(L,index);
|
||||||
|
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
@ -509,6 +510,18 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
|
|||||||
lua_settable(L, top_lvl2);
|
lua_settable(L, top_lvl2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (servers[i]["proto_min"].asString().size()) {
|
||||||
|
lua_pushstring(L,"proto_min");
|
||||||
|
lua_pushinteger(L,servers[i]["proto_min"].asInt());
|
||||||
|
lua_settable(L, top_lvl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servers[i]["proto_max"].asString().size()) {
|
||||||
|
lua_pushstring(L,"proto_max");
|
||||||
|
lua_pushinteger(L,servers[i]["proto_max"].asInt());
|
||||||
|
lua_settable(L, top_lvl2);
|
||||||
|
}
|
||||||
|
|
||||||
if (servers[i]["password"].asString().size()) {
|
if (servers[i]["password"].asString().size()) {
|
||||||
lua_pushstring(L,"password");
|
lua_pushstring(L,"password");
|
||||||
lua_pushboolean(L,servers[i]["password"].asBool());
|
lua_pushboolean(L,servers[i]["password"].asBool());
|
||||||
@ -1082,6 +1095,19 @@ int ModApiMainMenu::l_get_screen_info(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int ModApiMainMenu::l_get_min_supp_proto(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, CLIENT_PROTOCOL_VERSION_MIN);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModApiMainMenu::l_get_max_supp_proto(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, CLIENT_PROTOCOL_VERSION_MAX);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
int ModApiMainMenu::l_do_async_callback(lua_State *L)
|
int ModApiMainMenu::l_do_async_callback(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -1142,6 +1168,8 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
|
|||||||
API_FCT(gettext);
|
API_FCT(gettext);
|
||||||
API_FCT(get_video_drivers);
|
API_FCT(get_video_drivers);
|
||||||
API_FCT(get_screen_info);
|
API_FCT(get_screen_info);
|
||||||
|
API_FCT(get_min_supp_proto);
|
||||||
|
API_FCT(get_max_supp_proto);
|
||||||
API_FCT(do_async_callback);
|
API_FCT(do_async_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +137,12 @@ private:
|
|||||||
|
|
||||||
static int l_get_video_drivers(lua_State *L);
|
static int l_get_video_drivers(lua_State *L);
|
||||||
|
|
||||||
|
//version compatibility
|
||||||
|
static int l_get_min_supp_proto(lua_State *L);
|
||||||
|
|
||||||
|
static int l_get_max_supp_proto(lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
// async
|
// async
|
||||||
static int l_do_async_callback(lua_State *L);
|
static int l_do_async_callback(lua_State *L);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "network/networkprotocol.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include "convert_json.h"
|
#include "convert_json.h"
|
||||||
#include "httpfetch.h"
|
#include "httpfetch.h"
|
||||||
@ -67,8 +68,11 @@ std::vector<ServerListSpec> getLocal()
|
|||||||
|
|
||||||
std::vector<ServerListSpec> getOnline()
|
std::vector<ServerListSpec> getOnline()
|
||||||
{
|
{
|
||||||
Json::Value root = fetchJsonValue(
|
std::ostringstream geturl;
|
||||||
(g_settings->get("serverlist_url") + "/list").c_str(), NULL);
|
geturl << g_settings->get("serverlist_url") <<
|
||||||
|
"/list?proto_version_min=" << CLIENT_PROTOCOL_VERSION_MIN <<
|
||||||
|
"&proto_version_max=" << CLIENT_PROTOCOL_VERSION_MAX;
|
||||||
|
Json::Value root = fetchJsonValue(geturl.str(), NULL);
|
||||||
|
|
||||||
std::vector<ServerListSpec> server_list;
|
std::vector<ServerListSpec> server_list;
|
||||||
|
|
||||||
@ -205,9 +209,12 @@ void sendAnnounce(const std::string &action,
|
|||||||
server["address"] = g_settings->get("server_address");
|
server["address"] = g_settings->get("server_address");
|
||||||
}
|
}
|
||||||
if (action != "delete") {
|
if (action != "delete") {
|
||||||
|
bool strict_checking = g_settings->getBool("strict_protocol_version_checking");
|
||||||
server["name"] = g_settings->get("server_name");
|
server["name"] = g_settings->get("server_name");
|
||||||
server["description"] = g_settings->get("server_description");
|
server["description"] = g_settings->get("server_description");
|
||||||
server["version"] = minetest_version_simple;
|
server["version"] = minetest_version_simple;
|
||||||
|
server["proto_min"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN;
|
||||||
|
server["proto_max"] = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX;
|
||||||
server["url"] = g_settings->get("server_url");
|
server["url"] = g_settings->get("server_url");
|
||||||
server["creative"] = g_settings->getBool("creative_mode");
|
server["creative"] = g_settings->getBool("creative_mode");
|
||||||
server["damage"] = g_settings->getBool("enable_damage");
|
server["damage"] = g_settings->getBool("enable_damage");
|
||||||
|
Loading…
Reference in New Issue
Block a user