albibong 1.0.0__py3-none-any.whl

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 (46) hide show
  1. albibong/__init__.py +82 -0
  2. albibong/classes/__init__.py +0 -0
  3. albibong/classes/character.py +83 -0
  4. albibong/classes/coords.py +9 -0
  5. albibong/classes/dungeon.py +59 -0
  6. albibong/classes/item.py +41 -0
  7. albibong/classes/location.py +48 -0
  8. albibong/classes/logger.py +122 -0
  9. albibong/classes/packet_handler.py +61 -0
  10. albibong/classes/world_data.py +327 -0
  11. albibong/gui_dist/No Equipment.png +0 -0
  12. albibong/gui_dist/assets/index-BFSx0nua.css +1 -0
  13. albibong/gui_dist/assets/index-DAndaN_4.js +161 -0
  14. albibong/gui_dist/fame.png +0 -0
  15. albibong/gui_dist/index.html +14 -0
  16. albibong/gui_dist/re_spec.png +0 -0
  17. albibong/gui_dist/silver.png +0 -0
  18. albibong/gui_dist/vite.svg +1 -0
  19. albibong/photon_packet_parser/__init__.py +4 -0
  20. albibong/photon_packet_parser/command_type.py +7 -0
  21. albibong/photon_packet_parser/crc_calculator.py +16 -0
  22. albibong/photon_packet_parser/event_data.py +4 -0
  23. albibong/photon_packet_parser/message_type.py +6 -0
  24. albibong/photon_packet_parser/number_serializer.py +22 -0
  25. albibong/photon_packet_parser/operation_request.py +4 -0
  26. albibong/photon_packet_parser/operation_response.py +6 -0
  27. albibong/photon_packet_parser/photon_packet_parser.py +168 -0
  28. albibong/photon_packet_parser/protocol16_deserializer.py +302 -0
  29. albibong/photon_packet_parser/protocol16_type.py +23 -0
  30. albibong/photon_packet_parser/segmented_packet.py +5 -0
  31. albibong/resources/EventCode.py +579 -0
  32. albibong/resources/OperationCode.py +499 -0
  33. albibong/resources/event_code.json +577 -0
  34. albibong/resources/items.json +54035 -0
  35. albibong/resources/maps.json +3565 -0
  36. albibong/resources/operation_code.json +497 -0
  37. albibong/threads/__init__.py +0 -0
  38. albibong/threads/http_server.py +60 -0
  39. albibong/threads/packet_handler_thread.py +32 -0
  40. albibong/threads/sniffer_thread.py +27 -0
  41. albibong/threads/websocket_server.py +168 -0
  42. albibong-1.0.0.dist-info/METADATA +15 -0
  43. albibong-1.0.0.dist-info/RECORD +46 -0
  44. albibong-1.0.0.dist-info/WHEEL +4 -0
  45. albibong-1.0.0.dist-info/entry_points.txt +2 -0
  46. albibong-1.0.0.dist-info/licenses/LICENSE +19 -0
