robloxmemoryapi 0.2.2.1__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {robloxmemoryapi-0.2.2.1/src/robloxmemoryapi.egg-info → robloxmemoryapi-0.2.4}/PKG-INFO +1 -1
  2. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/pyproject.toml +1 -1
  3. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/rbx/datastructures.py +25 -1
  4. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/rbx/fflags.py +4 -14
  5. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/rbx/instance.py +752 -22
  6. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4/src/robloxmemoryapi.egg-info}/PKG-INFO +1 -1
  7. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/LICENSE.md +0 -0
  8. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/README.md +0 -0
  9. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/setup.cfg +0 -0
  10. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/__init__.py +0 -0
  11. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/__init__.py +0 -0
  12. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/luau/__init__.py +0 -0
  13. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/luau/parser.py +0 -0
  14. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/memory.py +0 -0
  15. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/offsets.py +0 -0
  16. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/rbx/__init__.py +0 -0
  17. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/rbx/bytecode/decryptor.py +0 -0
  18. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi/utils/rbx/bytecode/encryptor.py +0 -0
  19. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi.egg-info/SOURCES.txt +0 -0
  20. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi.egg-info/dependency_links.txt +0 -0
  21. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi.egg-info/requires.txt +0 -0
  22. {robloxmemoryapi-0.2.2.1 → robloxmemoryapi-0.2.4}/src/robloxmemoryapi.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robloxmemoryapi
3
- Version: 0.2.2.1
3
+ Version: 0.2.4
4
4
  Summary: Python Library that abstracts reading and writing data from the Roblox DataModel
5
5
  Author-email: upio <notpoiu@users.noreply.github.com>, mstudio45 <mstudio45@users.noreply.github.com>, ActualMasterOogway <ActualMasterOogway@users.noreply.github.com>
6
6
  License: Copyright 2025 upio, mstudio45, master oogway
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "robloxmemoryapi"
7
- version = "0.2.2.1"
7
+ version = "0.2.4"
8
8
  description = "Python Library that abstracts reading and writing data from the Roblox DataModel"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.9"
@@ -389,4 +389,28 @@ class AnimationTrack:
389
389
 
390
390
  @property
391
391
  def IsPlaying(self):
392
- return self.memory_module.read_bool(self.raw_address, self._offsets["IsPlaying"])
392
+ return self.memory_module.read_bool(self.raw_address, self._offsets["IsPlaying"])
393
+
394
+ class FFlag:
395
+ __slots__ = ("name", "type", "_value", "offset", "_manager")
396
+
397
+ def __init__(self, name: str, flag_type: str, value, offset: int, manager=None):
398
+ self.name = name
399
+ self.type = flag_type
400
+ self._value = value
401
+ self.offset = offset
402
+ self._manager = manager
403
+
404
+ @property
405
+ def value(self):
406
+ return self._value
407
+
408
+ @value.setter
409
+ def value(self, new_value):
410
+ if self._manager is None:
411
+ raise RuntimeError("Cannot set value: FFlag not bound to an FFlagManager")
412
+ result = self._manager.set(self.name, new_value)
413
+ self._value = result._value
414
+
415
+ def __repr__(self):
416
+ return f"FFlag(name={self.name!r}, type={self.type!r}, value={self._value!r})"
@@ -1,4 +1,5 @@
1
1
  from ..offsets import get_fflag_offsets
2
+ from .datastructures import FFlag
2
3
 
3
4
  _MODULE_SIZE_LIMIT = 0x20000000
4
5
 
@@ -33,17 +34,6 @@ def _encode_flog(value: str) -> int:
33
34
  return (level_byte << 8) | (param & 0xFF)
34
35
 
35
36
 
36
- class FFlag:
37
- __slots__ = ("name", "type", "value", "offset")
38
-
39
- def __init__(self, name: str, flag_type: str, value, offset: int):
40
- self.name = name
41
- self.type = flag_type # "bool", "int", or "string"
42
- self.value = value
43
- self.offset = offset
44
-
45
- def __repr__(self):
46
- return f"FFlag(name={self.name!r}, type={self.type!r}, value={self.value!r})"
47
37
 
48
38
  class FFlagManager:
49
39
  def __init__(self, memory_module):
@@ -109,7 +99,7 @@ class FFlagManager:
109
99
  if offset is None:
110
100
  return None
111
101
  flag_type, value = self._reflect(name, offset)
112
- return FFlag(name, flag_type, value, offset)
102
+ return FFlag(name, flag_type, value, offset, manager=self)
113
103
 
114
104
  def get_many(self, *names: str) -> dict[str, FFlag]:
115
105
  self._ensure_offsets()
@@ -126,7 +116,7 @@ class FFlagManager:
126
116
  for name, offset in self._offsets.items():
127
117
  try:
128
118
  flag_type, value = self._reflect(name, offset)
129
- out[name] = FFlag(name, flag_type, value, offset)
119
+ out[name] = FFlag(name, flag_type, value, offset, manager=self)
130
120
  except OSError:
131
121
  pass
132
122
  return out
@@ -165,7 +155,7 @@ class FFlagManager:
165
155
  raise RuntimeError(f"Cannot write to flag with unknown type '{flag_type}'")
166
156
 
167
157
  new_type, new_value = self._reflect(name, offset)
168
- return FFlag(name, new_type, new_value, offset)
158
+ return FFlag(name, new_type, new_value, offset, manager=self)
169
159
 
170
160
  def __getitem__(self, name: str) -> FFlag:
171
161
  flag = self.get(name)
@@ -7,6 +7,7 @@ from .bytecode import decryptor, encryptor
7
7
 
