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

Expose client version information in non-debug builds (#15708)

Co-authored-by: SmallJoker <SmallJoker@users.noreply.github.com>
Co-authored-by: Lars Mueller <appgurulars@gmx.de>
Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
ROllerozxa 2025-02-09 18:09:07 +01:00 committed by GitHub
parent e6cf08169e
commit dd0070a6b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 95 additions and 24 deletions

View file

@ -112,3 +112,25 @@ if core.set_push_moveresult1 then
end) end)
core.set_push_moveresult1 = nil core.set_push_moveresult1 = nil
end end
-- Protocol version table
-- see also src/network/networkprotocol.cpp
core.protocol_versions = {
["5.0.0"] = 37,
["5.1.0"] = 38,
["5.2.0"] = 39,
["5.3.0"] = 39,
["5.4.0"] = 39,
["5.5.0"] = 40,
["5.6.0"] = 41,
["5.7.0"] = 42,
["5.8.0"] = 43,
["5.9.0"] = 44,
["5.9.1"] = 45,
["5.10.0"] = 46,
["5.11.0"] = 47,
}
setmetatable(core.protocol_versions, {__newindex = function()
error("core.protocol_versions is read-only")
end})

View file

@ -5578,7 +5578,7 @@ Utilities
* It's possible that multiple Luanti instances are running at the same * It's possible that multiple Luanti instances are running at the same
time, which may lead to corruption if you are not careful. time, which may lead to corruption if you are not careful.
* `core.is_singleplayer()` * `core.is_singleplayer()`
* `core.features`: Table containing API feature flags * `core.features`: Table containing *server-side* API feature flags
```lua ```lua
{ {
@ -5693,6 +5693,7 @@ Utilities
``` ```
* `core.has_feature(arg)`: returns `boolean, missing_features` * `core.has_feature(arg)`: returns `boolean, missing_features`
* checks for *server-side* feature availability
* `arg`: string or table in format `{foo=true, bar=true}` * `arg`: string or table in format `{foo=true, bar=true}`
* `missing_features`: `{foo=true, bar=true}` * `missing_features`: `{foo=true, bar=true}`
* `core.get_player_information(player_name)`: Table containing information * `core.get_player_information(player_name)`: Table containing information
@ -5714,17 +5715,40 @@ Utilities
min_jitter = 0.01, -- minimum packet time jitter min_jitter = 0.01, -- minimum packet time jitter
max_jitter = 0.5, -- maximum packet time jitter max_jitter = 0.5, -- maximum packet time jitter
avg_jitter = 0.03, -- average packet time jitter avg_jitter = 0.03, -- average packet time jitter
-- The version information is provided by the client and may be spoofed
-- or inconsistent in engine forks. You must not use this for checking
-- feature availability of clients. Instead, do use the fields
-- `protocol_version` and `formspec_version` where it matters.
-- Use `core.protocol_versions` to map Luanti versions to protocol versions.
-- This version string is only suitable for analysis purposes.
version_string = "0.4.9-git", -- full version string
-- the following information is available in a debug build only!!! -- the following information is available in a debug build only!!!
-- DO NOT USE IN MODS -- DO NOT USE IN MODS
--serialization_version = 26, -- serialization version used by client --serialization_version = 26, -- serialization version used by client
--major = 0, -- major version number --major = 0, -- major version number
--minor = 4, -- minor version number --minor = 4, -- minor version number
--patch = 10, -- patch version number --patch = 10, -- patch version number
--version_string = "0.4.9-git", -- full version string
--state = "Active" -- current client state --state = "Active" -- current client state
} }
``` ```
* `core.protocol_versions`:
* Table mapping Luanti versions to corresponding protocol versions for modder convenience.
* For example, to check whether a client has at least the feature set
of Luanti 5.8.0 or newer, you could do:
`core.get_player_information(player_name).protocol_version >= core.protocol_versions["5.8.0"]`
* (available since 5.11)
```lua
{
[version string] = protocol version at time of release
-- every major and minor version has an entry
-- patch versions only for the first release whose protocol version is not already present in the table
}
```
* `core.get_player_window_information(player_name)`: * `core.get_player_window_information(player_name)`:
```lua ```lua

View file

@ -31,7 +31,7 @@ read_globals = {
"PcgRandom", "PcgRandom",
string = {fields = {"split", "trim"}}, string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn", "indexof", "insert_all"}}, table = {fields = {"copy", "getn", "indexof", "insert_all", "key_value_swap"}},
math = {fields = {"hypot", "round"}}, math = {fields = {"hypot", "round"}},
} }