Binary file
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vite + React + TS</title>
8
+ <script type="module" crossorigin src="/assets/index-DAndaN_4.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-BFSx0nua.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
Binary file
Binary file
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1,4 @@
1
+ from albibong.photon_packet_parser.photon_packet_parser import PhotonPacketParser
2
+ from albibong.photon_packet_parser.event_data import EventData
3
+ from albibong.photon_packet_parser.operation_request import OperationRequest
4
+ from albibong.photon_packet_parser.operation_response import OperationResponse
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+ class CommandType(Enum):
4
+ Disconnect = 4
5
+ SendReliable = 6
6
+ SendUnreliable = 7
7
+ SendFragment = 8
@@ -0,0 +1,16 @@
1
+ class CrcCalculator:
2
+ @staticmethod
3
+ def calculate(_bytes, length):
4
+ result = 4294967295
5
+ key = 3988292384
6
+
7
+ for i in range(length):
8
+ result ^= _bytes[i]
9
+
10
+ for _ in range(8):
11
+ if (result & 1) > 0:
12
+ result = result >> 1 ^ key
13
+ else:
14
+ result >>= 1
15
+
16
+ return result
@@ -0,0 +1,4 @@
1
+ class EventData:
2
+ def __init__(self, code, parameters):
3
+ self.code = code
4
+ self.parameters = parameters
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+ class MessageType(Enum):
4
+ OperationRequest = 2
5
+ OperationResponse = 3
6
+ Event = 4
@@ -0,0 +1,22 @@
1
+ import io
2
+ import struct
3
+
4
+
5
+ class NumberSerializer:
6
+ @staticmethod
7
+ def deserialize_int(source: io.BytesIO):
8
+ buffer = source.read(4)
9
+ return struct.unpack(">i", buffer)[0]
10
+
11
+ @staticmethod
12
+ def deserialize_short(source: io.BytesIO):
13
+ buffer = source.read(2)
14
+ return struct.unpack(">h", buffer)[0]
15
+
16
+ @staticmethod
17
+ def serialize_int(value, target: io.BytesIO):
18
+ target.write(value >> 24)
19
+ target.write(value >> 16)
20
+ target.write(value >> 8)
21
+ target.write(value)
22
+ return target
@@ -0,0 +1,4 @@
1
+ class OperationRequest:
2
+ def __init__(self, operation_code, parameters):
3
+ self.operation_code = operation_code
4
+ self.parameters = parameters
@@ -0,0 +1,6 @@
1
+ class OperationResponse:
2
+ def __init__(self, operation_code, return_code, debug_message, parameters):
3
+ self.operation_code = operation_code
4
+ self.return_code = return_code
5
+ self.debug_message = debug_message
6
+ self.parameters = parameters
@@ -0,0 +1,168 @@
1
+ import io
2
+ from albibong.photon_packet_parser.message_type import MessageType
3
+ from albibong.photon_packet_parser.command_type import CommandType
4
+ from albibong.photon_packet_parser.segmented_packet import SegmentedPacket
5
+ from albibong.photon_packet_parser.protocol16_deserializer import Protocol16Deserializer
6
+ from albibong.photon_packet_parser.crc_calculator import CrcCalculator
7
+ from albibong.photon_packet_parser.number_serializer import NumberSerializer
8
+
9
+ COMMAND_HEADER_LENGTH = 12
10
+ PHOTON_HEADER_LENGTH = 12
11
+
12
+
13
+ class PhotonPacketParser:
14
+ def __init__(self, on_event, on_request, on_response):
15
+ self._pending_segments = {}
16
+ self.on_event = on_event
17
+ self.on_request = on_request
18
+ self.on_response = on_response
19
+
20
+ # MITIGATOR Challenge Response Packet
21
+ def is_mcr_packet(self, payload):
22
+ signatures = {
23
+ b"\x4d\x43\x52\x48\x33\x31\x31\x30",
24
+ b"\xe9\x71\x2d\xd5\x00\x01\x00\x00",
25
+ b"\xe9\x71\x2d\xd5\x01\x01\x00\x00",
26
+ b"\xe9\x71\x2d\xd5\x11\x01\x00\x00",
27
+ }
28
+ return payload[:8] in signatures
29
+
30
+ def handle_payload(self, payload):
31
+ if self.is_mcr_packet(payload):
32
+ return
33
+
34
+ payload = io.BytesIO(payload)
35
+ if payload.getbuffer().nbytes < PHOTON_HEADER_LENGTH:
36
+ return
37
+
38
+ peer_id = NumberSerializer.deserialize_short(payload)
39
+ flags = payload.read(1)[0]
40
+ command_count = payload.read(1)[0]
41
+ timestamp = NumberSerializer.deserialize_int(payload)
42
+ challenge = NumberSerializer.deserialize_int(payload)
43
+
44
+ is_encrypted = flags == 1
45
+ is_crc_enabled = flags == 0xCC
46
+
47
+ if is_encrypted:
48
+ return
49
+
50
+ if is_crc_enabled:
51
+ offset = payload.tell()
52
+ payload.seek(0)
53
+ crc = NumberSerializer.deserialize_int(payload)
54
+
55
+ payload.seek(offset)
56
+ payload = NumberSerializer.serialize_int(0, payload)
57
+
58
+ if crc != CrcCalculator.calculate(payload, payload.getbuffer().nbytes):
59
+ return
60
+
61
+ for _ in range(command_count):
62
+ self.handle_command(payload)
63
+
64
+ def handle_command(self, source: io.BytesIO):
65
+ command_type = source.read(1)[0]
66
+ channel_id = source.read(1)[0]
67
+ command_flags = source.read(1)[0]
68
+ # Skip 1 byte
69
+ source.read(1)
70
+ command_length = NumberSerializer.deserialize_int(source)
71
+ sequence_number = NumberSerializer.deserialize_int(source)
72
+ command_length -= COMMAND_HEADER_LENGTH
73
+
74
+ if command_type == CommandType.Disconnect.value:
75
+ return
76
+ elif command_type == CommandType.SendUnreliable.value:
77
+ source.read(4)
78
+ command_length -= 4
79
+ self.handle_send_reliable(source, command_length)
80
+ elif command_type == CommandType.SendReliable.value:
81
+ self.handle_send_reliable(source, command_length)
82
+ elif command_type == CommandType.SendFragment.value:
83
+ self.handle_send_fragment(source, command_length)
84
+ else:
85
+ source.read(command_length)
86
+
87
+ def handle_send_reliable(self, source: io.BytesIO, command_length: int):
88
+ # Skip 1 byte
89
+ source.read(1)
90
+ command_length -= 1
91
+ message_type = source.read(1)[0]
92
+ command_length -= 1
93
+
94
+ operation_length = command_length
95
+ payload = io.BytesIO(source.read(operation_length))
96
+
97
+ if message_type == MessageType.OperationRequest.value:
98
+ request_data = Protocol16Deserializer.deserialize_operation_request(payload)
99
+ self.on_request(request_data)
100
+ elif message_type == MessageType.OperationResponse.value:
101
+ response_data = Protocol16Deserializer.deserialize_operation_response(
102
+ payload
103
+ )
104
+ self.on_response(response_data)
105
+ elif message_type == MessageType.Event.value:
106
+ event_data = Protocol16Deserializer.deserialize_event_data(payload)
107
+ self.on_event(event_data)
108
+ # else:
109
+ # print("Unknown message type: ", message_type)
110
+
111
+ def handle_send_fragment(self, source: io.BytesIO, command_length: int):
112
+ start_sequence_number = NumberSerializer.deserialize_int(source)
113
+ command_length -= 4
114
+ fragment_count = NumberSerializer.deserialize_int(source)
115
+ command_length -= 4
116
+ fragment_number = NumberSerializer.deserialize_int(source)
117
+ command_length -= 4
118
+ total_length = NumberSerializer.deserialize_int(source)
119
+ command_length -= 4
120
+ fragment_offset = NumberSerializer.deserialize_int(source)
121
+ command_length -= 4
122
+
123
+ fragment_length = command_length
124
+
125
+ self.handle_segmented_payload(
126
+ start_sequence_number,
127
+ total_length,
128
+ fragment_length,
129
+ fragment_offset,
130
+ source,
131
+ )
132
+
133
+ def handle_finished_segmented_packet(self, total_payload: bytearray):
134
+ command_length = len(total_payload)
135
+ self.handle_send_reliable(io.BytesIO(total_payload), command_length)
136
+
137
+ def handle_segmented_payload(
138
+ self,
139
+ start_sequence_number,
140
+ total_length,
141
+ fragment_length,
142
+ fragment_offset,
143
+ source,
144
+ ):
145
+ segmented_packet = self.get_segmented_packet(
146
+ start_sequence_number, total_length
147
+ )
148
+
149
+ for i in range(fragment_length):
150
+ segmented_packet.total_payload[fragment_offset + i] = source.read(1)[0]
151
+
152
+ segmented_packet.bytes_written += fragment_length
153
+
154
+ if segmented_packet.bytes_written >= segmented_packet.total_length:
155
+ self._pending_segments.pop(start_sequence_number)
156
+ self.handle_finished_segmented_packet(segmented_packet.total_payload)
157
+
158
+ def get_segmented_packet(self, start_sequence_number, total_length):
159
+ if start_sequence_number in self._pending_segments:
160
+ return self._pending_segments[start_sequence_number]
161
+
162
+ segmented_packet = SegmentedPacket(
163
+ total_length=total_length, total_payload=bytearray(total_length)
164
+ )
165
+
166
+ self._pending_segments[start_sequence_number] = segmented_packet
167
+
168
+ return segmented_packet
@@ -0,0 +1,302 @@
1
+ import io
2
+ import struct
3
+ import sys
4
+ from albibong.photon_packet_parser.protocol16_type import Protocol16Type
5
+ from albibong.photon_packet_parser.operation_request import OperationRequest
6
+ from albibong.photon_packet_parser.operation_response import OperationResponse
7
+ from albibong.photon_packet_parser.event_data import EventData
8
+
9
+
10
+ class Protocol16Deserializer:
11
+
12
+ @staticmethod
13
+ def deserialize(input: io.BytesIO, type_code: int):
14
+ if (
15
+ type_code == Protocol16Type.UNKNOWN.value
16
+ or type_code == Protocol16Type.NULL.value
17
+ ):
18
+ return None
19
+ elif type_code == Protocol16Type.DICTIONARY.value:
20
+ return Protocol16Deserializer.deserialize_dictionary(input)
21
+ elif type_code == Protocol16Type.STRINGARRAY.value:
22
+ return Protocol16Deserializer.deserialize_string_array(input)
23
+ elif type_code == Protocol16Type.BYTE.value:
24
+ return Protocol16Deserializer.deserialize_byte(input)
25
+ elif type_code == Protocol16Type.DOUBLE.value:
26
+ return Protocol16Deserializer.deserialize_double(input)
27
+ elif type_code == Protocol16Type.EVENTDATA.value:
28
+ return Protocol16Deserializer.deserialize_event_data(input)
29
+ elif type_code == Protocol16Type.FLOAT.value:
30
+ return Protocol16Deserializer.deserialize_float(input)
31
+ elif type_code == Protocol16Type.INTEGER.value:
32
+ return Protocol16Deserializer.deserialize_integer(input)
33
+ elif type_code == Protocol16Type.HASHTABLE.value:
34
+ return Protocol16Deserializer.deserialize_hash_table(input)
35
+ elif type_code == Protocol16Type.SHORT.value:
36
+ return Protocol16Deserializer.deserialize_short(input)
37
+ elif type_code == Protocol16Type.LONG.value:
38
+ return Protocol16Deserializer.deserialize_long(input)
39
+ elif type_code == Protocol16Type.INTEGERARRAY.value:
40
+ return Protocol16Deserializer.deserialize_integer_array(input)
41
+ elif type_code == Protocol16Type.BOOLEAN.value:
42
+ return Protocol16Deserializer.deserialize_boolean(input)
43
+ elif type_code == Protocol16Type.OPERATIONRESPONSE.value:
44
+ return Protocol16Deserializer.deserialize_operation_response(input)
45
+ elif type_code == Protocol16Type.OPERATIONREQUEST.value:
46
+ return Protocol16Deserializer.deserialize_operation_request(input)
47
+ elif type_code == Protocol16Type.STRING.value:
48
+ return Protocol16Deserializer.deserialize_string(input)
49
+ elif type_code == Protocol16Type.BYTEARRAY.value:
50
+ return Protocol16Deserializer.deserialize_byte_array(input)
51
+ elif type_code == Protocol16Type.ARRAY.value:
52
+ return Protocol16Deserializer.deserialize_array(input)
53
+ elif type_code == Protocol16Type.OBJECTARRAY.value:
54
+ return Protocol16Deserializer.deserialize_object_array(input)
55
+ else:
56
+ raise Exception("Unknown type code: " + str(type_code))
57
+
58
+ @staticmethod
59
+ def deserialize_operation_request(input: io.BytesIO):
60
+ code = Protocol16Deserializer.deserialize_byte(input)
61
+ table = Protocol16Deserializer.deserialize_parameter_table(input)
62
+ return OperationRequest(code, table)
63
+
64
+ @staticmethod
65
+ def deserialize_operation_response(input: io.BytesIO):
66
+ code = Protocol16Deserializer.deserialize_byte(input)
67
+ return_code = Protocol16Deserializer.deserialize_short(input)
68
+ debug_message = Protocol16Deserializer.deserialize(
69
+ input, Protocol16Deserializer.deserialize_byte(input)
70
+ )
71
+ parameters = Protocol16Deserializer.deserialize_parameter_table(input)
72
+ return OperationResponse(code, return_code, debug_message, parameters)
73
+
74
+ @staticmethod
75
+ def deserialize_event_data(input: io.BytesIO):
76
+ code = Protocol16Deserializer.deserialize_byte(input)
77
+ parameters = Protocol16Deserializer.deserialize_parameter_table(input)
78
+ return EventData(code, parameters)
79
+
80
+ @staticmethod
81
+ def deserialize_parameter_table(input):
82
+ dictionary_size = Protocol16Deserializer.deserialize_short(input)
83
+ dictionary = {}
84
+
85
+ for _ in range(dictionary_size):
86
+ key = Protocol16Deserializer.deserialize_byte(input)
87
+ value_type_code = Protocol16Deserializer.deserialize_byte(input)
88
+ value = Protocol16Deserializer.deserialize(input, value_type_code)
89
+ dictionary[key] = value
90
+
91
+ return dictionary
92
+
93
+ @staticmethod
94
+ def deserialize_short(input: io.BytesIO):
95
+ buffer = input.read(2)
96
+ return struct.unpack(">h", buffer)[0]
97
+
98
+ @staticmethod
99
+ def deserialize_byte(input: io.BytesIO):
100
+ return input.read(1)[0]
101
+
102
+ @staticmethod
103
+ def deserialize_boolean(input: io.BytesIO):
104
+ return input.read(1)[0] != 0
105
+
106
+ @staticmethod
107
+ def deserialize_integer(input: io.BytesIO):
108
+ buffer = input.read(4)
109
+ return struct.unpack(">i", buffer)[0]
110
+
111
+ @staticmethod
112
+ def deserialize_long(input: io.BytesIO):
113
+ buffer = input.read(8)
114
+
115
+ if sys.byteorder == "little":
116
+ return struct.unpack(">q", buffer)[0]
117
+
118
+ return struct.unpack("<q", buffer)[0]
119
+
120
+ @staticmethod
121
+ def deserialize_float(input: io.BytesIO):
122
+ buffer = input.read(4)
123
+
124
+ if sys.byteorder == "little":
125
+ return struct.unpack(">f", buffer)[0]
126
+
127
+ return struct.unpack("<f", buffer)[0]
128
+
129
+ @staticmethod
130
+ def deserialize_double(input: io.BytesIO):
131
+ buffer = input.read(8)
132
+
133
+ if sys.byteorder == "little":
134
+ return struct.unpack(">d", buffer)[0]
135
+
136
+ return struct.unpack("<d", buffer)[0]
137
+
138
+ @staticmethod
139
+ def deserialize_string(input: io.BytesIO):
140
+ string_size = Protocol16Deserializer.deserialize_short(input)
141
+
142
+ if string_size == 0:
143
+ return ""
144
+
145
+ buffer = input.read(string_size)
146
+ return buffer.decode("utf-8")
147
+
148
+ @staticmethod
149
+ def deserialize_byte_array(input: io.BytesIO):
150
+ array_size = Protocol16Deserializer.deserialize_integer(input)
151
+
152
+ array = []
153
+ for _ in range(array_size):
154
+ tmp = Protocol16Deserializer.deserialize_byte(input)
155
+ array.append(tmp)
156
+
157
+ return array
158
+
159
+ @staticmethod
160
+ def deserialize_integer_array(input: io.BytesIO):
161
+ array_size = Protocol16Deserializer.deserialize_integer(input)
162
+
163
+ array = []
164
+ for _ in range(array_size):
165
+ tmp = Protocol16Deserializer.deserialize_integer(input)
166
+ array.append(tmp)
167
+
168
+ return array
169
+
170
+ @staticmethod
171
+ def deserialize_string_array(input: io.BytesIO):
172
+ array_size = Protocol16Deserializer.deserialize_short(input)
173
+
174
+ array = []
175
+ for _ in range(array_size):
176
+ tmp = Protocol16Deserializer.deserialize_string(input)
177
+ array.append(tmp)
178
+
179
+ return array
180
+
181
+ @staticmethod
182
+ def deserialize_object_array(input: io.BytesIO):
183
+ array_size = Protocol16Deserializer.deserialize_short(input)
184
+
185
+ array = []
186
+ for _ in range(array_size):
187
+ typeCode = Protocol16Deserializer.deserialize_byte(input)
188
+ tmp = Protocol16Deserializer.deserialize(input, typeCode)
189
+ array.append(tmp)
190
+
191
+ return array
192
+
193
+ @staticmethod
194
+ def deserialize_array(input: io.BytesIO):
195
+ array_size = Protocol16Deserializer.deserialize_short(input)
196
+ type_code = Protocol16Deserializer.deserialize_byte(input)
197
+
198
+ if type_code == Protocol16Type.ARRAY.value:
199
+ result = []
200
+ for _ in range(0, array_size):
201
+ tmp = Protocol16Deserializer.deserialize_array(input)
202
+ result.append(tmp)
203
+
204
+ return result
205
+ elif type_code == Protocol16Type.BYTEARRAY.value:
206
+ result = []
207
+ for _ in range(array_size):
208
+ tmp = Protocol16Deserializer.deserialize_byte_array(input)
209
+ result.append(tmp)
210
+
211
+ return result
212
+ elif type_code == Protocol16Type.DICTIONARY.value:
213
+ return Protocol16Deserializer.deserialize_dictionary_array(
214
+ input, array_size
215
+ )
216
+ else:
217
+ result = []
218
+ for _ in range(array_size):
219
+ tmp = Protocol16Deserializer.deserialize(input, type_code)
220
+ result.append(tmp)
221
+
222
+ return result
223
+
224
+ @staticmethod
225
+ def deserialize_dictionary(input: io.BytesIO):
226
+ key_type_code = Protocol16Deserializer.deserialize_byte(input)
227
+ value_type_code = Protocol16Deserializer.deserialize_byte(input)
228
+ dictionary_size = Protocol16Deserializer.deserialize_short(input)
229
+ return Protocol16Deserializer.deserialize_dictionary_elements(
230
+ input, dictionary_size, key_type_code, value_type_code
231
+ )
232
+
233
+ @staticmethod
234
+ def deserialize_dictionary_elements(
235
+ input: io.BytesIO,
236
+ dictionary_size: int,
237
+ key_type_code: int,
238
+ value_type_code: int,
239
+ ):
240
+ output = {}
241
+ for _ in range(dictionary_size):
242
+ key = Protocol16Deserializer.deserialize(
243
+ input,
244
+ (
245
+ Protocol16Deserializer.deserialize_byte(input)
246
+ if key_type_code == 0 or key_type_code == 42
247
+ else key_type_code
248
+ ),
249
+ )
250
+ value = Protocol16Deserializer.deserialize(
251
+ input,
252
+ (
253
+ Protocol16Deserializer.deserialize_byte(input)
254
+ if value_type_code == 0 or value_type_code == 42
255
+ else value_type_code
256
+ ),
257
+ )
258
+ output[key] = value
259
+
260
+ return output
261
+
262
+ @staticmethod
263
+ def deserialize_dictionary_array(input: io.BytesIO, size: int):
264
+ key_type_code = Protocol16Deserializer.deserialize_byte(input)
265
+ value_type_code = Protocol16Deserializer.deserialize_byte(input)
266
+ output = []
267
+
268
+ for _ in range(size):
269
+ dictionary_size = Protocol16Deserializer.deserialize_short(input)
270
+
271
+ dictionary = {}
272
+ for _ in range(dictionary_size):
273
+ key = None
274
+ if key_type_code > 0:
275
+ key = Protocol16Deserializer.deserialize(input, key_type_code)
276
+ else:
277
+ next_key_type_code = Protocol16Deserializer.deserialize_byte(input)
278
+ key = Protocol16Deserializer.deserialize(input, next_key_type_code)
279
+
280
+ value = None
281
+ if value_type_code > 0:
282
+ value = Protocol16Deserializer.deserialize(input, value_type_code)
283
+ else:
284
+ next_value_type_code = Protocol16Deserializer.deserialize_byte(
285
+ input
286
+ )
287
+ value = Protocol16Deserializer.deserialize(
288
+ input, next_value_type_code
289
+ )
290
+
291
+ dictionary[key] = value
292
+
293
+ output.append(dictionary)
294
+
295
+ return output
296
+
297
+ @staticmethod
298
+ def deserialize_hash_table(input: io.BytesIO):
299
+ size = Protocol16Deserializer.deserialize_short(input)
300
+ return Protocol16Deserializer.deserialize_dictionary_elements(
301
+ input, size, Protocol16Type.UNKNOWN, Protocol16Type.UNKNOWN
302
+ )
@@ -0,0 +1,23 @@
1
+ from enum import Enum
2
+
3
+ class Protocol16Type(Enum):
4
+ UNKNOWN = 0
5
+ NULL = 42
6
+ DICTIONARY = 68
7
+ STRINGARRAY = 97
8
+ BYTE = 98
9
+ DOUBLE = 100
10
+ EVENTDATA = 101
11
+ FLOAT = 102
12
+ INTEGER = 105
13
+ HASHTABLE = 104
14
+ SHORT = 107
15
+ LONG = 108
16
+ INTEGERARRAY = 110
17
+ BOOLEAN = 111
18
+ OPERATIONRESPONSE = 112
19
+ OPERATIONREQUEST = 113
20
+ STRING = 115
21
+ BYTEARRAY = 120
22
+ ARRAY = 121
23
+ OBJECTARRAY = 122
@@ -0,0 +1,5 @@
1
+ class SegmentedPacket:
2
+ def __init__(self, total_length=0, bytes_written=0, total_payload=bytearray(0)):
3
+ self.total_length = total_length
4
+ self.bytes_written = bytes_written
5
+ self.total_payload = total_payload