8
8
  instance_offsets = Offsets["Instance"]
9
9
  basepart_offsets = Offsets["BasePart"]
10
+ primitive_offsets = Offsets["Primitive"]
10
11
  camera_offsets = Offsets["Camera"]
11
12
  gui_offsets = Offsets["GuiObject"]
12
13
  misc_offsets = Offsets["Misc"]
@@ -18,6 +19,13 @@ statsitem_offsets = Offsets["StatsItem"]
18
19
  inputobject_offsets = Offsets["MouseService"] # InputObject uses MouseService offsets
19
20
  animator_offsets = Offsets["Animator"]
20
21
  animationtrack_offsets = Offsets["AnimationTrack"]
22
+ tool_offsets = Offsets["Tool"]
23
+ world_offsets = Offsets["World"]
24
+ sound_offsets = Offsets["Sound"]
25
+ spawnlocation_offsets = Offsets["SpawnLocation"]
26
+ clothing_offsets = Offsets["Clothing"]
27
+ charactermesh_offsets = Offsets["CharacterMesh"]
28
+ attachment_offsets = Offsets["Attachment"]
21
29
 
22
30
  ROTATION_MATRIX_FLOATS = 9
23
31
 
@@ -141,6 +149,11 @@ class RBXInstance:
141
149
  else:
142
150
  raise TypeError("Parent must be set to an RBXInstance, int address, or None.")
143
151
  self._ensure_writable()
152
+
153
+ current_parent = self.Parent
154
+ if current_parent is not None:
155
+ current_parent.Children.remove(self)
156
+
144
157
  self.memory_module.write_long(
145
158
  self.raw_address + instance_offsets["Parent"],
146
159
  target
@@ -181,11 +194,11 @@ class RBXInstance:
181
194
 
182
195
  if "part" in className.lower():
183
196
  CFrameRotation = self.memory_module.read_floats(
184
- self.primitive_address + basepart_offsets["Rotation"],
197
+ self.primitive_address + primitive_offsets["Rotation"],
185
198
  ROTATION_MATRIX_FLOATS
186
199
  )
187
200
  PositionData = self.memory_module.read_floats(
188
- self.primitive_address + basepart_offsets["Position"],
201
+ self.primitive_address + primitive_offsets["Position"],
189
202
  3
190
203
  )
191
204
  elif className == "Camera":
@@ -226,8 +239,8 @@ class RBXInstance:
226
239
 
227
240
  className = self.ClassName
228
241
  if "part" in className.lower():
229
- rotation_address = self.primitive_address + basepart_offsets["Rotation"]
230
- position_address = self.primitive_address + basepart_offsets["Position"]
242
+ rotation_address = self.primitive_address + primitive_offsets["Rotation"]
243
+ position_address = self.primitive_address + primitive_offsets["Position"]
231
244
  elif className == "Camera":
232
245
  rotation_address = self.raw_address + camera_offsets["Rotation"]
233
246
  position_address = self.raw_address + camera_offsets["Position"]
@@ -242,7 +255,7 @@ class RBXInstance:
242
255
  className = self.ClassName.lower()
243
256
  if "part" in className:
244
257
  position_vector3 = self.memory_module.read_floats(
245
- self.primitive_address + basepart_offsets["Position"],
258
+ self.primitive_address + primitive_offsets["Position"],
246
259
  3
247
260
  )
248
261
  return Vector3(*position_vector3)
@@ -263,7 +276,7 @@ class RBXInstance:
263
276
  if "part" in className:
264
277
  vec = self._as_vector3(value, "Position")
265
278
  self.memory_module.write_floats(
266
- self.primitive_address + basepart_offsets["Position"],
279
+ self.primitive_address + primitive_offsets["Position"],
267
280
  (vec.X, vec.Y, vec.Z)
268
281
  )
269
282
 
@@ -284,7 +297,7 @@ class RBXInstance:
284
297
 
285
298
  if "part" in className.lower():
286
299
  velocity_vector3 = self.memory_module.read_floats(
287
- self.primitive_address + basepart_offsets["AssemblyLinearVelocity"],
300
+ self.primitive_address + primitive_offsets["AssemblyLinearVelocity"],
288
301
  3
289
302
  )
290
303
  return Vector3(*velocity_vector3)
@@ -301,7 +314,7 @@ class RBXInstance:
301
314
 
302
315
  self._ensure_writable()
303
316
  self.memory_module.write_floats(
304
- self.primitive_address + basepart_offsets["AssemblyLinearVelocity"],
317
+ self.primitive_address + primitive_offsets["AssemblyLinearVelocity"],
305
318
  (vec.X, vec.Y, vec.Z)
306
319
  )
307
320
 
@@ -311,7 +324,7 @@ class RBXInstance:
311
324
 
312
325
  if "part" in className.lower():
313
326
  velocity_vector3 = self.memory_module.read_floats(
314
- self.primitive_address + basepart_offsets["AssemblyAngularVelocity"],
327
+ self.primitive_address + primitive_offsets["AssemblyAngularVelocity"],
315
328
  3
316
329
  )
317
330
  return Vector3(*velocity_vector3)
@@ -328,7 +341,7 @@ class RBXInstance:
328
341
 
329
342
  self._ensure_writable()
330
343
  self.memory_module.write_floats(
331
- self.primitive_address + basepart_offsets["AssemblyAngularVelocity"],
344
+ self.primitive_address + primitive_offsets["AssemblyAngularVelocity"],
332
345
  (vec.X, vec.Y, vec.Z)
333
346
  )
334
347
 
@@ -367,6 +380,21 @@ class RBXInstance:
367
380
  self.raw_address,
368
381
  proximityprompt_offsets["Enabled"]
369
382
  )
