Skip to content

Commit 6bfead8

Browse files
committed
fix(atArray): fix data size
- Use fixed pointer size since this is a pointer to pointer array, not an array of inline objects like the real atArray class. - Add a cheesy `NULLPTR` because why not. - Add an equality method to the API's `memory.pointer` usertype.
1 parent 33de4e4 commit 6bfead8

File tree

4 files changed

+57
-41
lines changed

4 files changed

+57
-41
lines changed

SmallBase/includes/classes/atArray.lua

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@
88
---@class atArray<T>
99
---@field private m_address pointer
1010
---@field private m_data_ptr pointer
11-
---@field private m_size integer
11+
---@field private m_size uint16_t
1212
---@field private m_count uint16_t
13-
---@field private m_data_type any
14-
---@field private m_data_size uint16_t
1513
---@field private m_data array<pointer>
14+
---@field private m_data_type any
1615
---@field private m_last_update_time Time.TimePoint
17-
---@overload fun(address: pointer, data_type: any, data_size?: number): atArray
16+
---@overload fun(address: pointer, data_type?: ClassMeta): atArray
1817
atArray = {}
1918
atArray.__index = atArray
2019
atArray.__type = "atArray"
@@ -26,60 +25,52 @@ setmetatable(atArray, {
2625

2726
---@generic T
2827
---@param address pointer
29-
---@param data_type? T
30-
---@param data_size? integer
28+
---@param data_type? ClassMeta<T>
3129
---@return atArray<T>
32-
function atArray.new(address, data_type, data_size)
33-
local default = setmetatable(
30+
function atArray.new(address, data_type)
31+
local instance = setmetatable(
3432
{
35-
m_address = 0x0,
36-
m_data_ptr = 0x0,
37-
m_size = 0,
38-
m_count = 0,
39-
m_data_size = 0,
40-
m_data = {}
33+
m_address = NULLPTR,
34+
m_data_ptr = NULLPTR,
35+
m_size = 0x0,
36+
m_count = 0x0,
37+
m_data = {},
38+
m_data_type = nil
4139
},
4240
atArray
4341
)
4442

4543
if not (IsInstance(address, "pointer") and address:is_valid()) then
46-
return default
44+
return instance
4745
end
4846

4947
local array_size = address:add(0x8):get_word()
5048
if (array_size == 0) then
51-
return default
49+
return instance
5250
end
5351

54-
data_type = data_type or GenericClass
55-
data_size = data_size or SizeOf(data_type)
56-
local instance = setmetatable(
57-
{
58-
m_address = address,
59-
m_data_ptr = address:deref(),
60-
m_size = array_size,
61-
m_count = address:add(0xA):get_word(),
62-
m_data_type = data_type,
63-
m_data_size = data_size,
64-
m_data = {},
65-
m_last_update_time = TimePoint:new()
66-
},
67-
atArray
68-
)
52+
instance.m_address = address
53+
instance.m_data_ptr = address:deref()
54+
instance.m_size = array_size
55+
instance.m_count = address:add(0xA):get_word()
56+
instance.m_data_type = data_type
57+
instance.m_last_update_time = TimePoint:new()
6958

7059
for i = 0, array_size - 1 do
71-
instance.m_data[i+1] = instance.m_data_ptr:add(i * data_size):deref()
60+
instance.m_data[i+1] = instance.m_data_ptr:add(i * 0x8):deref()
7261
end
7362

7463
return instance
7564
end
7665

7766
---@return boolean
7867
function atArray:IsValid()
79-
return IsInstance(self.m_address, "pointer")
80-
and IsInstance(self.m_data_ptr, "pointer")
81-
and self.m_address:is_valid()
82-
and self.m_data_ptr:is_valid()
68+
return self.m_address:is_valid() and self.m_data_ptr:is_valid()
69+
end
70+
71+
---@return boolean
72+
function atArray:IsNull()
73+
return not self:IsValid()
8374
end
8475

8576
---@return boolean
@@ -88,6 +79,16 @@ function atArray:IsEmpty()
8879
return self.m_size == 0
8980
end
9081

82+
function atArray:Clear()
83+
self.m_address = NULLPTR
84+
self.m_data_ptr = NULLPTR
85+
self.m_data = {}
86+
self.m_size = 0x0
87+
self.m_count = 0x0
88+
self.m_data_type = nil
89+
self.m_last_update_time:reset()
90+
end
91+
9192
function atArray:Update()
9293
if not self:IsValid() then
9394
return
@@ -106,7 +107,7 @@ function atArray:Update()
106107
end
107108

108109
for i = 0, self.m_size - 1 do
109-
self.m_data[i+1] = self.m_data_ptr:add(i * self.m_data_size):deref()
110+
self.m_data[i+1] = self.m_data_ptr:add(i * 0x8):deref()
110111
end
111112

112113
self.m_last_update_time:reset()
@@ -154,12 +155,12 @@ end
154155

155156
---@return uint16_t
156157
function atArray:DataSize()
157-
return self.m_data_size
158+
return SizeOf(self.m_data)
158159
end
159160

160161
---@return string
161162
function atArray:DataType()
162-
return (self.m_data_type and self.m_data_type.__type) or "None"
163+
return (self.m_data_type and self.m_data_type.__type) or "pointer<undefined>"
163164
end
164165

165166
---@param i number

SmallBase/includes/lib/types.lua

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
GenericClass = setmetatable({}, {
1818
__index = { m_size = 0x40, __type = "GenericClass" },
1919
__newindex = function(...)
20-
error("Attempt to modify read-only GenericClass!")
20+
error("Attempt to modify read-only Generic Class!")
2121
end,
2222
__metatable = false
2323
})
@@ -55,6 +55,13 @@ GenericClass = setmetatable({}, {
5555
---@alias Predicate<P1, P2, P3, P4, P5> fun(p1: P1, p2?: P2, p3?: P3, p4?: P4, p5?: P5): boolean
5656
---@alias Comparator<A, B> fun(a: A, b: B): boolean
5757

58+
-- A poor man's `nullptr` 🥲
59+
NULLPTR = (function()
60+
local p = memory.scan_pattern("48 8B C4")
61+
p:set_address(0x0)
62+
return p
63+
end)()
64+
5865
---@generic T
5966
---@param t array<T>
6067
---@return array<T>

SmallBase/includes/lib/utils.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ end
340340

341341
--#region extensions
342342

343+
---@type Comparator<pointer, pointer>
344+
function memory.pointer:__eq(right)
345+
if not IsInstance(right, "pointer") then
346+
return false
347+
end
348+
349+
return self:get_address() == right:get_address()
350+
end
343351

344352
-- Retrieves a 32-bit displacement value from the memory address, optionally adding an offset and adjustment.
345353
--

SmallBase/main.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ CommandExecutor:RegisterCommand("spawnjsonveh", function(args)
4444
Vehicle.CreateFromJSON(filename, warp)
4545
end)
4646
end, {
47-
args = {"filename<string>", "Optional: warp_into<boolean>"},
47+
args = { "filename<string>", "Optional: warp_into<boolean>" },
4848
description = "Spawns a vehicle from JSON."
4949
})
5050

0 commit comments

Comments
 (0)