Skip to content

Commit 5e580cd

Browse files
committed
2026-04-30T0307Z
1 parent 29a30a6 commit 5e580cd

14 files changed

Lines changed: 352 additions & 1238 deletions

File tree

.vscode/launch.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"server",
3737
"--config",
3838
"${file}",
39+
"--clear_temp_cache",
3940
],
4041
"console": "integratedTerminal",
4142
"justMyCode": true
@@ -51,6 +52,7 @@
5152
"--config",
5253
"${file}",
5354
"--debug",
55+
"--clear_temp_cache",
5456
],
5557
"console": "integratedTerminal",
5658
"justMyCode": true
@@ -68,6 +70,7 @@
6870
"VisualPlugin",
6971
"--config",
7072
"${file}",
73+
"--clear_temp_cache",
7174
],
7275
"console": "integratedTerminal",
7376
"justMyCode": true

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- feat: add GameConfig option `server_core.retrieve_membership_type(id_num, user_code)`
1212
- feat: add `/Game/Badge/HasBadge.ashx` and `/assets/award-badge` endpoints
1313
- feat: support for modern _CSGMDL5_ unions
14-
- fix: disable SSL certificate verification to work around PyInstaller incompatiblity #160
14+
- [fix](https://github.com/Windows81/Roblox-Freedom-Distribution/pull/160): disable SSL certificate verification to work around PyInstaller incompatiblity
1515
- fix: route `/Asset` and `/Asset/` to existing `/v1/asset`
1616
- fix: persistence `target` not existing on route `/persistence/set`
1717
- fix: repaired `--clear_temp_cache` command flag

Source/assets/serialisers/csg/csgmdl5.py

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
https://github.com/krakow10/rbx_mesh/blob/master/src/mesh_data.rs#L242
66
'''
77

8-
from .util import xor_encrypt, create_hash, CSG_HEADER
8+
from . import util
99
import itertools
1010
import struct
1111
import io
1212

13-
from assets.serialisers.csg import util
14-
1513

1614
def wrap_number(x: float, min_val: float, max_val: float) -> float:
1715
range_val = max_val - min_val
@@ -21,7 +19,7 @@ def wrap_number(x: float, min_val: float, max_val: float) -> float:
2119
return wrapped + min_val
2220

2321

24-
def quantize(x: float, max_val=0x7f) -> float:
22+
def quantize(x: float, max_val=0x7F) -> float:
2523
return wrap_number(
2624
x - max_val,
2725
-max_val - 1,
@@ -91,11 +89,8 @@ def trim_indices(indices: list[int], range_markers: list[int]) -> list[int]:
9189

9290

9391
def read_chunks_vector3(stream: io.BytesIO) -> list[bytes]:
94-
# Reads an unsigned short (2 bytes).
95-
count = struct.unpack('<H', stream.read(2))[0]
96-
97-
# Reads an unsigned int (4 bytes).
98-
data_len = struct.unpack('<I', stream.read(4))[0]
92+
count = util.read_u16(stream)
93+
data_len = util.read_u32(stream)
9994

10095
result = list[bytes]()
10196
for _ in range(count):
@@ -104,17 +99,16 @@ def read_chunks_vector3(stream: io.BytesIO) -> list[bytes]:
10499
'fff',
105100

106101
# Quantises to 4 bits and pack as float.
107-
quantize(struct.unpack('<h', stream.read(2))[0], max_val=15),
108-
quantize(struct.unpack('<h', stream.read(2))[0], max_val=15),
109-
quantize(struct.unpack('<h', stream.read(2))[0], max_val=15),
102+
quantize(struct.unpack('<h', stream.read(2))[0], max_val=0xF),
103+
quantize(struct.unpack('<h', stream.read(2))[0], max_val=0xF),
104+
quantize(struct.unpack('<h', stream.read(2))[0], max_val=0xF),
110105
))
111106

112107
return result
113108

114109

115110
def read_chunks(stream: io.BytesIO, individual_size: int) -> list[bytes]:
116-
# Reads an unsigned short (2 bytes).
117-
count = struct.unpack('<H', stream.read(2))[0]
111+
count = util.read_u16(stream)
118112

119113
result = list[bytes]()
120114
for _ in range(count):
@@ -124,8 +118,7 @@ def read_chunks(stream: io.BytesIO, individual_size: int) -> list[bytes]:
124118

125119

126120
def read_positions(stream: io.BytesIO) -> list[bytes]:
127-
# Reads an unsigned short (2 bytes).
128-
count = struct.unpack('<H', stream.read(2))[0]
121+
count = util.read_u16(stream)
129122

130123
result = list[bytes]()
131124
for _ in range(count):
@@ -138,8 +131,7 @@ def read_positions(stream: io.BytesIO) -> list[bytes]:
138131

139132

140133
def read_normal_idens(stream: io.BytesIO) -> list[bytes]:
141-
# Reads an unsigned short (2 bytes).
142-
count = struct.unpack('<H', stream.read(2))[0]
134+
count = util.read_u16(stream)
143135

144136
result = list[bytes]()
145137
for _ in range(count):
@@ -152,46 +144,37 @@ def read_normal_idens(stream: io.BytesIO) -> list[bytes]:
152144

153145

154146
def read_vertices(stream: io.BytesIO) -> tuple[list[int], int]:
155-
# Reads an unsigned int (4 bytes).
156-
vertex_count = struct.unpack('<I', stream.read(4))[0]
157-
158-
# Reads an unsigned int (4 bytes).
159-
vertex_data_len = struct.unpack('<I', stream.read(4))[0]
147+
vertex_count = util.read_u32(stream)
148+
vertex_data_len = util.read_u32(stream)
160149

161150
vertex_data = list[int]()
162151
for _ in range(vertex_data_len):
163-
vertex_data.append(
164-
# Reads a single byte (1 byte).
165-
struct.unpack('<B', stream.read(1))[0],
166-
)
152+
vertex_data.append(util.read_u8(stream))
167153

168154
return (vertex_data, vertex_count)
169155

170156

171157
def read_range_markers(stream: io.BytesIO) -> list[int]:
172158
# Reads an unsigned char (1 byte).
173-
n_range_markers = struct.unpack('<B', stream.read(1))[0]
159+
n_range_markers = util.read_u8(stream)
174160

175161
range_markers = list[int]()
176162
for _ in range(n_range_markers):
177-
range_markers.append(
178-
# Reads an unsigned int (4 bytes).
179-
struct.unpack('<I', stream.read(4))[0],
180-
)
163+
range_markers.append(util.read_u32(stream))
181164

182165
return range_markers
183166

184167

185168
def convert_to_csgmdl2(csgmdl_buffer: bytes) -> bytes:
186-
# Create a buffer stream for reading the data
169+
# Creates a buffer stream for reading the data.
187170
stream = io.BytesIO(csgmdl_buffer)
188171

189-
# Define the header and check if it matches the expected value
172+
# Defines the header and check if it matches the expected value.
190173
header = stream.read(10)
191174
assert header == util.CSG_HEADER.MDL5.value, "Buffer is not CSGMDLV5"
192175

193176
# Reads three floats (12 bytes).
194-
positions = read_chunks(stream, 3*4)
177+
positions = read_chunks(stream, individual_size=3*4)
195178

196179
normals = read_chunks_vector3(stream)
197180

@@ -281,12 +264,12 @@ def convert_to_csgmdl2(csgmdl_buffer: bytes) -> bytes:
281264
'''
282265
return b''.join([
283266

284-
# Skip re-encrypting header since the header is already encrypted.
285-
CSG_HEADER.MDL2.value,
267+
# Skips re-encrypting header since the header is already encrypted.
268+
util.CSG_HEADER.MDL2.value,
286269

287-
xor_encrypt(b''.join([
270+
util.xor_encrypt(b''.join([
288271
# Hash
289-
create_hash(
272+
util.create_hash(
290273
vertices=vertices_packed,
291274
indices=indices_packed,
292275
salt=b'67'*8,
@@ -307,5 +290,5 @@ def convert_to_csgmdl2(csgmdl_buffer: bytes) -> bytes:
307290
# Index data
308291
indices_packed,
309292

310-
]), offset=len(CSG_HEADER.MDL2.value))
293+
]), offset=len(util.CSG_HEADER.MDL2.value))
311294
])

0 commit comments

Comments
 (0)