383
+ elif self.ClassName == "Tool":
384
+ return self.memory_module.read_bool(
385
+ self.raw_address,
386
+ tool_offsets["Enabled"]
387
+ )
388
+ elif self.ClassName == "ColorCorrectionEffect":
389
+ return self.memory_module.read_bool(
390
+ self.raw_address,
391
+ Offsets["ColorCorrectionEffect"]["Enabled"]
392
+ )
393
+ elif self.ClassName == "SpawnLocation":
394
+ return self.memory_module.read_bool(
395
+ self.raw_address,
396
+ spawnlocation_offsets["Enabled"]
397
+ )
370
398
  return None
371
399
 
372
400
  @Enabled.setter
@@ -383,8 +411,26 @@ class RBXInstance:
383
411
  self.raw_address + proximityprompt_offsets["Enabled"],
384
412
  value
385
413
  )
414
+ elif self.ClassName == "Tool":
415
+ self._ensure_writable()
416
+ self.memory_module.write_bool(
417
+ self.raw_address + tool_offsets["Enabled"],
418
+ bool(value)
419
+ )
420
+ elif self.ClassName == "ColorCorrectionEffect":
421
+ self._ensure_writable()
422
+ self.memory_module.write_bool(
423
+ self.raw_address + Offsets["ColorCorrectionEffect"]["Enabled"],
424
+ bool(value)
425
+ )
426
+ elif self.ClassName == "SpawnLocation":
427
+ self._ensure_writable()
428
+ self.memory_module.write_bool(
429
+ self.raw_address + spawnlocation_offsets["Enabled"],
430
+ bool(value)
431
+ )
386
432
  else:
387
- raise AttributeError("Enabled is only available on ScreenGui or ProximityPrompt instances.")
433
+ raise AttributeError("Enabled is only available on ScreenGui, ProximityPrompt, Tool, ColorCorrectionEffect, or SpawnLocation instances.")
388
434
 
389
435
  @property
390
436
  def Visible(self):
@@ -420,7 +466,7 @@ class RBXInstance:
420
466
  def Size(self):
421
467
  if "part" in self.ClassName.lower():
422
468
  size_vector3 = self.memory_module.read_floats(
423
- self.primitive_address + basepart_offsets["Size"],
469
+ self.primitive_address + primitive_offsets["Size"],
424
470
  3
425
471
  )
426
472
  return Vector3(*size_vector3)
@@ -433,7 +479,7 @@ class RBXInstance:
433
479
  if "part" in self.ClassName.lower():
434
480
  vec = self._as_vector3(value, "Size")
435
481
  self.memory_module.write_floats(
436
- self.primitive_address + basepart_offsets["Size"],
482
+ self.primitive_address + primitive_offsets["Size"],
437
483
  (vec.X, vec.Y, vec.Z)
438
484
  )
439
485
  else:
@@ -486,7 +532,7 @@ class RBXInstance:
486
532
 
487
533
  def _read_primitive_flags(self):
488
534
  data = self.memory_module.read(
489
- self.primitive_address + basepart_offsets["PrimitiveFlags"],
535
+ self.primitive_address + primitive_offsets["Flags"],
490
536
  1
491
537
  )
492
538
  return int.from_bytes(data, 'little') if data else 0
@@ -494,7 +540,7 @@ class RBXInstance:
494
540
  def _write_primitive_flags(self, flags: int):
495
541
  self._ensure_writable()
496
542
  self.memory_module.write(
497
- self.primitive_address + basepart_offsets["PrimitiveFlags"],
543
+ self.primitive_address + primitive_offsets["Flags"],
498
544
  (flags & 0xFF).to_bytes(1, 'little')
499
545
  )
500
546
 
@@ -907,6 +953,531 @@ class RBXInstance:
907
953
  float(value)
908
954
  )
909
955
 
