From 29f5373d81853a1ac1397d0e07484978fa117100 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Wed, 22 Jul 2026 20:36:01 +1000 Subject: [PATCH 01/30] added bytearray view wrapper for float (float32) --- res/modules/internal/bytearray.lua | 2 ++ res/scripts/stdmin.lua | 1 + 2 files changed, 3 insertions(+) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 58b33a520..a90595979 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -305,6 +305,7 @@ local FFII16view = create_FFIview_class("FFII16view", "int16_t", 2) local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t", 2) local FFII32view = create_FFIview_class("FFII32view", "int32_t", 4) local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t", 4) +local FFIF32view = create_FFIview_class("FFIF32view", "float", 4) return { FFIBytearray = setmetatable(FFIBytearray, FFIBytearray), @@ -314,4 +315,5 @@ return { FFII16view = FFII16view, FFIU32view = FFIU32view, FFII32view = FFII32view, + FFIF32view = FFIF32view, } diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 2868dd634..01b61efc6 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -314,6 +314,7 @@ U16view = bytearray.FFIU16view I16view = bytearray.FFII16view U32view = bytearray.FFIU32view I32view = bytearray.FFII32view +F32view = bytearray.FFIF32view Bytearray_construct = function(...) return Bytearray(...) end bit.compile = require "core:bitwise/compiler" From 27bb3015e4793e21f27a40476b832ab0548a2eb7 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Thu, 23 Jul 2026 17:08:32 +1000 Subject: [PATCH 02/30] improved bytearray --- res/modules/internal/bytearray.lua | 102 ++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 32 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index a90595979..f7cab06d9 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -4,6 +4,7 @@ local FFI = ffi FFI.cdef[[ void* malloc(size_t); + void *realloc(void *, size_t); void free(void*); typedef struct { unsigned char* bytes; @@ -22,12 +23,33 @@ local GC_THRESHOLD = 50 * 1024 * 1024 local function malloc(size) local raw = FFI.C.malloc(size) - if raw == nil then - return nil + if not raw then + error("failed memory allocation of " .. size .. " bytes") end allocated_bytes = allocated_bytes + size + if allocated_bytes >= GC_THRESHOLD then + collectgarbage("step", 200) + allocated_bytes = 0 + end + return raw +end + +local function realloc(buff, size, throwerror) + if throwerror == nil then throwerror = true end + + if size <= 0 then + free(buff) + return + end + + local raw = FFI.C.realloc(buff, size) + if not raw and throwerror then + error("failed memory reallocation of block " .. buff .. " to new size " .. size) + end + + allocated_bytes = allocated_bytes + size if allocated_bytes >= GC_THRESHOLD then collectgarbage("step", 200) allocated_bytes = 0 @@ -38,23 +60,17 @@ end local function grow_buffer(self, elems) local new_capacity = math.ceil(self.capacity / 0.75 + elems) - local prev = self.bytes - self.bytes = malloc(new_capacity) - FFI.copy(self.bytes, prev, self.size) + self.bytes = realloc(self.bytes, new_capacity) self.capacity = new_capacity - free(prev) end local function trim_buffer(self) - if self.size == self.capacity then - return + if self.size == self.capacity then return end + local new_bytes = realloc(self.bytes, self.size, false) + if new_bytes then + self.bytes = new_bytes + self.capacity = self.size end - local size = self.size - local prev = self.bytes - self.bytes = malloc(size) - FFI.copy(self.bytes, prev, self.size) - self.capacity = size - free(prev) end local function count_elements(b) @@ -125,15 +141,16 @@ local function clear(self) self.size = 0 end -local function reserve(self, new_capacity) - if new_capacity <= self.capacity then - return +local function fill(self, byte) + if self.size > 0 then + FFI.fill(self.bytes, self.size, byte) end - local prev = self.bytes - self.bytes = malloc(new_capacity) - FFI.copy(self.bytes, prev, self.size) +end + +local function reserve(self, new_capacity) + if new_capacity <= self.capacity then return end + self.bytes = realloc(self.bytes, new_capacity) self.capacity = new_capacity - free(prev) end local function get_capacity(self) @@ -150,22 +167,43 @@ local function slice(self, offset, length) length = self.size - offset + 1 end local buffer = malloc(length) - if not buffer then - error("malloc(" .. length .. ") returned NULL") - end FFI.copy(buffer, self.bytes + (offset - 1), length) return bytearray_type(buffer, length, length) end +local function copy(self, srcindex, dst, dstindex, size) + if srcindex > 0 and dstindex > 0 and size > 0 and + srcindex + size - 1 <= self.size and + dstindex + size - 1 <= dst.size + then + FFI.copy(dst.bytes + dstindex - 1, self.bytes + srcindex - 1, size) + end +end + +local function move(self, fromindex, toindex, size) + if fromindex > 0 and toindex > 0 and size > 0 and + fromindex + size - 1 <= self.size and + toindex + size - 1 <= self.size + then + local buff = malloc(size) + FFI.copy(buff, self.bytes + fromindex - 1, size) + FFI.copy(self.bytes + toindex - 1, buff, size) + free(buff) + end +end + local bytearray_methods = { - append=append, - insert=insert, - remove=remove, - trim=trim_buffer, - clear=clear, - reserve=reserve, - get_capacity=get_capacity, - slice=slice, + append = append, + insert = insert, + remove = remove, + trim = trim_buffer, + clear = clear, + reserve = reserve, + get_capacity = get_capacity, + slice = slice, + fill = fill, + copy = copy, + move = move } local bytearray_mt = { From 0d641fa82fe3f16773a9cf643f38b12b32ee3caa Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Thu, 23 Jul 2026 17:47:32 +1000 Subject: [PATCH 03/30] (i hope that correctry) optimized bytearray:move method --- res/modules/internal/bytearray.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index f7cab06d9..04212d3e1 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -185,10 +185,15 @@ local function move(self, fromindex, toindex, size) fromindex + size - 1 <= self.size and toindex + size - 1 <= self.size then - local buff = malloc(size) - FFI.copy(buff, self.bytes + fromindex - 1, size) - FFI.copy(self.bytes + toindex - 1, buff, size) - free(buff) + if toindex >= fromindex and toindex < fromindex + size then + local buff = malloc(size) + FFI.copy(buff, self.bytes + fromindex - 1, size) + FFI.copy(self.bytes + toindex - 1, buff, size) + free(buff) + else + -- убери(-те) это ветвление, если FFI будет производить копирование не побайтово, и оставь(-те) только верхний блок без условия вообще. + FFI.copy(self.bytes + toindex - 1, self.bytes + fromindex - 1, size) + end end end From 67da57d8708375b05865b714db8e1e560b6546c3 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Thu, 23 Jul 2026 19:29:19 +1000 Subject: [PATCH 04/30] upgraded/improved LuaCanvas::clear method --- .../scripting/lua/usertypes/lua_type_canvas.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp b/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp index c670e23df..d03b4e855 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp @@ -161,18 +161,11 @@ static LuaCanvas& require_canvas(State* L, int idx) { static int l_clear(State* L) { auto& canvas = require_canvas(L, 1); auto& image = canvas.getData(); - ubyte* data = image.getData(); - RGBA rgba {}; - if (gettop(L) == 1) { - std::fill(data, data + image.getDataSize(), 0); - return 0; - } - rgba = get_rgba(L, 2); - size_t pixels = image.getWidth() * image.getHeight(); - const size_t channels = 4; - for (size_t i = 0; i < pixels * channels; i++) { - data[i] = rgba.arr[i % channels]; - } + size_t pixelscount = image.getWidth() * image.getHeight(); + uint32_t* data = reinterpret_cast(image.getData()); + + if (gettop(L) == 1) std::fill(data, data + pixelscount, 0); + else std::fill(data, data + pixelscount, get_rgba(L, 2).rgba); return 0; } From 2eae8f6f275e7a41ac30309e61f8d22d8a644ac7 Mon Sep 17 00:00:00 2001 From: EsPaKira Date: Sun, 2 Aug 2026 19:18:37 +0400 Subject: [PATCH 05/30] fix block.index() calls in grass_block.lua and export base:util.calc_loot() --- res/content/base/modules/util.lua | 6 +++--- res/content/base/scripts/grass_block.lua | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/res/content/base/modules/util.lua b/res/content/base/modules/util.lua index b1a97ad06..1044eb394 100644 --- a/res/content/base/modules/util.lua +++ b/res/content/base/modules/util.lua @@ -12,14 +12,14 @@ function util.drop(ppos, itemid, count, data, pickup_delay) }}) end -local function calc_loot(loot_table) +function calc_loot(loot_table) local results = {} for _, loot in ipairs(loot_table) do local chance = loot.chance or 1 local count = loot.count or 1 - + local roll = math.random() - + if roll < chance then if loot.min and loot.max then count = math.random(loot.min, loot.max) diff --git a/res/content/base/scripts/grass_block.lua b/res/content/base/scripts/grass_block.lua index fb7482c20..b5965de43 100644 --- a/res/content/base/scripts/grass_block.lua +++ b/res/content/base/scripts/grass_block.lua @@ -1,3 +1,6 @@ +local dirtid = block.index("base:dirt") +local grass_blockid = block.index("base:grass_block") + local offsets = {} for lx=-1,1 do for ly=-1,1 do @@ -8,18 +11,17 @@ for lx=-1,1 do end function on_random_update(x, y, z) - local dirtid = block.index('base:dirt'); if block.is_solid_at(x, y+1, z) then block.set(x, y, z, dirtid, 0) return end - local grassblockid = block.index('base:grass_block') + for _, offset in ipairs(offsets) do local nx, ny, nz = x + offset[1], y + offset[2], z + offset[3] if block.get(nx, ny, nz) == dirtid and not block.is_solid_at(nx, ny + 1, nz) then - block.set(nx, ny, nz, grassblockid, 0) + block.set(nx, ny, nz, grass_blockid, 0) return end end From 9444dc0c4596bd0c1fd2710488c8d412da8aab1f Mon Sep 17 00:00:00 2001 From: EsPaKira Date: Sun, 2 Aug 2026 20:02:56 +0400 Subject: [PATCH 06/30] fix lua version compare --- res/layouts/pages/content.xml.lua | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/res/layouts/pages/content.xml.lua b/res/layouts/pages/content.xml.lua index cb63a96c7..70b5a486c 100644 --- a/res/layouts/pages/content.xml.lua +++ b/res/layouts/pages/content.xml.lua @@ -179,7 +179,7 @@ function place_pack(panel, packinfo, callback, position_func) end end -local Version = {}; +local Version = {} function Version.matches_pattern(version) for _, letter in string.gmatch(version, "%.+") do @@ -187,32 +187,32 @@ function Version.matches_pattern(version) return false; end - local t = string.split(version, "."); + local t = string.split(version, ".") return #t == 2 or #t == 3; end end function Version.__equal(ver1, ver2) - return ver1[1] == ver2[1] and ver1[2] == ver2[2] and ver1[3] == ver2[3]; + return ver1[1] == ver2[1] and ver1[2] == ver2[2] and ver1[3] == ver2[3] end function Version.__greater(ver1, ver2) - if ver1[1] ~= ver2[1] then return ver1[1] > ver2[1] end; - if ver1[2] ~= ver2[2] then return ver1[2] > ver2[2] end; - return ver1[3] > ver2[3]; + if ver1[1] ~= ver2[1] then return ver1[1] > ver2[1] end + if ver1[2] ~= ver2[2] then return ver1[2] > ver2[2] end + return ver1[3] > ver2[3] end function Version.__less(ver1, ver2) - return Version.__greater(ver2, ver1); + return Version.__greater(ver2, ver1) end function Version.__greater_or_equal(ver1, ver2) - return not Version.__less(ver1, ver2); + return not Version.__less(ver1, ver2) end function Version.__less_or_equal(ver1, ver2) - return not Version.__greater(ver1, ver2); + return not Version.__greater(ver1, ver2) end Version.operators = { @@ -224,8 +224,8 @@ Version.operators = { } function Version.compare(op, ver1, ver2) - ver1 = string.split(ver1, "."); - ver2 = string.split(ver2, "."); + ver1 = string.split(ver1, ".") + ver2 = string.split(ver2, ".") local comparison_func = Version.operators[op]; @@ -237,14 +237,14 @@ function Version.compare(op, ver1, ver2) end function Version.parse(version) - local op = string.sub(version, 1, 2); + local op = string.sub(version, 1, 2) if op == ">=" or op == "<=" then - return op, string.sub(version, #op + 1); + return op, string.sub(version, #op + 1) end op = string.sub(version, 1, 1); if op == ">" or op == "<" then - return op, string.sub(version, #op + 1); + return op, string.sub(version, #op + 1) end return "=", version; @@ -252,12 +252,12 @@ end local function compare_version(dependent_version, actual_version) if Version.matches_pattern(dependent_version) and Version.matches_pattern(actual_version) then - local op, dep_ver = Version.parse_version(dependent_version); - Version.compare(op, dep_ver, actual_version); + local op, dep_ver = Version.parse_version(dependent_version) + Version.compare(op, dep_ver, actual_version) elseif dependent_version == "*" or dependent_version == actual_version then - return true; + return true else - return false; + return false end end @@ -277,15 +277,15 @@ function check_dependencies(packinfo) ) end - local dep_pack = pack.get_info(depid); - + local dep_pack = pack.get_info(depid) + local op, ver = Version.parse(depver) + if not compare_version(depver, dep_pack.version) then - local op, ver = Version.parse(depver) return string.format( "%s: %s != %s (%s)", gui.str("error.dependency-version-not-met"), dep_pack.version, ver, depid - ); + ) end if table.has(packs_installed, packinfo.id) then From 4be73acc61f6805c9df2743e68a86ee646d43e25 Mon Sep 17 00:00:00 2001 From: EsPaKira Date: Sun, 2 Aug 2026 21:07:02 +0400 Subject: [PATCH 07/30] fix fix lua version comparision --- res/layouts/pages/content.xml.lua | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/res/layouts/pages/content.xml.lua b/res/layouts/pages/content.xml.lua index 70b5a486c..6d684b130 100644 --- a/res/layouts/pages/content.xml.lua +++ b/res/layouts/pages/content.xml.lua @@ -182,15 +182,15 @@ end local Version = {} function Version.matches_pattern(version) - for _, letter in string.gmatch(version, "%.+") do - if type(letter) ~= "number" or letter ~= "." then - return false; - end + local t = string.split(version, ".") + if #t ~= 2 and #t ~= 3 then return false end - local t = string.split(version, ".") - - return #t == 2 or #t == 3; + for i = 1, #t do + local matched = string.match(t[i], "^%d+$") + if not matched then return false end end + + return true end function Version.__equal(ver1, ver2) @@ -208,7 +208,7 @@ function Version.__less(ver1, ver2) end function Version.__greater_or_equal(ver1, ver2) - return not Version.__less(ver1, ver2) + return not Version.__less(ver2, ver1) end function Version.__less_or_equal(ver1, ver2) @@ -230,9 +230,9 @@ function Version.compare(op, ver1, ver2) local comparison_func = Version.operators[op]; if comparison_func then - return comparison_func(ver1, ver2); + return comparison_func(ver1, ver2) else - return false; + return false end end @@ -247,13 +247,12 @@ function Version.parse(version) return op, string.sub(version, #op + 1) end - return "=", version; + return "=", version end -local function compare_version(dependent_version, actual_version) +local function compare_version(op, dependent_version, actual_version) if Version.matches_pattern(dependent_version) and Version.matches_pattern(actual_version) then - local op, dep_ver = Version.parse_version(dependent_version) - Version.compare(op, dep_ver, actual_version) + return Version.compare(op, dep_ver, actual_version) elseif dependent_version == "*" or dependent_version == actual_version then return true else @@ -280,7 +279,7 @@ function check_dependencies(packinfo) local dep_pack = pack.get_info(depid) local op, ver = Version.parse(depver) - if not compare_version(depver, dep_pack.version) then + if not compare_version(op, ver, dep_pack.version) then return string.format( "%s: %s != %s (%s)", gui.str("error.dependency-version-not-met"), From 74cefdafbd1168f0ca678941322bdf62aa55e881 Mon Sep 17 00:00:00 2001 From: EsPaKira Date: Sun, 2 Aug 2026 21:39:33 +0400 Subject: [PATCH 08/30] fix calc_loot export --- res/content/base/modules/util.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/content/base/modules/util.lua b/res/content/base/modules/util.lua index 1044eb394..2f53ba6be 100644 --- a/res/content/base/modules/util.lua +++ b/res/content/base/modules/util.lua @@ -12,7 +12,7 @@ function util.drop(ppos, itemid, count, data, pickup_delay) }}) end -function calc_loot(loot_table) +function util.calc_loot(loot_table) local results = {} for _, loot in ipairs(loot_table) do local chance = loot.chance or 1 From a422ea1534f9bb47f0d48d16d6e7a450e9f00e16 Mon Sep 17 00:00:00 2001 From: EsPaKira Date: Sun, 2 Aug 2026 21:43:10 +0400 Subject: [PATCH 09/30] fix util --- res/content/base/modules/util.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/content/base/modules/util.lua b/res/content/base/modules/util.lua index 2f53ba6be..874e6d3d6 100644 --- a/res/content/base/modules/util.lua +++ b/res/content/base/modules/util.lua @@ -37,7 +37,7 @@ end function util.block_loot(blockid) local lootscheme = block.properties[blockid]["base:loot"] if lootscheme then - return calc_loot(lootscheme) + return util.calc_loot(lootscheme) end return {{item=block.get_picking_item(blockid), count=1}} end From f8a44c023f563f2adc511356a1e7865a20b9ab7b Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Mon, 3 Aug 2026 18:25:44 +1000 Subject: [PATCH 10/30] patched code after code review from MihailRis --- res/modules/internal/bytearray.lua | 37 +++++++++---------- .../lua/usertypes/lua_type_canvas.cpp | 7 +++- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 04212d3e1..1615d1a08 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -4,13 +4,14 @@ local FFI = ffi FFI.cdef[[ void* malloc(size_t); - void *realloc(void *, size_t); + void* realloc(void*, size_t); void free(void*); typedef struct { unsigned char* bytes; int size; int capacity; } bytearray_t; + void* memmove(void*, const void*, size_t); ]] local free = FFI.C.free @@ -172,29 +173,27 @@ local function slice(self, offset, length) end local function copy(self, srcindex, dst, dstindex, size) - if srcindex > 0 and dstindex > 0 and size > 0 and - srcindex + size - 1 <= self.size and - dstindex + size - 1 <= dst.size - then - FFI.copy(dst.bytes + dstindex - 1, self.bytes + srcindex - 1, size) + if size <= 0 then error("size of byte range must be positive non-zero integer") end + if srcindex < 1 or srcindex + size - 1 > self.size then + error("specified source byte range is out of source array bounds") end + if dstindex < 1 or dstindex + size - 1 > dst.size then + error("specified destination byte range is out of destination array bounds") + end + + FFI.copy(dst.bytes + dstindex - 1, self.bytes + srcindex - 1, size) end local function move(self, fromindex, toindex, size) - if fromindex > 0 and toindex > 0 and size > 0 and - fromindex + size - 1 <= self.size and - toindex + size - 1 <= self.size - then - if toindex >= fromindex and toindex < fromindex + size then - local buff = malloc(size) - FFI.copy(buff, self.bytes + fromindex - 1, size) - FFI.copy(self.bytes + toindex - 1, buff, size) - free(buff) - else - -- убери(-те) это ветвление, если FFI будет производить копирование не побайтово, и оставь(-те) только верхний блок без условия вообще. - FFI.copy(self.bytes + toindex - 1, self.bytes + fromindex - 1, size) - end + if size <= 0 then error("size of byte range must be positive non-zero integer") end + if fromindex < 1 or fromindex + size - 1 > self.size then + error("specified source byte range is out of array bounds") end + if toindex < 1 or toindex + size - 1 > self.size then + error("specified destination byte range is out of array bounds") + end + + FFI.C.memmove(self.bytes + self.toindex - 1, self.bytes + self.fromindex - 1, size) end local bytearray_methods = { diff --git a/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp b/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp index d03b4e855..928515e74 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp @@ -164,8 +164,11 @@ static int l_clear(State* L) { size_t pixelscount = image.getWidth() * image.getHeight(); uint32_t* data = reinterpret_cast(image.getData()); - if (gettop(L) == 1) std::fill(data, data + pixelscount, 0); - else std::fill(data, data + pixelscount, get_rgba(L, 2).rgba); + if (gettop(L) == 1) { + std::fill(data, data + pixelscount, 0); + } else { + std::fill(data, data + pixelscount, get_rgba(L, 2).rgba); + } return 0; } From 3eac247a6918398e6bbf92278d615eff8836c8d6 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Mon, 3 Aug 2026 22:09:11 +1000 Subject: [PATCH 11/30] eliminated hardcoded types sizes in bytearray-viewers declaratons and replaced on usage ffi.sizeof function --- res/modules/internal/bytearray.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 1615d1a08..d58839f15 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -298,7 +298,8 @@ local function FFIBytearray_as_string(bytes) end end -local function create_FFIview_class(name, typename, typesize) +local function create_FFIview_class(name, typename) + local typesize = FFI.sizeof(typename) local ptrtype = typename .. "*" local FFIview_mt = { __index = function(self, key) @@ -343,11 +344,11 @@ local function create_FFIview_class(name, typename, typesize) end end -local FFII16view = create_FFIview_class("FFII16view", "int16_t", 2) -local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t", 2) -local FFII32view = create_FFIview_class("FFII32view", "int32_t", 4) -local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t", 4) -local FFIF32view = create_FFIview_class("FFIF32view", "float", 4) +local FFII16view = create_FFIview_class("FFII16view", "int16_t") +local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t") +local FFII32view = create_FFIview_class("FFII32view", "int32_t") +local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t") +local FFIF32view = create_FFIview_class("FFIF32view", "float") return { FFIBytearray = setmetatable(FFIBytearray, FFIBytearray), From 2c72d33485fd38b5b69b8d9f80bb1bd53f1b720f Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Mon, 3 Aug 2026 22:45:48 +1000 Subject: [PATCH 12/30] improved Bytearray:fill method --- res/modules/internal/bytearray.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index d58839f15..586fa8e25 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -142,8 +142,13 @@ local function clear(self) self.size = 0 end -local function fill(self, byte) - if self.size > 0 then +local function fill(self, index, size, byte) + if index ~= nil and size ~= nil and size > 0 then + if index < 1 or index + size - 1 > self.size then + error("selected fill range is out of array bounds") + end + FFI.fill(self.bytes + index - 1, size, byte) + else FFI.fill(self.bytes, self.size, byte) end end From 5a0f63061ffc866052fa7f0d0bd190987ab447ed Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Mon, 3 Aug 2026 23:41:57 +1000 Subject: [PATCH 13/30] added & upgraded Russian docs for new bytearray functions, new bytearray views (viewers) and other features --- doc/ru/scripting/bytearray.md | 37 ++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/doc/ru/scripting/bytearray.md b/doc/ru/scripting/bytearray.md index c90b6d67e..138eed347 100644 --- a/doc/ru/scripting/bytearray.md +++ b/doc/ru/scripting/bytearray.md @@ -22,11 +22,31 @@ bytes:insert(index: int, value: int) -- Удаляет элемент(ы), если передан `count`, удалит `count` кол-во элементов с выбранного индекса. bytes:remove(index: int, [опционально] count: int) --- Очищает массив +-- Очищает массив. bytes:clear() +--[[ +Заполняет массив определённым байтом полностью либо в определённом диапазоне. +Логика работы следующая: если параметр size или index равны nil, то указанным байтом будет заполнен весь массив, + иначе будет заполнен диапазон внутри массива начиная с индекса index и размером size. +В случае выхода заполняемого блока за границы массива генерирует соответствующую ошибку. +]] +bytes:fill(index: posint/nil, size: posint/nil, byte: uint8) + -- Создаёт новый Bytearray, содержащий копию части данных с offset до offset+length bytes:slice(offset: int, length: int) -> Bytearray + +--[[ +Копирует блок байт из исходного массива, начиная с индекса srcindex, в массив dst, начиная в нём с индекса dstindex. +В случае выхода за границы исходного, конечного массива, либо при некорректном значении параметра size генерирует соответствующую ошибку. +]] +bytes:copy(srcindex: posint, dst: Bytearray, dstindex: posint, size: posint) + +--[[ +Безопасно копирует перекрывающиеся области памяти (байт) в пределах одного массива. +В случае выхода за пределы массива начального или конечного диапазона байт генерирует соответствующую ошибку. +]] +bytes:move(fromindex: posint, toindex: posint, size: posint) ``` ## View @@ -35,12 +55,15 @@ bytes:slice(offset: int, length: int) -> Bytearray Не имеет своих методов, является просто объектной ссылкой на оригинальный Bytearray. -| Класс | Тип элементов | Размер | -| ------------ | ------------------ | ------- | -| `I16view` | `int16_t` | 2 байта | -| `U16view` | `uint16_t` | 2 байта | -| `I32view` | `int32_t` | 4 байта | -| `U32view` | `uint32_t` | 4 байта | +| Класс | Тип элементов | Размер* | +| ------------ | ------------------ | -------- | +| `I16view` | `int16_t` | 2 байта | +| `U16view` | `uint16_t` | 2 байта | +| `I32view` | `int32_t` | 4 байта | +| `U32view` | `uint32_t` | 4 байта | +| `F32view` | `float` | 4 байта | + +* Размеры C-шных типов являются платформозависимыми. В данной таблице предоставлены наиболее распространённые размеры типов. --- From 7c9fff19e457e4d53d7bc68cb8d871ade80fb716 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 3 Aug 2026 19:54:54 +0300 Subject: [PATCH 14/30] add '--log' command line parameter --- src/engine/CoreParameters.hpp | 1 + src/main.cpp | 10 +++++++++- src/util/command_line.cpp | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/engine/CoreParameters.hpp b/src/engine/CoreParameters.hpp index b5d8074ce..9668ce1cd 100644 --- a/src/engine/CoreParameters.hpp +++ b/src/engine/CoreParameters.hpp @@ -12,6 +12,7 @@ struct CoreParameters { std::filesystem::path userFolder = "."; std::filesystem::path scriptFile; std::filesystem::path projectFolder; + std::filesystem::path logFile; std::string debugServerString; int tps = 20; int subProcessDepth = 0; diff --git a/src/main.cpp b/src/main.cpp index 402b829b3..4e739acde 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include #include +using namespace std::literals; static debug::Logger logger("main"); static void sigterm_handler(int signum) { @@ -36,7 +37,14 @@ int main(int argc, char** argv) { #ifdef NDEBUG std::signal(SIGINT, sigterm_handler); #endif - debug::Logger::init(coreParameters.userFolder.string() + "/latest.log"); + std::filesystem::path logFile = coreParameters.logFile; + if (logFile.empty()) { + logFile = coreParameters.userFolder.string() + "/latest"s + + (coreParameters.subProcessDepth > 0 + ? ".sub" + std::to_string(coreParameters.subProcessDepth) + : "") + ".log"s; + } + debug::Logger::init(logFile); platform::configure_encoding(); auto& engine = Engine::getInstance(); diff --git a/src/util/command_line.cpp b/src/util/command_line.cpp index f05231821..d5435e955 100644 --- a/src/util/command_line.cpp +++ b/src/util/command_line.cpp @@ -82,6 +82,10 @@ static bool perform_keyword( params.subProcessDepth = reader.nextInt(); return true; }, "", "sub-process depth"), + ArgC("--log", [](auto& params, auto& reader) -> bool { + params.logFile = reader.next(); + return true; + }, "", "target log file"), ArgC("--help", [](auto&, auto&) -> bool { std::cout << "VoxelCore v" << ENGINE_VERSION_STRING << "\n\n"; std::cout << "Command-line arguments:\n"; From 48a09b10be84880b3d6e9d53687d40f521d7deca Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 3 Aug 2026 20:02:30 +0300 Subject: [PATCH 15/30] update platform::new_engine_instance --- src/logic/scripting/lua/libs/libapp.cpp | 9 ++++----- src/util/platform.cpp | 9 +++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/logic/scripting/lua/libs/libapp.cpp b/src/logic/scripting/lua/libs/libapp.cpp index 9157b33a6..4885915ad 100644 --- a/src/logic/scripting/lua/libs/libapp.cpp +++ b/src/logic/scripting/lua/libs/libapp.cpp @@ -403,6 +403,7 @@ static int l_start_background_instance(lua::State* L) { "--script", io::resolve(scriptPath).u8string(), "--sub-depth", std::to_string(engine->getCoreParameters() .subProcessDepth + 1), + "--log", io::resolve(outputPath), }; args.emplace_back("--project"); args.emplace_back(io::resolve(engine->getProject().path).u8string()); @@ -417,11 +418,9 @@ static int l_start_background_instance(lua::State* L) { if (handle == -1) { throw std::runtime_error("sub-processes limit exceeded"); } - ::processes[handle] = platform::new_engine_instance( - std::move(args), - outputPath.empty() ? "" : io::resolve(outputPath), - true - ); + ::processes[handle] = + platform::new_engine_instance(std::move(args), "", true); + return lua::pushinteger(L, handle); } diff --git a/src/util/platform.cpp b/src/util/platform.cpp index 7b08639e9..c7b945510 100644 --- a/src/util/platform.cpp +++ b/src/util/platform.cpp @@ -28,6 +28,8 @@ #include #endif +using namespace std::literals; + namespace platform::internal { std::filesystem::path get_executable_path(); } @@ -356,7 +358,7 @@ std::unique_ptr platform::new_engine_instance( if (!outputFile.empty()) { si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = CreateFileW( - toWString(outputFile.u8string()).data(), + toWString(outputFile.empty() ? outputFile.u8string() : "NUL"s,).data(), GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, @@ -434,9 +436,12 @@ std::unique_ptr platform::new_engine_instance( if (subProcess) { pid_t pid = fork(); + if (outputFile.empty()) { + outputFile = "/dev/null"; + } int fd = open( outputFile.string().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644 - ); + ); if (pid == 0) { prctl(PR_SET_PDEATHSIG, SIGTERM); From 099830d2fafeb2a4846746df74deb74957dee353 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 3 Aug 2026 20:19:03 +0300 Subject: [PATCH 16/30] fix windows build --- src/logic/scripting/lua/libs/libapp.cpp | 2 +- src/util/platform.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logic/scripting/lua/libs/libapp.cpp b/src/logic/scripting/lua/libs/libapp.cpp index 4885915ad..84f319a9c 100644 --- a/src/logic/scripting/lua/libs/libapp.cpp +++ b/src/logic/scripting/lua/libs/libapp.cpp @@ -403,7 +403,7 @@ static int l_start_background_instance(lua::State* L) { "--script", io::resolve(scriptPath).u8string(), "--sub-depth", std::to_string(engine->getCoreParameters() .subProcessDepth + 1), - "--log", io::resolve(outputPath), + "--log", io::resolve(outputPath).u8string(), }; args.emplace_back("--project"); args.emplace_back(io::resolve(engine->getProject().path).u8string()); diff --git a/src/util/platform.cpp b/src/util/platform.cpp index c7b945510..5d5e489bc 100644 --- a/src/util/platform.cpp +++ b/src/util/platform.cpp @@ -358,7 +358,7 @@ std::unique_ptr platform::new_engine_instance( if (!outputFile.empty()) { si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = CreateFileW( - toWString(outputFile.empty() ? outputFile.u8string() : "NUL"s,).data(), + toWString(outputFile.empty() ? outputFile.u8string() : "NUL"s).data(), GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, From d6923b0e0f2185bb916fcf20b728af5b11aa6ce0 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 3 Aug 2026 20:36:16 +0300 Subject: [PATCH 17/30] fix windows build again --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 4e739acde..9d8d8e551 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) { ? ".sub" + std::to_string(coreParameters.subProcessDepth) : "") + ".log"s; } - debug::Logger::init(logFile); + debug::Logger::init(logFile.u8string()); platform::configure_encoding(); auto& engine = Engine::getInstance(); From b30207917fb614c941bf8c7b8675fb16f9dc4fb3 Mon Sep 17 00:00:00 2001 From: RomanDonw <126128023+RomanDonw@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:59:28 +1000 Subject: [PATCH 18/30] made Russian docs more exact --- doc/ru/scripting/bytearray.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/ru/scripting/bytearray.md b/doc/ru/scripting/bytearray.md index 138eed347..50ec15d9d 100644 --- a/doc/ru/scripting/bytearray.md +++ b/doc/ru/scripting/bytearray.md @@ -55,15 +55,15 @@ bytes:move(fromindex: posint, toindex: posint, size: posint) Не имеет своих методов, является просто объектной ссылкой на оригинальный Bytearray. -| Класс | Тип элементов | Размер* | -| ------------ | ------------------ | -------- | -| `I16view` | `int16_t` | 2 байта | -| `U16view` | `uint16_t` | 2 байта | -| `I32view` | `int32_t` | 4 байта | -| `U32view` | `uint32_t` | 4 байта | -| `F32view` | `float` | 4 байта | +| Класс | Тип элементов | Размер | +| ------------ | ------------------ | --------- | +| `I16view` | `int16_t` | 2 байта | +| `U16view` | `uint16_t` | 2 байта | +| `I32view` | `int32_t` | 4 байта | +| `U32view` | `uint32_t` | 4 байта | +| `F32view` | `float` | 4 байта* | -* Размеры C-шных типов являются платформозависимыми. В данной таблице предоставлены наиболее распространённые размеры типов. +* Размеры "оригинальных" C-шных типов являются платформозависимыми и их точный размер не описан в стандарте языка. В данной таблице предоставлены наиболее распространённые размеры типов. --- @@ -82,4 +82,4 @@ print(i16[3]) -- -6 (signed вьюшка) for _, num in ipairs(i16) do print(num) end -- 1; 2; -6 -``` \ No newline at end of file +``` From e0afe5c6499f7b24e3bad0b03efc7060b0e862ee Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Tue, 4 Aug 2026 17:18:58 +1000 Subject: [PATCH 19/30] added typesize method for bytearray views (viewers) (both to Lua and docs (only Russian for now)) --- doc/ru/scripting/bytearray.md | 7 +++++++ res/modules/internal/bytearray.lua | 3 +++ 2 files changed, 10 insertions(+) diff --git a/doc/ru/scripting/bytearray.md b/doc/ru/scripting/bytearray.md index 50ec15d9d..b16b3fd39 100644 --- a/doc/ru/scripting/bytearray.md +++ b/doc/ru/scripting/bytearray.md @@ -65,6 +65,13 @@ bytes:move(fromindex: posint, toindex: posint, size: posint) * Размеры "оригинальных" C-шных типов являются платформозависимыми и их точный размер не описан в стандарте языка. В данной таблице предоставлены наиболее распространённые размеры типов. +### Специфические методы "вьюшек" + +```lua +-- Возвращает размер типа вьюшки (полезно для вьюшек, использующих C-шные типы нефиксированного размера: те же float или double). +view:typesize() -> posint +``` + --- ### Пример использования diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 586fa8e25..556085515 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -339,6 +339,9 @@ local function create_FFIview_class(name, typename) return i, ptr[i - 1] end end + end, + typesize = function() + return typesize end } return function (bytes) From 9fc94e40b20f6f686b4113dcd7fe530f04020fba Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Tue, 4 Aug 2026 17:41:24 +1000 Subject: [PATCH 20/30] renamed bytearray F32view to FLT view & improved bytearray Russian docs --- doc/ru/scripting/bytearray.md | 9 +++++++-- res/modules/internal/bytearray.lua | 4 ++-- res/scripts/stdmin.lua | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/ru/scripting/bytearray.md b/doc/ru/scripting/bytearray.md index b16b3fd39..032182891 100644 --- a/doc/ru/scripting/bytearray.md +++ b/doc/ru/scripting/bytearray.md @@ -2,6 +2,8 @@ *Bytearray* - динамический байтовый массив, реализованный через LuaJIT FFI. По нему можно итерироваться стандартными функциями **pairs** и **ipairs** +Примечание касаемо условных обозначений в документации: псведотип `posint` означает натуральное (положительное ненулевое целое) число. + ## Основное ### Создание массива ```lua @@ -61,14 +63,17 @@ bytes:move(fromindex: posint, toindex: posint, size: posint) | `U16view` | `uint16_t` | 2 байта | | `I32view` | `int32_t` | 4 байта | | `U32view` | `uint32_t` | 4 байта | -| `F32view` | `float` | 4 байта* | +| `FLTview` | `float` | 4 байта* | * Размеры "оригинальных" C-шных типов являются платформозависимыми и их точный размер не описан в стандарте языка. В данной таблице предоставлены наиболее распространённые размеры типов. ### Специфические методы "вьюшек" ```lua --- Возвращает размер типа вьюшки (полезно для вьюшек, использующих C-шные типы нефиксированного размера: те же float или double). +--[[ +Возвращает размер типа вьюшки. Результат тот же, что и от применения оператора sizeof() из языка C для данного типа. + Полезно для вьюшек, использующих C-шные типы нефиксированного размера, например те же float или double. +]] view:typesize() -> posint ``` diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 556085515..27472f491 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -356,7 +356,7 @@ local FFII16view = create_FFIview_class("FFII16view", "int16_t") local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t") local FFII32view = create_FFIview_class("FFII32view", "int32_t") local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t") -local FFIF32view = create_FFIview_class("FFIF32view", "float") +local FFIFLTview = create_FFIview_class("FFIFLTview", "float") return { FFIBytearray = setmetatable(FFIBytearray, FFIBytearray), @@ -366,5 +366,5 @@ return { FFII16view = FFII16view, FFIU32view = FFIU32view, FFII32view = FFII32view, - FFIF32view = FFIF32view, + FFIFLTview = FFIFLTview, } diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 01b61efc6..a7c7bdbd2 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -314,7 +314,7 @@ U16view = bytearray.FFIU16view I16view = bytearray.FFII16view U32view = bytearray.FFIU32view I32view = bytearray.FFII32view -F32view = bytearray.FFIF32view +FLTview = bytearray.FFIFLTview Bytearray_construct = function(...) return Bytearray(...) end bit.compile = require "core:bitwise/compiler" From 457fc573492dd9ec2f9399386bd1e1070c723830 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Tue, 4 Aug 2026 18:07:11 +1000 Subject: [PATCH 21/30] added more new views (viewers) for bytearray (again both to Lua & Russian docs) --- doc/ru/scripting/bytearray.md | 10 ++++++---- res/modules/internal/bytearray.lua | 8 ++++++++ res/scripts/stdmin.lua | 4 ++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/doc/ru/scripting/bytearray.md b/doc/ru/scripting/bytearray.md index 032182891..d15cd6a58 100644 --- a/doc/ru/scripting/bytearray.md +++ b/doc/ru/scripting/bytearray.md @@ -55,15 +55,19 @@ bytes:move(fromindex: posint, toindex: posint, size: posint) Это "вьюшки" поверх Bytearray, которые интерпретируют его байты как массив чисел другого размера - **без копирования данных**. -Не имеет своих методов, является просто объектной ссылкой на оригинальный Bytearray. +Практически не имеют своих методов, являются простыми объектными ссылками на оригинальный Bytearray. | Класс | Тип элементов | Размер | | ------------ | ------------------ | --------- | +| `I8view` | `int8_t` | 1 байт | | `I16view` | `int16_t` | 2 байта | | `U16view` | `uint16_t` | 2 байта | | `I32view` | `int32_t` | 4 байта | | `U32view` | `uint32_t` | 4 байта | +| `I64view` | `int64_t` | 8 байт | +| `U64view` | `uint64_t` | 8 байт | | `FLTview` | `float` | 4 байта* | +| `DBLview` | `double` | 8 байт* | * Размеры "оригинальных" C-шных типов являются платформозависимыми и их точный размер не описан в стандарте языка. В данной таблице предоставлены наиболее распространённые размеры типов. @@ -77,9 +81,7 @@ bytes:move(fromindex: posint, toindex: posint, size: posint) view:typesize() -> posint ``` ---- - -### Пример использования +## Пример использования ```lua local bytes = Bytearray({1, 0, 2, 0, 250, 255}) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 27472f491..42f6bddcd 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -352,19 +352,27 @@ local function create_FFIview_class(name, typename) end end +local FFII8view = create_FFIview_class("FFII8view", "int8_t") local FFII16view = create_FFIview_class("FFII16view", "int16_t") local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t") local FFII32view = create_FFIview_class("FFII32view", "int32_t") local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t") +local FFII64view = create_FFIview_class("FFII32view", "int64_t") +local FFIU64view = create_FFIview_class("FFIU32view", "uint64_t") local FFIFLTview = create_FFIview_class("FFIFLTview", "float") +local FFIDBLview = create_FFIview_class("FFIDBLview", "double") return { FFIBytearray = setmetatable(FFIBytearray, FFIBytearray), FFIBytearray_as_string = FFIBytearray_as_string, FFIBytearray_as_ptr = FFIBytearray_as_ptr, + FFII8view = FFII8view, FFIU16view = FFIU16view, FFII16view = FFII16view, FFIU32view = FFIU32view, FFII32view = FFII32view, + FFIU64view = FFIU64view, + FFII64view = FFII64view, FFIFLTview = FFIFLTview, + FFIDBLview = FFIDBLview, } diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index a7c7bdbd2..93bdf118e 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -310,11 +310,15 @@ local bytearray = require "core:internal/bytearray" Bytearray = bytearray.FFIBytearray Bytearray_as_string = bytearray.FFIBytearray_as_string Bytearray_as_ptr = bytearray.FFIBytearray_as_ptr +I8view = bytearray.FFII8view U16view = bytearray.FFIU16view I16view = bytearray.FFII16view U32view = bytearray.FFIU32view I32view = bytearray.FFII32view +U64view = bytearray.FFIU64view +I64view = bytearray.FFII64view FLTview = bytearray.FFIFLTview +DBLview = bytearray.FFIDBLview Bytearray_construct = function(...) return Bytearray(...) end bit.compile = require "core:bitwise/compiler" From e203b5ef4cc77fd812e5e8f0e3775064ab4cb5ab Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Tue, 4 Aug 2026 19:50:55 +1000 Subject: [PATCH 22/30] fixed two (2) typos in Bytearray:move method implementation --- res/modules/internal/bytearray.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 42f6bddcd..cfae8b53d 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -198,7 +198,7 @@ local function move(self, fromindex, toindex, size) error("specified destination byte range is out of array bounds") end - FFI.C.memmove(self.bytes + self.toindex - 1, self.bytes + self.fromindex - 1, size) + FFI.C.memmove(self.bytes + toindex - 1, self.bytes + fromindex - 1, size) end local bytearray_methods = { From 5843e5828b5e568ed271f55852eb1329e071e417 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Tue, 4 Aug 2026 20:25:15 +1000 Subject: [PATCH 23/30] upgraded bytearray's test (added testing new bytearray functions and views/viewers) --- dev/tests/bytearray.lua | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/dev/tests/bytearray.lua b/dev/tests/bytearray.lua index 415768c65..2a3d6140b 100644 --- a/dev/tests/bytearray.lua +++ b/dev/tests/bytearray.lua @@ -34,3 +34,67 @@ arr:insert(2, {5, 6}) assert(arr[#arr] == 25) assert(arr[2] == 5) assert(arr[3] == 6) + +-- ============================= + +local arr2 = Bytearray({254, 255, 255, 255, 255, 255, 255, 255}) +--assert(U64view(arr2)[1] == 2 ^ 64 - 2) +assert(I64view(arr2)[1] == -2) +assert(U32view(arr2)[1] == 2 ^ 32 - 2) +assert(I32view(arr2)[1] == -2) +assert(U16view(arr2)[1] == 2 ^ 16 - 2) +assert(I16view(arr2)[1] == -2) +assert(I8view(arr2)[1] == -2) + +assert(I8view(arr2)[2] == -1) +assert(I32view(arr2)[2] == -1) + +local arr3 = Bytearray({0xFF, 0x7F}) +local arr3i16 = I16view(arr3) +local arr3u16 = U16view(arr3) +assert(arr3i16[1] == 32767) + +arr3u16[1] = arr3u16[1] + 1 +assert(arr3i16[1] == -32768) +assert(arr3u16[1] == 32768) + +local arr4 = Bytearray({0x9A, 0x99, 0x59, 0x40}) -- approx. equal 3.4 in hexadecimal representation of single-precision float number. +local arr4flt = FLTview(arr4) +local arr4u32 = U32view(arr4) +assert(arr4flt[1] == 3.4000000953674316) +assert(arr4u32[1] == 0x4059999A) + +arr4flt[1] = arr4flt[1] + 0.1 +assert(arr4flt[1] == 3.5) +assert(arr4u32[1] == 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. + +-- ============================================= + +function barrtostr(barr) + local outstr = "" + for i = 1, #barr do + local lastfmt = "" + if i ~= #barr then lastfmt = "|" end + outstr = outstr .. barr[i] .. lastfmt + end + return outstr +end + +local arr5 = Bytearray({0, 5, 34, 87, 21, 0, 210}) +assert(barrtostr(arr5) == "0|5|34|87|21|0|210") +arr5:move(2, 3, 4) +assert(barrtostr(arr5) == "0|5|5|34|87|21|210") + +local arr6 = Bytearray({1, 2, 3, 4, 6, 7, 8}) +assert(barrtostr(arr6) == "1|2|3|4|6|7|8") +arr5:copy(4, arr6, 2, 3) +assert(barrtostr(arr6) == "1|34|87|21|6|7|8") + +arr5:fill(nil, nil, 192) +assert(barrtostr(arr5) == "192|192|192|192|192|192|192") +arr5:fill(nil, 3, 233) +assert(barrtostr(arr5) == "233|233|233|233|233|233|233") +arr5:fill(2, nil, 254) +assert(barrtostr(arr5) == "254|254|254|254|254|254|254") +arr5:fill(2, 2, 66) +assert(barrtostr(arr5) == "254|66|66|254|254|254|254") \ No newline at end of file From 074f01b1bb1fae161fd83d3f9061594af2c6ce71 Mon Sep 17 00:00:00 2001 From: RomanDonw Date: Tue, 4 Aug 2026 22:40:59 +1000 Subject: [PATCH 24/30] upgraded bytearray test & added DBLview testing section --- dev/tests/bytearray.lua | 85 +++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/dev/tests/bytearray.lua b/dev/tests/bytearray.lua index 2a3d6140b..cbd537100 100644 --- a/dev/tests/bytearray.lua +++ b/dev/tests/bytearray.lua @@ -37,36 +37,39 @@ assert(arr[3] == 6) -- ============================= -local arr2 = Bytearray({254, 255, 255, 255, 255, 255, 255, 255}) ---assert(U64view(arr2)[1] == 2 ^ 64 - 2) -assert(I64view(arr2)[1] == -2) -assert(U32view(arr2)[1] == 2 ^ 32 - 2) -assert(I32view(arr2)[1] == -2) -assert(U16view(arr2)[1] == 2 ^ 16 - 2) -assert(I16view(arr2)[1] == -2) -assert(I8view(arr2)[1] == -2) +arr = Bytearray({254, 255, 255, 255, 255, 255, 255, 255}) +--assert(U64view(arr)[1] == 2 ^ 64 - 2) +assert(I64view(arr)[1] == -2) +assert(U32view(arr)[1] == 2 ^ 32 - 2) +assert(I32view(arr)[1] == -2) +assert(U16view(arr)[1] == 2 ^ 16 - 2) +assert(I16view(arr)[1] == -2) +assert(I8view(arr)[1] == -2) -assert(I8view(arr2)[2] == -1) -assert(I32view(arr2)[2] == -1) +assert(I8view(arr)[2] == -1) +assert(I32view(arr)[2] == -1) -local arr3 = Bytearray({0xFF, 0x7F}) -local arr3i16 = I16view(arr3) -local arr3u16 = U16view(arr3) -assert(arr3i16[1] == 32767) +arr = Bytearray({0xFF, 0x7F}) +local arri16 = I16view(arr) +local arru16 = U16view(arr) +assert(arri16[1] == 32767) -arr3u16[1] = arr3u16[1] + 1 -assert(arr3i16[1] == -32768) -assert(arr3u16[1] == 32768) +arru16[1] = arru16[1] + 1 +assert(arri16[1] == -32768) +assert(arru16[1] == 32768) -local arr4 = Bytearray({0x9A, 0x99, 0x59, 0x40}) -- approx. equal 3.4 in hexadecimal representation of single-precision float number. -local arr4flt = FLTview(arr4) -local arr4u32 = U32view(arr4) -assert(arr4flt[1] == 3.4000000953674316) -assert(arr4u32[1] == 0x4059999A) +arr = Bytearray({0x9A, 0x99, 0x59, 0x40}) -- approx. equal 3.4 in hexadecimal representation of single-precision float number. +local arrflt = FLTview(arr) +local arru32 = U32view(arr) +assert(arrflt[1] == 3.4000000953674316) +assert(arru32[1] == 0x4059999A) -arr4flt[1] = arr4flt[1] + 0.1 -assert(arr4flt[1] == 3.5) -assert(arr4u32[1] == 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. +arrflt[1] = arrflt[1] + 0.1 +assert(arrflt[1] == 3.5) +assert(arru32[1] == 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. + +arr = Bytearray({0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 9, 64}) -- hexadecimal representation of 3.141592653589793 double-precision float number. +assert(DBLview(arr)[1] == 3.141592653589793) -- ============================================= @@ -80,21 +83,21 @@ function barrtostr(barr) return outstr end -local arr5 = Bytearray({0, 5, 34, 87, 21, 0, 210}) -assert(barrtostr(arr5) == "0|5|34|87|21|0|210") -arr5:move(2, 3, 4) -assert(barrtostr(arr5) == "0|5|5|34|87|21|210") +arr = Bytearray({0, 5, 34, 87, 21, 0, 210}) +assert(barrtostr(arr) == "0|5|34|87|21|0|210") +arr:move(2, 3, 4) +assert(barrtostr(arr) == "0|5|5|34|87|21|210") -local arr6 = Bytearray({1, 2, 3, 4, 6, 7, 8}) -assert(barrtostr(arr6) == "1|2|3|4|6|7|8") -arr5:copy(4, arr6, 2, 3) -assert(barrtostr(arr6) == "1|34|87|21|6|7|8") +local arr2 = Bytearray({1, 2, 3, 4, 6, 7, 8}) +assert(barrtostr(arr2) == "1|2|3|4|6|7|8") +arr:copy(4, arr2, 2, 3) +assert(barrtostr(arr2) == "1|34|87|21|6|7|8") -arr5:fill(nil, nil, 192) -assert(barrtostr(arr5) == "192|192|192|192|192|192|192") -arr5:fill(nil, 3, 233) -assert(barrtostr(arr5) == "233|233|233|233|233|233|233") -arr5:fill(2, nil, 254) -assert(barrtostr(arr5) == "254|254|254|254|254|254|254") -arr5:fill(2, 2, 66) -assert(barrtostr(arr5) == "254|66|66|254|254|254|254") \ No newline at end of file +arr:fill(nil, nil, 192) +assert(barrtostr(arr) == "192|192|192|192|192|192|192") +arr:fill(nil, 3, 233) +assert(barrtostr(arr) == "233|233|233|233|233|233|233") +arr:fill(2, nil, 254) +assert(barrtostr(arr) == "254|254|254|254|254|254|254") +arr:fill(2, 2, 66) +assert(barrtostr(arr) == "254|66|66|254|254|254|254") \ No newline at end of file From 7a88bd454a98bfc3ae8c71b4198e2f8dd16b7ca3 Mon Sep 17 00:00:00 2001 From: RomanDonw <126128023+RomanDonw@users.noreply.github.com> Date: Wed, 5 Aug 2026 00:39:21 +1000 Subject: [PATCH 25/30] fixed typo in FFIU64view & FFII64view bytearray views (viewers) declaration (bytearray.lua) --- res/modules/internal/bytearray.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index cfae8b53d..0908b8c9a 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -357,8 +357,8 @@ local FFII16view = create_FFIview_class("FFII16view", "int16_t") local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t") local FFII32view = create_FFIview_class("FFII32view", "int32_t") local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t") -local FFII64view = create_FFIview_class("FFII32view", "int64_t") -local FFIU64view = create_FFIview_class("FFIU32view", "uint64_t") +local FFII64view = create_FFIview_class("FFII64view", "int64_t") +local FFIU64view = create_FFIview_class("FFIU64view", "uint64_t") local FFIFLTview = create_FFIview_class("FFIFLTview", "float") local FFIDBLview = create_FFIview_class("FFIDBLview", "double") From 7f04d2884e7273f11ede01ef3f943aa139fca0c3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 4 Aug 2026 18:54:37 +0300 Subject: [PATCH 26/30] fix view classes static typesize method --- res/modules/internal/bytearray.lua | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 0908b8c9a..896f43188 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -340,16 +340,20 @@ local function create_FFIview_class(name, typename) end end end, - typesize = function() - return typesize - end } - return function (bytes) - local x = setmetatable({ - bytes=bytes, - }, FFIview_mt) - return x - end + return setmetatable({}, { + __call = function (self, bytes) + local x = setmetatable({ + bytes=bytes, + }, FFIview_mt) + return x + end, + __index = { + typesize = function() + return typesize + end + } + }) end local FFII8view = create_FFIview_class("FFII8view", "int8_t") From 5f94e707ea9fdd53d6272b5c718b8c226222c8ee Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 4 Aug 2026 18:55:10 +0300 Subject: [PATCH 27/30] update bytearray test --- dev/tests/bytearray.lua | 58 ++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/dev/tests/bytearray.lua b/dev/tests/bytearray.lua index cbd537100..0d1bdb6ae 100644 --- a/dev/tests/bytearray.lua +++ b/dev/tests/bytearray.lua @@ -18,55 +18,55 @@ Bytearray.insert(arr, {5, 3, 6}) assert(#arr == 12) Bytearray.insert(arr, 2, 8) -assert(#arr == 13) +asserts.equals(13, #arr) for i=1,10 do assert(arr[i] == 10 - i) end print(#arr, arr:get_capacity()) arr:trim() -assert(#arr == arr:get_capacity()) +asserts.equals(#arr, arr:get_capacity()) arr = Bytearray({0, 2, 7, 1, 16, 75, 25}) assert(arr[6] == 75) arr:insert(2, {5, 6}) -assert(arr[#arr] == 25) -assert(arr[2] == 5) -assert(arr[3] == 6) +asserts.equals(25, arr[#arr]) +asserts.equals(5, arr[2]) +asserts.equals(6, arr[3]) -- ============================= arr = Bytearray({254, 255, 255, 255, 255, 255, 255, 255}) ---assert(U64view(arr)[1] == 2 ^ 64 - 2) -assert(I64view(arr)[1] == -2) -assert(U32view(arr)[1] == 2 ^ 32 - 2) -assert(I32view(arr)[1] == -2) -assert(U16view(arr)[1] == 2 ^ 16 - 2) -assert(I16view(arr)[1] == -2) -assert(I8view(arr)[1] == -2) +-- asserts.equals(U64view(arr)[1], 2 ^ 64 - 2) +asserts.equals(I64view(arr)[1], -2) +asserts.equals(U32view(arr)[1], 2 ^ 32 - 2) +asserts.equals(I32view(arr)[1], -2) +asserts.equals(U16view(arr)[1], 2 ^ 16 - 2) +asserts.equals(I16view(arr)[1], -2) +asserts.equals(I8view(arr)[1], -2) -assert(I8view(arr)[2] == -1) -assert(I32view(arr)[2] == -1) +asserts.equals(I8view(arr)[2], -1) +asserts.equals(I32view(arr)[2], -1) arr = Bytearray({0xFF, 0x7F}) local arri16 = I16view(arr) local arru16 = U16view(arr) -assert(arri16[1] == 32767) +asserts.equals(arri16[1], 32767) arru16[1] = arru16[1] + 1 -assert(arri16[1] == -32768) -assert(arru16[1] == 32768) +asserts.equals(arri16[1], -32768) +asserts.equals(arru16[1], 32768) arr = Bytearray({0x9A, 0x99, 0x59, 0x40}) -- approx. equal 3.4 in hexadecimal representation of single-precision float number. local arrflt = FLTview(arr) local arru32 = U32view(arr) -assert(arrflt[1] == 3.4000000953674316) -assert(arru32[1] == 0x4059999A) +asserts.equals(arrflt[1], 3.4000000953674316) +asserts.equals(arru32[1], 0x4059999A) arrflt[1] = arrflt[1] + 0.1 -assert(arrflt[1] == 3.5) -assert(arru32[1] == 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. +asserts.equals(arrflt[1], 3.5) +asserts.equals(arru32[1], 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. arr = Bytearray({0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 9, 64}) -- hexadecimal representation of 3.141592653589793 double-precision float number. assert(DBLview(arr)[1] == 3.141592653589793) @@ -84,20 +84,20 @@ function barrtostr(barr) end arr = Bytearray({0, 5, 34, 87, 21, 0, 210}) -assert(barrtostr(arr) == "0|5|34|87|21|0|210") +asserts.equals(barrtostr(arr), "0|5|34|87|21|0|210") arr:move(2, 3, 4) -assert(barrtostr(arr) == "0|5|5|34|87|21|210") +asserts.equals(barrtostr(arr), "0|5|5|34|87|21|210") local arr2 = Bytearray({1, 2, 3, 4, 6, 7, 8}) -assert(barrtostr(arr2) == "1|2|3|4|6|7|8") +asserts.equals(barrtostr(arr2), "1|2|3|4|6|7|8") arr:copy(4, arr2, 2, 3) -assert(barrtostr(arr2) == "1|34|87|21|6|7|8") +asserts.equals(barrtostr(arr2), "1|34|87|21|6|7|8") arr:fill(nil, nil, 192) -assert(barrtostr(arr) == "192|192|192|192|192|192|192") +asserts.equals(barrtostr(arr), "192|192|192|192|192|192|192") arr:fill(nil, 3, 233) -assert(barrtostr(arr) == "233|233|233|233|233|233|233") +asserts.equals(barrtostr(arr), "233|233|233|233|233|233|233") arr:fill(2, nil, 254) -assert(barrtostr(arr) == "254|254|254|254|254|254|254") +asserts.equals(barrtostr(arr), "254|254|254|254|254|254|254") arr:fill(2, 2, 66) -assert(barrtostr(arr) == "254|66|66|254|254|254|254") \ No newline at end of file +asserts.equals(barrtostr(arr), "254|66|66|254|254|254|254") From 5422eb7ccc4ce7b8cf69b30c2f58a57f23b0b271 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 4 Aug 2026 19:19:50 +0300 Subject: [PATCH 28/30] add ctypes library --- res/modules/internal/ctypes.lua | 38 +++++++++++++++++++++++++++++++++ res/scripts/stdmin.lua | 2 ++ 2 files changed, 40 insertions(+) create mode 100644 res/modules/internal/ctypes.lua diff --git a/res/modules/internal/ctypes.lua b/res/modules/internal/ctypes.lua new file mode 100644 index 000000000..032ea34b5 --- /dev/null +++ b/res/modules/internal/ctypes.lua @@ -0,0 +1,38 @@ +local FFI = ffi + +FFI.cdef[[ + unsigned long long strtoull(const char* nptr, char** endptr, int base); + long long strtoll(const char* nptr, char** endptr, int base); +]] + +local this = {} + +local function create_integral_type(ctype_name, signed) + local parse_func = signed and FFI.C.strtoll or FFI.C.strtoull + return function(value, base) + value = value or 0 + local typename = type(value) + if typename == "number" then + return FFI.cast(ctype_name, value) + elseif typename == "string" then + if type(base) ~= "number" then + base = 10 + end + return parse_func(value, nil, base) + end + error(string.format("invalid value type: %s", typename)) + end +end + + +this.uint8 = create_integral_type("uint8_t", false) +this.uint16 = create_integral_type("uint16_t", false) +this.uint32 = create_integral_type("uint32_t", false) +this.uint64 = create_integral_type("uint64_t", false) + +this.int8 = create_integral_type("int8_t", true) +this.int16 = create_integral_type("int16_t", true) +this.int32 = create_integral_type("int32_t", true) +this.int64 = create_integral_type("int64_t", true) + +return this diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 196bf8942..03de8cbaa 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -322,6 +322,8 @@ FLTview = bytearray.FFIFLTview DBLview = bytearray.FFIDBLview Bytearray_construct = function(...) return Bytearray(...) end +ctypes = require "core:internal/ctypes" + bit.compile = require "core:bitwise/compiler" bit.execute = require "core:bitwise/executor" From 40a61307b32c9b2c386346c4f17f415cd1bede93 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 4 Aug 2026 19:54:08 +0300 Subject: [PATCH 29/30] update bytearray test --- dev/tests/bytearray.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/bytearray.lua b/dev/tests/bytearray.lua index 0d1bdb6ae..71e895d37 100644 --- a/dev/tests/bytearray.lua +++ b/dev/tests/bytearray.lua @@ -38,7 +38,7 @@ asserts.equals(6, arr[3]) -- ============================= arr = Bytearray({254, 255, 255, 255, 255, 255, 255, 255}) --- asserts.equals(U64view(arr)[1], 2 ^ 64 - 2) +asserts.equals(U64view(arr)[1], ctypes.uint64(2) ^ 64 - 2) asserts.equals(I64view(arr)[1], -2) asserts.equals(U32view(arr)[1], 2 ^ 32 - 2) asserts.equals(I32view(arr)[1], -2) From 4a381ec2f4c5638659eaae7422e0b6648d1b8add Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 4 Aug 2026 20:24:58 +0300 Subject: [PATCH 30/30] add ctypes docs (minimal) --- doc/en/scripting.md | 1 + doc/en/scripting/builtins/libctypes.md | 28 ++++++++++++++++++++++++++ doc/ru/scripting.md | 1 + doc/ru/scripting/builtins/libctypes.md | 28 ++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 doc/en/scripting/builtins/libctypes.md create mode 100644 doc/ru/scripting/builtins/libctypes.md diff --git a/doc/en/scripting.md b/doc/en/scripting.md index 09cf40ef4..2072d4353 100644 --- a/doc/en/scripting.md +++ b/doc/en/scripting.md @@ -16,6 +16,7 @@ Subsections: - [block](scripting/builtins/libblock.md) - [byteutil](scripting/builtins/libbyteutil.md) - [cameras](scripting/builtins/libcameras.md) + - [ctypes](scripting/builtins/libctypes.md) - [entities](scripting/builtins/libentities.md) - [file](scripting/builtins/libfile.md) - [gfx.blockwraps](scripting/builtins/libgfx-blockwraps.md) diff --git a/doc/en/scripting/builtins/libctypes.md b/doc/en/scripting/builtins/libctypes.md new file mode 100644 index 000000000..5517af0fa --- /dev/null +++ b/doc/en/scripting/builtins/libctypes.md @@ -0,0 +1,28 @@ +# *ctypes* Library + +A library for safe work with C types. + +| ctypes.\ | C-Type | Minimum | Maximum | +| --------------- | -------- | -------------------- | -------------------- | +| uint8 | uint8_t | 0 | 255 | +| uint16 | uint16_t | 0 | 65535 | +| uint32 | uint32_t | 0 | 4294967295 | +| uint64 | uint64_t | 0 | 18446744073709551615 | +| int8 | int8_t | -128 | 127 | +| int16 | int16_t | -32768 | 32767 | +| int32 | int32_t | -2147483648 | 2147483647 | +| int64 | int64_t | -9223372036854775808 | 9223372036854775807 | + + +Usage examples: + +```lua +local x = ctypes.uint64(1234) +print(x) --> 1234ULL (cdata) +local y = ctypes.uint64("18446744073709551615") +print(y) --> 18446744073709551615ULL (cdata) +print(x + y) --> 1233ULL + +local z = tonumber(x) +print(z) --> 1234 (number) +``` diff --git a/doc/ru/scripting.md b/doc/ru/scripting.md index db3fcd921..1e6d73098 100644 --- a/doc/ru/scripting.md +++ b/doc/ru/scripting.md @@ -16,6 +16,7 @@ - [block](scripting/builtins/libblock.md) - [byteutil](scripting/builtins/libbyteutil.md) - [cameras](scripting/builtins/libcameras.md) + - [ctypes](scripting/builtins/libctypes.md) - [entities](scripting/builtins/libentities.md) - [file](scripting/builtins/libfile.md) - [gfx.blockwraps](scripting/builtins/libgfx-blockwraps.md) diff --git a/doc/ru/scripting/builtins/libctypes.md b/doc/ru/scripting/builtins/libctypes.md new file mode 100644 index 000000000..d6c985b44 --- /dev/null +++ b/doc/ru/scripting/builtins/libctypes.md @@ -0,0 +1,28 @@ +# Библиотека *ctypes* + +Библиотека для безопасной работы с типами языка С. + +| ctypes.\ | С-тип | Минимум | Максимум | +| ------------- | -------- | -------------------- | -------------------- | +| uint8 | uint8_t | 0 | 255 | +| uint16 | uint16_t | 0 | 65535 | +| uint32 | uint32_t | 0 | 4294967295 | +| uint64 | uint64_t | 0 | 18446744073709551615 | +| int8 | int8_t | -128 | 127 | +| int16 | int16_t | -32768 | 32767 | +| int32 | int32_t | -2147483648 | 2147483647 | +| int64 | int64_t | -9223372036854775808 | 9223372036854775807 | + + +Примеры использования: + +```lua +local x = ctypes.uint64(1234) +print(x) --> 1234ULL (cdata) +local y = ctypes.uint64("18446744073709551615") +print(y) --> 18446744073709551615ULL (cdata) +print(x + y) --> 1233ULL + +local z = tonumber(x) +print(z) --> 1234 (number) +```