Skip to content

Commit 7e4f1b8

Browse files
committed
refactor: restructured library
1 parent 226a909 commit 7e4f1b8

8 files changed

Lines changed: 150 additions & 58 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.DS_Store
2+
offset_finder.py
23
**/__pycache__/

‎data/offsets.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"Text": "0xC10",
3-
"Character": "0x328"
3+
"Character": "0x328",
4+
"CFrame": "0x128"
45
}

‎example.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
print("Failed to get data model")
1212
exit()
1313

14+
LocalPlayer = game.Players.LocalPlayer
15+
1416
# Print some info about the game
1517
print("RobloxMemoryAPI Demo:")
1618
print("A External Roblox Memory Reader")
@@ -19,7 +21,11 @@
1921
print("GameID:", game.GameId)
2022
print("JobId:", game.JobId)
2123
print("==============================")
22-
print("Player Name:", game.Players.LocalPlayer.Name)
23-
print("Player Character Parent:", game.Players.LocalPlayer.Character.Parent.Name)
24+
print("Player Name:", LocalPlayer.Name)
25+
print("Player Character Parent:", LocalPlayer.Character.HumanoidRootPart.GetFullName())
2426
print("Player Count:", len(game.Players.GetPlayers()))
25-
print("==============================")
27+
print("==============================")
28+
29+
# 1.0511624813079834, 2.9980251789093018, -1.8010846376419067
30+
print("Player Position:", LocalPlayer.Character.HumanoidRootPart.Position)
31+
print("Player HRP Size:", LocalPlayer.Character.HumanoidRootPart.Size)

‎robloxmemoryapi.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from utils.memory import EvasiveProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ, get_pid_by_name
2-
from utils.rbxinstance import DataModel
2+
from utils.rbx.instance import DataModel
33
import platform
44

55
if platform.system() != "Windows":

‎utils/memory.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ def read_float(self, address: int) -> float:
226226
return struct.unpack('<f', float_bytes)[0] if len(float_bytes) == 4 else 0.0
227227
except (OSError, struct.error):
228228
return 0.0
229+
230+
def read_floats(self, address: int, amount: int):
231+
try:
232+
bulk_float_bytes = self.read(address, 4 * amount)
233+
floats = []
234+
for i in range(amount):
235+
start_range = i * 4
236+
float_bytes = bulk_float_bytes[start_range:start_range + 4]
237+
if len(float_bytes) == 4:
238+
floats.append(struct.unpack('<f', float_bytes)[0])
239+
else:
240+
floats.append(0.0)
241+
242+
return floats
243+
except (OSError, struct.error) as e:
244+
print(e)
245+
return [0.0]
229246

230247
# bool #
231248
def read_bool(self, address: int) -> bool:

‎utils/offsets.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import json, requests
2+
3+
OffsetsRequest = requests.get("https://offsets.ntgetwritewatch.workers.dev/offsets.json")
4+
Offsets = OffsetsRequest.json()
5+
6+
for key in Offsets:
7+
try:
8+
Offsets[key] = int(Offsets[key], 16)
9+
except (ValueError, TypeError):
10+
pass
11+
12+
with open("data/offsets.json", "r") as f:
13+
LoadedOffsets = json.load(f)
14+
f.close()
15+
16+
for key in LoadedOffsets:
17+
Offsets[key] = int(LoadedOffsets[key], 16)

‎utils/rbx/datastructures.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class UDim2:
2+
def __init__(self, scaleX, offsetX, scaleY, offsetY):
3+
self.X = {
4+
["Offset"]: offsetX,
5+
["Scale"]: scaleX
6+
}
7+
8+
self.Y = {
9+
["Offset"]: offsetY,
10+
["Scale"]: scaleY
11+
}
12+
13+
self.Width = self.X
14+
self.Height = self.Y
15+
16+
def __str__(self):
17+
return f"{{{self.X.Scale}, {self.X.Offset}}}, {{{self.Y.Scale}, {self.Y.Offset}}}"
18+
19+
def fromScale(scaleX, scaleY):
20+
return UDim2(scaleX, 0, scaleY, 0)
21+
22+
def fromOffset(offsetX, offsetY):
23+
return UDim2(0, offsetX, 0, offsetY)
24+
25+
class Vector3:
26+
def __init__(self, x, y, z):
27+
self.x = x
28+
self.y = y
29+
self.z = z
30+
31+
def __str__(self):
32+
return f"{self.x}, {self.y}, {self.z}"
33+
34+
def __eq__(self, vector):
35+
if isinstance(vector, Vector3):
36+
return vector.x == self.x and vector.y == self.y and vector.z == self.y
Lines changed: 67 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,30 @@
1-
import requests
1+
from ..offsets import *
22
import time
3-
import json
4-
5-
OffsetsRequest = requests.get("https://offsets.ntgetwritewatch.workers.dev/offsets.json")
6-
Offsets = OffsetsRequest.json()
7-
8-
for key in Offsets:
9-
try:
10-
Offsets[key] = int(Offsets[key], 16)
11-
except (ValueError, TypeError):
12-
pass
13-
14-
with open("data/offsets.json", "r") as f:
15-
LoadedOffsets = json.load(f)
16-
f.close()
17-
18-
for key in LoadedOffsets:
19-
Offsets[key] = int(LoadedOffsets[key], 16)
3+
from utils.rbx.datastructures import *
204