956
+ @property
957
+ def BackgroundTransparency(self):
958
+ return self.memory_module.read_float(
959
+ self.raw_address,
960
+ gui_offsets["BackgroundTransparency"]
961
+ )
962
+
963
+ @BackgroundTransparency.setter
964
+ def BackgroundTransparency(self, value: float):
965
+ self._ensure_writable()
966
+ self.memory_module.write_float(
967
+ self.raw_address + gui_offsets["BackgroundTransparency"],
968
+ float(value)
969
+ )
970
+
971
+ @property
972
+ def ZIndex(self):
973
+ return self.memory_module.read_int(
974
+ self.raw_address,
975
+ gui_offsets["ZIndex"]
976
+ )
977
+
978
+ @ZIndex.setter
979
+ def ZIndex(self, value: int):
980
+ self._ensure_writable()
981
+ self.memory_module.write_int(
982
+ self.raw_address + gui_offsets["ZIndex"],
983
+ int(value)
984
+ )
985
+
986
+ # tool props #
987
+ @property
988
+ def CanBeDropped(self):
989
+ if self.ClassName != "Tool":
990
+ return None
991
+ return self.memory_module.read_bool(
992
+ self.raw_address,
993
+ tool_offsets["CanBeDropped"]
994
+ )
995
+
996
+ @CanBeDropped.setter
997
+ def CanBeDropped(self, value: bool):
998
+ if self.ClassName != "Tool":
999
+ raise AttributeError("CanBeDropped is only available on Tool instances.")
1000
+ self._ensure_writable()
1001
+ self.memory_module.write_bool(
1002
+ self.raw_address + tool_offsets["CanBeDropped"],
1003
+ bool(value)
1004
+ )
1005
+
1006
+ @property
1007
+ def Grip(self):
1008
+ if self.ClassName != "Tool":
1009
+ return None
1010
+ grip_data = self.memory_module.read_floats(
1011
+ self.raw_address + tool_offsets["Grip"],
1012
+ 12 # CFrame: 9 rotation + 3 position
1013
+ )
1014
+ return grip_data
1015
+
1016
+ @property
1017
+ def ManualActivationOnly(self):
1018
+ if self.ClassName != "Tool":
1019
+ return None
1020
+ return self.memory_module.read_bool(
1021
+ self.raw_address,
1022
+ tool_offsets["ManualActivationOnly"]
1023
+ )
1024
+
1025
+ @ManualActivationOnly.setter
1026
+ def ManualActivationOnly(self, value: bool):
1027
+ if self.ClassName != "Tool":
1028
+ raise AttributeError("ManualActivationOnly is only available on Tool instances.")
1029
+ self._ensure_writable()
1030
+ self.memory_module.write_bool(
1031
+ self.raw_address + tool_offsets["ManualActivationOnly"],
1032
+ bool(value)
1033
+ )
1034
+
1035
+ @property
1036
+ def RequiresHandle(self):
1037
+ if self.ClassName != "Tool":
1038
+ return None
1039
+ return self.memory_module.read_bool(
1040
+ self.raw_address,
1041
+ tool_offsets["RequiresHandle"]
1042
+ )
1043
+
1044
+ @RequiresHandle.setter
1045
+ def RequiresHandle(self, value: bool):
1046
+ if self.ClassName != "Tool":
1047
+ raise AttributeError("RequiresHandle is only available on Tool instances.")
1048
+ self._ensure_writable()
1049
+ self.memory_module.write_bool(
1050
+ self.raw_address + tool_offsets["RequiresHandle"],
1051
+ bool(value)
1052
+ )
1053
+
1054
+ @property
1055
+ def TextureId(self):
1056
+ if self.ClassName != "Tool":
1057
+ return None
1058
+ return self.memory_module.read_string(
1059
+ self.raw_address,
1060
+ tool_offsets["TextureId"]
1061
+ )
1062
+
1063
+ @TextureId.setter
1064
+ def TextureId(self, value: str):
1065
+ if self.ClassName != "Tool":
1066
+ raise AttributeError("TextureId is only available on Tool instances.")
1067
+ self._ensure_writable()
1068
+ self.memory_module.write_string(
1069
+ self.raw_address + tool_offsets["TextureId"],
1070
+ str(value)
1071
+ )
1072
+
1073
+ @property
1074
+ def Tooltip(self):
1075
+ if self.ClassName != "Tool":
1076
+ return None
1077
+ return self.memory_module.read_string(
1078
+ self.raw_address,
1079
+ tool_offsets["Tooltip"]
1080
+ )
1081
+
1082
+ @Tooltip.setter
1083
+ def Tooltip(self, value: str):
1084
+ if self.ClassName != "Tool":
1085
+ raise AttributeError("Tooltip is only available on Tool instances.")
1086
+ self._ensure_writable()
1087
+ self.memory_module.write_string(
1088
+ self.raw_address + tool_offsets["Tooltip"],
1089
+ str(value)
1090
+ )
1091
+
1092
+ # colorcorrection props #
1093
+ @property
1094
+ def Brightness(self):
1095
+ if self.ClassName == "ColorCorrectionEffect":
1096
+ return self.memory_module.read_float(
1097
+ self.raw_address,
1098
+ Offsets["ColorCorrectionEffect"]["Brightness"]
1099
+ )
1100
+ return None
1101
+
1102
+ @Brightness.setter
1103
+ def Brightness(self, value: float):
1104
+ if self.ClassName == "ColorCorrectionEffect":
1105
+ self._ensure_writable()
1106
+ self.memory_module.write_float(
1107
+ self.raw_address + Offsets["ColorCorrectionEffect"]["Brightness"],
1108
+ float(value)
1109
+ )
1110
+ else:
1111
+ raise AttributeError("Brightness is only available on ColorCorrectionEffect instances (use LightingService.Brightness for Lighting).")
1112
+
1113
+ @property
1114
+ def Contrast(self):
1115
+ if self.ClassName != "ColorCorrectionEffect":
1116
+ return None
1117
+ return self.memory_module.read_float(
1118
+ self.raw_address,
1119
+ Offsets["ColorCorrectionEffect"]["Contrast"]
1120
+ )
1121
+
1122
+ @Contrast.setter
1123
+ def Contrast(self, value: float):
1124
+ if self.ClassName != "ColorCorrectionEffect":
1125
+ raise AttributeError("Contrast is only available on ColorCorrectionEffect instances.")
1126
+ self._ensure_writable()
1127
+ self.memory_module.write_float(
1128
+ self.raw_address + Offsets["ColorCorrectionEffect"]["Contrast"],
1129
+ float(value)
1130
+ )
1131
+
1132
+ @property
1133
+ def TintColor(self):
1134
+ if self.ClassName != "ColorCorrectionEffect":
1135
+ return None
1136
+ color_data = self.memory_module.read_floats(
1137
+ self.raw_address + Offsets["ColorCorrectionEffect"]["TintColor"],
1138
+ 3
1139
+ )
1140
+ return Color3(*color_data)
1141
+
1142
+ @TintColor.setter
1143
+ def TintColor(self, value):
1144
+ if self.ClassName != "ColorCorrectionEffect":
1145
+ raise AttributeError("TintColor is only available on ColorCorrectionEffect instances.")
1146
+ self._ensure_writable()
1147
+ vec = self._as_color3(value, "TintColor")
1148
+ self.memory_module.write_floats(
1149
+ self.raw_address + Offsets["ColorCorrectionEffect"]["TintColor"],
1150
+ (vec.X, vec.Y, vec.Z)
1151
+ )
1152
+
1153
+ # attachment props #
1154
+ @property
1155
+ def AttachmentPosition(self):
1156
+ if self.ClassName != "Attachment":
1157
+ return None
1158
+ pos_data = self.memory_module.read_floats(
1159
+ self.raw_address + attachment_offsets["Position"],
1160
+ 3
1161
+ )
1162
+ return Vector3(*pos_data)
1163
+
1164
+ @AttachmentPosition.setter
1165
+ def AttachmentPosition(self, value):
1166
+ if self.ClassName != "Attachment":
1167
+ raise AttributeError("AttachmentPosition is only available on Attachment instances.")
1168
+ self._ensure_writable()
1169
+ vec = self._as_vector3(value, "AttachmentPosition")
1170
+ self.memory_module.write_floats(
1171
+ self.raw_address + attachment_offsets["Position"],
1172
+ (vec.X, vec.Y, vec.Z)
1173
+ )
1174
+
1175
+ # charactermesh props #
1176
+ @property
1177
+ def BaseTextureId(self):
1178
+ if self.ClassName != "CharacterMesh":
1179
+ return None
1180
+ return self.memory_module.read_long(
1181
+ self.raw_address,
1182
+ charactermesh_offsets["BaseTextureId"]
1183
+ )
1184
+
1185
+ @BaseTextureId.setter
1186
+ def BaseTextureId(self, value: int):
1187
+ if self.ClassName != "CharacterMesh":
1188
+ raise AttributeError("BaseTextureId is only available on CharacterMesh instances.")
1189
+ self._ensure_writable()
1190
+ self.memory_module.write_long(
1191
+ self.raw_address + charactermesh_offsets["BaseTextureId"],
1192
+ int(value)
1193
+ )
1194
+
1195
+ @property
1196
+ def OverlayTextureId(self):
1197
+ if self.ClassName != "CharacterMesh":
1198
+ return None
1199
+ return self.memory_module.read_long(
1200
+ self.raw_address,
1201
+ charactermesh_offsets["OverlayTextureId"]
1202
+ )
1203
+
1204
+ @OverlayTextureId.setter
1205
+ def OverlayTextureId(self, value: int):
1206
+ if self.ClassName != "CharacterMesh":
1207
+ raise AttributeError("OverlayTextureId is only available on CharacterMesh instances.")
1208
+ self._ensure_writable()
1209
+ self.memory_module.write_long(
1210
+ self.raw_address + charactermesh_offsets["OverlayTextureId"],
1211
+ int(value)
1212
+ )
1213
+
1214
+ @property
1215
+ def BodyPart(self):
1216
+ if self.ClassName != "CharacterMesh":
1217
+ return None
1218
+ return self.memory_module.read_int(
1219
+ self.raw_address,
1220
+ charactermesh_offsets["BodyPart"]
1221
+ )
1222
+
1223
+ @property
1224
+ def CharacterMeshId(self):
1225
+ if self.ClassName != "CharacterMesh":
1226
+ return None
1227
+ return self.memory_module.read_long(
1228
+ self.raw_address,
1229
+ charactermesh_offsets["MeshId"]
1230
+ )
1231
+
1232
+ # clothing props (Shirt/Pants) #
1233
+ @property
1234
+ def ClothingColor3(self):
1235
+ cn = self.ClassName
1236
+ if cn != "Shirt" and cn != "Pants":
1237
+ return None
1238
+ color_data = self.memory_module.read_floats(
1239
+ self.raw_address + clothing_offsets["Color3"],
1240
+ 3
1241
+ )
1242
+ return Color3(*color_data)
1243
+
1244
+ @ClothingColor3.setter
1245
+ def ClothingColor3(self, value):
1246
+ cn = self.ClassName
1247
+ if cn != "Shirt" and cn != "Pants":
1248
+ raise AttributeError("ClothingColor3 is only available on Shirt or Pants instances.")
1249
+ self._ensure_writable()
1250
+ vec = self._as_color3(value, "ClothingColor3")
1251
+ self.memory_module.write_floats(
1252
+ self.raw_address + clothing_offsets["Color3"],
1253
+ (vec.X, vec.Y, vec.Z)
1254
+ )
1255
+
1256
+ @property
1257
+ def Template(self):
1258
+ cn = self.ClassName
1259
+ if cn != "Shirt" and cn != "Pants":
1260
+ return None
1261
+ return self.memory_module.read_string(
1262
+ self.raw_address,
1263
+ clothing_offsets["Template"]
1264
+ )
1265
+
1266
+ @Template.setter
1267
+ def Template(self, value: str):
1268
+ cn = self.ClassName
1269
+ if cn != "Shirt" and cn != "Pants":
1270
+ raise AttributeError("Template is only available on Shirt or Pants instances.")
1271
+ self._ensure_writable()
1272
+ self.memory_module.write_string(
1273
+ self.raw_address + clothing_offsets["Template"],
1274
+ str(value)
1275
+ )
1276
+
1277
+ # sound props #
1278
+ @property
1279
+ def SoundId(self):
1280
+ if self.ClassName != "Sound":
1281
+ return None
1282
+ return self.memory_module.read_string(
1283
+ self.raw_address,
1284
+ sound_offsets["SoundId"]
1285
+ )
1286
+
1287
+ @SoundId.setter
1288
+ def SoundId(self, value: str):
1289
+ if self.ClassName != "Sound":
1290
+ raise AttributeError("SoundId is only available on Sound instances.")
1291
+ self._ensure_writable()
1292
+ self.memory_module.write_string(
1293
+ self.raw_address + sound_offsets["SoundId"],
1294
+ str(value)
1295
+ )
1296
+
1297
+ @property
1298
+ def Volume(self):
1299
+ if self.ClassName != "Sound":
1300
+ return None
1301
+ return self.memory_module.read_float(
1302
+ self.raw_address,
1303
+ sound_offsets["Volume"]
1304
+ )
1305
+
1306
+ @Volume.setter
1307
+ def Volume(self, value: float):
1308
+ if self.ClassName != "Sound":
1309
+ raise AttributeError("Volume is only available on Sound instances.")
1310
+ self._ensure_writable()
1311
+ self.memory_module.write_float(
1312
+ self.raw_address + sound_offsets["Volume"],
1313
+ float(value)
1314
+ )
1315
+
1316
+ @property
1317
+ def PlaybackSpeed(self):
1318
+ if self.ClassName != "Sound":
1319
+ return None
1320
+ return self.memory_module.read_float(
1321
+ self.raw_address,
1322
+ sound_offsets["PlaybackSpeed"]
1323
+ )
1324
+
1325
+ @PlaybackSpeed.setter
1326
+ def PlaybackSpeed(self, value: float):
1327
+ if self.ClassName != "Sound":
1328
+ raise AttributeError("PlaybackSpeed is only available on Sound instances.")
1329
+ self._ensure_writable()
1330
+ self.memory_module.write_float(
1331
+ self.raw_address + sound_offsets["PlaybackSpeed"],
1332
+ float(value)
1333
+ )
1334
+
1335
+ @property
1336
+ def Looped(self):
1337
+ if self.ClassName != "Sound":
1338
+ return None
1339
+ return self.memory_module.read_bool(
1340
+ self.raw_address,
1341
+ sound_offsets["Looped"]
1342
+ )
1343
+
1344
+ @Looped.setter
1345
+ def Looped(self, value: bool):
1346
+ if self.ClassName != "Sound":
1347
+ raise AttributeError("Looped is only available on Sound instances.")
1348
+ self._ensure_writable()
1349
+ self.memory_module.write_bool(
1350
+ self.raw_address + sound_offsets["Looped"],
1351
+ bool(value)
1352
+ )
1353
+
1354
+ @property
1355
+ def RollOffMaxDistance(self):
1356
+ if self.ClassName != "Sound":
1357
+ return None
1358
+ return self.memory_module.read_float(
1359
+ self.raw_address,
1360
+ sound_offsets["RollOffMaxDistance"]
1361
+ )
1362
+
1363
+ @RollOffMaxDistance.setter
1364
+ def RollOffMaxDistance(self, value: float):
1365
+ if self.ClassName != "Sound":
1366
+ raise AttributeError("RollOffMaxDistance is only available on Sound instances.")
1367
+ self._ensure_writable()
1368
+ self.memory_module.write_float(
1369
+ self.raw_address + sound_offsets["RollOffMaxDistance"],
1370
+ float(value)
1371
+ )
1372
+
1373
+ @property
1374
+ def RollOffMinDistance(self):
1375
+ if self.ClassName != "Sound":
1376
+ return None
1377
+ return self.memory_module.read_float(
1378
+ self.raw_address,
1379
+ sound_offsets["RollOffMinDistance"]
1380
+ )
1381
+
1382
+ @RollOffMinDistance.setter
1383
+ def RollOffMinDistance(self, value: float):
1384
+ if self.ClassName != "Sound":
1385
+ raise AttributeError("RollOffMinDistance is only available on Sound instances.")
1386
+ self._ensure_writable()
1387
+ self.memory_module.write_float(
1388
+ self.raw_address + sound_offsets["RollOffMinDistance"],
1389
+ float(value)
1390
+ )
1391
+
1392
+ @property
1393
+ def SoundGroup(self):
1394
+ if self.ClassName != "Sound":
1395
+ return None
1396
+ ptr = self.memory_module.get_pointer(
1397
+ self.raw_address,
1398
+ sound_offsets["SoundGroup"]
1399
+ )
1400
+ if ptr == 0:
1401
+ return None
1402
+ return RBXInstance(ptr, self.memory_module)
1403
+
1404
+ # spawnlocation props #
1405
+ @property
1406
+ def AllowTeamChangeOnTouch(self):
1407
+ if self.ClassName != "SpawnLocation":
1408
+ return None
1409
+ return self.memory_module.read_bool(
1410
+ self.raw_address,
1411
+ spawnlocation_offsets["AllowTeamChangeOnTouch"]
1412
+ )
1413
+
1414
+ @AllowTeamChangeOnTouch.setter
1415
+ def AllowTeamChangeOnTouch(self, value: bool):
1416
+ if self.ClassName != "SpawnLocation":
1417
+ raise AttributeError("AllowTeamChangeOnTouch is only available on SpawnLocation instances.")
1418
+ self._ensure_writable()
1419
+ self.memory_module.write_bool(
1420
+ self.raw_address + spawnlocation_offsets["AllowTeamChangeOnTouch"],
1421
+ bool(value)
1422
+ )
1423
+
1424
+ @property
1425
+ def Neutral(self):
1426
+ if self.ClassName != "SpawnLocation":
1427
+ return None
1428
+ return self.memory_module.read_bool(
1429
+ self.raw_address,
1430
+ spawnlocation_offsets["Neutral"]
1431
+ )
1432
+
1433
+ @Neutral.setter
1434
+ def Neutral(self, value: bool):
1435
+ if self.ClassName != "SpawnLocation":
1436
+ raise AttributeError("Neutral is only available on SpawnLocation instances.")
1437
+ self._ensure_writable()
1438
+ self.memory_module.write_bool(
1439
+ self.raw_address + spawnlocation_offsets["Neutral"],
1440
+ bool(value)
1441
+ )
1442
+
1443
+ @property
1444
+ def ForcefieldDuration(self):
1445
+ if self.ClassName != "SpawnLocation":
1446
+ return None
1447
+ return self.memory_module.read_int(
1448
+ self.raw_address,
1449
+ spawnlocation_offsets["ForcefieldDuration"]
1450
+ )
1451
+
1452
+ @ForcefieldDuration.setter
1453
+ def ForcefieldDuration(self, value: int):
1454
+ if self.ClassName != "SpawnLocation":
1455
+ raise AttributeError("ForcefieldDuration is only available on SpawnLocation instances.")
1456
+ self._ensure_writable()
1457
+ self.memory_module.write_int(
1458
+ self.raw_address + spawnlocation_offsets["ForcefieldDuration"],
1459
+ int(value)
1460
+ )
1461
+
1462
+ @property
1463
+ def TeamColor(self):
1464
+ if self.ClassName != "SpawnLocation":
1465
+ return None
1466
+ return self.memory_module.read_int(
1467
+ self.raw_address,
1468
+ spawnlocation_offsets["TeamColor"]
1469
+ )
1470
+
1471
+ @TeamColor.setter
1472
+ def TeamColor(self, value: int):
1473
+ if self.ClassName != "SpawnLocation":
1474
+ raise AttributeError("TeamColor is only available on SpawnLocation instances.")
1475
+ self._ensure_writable()
1476
+ self.memory_module.write_int(
1477
+ self.raw_address + spawnlocation_offsets["TeamColor"],
1478
+ int(value)
1479
+ )
1480
+
910
1481
  # humanoid props #