View file

@ -1,16 +0,0 @@
unittests.register("test_get_version", function()
local version = core.get_version()
assert(type(version) == "table")
assert(type(version.project) == "string")
assert(type(version.string) == "string")
assert(type(version.proto_min) == "number")
assert(type(version.proto_max) == "number")
assert(version.proto_max >= version.proto_min)
assert(type(version.is_dev) == "boolean")
if version.is_dev then
assert(type(version.hash) == "string")
else
assert(version.hash == nil)
end
end)

View file

@ -192,7 +192,7 @@ dofile(modpath .. "/crafting.lua")
dofile(modpath .. "/itemdescription.lua") dofile(modpath .. "/itemdescription.lua")
dofile(modpath .. "/async_env.lua") dofile(modpath .. "/async_env.lua")
dofile(modpath .. "/entity.lua") dofile(modpath .. "/entity.lua")
dofile(modpath .. "/get_version.lua") dofile(modpath .. "/version.lua")
dofile(modpath .. "/itemstack_equals.lua") dofile(modpath .. "/itemstack_equals.lua")
dofile(modpath .. "/content_ids.lua") dofile(modpath .. "/content_ids.lua")
dofile(modpath .. "/metadata.lua") dofile(modpath .. "/metadata.lua")

View file

@ -0,0 +1,40 @@
unittests.register("test_get_version", function()
local version = core.get_version()
assert(type(version) == "table")
assert(type(version.project) == "string")
assert(type(version.string) == "string")
assert(type(version.proto_min) == "number")
assert(type(version.proto_max) == "number")
assert(version.proto_max >= version.proto_min)
assert(type(version.is_dev) == "boolean")
if version.is_dev then
assert(type(version.hash) == "string")
else
assert(version.hash == nil)
end
end)
unittests.register("test_protocol_version", function(player)
local info = core.get_player_information(player:get_player_name())
local maxver = 0
for _, v in pairs(core.protocol_versions) do
maxver = math.max(maxver, v)
end
assert(maxver > 0) -- table must contain something valid
-- If the client is older than a known version then it's pointless.
if info.protocol_version < maxver then
core.log("warning", "test_protocol_version: client is outdated, skipping test!")
return
end
local info_server = core.get_version()
if info.version_string ~= (info_server.hash or info_server.string) then
core.log("warning", "test_protocol_version: client is not the same version. False-positive possible.")
end
-- The protocol version the client and server agreed on must exist in the table.
local match = table.key_value_swap(core.protocol_versions)[info.protocol_version]
assert(match ~= nil)
print(string.format("client proto matched: %s sent: %s", match, info.version_string))
end, {player = true})

View file

@ -64,6 +64,7 @@
[scheduled bump for 5.11.0] [scheduled bump for 5.11.0]
*/ */
// Note: Also update core.protocol_versions in builtin when bumping
const u16 LATEST_PROTOCOL_VERSION = 47; const u16 LATEST_PROTOCOL_VERSION = 47;
// See also formspec [Version History] in doc/lua_api.md // See also formspec [Version History] in doc/lua_api.md

View file

@ -239,6 +239,10 @@ int ModApiServer::l_get_player_information(lua_State *L)
lua_pushstring(L, info.lang_code.c_str()); lua_pushstring(L, info.lang_code.c_str());
lua_settable(L, table); lua_settable(L, table);
lua_pushstring(L, "version_string");
lua_pushstring(L, info.vers_string.c_str());
lua_settable(L, table);
#ifndef NDEBUG #ifndef NDEBUG
lua_pushstring(L,"serialization_version"); lua_pushstring(L,"serialization_version");
lua_pushnumber(L, info.ser_vers); lua_pushnumber(L, info.ser_vers);
@ -256,10 +260,6 @@ int ModApiServer::l_get_player_information(lua_State *L)
lua_pushnumber(L, info.patch); lua_pushnumber(L, info.patch);
lua_settable(L, table); lua_settable(L, table);
lua_pushstring(L,"version_string");
lua_pushstring(L, info.vers_string.c_str());
lua_settable(L, table);
lua_pushstring(L,"state"); lua_pushstring(L,"state");
lua_pushstring(L, ClientInterface::state2Name(info.state).c_str()); lua_pushstring(L, ClientInterface::state2Name(info.state).c_str());
lua_settable(L, table); lua_settable(L, table);