Browse Source

Improve `MetaDataRef:{get,set}_float` precision (#13130)

Jude Melton-Houghton 1 year ago
parent
commit
3992a13f24
2 changed files with 13 additions and 3 deletions
  1. 7 0
      games/devtest/mods/unittests/metadata.lua
  2. 6 3
      src/script/lua_api/l_metadata.cpp

+ 7 - 0
games/devtest/mods/unittests/metadata.lua

@@ -63,6 +63,13 @@ local function test_metadata(meta)
 	assert(meta:get_float("h") > 1)
 	assert(meta:get_string("i") == "${f}")
 
+	meta:set_float("j", 1.23456789)
+	assert(meta:get_float("j") == 1.23456789)
+	meta:set_float("j", -1 / 0)
+	assert(meta:get_float("j") == -1 / 0)
+	meta:set_float("j", 0 / 0)
+	assert(core.is_nan(meta:get_float("j")))
+
 	meta:from_table()
 	assert(next(meta:to_table().fields) == nil)
 	assert(#meta:get_keys() == 0)

+ 6 - 3
src/script/lua_api/l_metadata.cpp

@@ -177,7 +177,9 @@ int MetaDataRef::l_get_float(lua_State *L)
 
 	std::string str_;
 	const std::string &str = meta->getString(name, &str_);
-	lua_pushnumber(L, stof(str));
+	// Convert with Lua, as is done in set_float.
+	lua_pushlstring(L, str.data(), str.size());
+	lua_pushnumber(L, lua_tonumber(L, -1));
 	return 1;
 }
 
@@ -188,8 +190,9 @@ int MetaDataRef::l_set_float(lua_State *L)
 
 	MetaDataRef *ref = checkAnyMetadata(L, 1);
 	std::string name = luaL_checkstring(L, 2);
-	float a = readParam<float>(L, 3);
-	std::string str = ftos(a);
+	luaL_checknumber(L, 3);
+	// Convert number to string with Lua as it gives good precision.
+	std::string str = readParam<std::string>(L, 3);
 
 	IMetadata *meta = ref->getmeta(true);
 	if (meta != NULL && meta->setString(name, str))