911
1482
  @property
912
1483
  def WalkSpeed(self):
@@ -1353,6 +1924,35 @@ class RBXInstance:
1353
1924
 
1354
1925
  self.memory_module.write_long(bytecode_ptr + Offsets["ByteCode"]["Pointer"], new_content_ptr)
1355
1926
  self.memory_module.write_int(bytecode_ptr + Offsets["ByteCode"]["Size"], new_size)
1927
+
1928
+ # script identification #
1929
+ @property
1930
+ def GUID(self):
1931
+ classname = self.ClassName
1932
+ if classname == "LocalScript":
1933
+ guid_offset = Offsets["LocalScript"]["GUID"]
1934
+ elif classname == "ModuleScript":
1935
+ guid_offset = Offsets["ModuleScript"]["GUID"]
1936
+ else:
1937
+ return None
1938
+ return self.memory_module.read_string(
1939
+ self.raw_address,
1940
+ guid_offset
1941
+ )
1942
+
1943
+ @property
1944
+ def Hash(self):
1945
+ classname = self.ClassName
1946
+ if classname == "LocalScript":
1947
+ hash_offset = Offsets["LocalScript"]["Hash"]
1948
+ elif classname == "ModuleScript":
1949
+ hash_offset = Offsets["ModuleScript"]["Hash"]
1950
+ else:
1951
+ return None
1952
+ return self.memory_module.read_string(
1953
+ self.raw_address,
1954
+ hash_offset
1955
+ )
1356
1956
 