215
class RBXInstance:
226
def __init__(self, address, memory_module):
237
self.raw_address = address
248
self.memory_module = memory_module
259

26-
# props #
27-
@property
28-
def parent_address(self):
29-
return self.raw_address + Offsets["Parent"]
10+
def __eq__(self, value):
11+
return value.raw_address == self.raw_address
12+
13+
def __getattr__(self, key):
14+
return self.FindFirstChild(key)
3015

16+
# props #
3117
@property
3218
def Parent(self):
3319
parent_pointer = int.from_bytes(self.memory_module.read(self.raw_address + Offsets["Parent"], 8), 'little')
34-
return RBXInstance(parent_pointer, self.memory_module)
20+
instance = RBXInstance(parent_pointer, self.memory_module)
21+
22+
try:
23+
thing = instance.ClassName
24+
except Exception as e:
25+
return None
26+
27+
return instance
3528

3629
@property
3730
def Name(self):
@@ -51,39 +44,37 @@ def ClassName(self):
5144
)
5245
return self.memory_module.read_string(class_name_address)
5346

54-
# frame properties #
5547
@property
5648
def Position(self):
57-
try:
58-
x = self.memory_module.read_float(self.raw_address + Offsets["FramePositionX"])
59-
x_offset = self.memory_module.read_int(self.raw_address + Offsets["FramePositionOffsetX "])
60-
61-
y = self.memory_module.read_float(self.raw_address + Offsets["FramePositionY"])
62-
y_offset = self.memory_module.read_int(self.raw_address + Offsets["FramePositionOffsetY"])
63-
64-
return (x, x_offset, y, y_offset)
65-
except (KeyError, OSError) as e:
66-
print(f"Error reading position: {e}")
67-
return (0.0, 0, 0.0, 0)
49+
if "part" in self.ClassName.lower():
50+
position_vector3 = self.memory_module.read_floats(self.raw_address + Offsets["Position"], 3)
51+
return Vector3(*position_vector3)
52+
else:
53+
try:
54+
x = self.memory_module.read_float(self.raw_address + Offsets["FramePositionX"])
55+
x_offset = self.memory_module.read_int(self.raw_address + Offsets["FramePositionOffsetX "])
56+
57+
y = self.memory_module.read_float(self.raw_address + Offsets["FramePositionY"])
58+
y_offset = self.memory_module.read_int(self.raw_address + Offsets["FramePositionOffsetY"])
59+
60+
return UDim2(x, x_offset, y, y_offset)
61+
except (KeyError, OSError) as e:
62+
print(f"Error reading position: {e}")
63+
return (0.0, 0, 0.0, 0)
6864

6965
@property
7066
def Size(self):
71-
try:
72-
x = self.memory_module.read_float(self.raw_address + Offsets["FrameSizeX"])
73-
y = self.memory_module.read_float(self.raw_address + Offsets["FrameSizeY"])
74-
return (x, y)
75-
except (KeyError, OSError) as e:
76-
print(f"Error reading position: {e}")
77-
return (0.0, 0.0)
78-
79-
"""@property
80-
def ScreenPosition(self):
81-
udim2_x_scale, udim2_y_scale, udim2_x_offset, udim2_y_offset = self.Position
82-
83-
real_x = (udim2_x_scale * SCREEN_WIDTH) + udim2_x_offset
84-
real_y = (udim2_y_scale * SCREEN_HEIGHT) + udim2_y_offset
85-
86-
return (real_x, real_y)"""
67+
if "part" in self.ClassName.lower():
68+
size_vector3 = self.memory_module.read_floats(self.raw_address + Offsets["PartSize"], 3)
69+
return Vector3(*size_vector3)
70+
else:
71+
try:
72+
x = self.memory_module.read_float(self.raw_address + Offsets["FrameSizeX"])
73+
y = self.memory_module.read_float(self.raw_address + Offsets["FrameSizeY"])
74+
return (x, y)
75+
except (KeyError, OSError) as e:
76+
print(f"Error reading position: {e}")
77+
return (0.0, 0.0)
8778

8879
# XXXXValue props #
8980
@property
@@ -103,8 +94,7 @@ def Value(self):
10394
# text props #
10495
@property
10596
def Text(self):
106-
classname = self.ClassName
107-
if classname == "TextLabel":
97+
if "text" in self.ClassName.lower():
10898
return self.memory_module.read_string(self.raw_address + Offsets["Text"])
10999

110100
return None
@@ -129,6 +119,30 @@ def GetChildren(self):
129119

130120
return children
131121

122+
def GetFullName(self):
123+
if self.ClassName == "DataModel":
124+
return self.Name
125+
126+
ObjectPointer = self
127+
ObjectPath = self.Name
128+
129+
while True:
130+
if ObjectPointer.Parent.ClassName == "DataModel":
131+
break
132+
133+
ObjectPointer = ObjectPointer.Parent
134+
ObjectPath = f"{ObjectPointer.Name}." + ObjectPath
135+
136+
return ObjectPath
137+
138+
def GetDescendants(self):
139+
descendants = []
140+
for child in self.GetChildren():
141+
descendants.append(child)
142+
descendants.extend(child.GetDescendants())
143+
return descendants
144+
145+
132146
def FindFirstChild(self, name, recursive=False):
133147
try:
134148
children = self.GetChildren()

0 commit comments

Comments
 (0)