ID representations#
UI handles, script component IDs and UniverseID cdata have different contracts. Establish what one call returns and the next expects. In X4 9.00 research, applying ConvertIDTo64Bit to an already numeric ID returned nil. A precautionary universal conversion is not a substitute for checking types.
Exact integer range#
A double-based Lua number cannot represent every integer above 2^53. This matters for NPCSeed and other 64-bit values. The example demonstrates LuaJIT representation, not a game call. Define a canonical storage type and encoding; do not pass exact values through tonumber when the range can exceed double precision. tostring(cdata) may contain a type suffix.
local ffi = require("ffi")
-- Синтаксис 64-битного литерала LuaJIT.
local exact = ffi.new("uint64_t", 9007199254740993ULL)
local text = tostring(exact)
-- У tostring(cdata) может быть суффикс типа.Reference lifetime#
Do not store a temporary UI handle as a permanent ship reference across loads. Resolve the object again in the current context and check existence. A name or macro is not a unique instance identifier.
Verification#
Round-trip a large seed through your real read/storage path. Include invalid and missing objects, reopening the menu and save loading. Compare original and restored values without intermediate rounding.