1357
1957
  # functions #
1358
1958
  def GetChildren(self):
@@ -1725,6 +2325,36 @@ class PlayerClass(RBXInstance):
1725
2325
  int(value)
1726
2326
  )
1727
2327
 
2328
+ @property
2329
+ def HealthDisplayDistance(self):
2330
+ return self.memory_module.read_float(
2331
+ self.raw_address,
2332
+ self.offset_base["HealthDisplayDistance"]
2333
+ )
2334
+
2335
+ @HealthDisplayDistance.setter
2336
+ def HealthDisplayDistance(self, value: float):
2337
+ self._ensure_writable()
2338
+ self.memory_module.write_float(
2339
+ self.raw_address + self.offset_base["HealthDisplayDistance"],
2340
+ float(value)
2341
+ )
2342
+
2343
+ @property
2344
+ def NameDisplayDistance(self):
2345
+ return self.memory_module.read_float(
2346
+ self.raw_address,
2347
+ self.offset_base["NameDisplayDistance"]
2348
+ )
2349
+
2350
+ @NameDisplayDistance.setter
2351
+ def NameDisplayDistance(self, value: float):
2352
+ self._ensure_writable()
2353
+ self.memory_module.write_float(
2354
+ self.raw_address + self.offset_base["NameDisplayDistance"],
2355
+ float(value)
2356
+ )
2357
+
1728
2358
  class CameraClass(RBXInstance):
1729
2359
  def __init__(self, memory_module, camera: RBXInstance):
1730
2360
  super().__init__(camera.raw_address, memory_module)
@@ -2235,27 +2865,27 @@ class WorkspaceService(ServiceBase):
2235
2865
 
2236
2866
  @property
2237
2867
  def Gravity(self):
2238
- GravityContainer = self.memory_module.get_pointer(
2868
+ World = self.memory_module.get_pointer(
2239
2869
  self.instance.raw_address,
2240
- self.offset_base["GravityContainer"]
2870
+ self.offset_base["World"]
2241
2871
  )
2242
2872
 
2243
2873
  return self.memory_module.read_float(
2244
- GravityContainer,
2245
- self.offset_base["Gravity"]
2874
+ World,
2875
+ world_offsets["Gravity"]
2246
2876
  )
2247
2877
 
2248
2878
  @Gravity.setter
2249
2879
  def Gravity(self, value: float):
2250
2880
  self._ensure_writable()
2251
2881
 
2252
- GravityContainer = self.memory_module.get_pointer(
2882
+ World = self.memory_module.get_pointer(
2253
2883
  self.instance.raw_address,
2254
- self.offset_base["GravityContainer"]
2884
+ self.offset_base["World"]
2255
2885
  )
2256
2886
 
2257
2887
  self.memory_module.write_float(
2258
- GravityContainer + self.offset_base["Gravity"],
2888
+ World + world_offsets["Gravity"],
2259
2889
  float(value)
2260
2890
  )
2261
2891
 
@@ -2269,6 +2899,35 @@ class WorkspaceService(ServiceBase):
2269
2899
  self.offset_base["DistributedGameTime"]
2270
2900
  )
2271
2901
 
2902
+ @property
2903
+ def WorldStepsPerSec(self):
2904
+ if self.failed:
2905
+ return 0.0
2906
+
2907
+ World = self.memory_module.get_pointer(
2908
+ self.instance.raw_address,
2909
+ self.offset_base["World"]
2910
+ )
2911
+
2912
+ return self.memory_module.read_float(
2913
+ World,
2914
+ world_offsets["worldStepsPerSec"]
2915
+ )
2916
+
2917
+ @WorldStepsPerSec.setter
2918
+ def WorldStepsPerSec(self, value: float):
2919
+ self._ensure_writable()
2920
+
2921
+ World = self.memory_module.get_pointer(
2922
+ self.instance.raw_address,
2923
+ self.offset_base["World"]
2924
+ )
2925
+
2926
+ self.memory_module.write_float(
2927
+ World + world_offsets["worldStepsPerSec"],
2928
+ float(value)
2929
+ )
2930
+
2272
2931
  class LightingService(ServiceBase):
2273
2932
  def __init__(self, memory_module, game: DataModel):
2274
2933
  super().__init__()
@@ -2469,6 +3128,77 @@ class LightingService(ServiceBase):
2469
3128
  float(value)
2470
3129
  )
2471
3130
 
3131
+ @property
3132
+ def Sky(self):
3133
+ if self.failed: return None
3134
+ sky_ptr = self.memory_module.get_pointer(
3135
+ self.instance.raw_address,
3136
+ self.offset_base["Sky"]
3137
+ )
3138
+ if sky_ptr == 0:
3139
+ return None
3140
+ return RBXInstance(sky_ptr, self.memory_module)
3141
+
3142
+ @property
3143
+ def Source(self):
3144
+ if self.failed: return None
3145
+ return self.memory_module.read_int(
3146
+ self.instance.raw_address,
3147
+ self.offset_base["Source"]
3148
+ )
3149
+
3150
+ @property
3151
+ def SunPosition(self):
3152
+ if self.failed: return None
3153
+ pos_data = self.memory_module.read_floats(
3154
+ self.instance.raw_address + self.offset_base["SunPosition"],
3155
+ 3
3156
+ )
3157
+ return Vector3(*pos_data)
3158
+
3159
+ @property
3160
+ def MoonPosition(self):
3161
+ if self.failed: return None
3162
+ pos_data = self.memory_module.read_floats(
3163
+ self.instance.raw_address + self.offset_base["MoonPosition"],
3164
+ 3
3165
+ )
3166
+ return Vector3(*pos_data)
3167
+
3168
+ @property
3169
+ def EnvironmentDiffuseScale(self):
3170
+ if self.failed: return 0.0
3171
+ return self.memory_module.read_float(
3172
+ self.instance.raw_address,
3173
+ self.offset_base["EnvironmentDiffuseScale"]
3174
+ )
3175
+
3176
+ @EnvironmentDiffuseScale.setter
3177
+ def EnvironmentDiffuseScale(self, value: float):
3178
+ if self.failed: return
3179
+ self._ensure_writable()
3180
+ self.memory_module.write_float(
3181
+ self.instance.raw_address + self.offset_base["EnvironmentDiffuseScale"],
3182
+ float(value)
3183
+ )
3184
+
3185
+ @property
3186
+ def EnvironmentSpecularScale(self):
3187
+ if self.failed: return 0.0
3188
+ return self.memory_module.read_float(
3189
+ self.instance.raw_address,
3190
+ self.offset_base["EnvironmentSpecularScale"]
3191
+ )
3192
+
3193
+ @EnvironmentSpecularScale.setter
3194
+ def EnvironmentSpecularScale(self, value: float):
3195
+ if self.failed: return
3196
+ self._ensure_writable()
3197
+ self.memory_module.write_float(
3198
+ self.instance.raw_address + self.offset_base["EnvironmentSpecularScale"],
3199
+ float(value)
3200
+ )
3201
+
2472
3202
  class InputObject(RBXInstance):
2473
3203
  def __init__(self, raw_address: int, memory_module):
2474
3204
  super().__init__(raw_address, memory_module)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robloxmemoryapi
3
- Version: 0.2.2.1
3
+ Version: 0.2.4
4
4
  Summary: Python Library that abstracts reading and writing data from the Roblox DataModel
5
5
  Author-email: upio <notpoiu@users.noreply.github.com>, mstudio45 <mstudio45@users.noreply.github.com>, ActualMasterOogway <ActualMasterOogway@users.noreply.github.com>
6
6
  License: Copyright 2025 upio, mstudio45, master oogway