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
@@ -0,0 +1,327 @@
1
+ import json
2
+ import os
3
+ from collections import deque
4
+
5
+ from albibong.classes.character import Character
6
+ from albibong.classes.coords import Coords
7
+ from albibong.classes.dungeon import Dungeon
8
+ from albibong.classes.item import Item
9
+ from albibong.classes.location import Location
10
+ from albibong.resources.EventCode import EventCode
11
+ from albibong.resources.OperationCode import OperationCode
12
+ from albibong.threads.websocket_server import send_event
13
+
14
+ FILENAME = os.path.join(os.path.expanduser("~"), "Albibong/list_dungeon.json")
15
+ os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
16
+
17
+
18
+ class WorldData:
19
+
20
+ def __init__(self) -> None:
21
+ self.me: Character = Character(
22
+ id=None,
23
+ username="not initialized",
24
+ guild="not initialized",
25
+ alliance="not initialized",
26
+ coords=Coords(0, 0),
27
+ )
28
+ self.current_map: Location = None
29
+ self.current_dungeon: Dungeon = None
30
+ self.characters: dict[str, Character] = {}
31
+ self.char_id_to_username: dict[int, str] = {self.me.id: self.me.username}
32
+ self.change_equipment_log: dict[int, list] = {}
33
+ self.party_members: set[str] = set()
34
+ self.is_dps_meter_running: bool = True
35
+
36
+ def handle_response(self, parameters):
37
+ if 253 in parameters:
38
+ if parameters[253] == OperationCode.JOIN.value:
39
+ self.handle_join_response(parameters)
40
+ elif parameters[253] == OperationCode.CHANGE_CLUSTER.value:
41
+ self.set_location(parameters)
42
+
43
+ def handle_event(self, parameters):
44
+ if 252 in parameters:
45
+ if parameters[252] == EventCode.OTHER_GRABBED_LOOT.value:
46
+ if 2 in parameters and parameters[2] in self.characters:
47
+ char: Character = self.characters[parameters[2]]
48
+ char.update_loot(parameters)
49
+ if self.current_dungeon and parameters[2] == self.me.username:
50
+ self.current_dungeon.update_loot(parameters)
51
+ elif parameters[252] == EventCode.UPDATE_FAME.value:
52
+ self.me.update_fame(parameters)
53
+ if self.current_dungeon:
54
+ self.current_dungeon.update_fame(parameters)
55
+ elif parameters[252] == EventCode.UPDATE_RE_SPEC_POINTS.value:
56
+ self.me.update_re_spec(parameters)
57
+ if self.current_dungeon:
58
+ self.current_dungeon.update_re_spec(parameters)
59
+ elif parameters[252] == EventCode.CHARACTER_EQUIPMENT_CHANGED.value:
60
+ self.change_character_equipment(parameters)
61
+ elif (
62
+ parameters[252] == EventCode.HEALTH_UPDATE.value
63
+ and self.is_dps_meter_running
64
+ ):
65
+ self.update_dps_meter(parameters)
66
+ elif (
67
+ parameters[252] == EventCode.PARTY_JOINED.value
68
+ or parameters[252] == EventCode.PARTY_PLAYER_JOINED.value
69
+ or parameters[252] == EventCode.PARTY_PLAYER_LEFT.value
70
+ or parameters[252] == EventCode.PARTY_DISBANDED.value
71
+ ):
72
+ self.update_party_member(parameters)
73
+ elif parameters[252] == EventCode.NEW_CHARACTER.value:
74
+ self.create_character(
75
+ id=parameters[0],
76
+ username=parameters[1],
77
+ guild=parameters[8] if 8 in parameters else "",
78
+ alliance=parameters[49] if 49 in parameters else "",
79
+ coords=(
80
+ Coords(parameters[15][0], parameters[15][1])
81
+ if 15 in parameters
82
+ else Coords(0, 0)
83
+ ),
84
+ equipments=parameters[38] if 38 in parameters else [],
85
+ )
86
+ ...
87
+
88
+ def handle_request(self, parameters):
89
+ if 253 in parameters:
90
+ if parameters[253] == OperationCode.MOVE.value and self.me:
91
+ self.me.update_coords(parameters)
92
+ ...
93
+
94
+ def end_current_dungeon(self):
95
+ if self.current_dungeon:
96
+ list_dungeon = deque()
97
+
98
+ try:
99
+ with open(FILENAME) as json_file:
100
+ list_dungeon = deque(json.load(json_file))
101
+ except:
102
+ pass
103
+
104
+ self.current_dungeon.get_elapsed_time()
105
+ list_dungeon.appendleft(Dungeon.serialize(self.current_dungeon))
106
+
107
+ with open(FILENAME, "w") as json_file:
108
+ json.dump(list(list_dungeon), json_file)
109
+
110
+ event = {
111
+ "type": "update_dungeon",
112
+ "payload": {"list_dungeon": list(list_dungeon)},
113
+ }
114
+ send_event(event)
115
+ self.current_dungeon = None
116
+
117
+ def start_current_dungeon(self, type, name):
118
+ if self.current_dungeon == None:
119
+ new_dungeon = Dungeon(type, name)
120
+ self.current_dungeon = new_dungeon
121
+
122
+ def set_dungeon_status(self, check_map, map_type_splitted):
123
+ if "EXPEDITION" in map_type_splitted or "DUNGEON" in map_type_splitted:
124
+ self.start_current_dungeon(type=check_map.type, name=check_map.name)
125
+ elif (
126
+ "EXPEDITION" not in map_type_splitted or "DUNGEON" not in map_type_splitted
127
+ ):
128
+ self.end_current_dungeon()
129
+ return False
130
+
131
+ def set_location(self, parameters):
132
+ self.change_equipment_log = {}
133
+
134
+ if 1 in parameters:
135
+ check_map = Location.get_location_from_code(parameters[1])
136
+ map_type_splitted = set(check_map.type.split("_"))
137
+ self.set_dungeon_status(check_map, map_type_splitted)
138
+
139
+ if "ISLAND" in map_type_splitted or "HIDEOUT" in map_type_splitted:
140
+ check_map.name = f"{parameters[2]}'s {check_map.name}"
141
+ self.current_map = check_map
142
+
143
+ elif 0 in parameters:
144
+ check_map = Location.get_location_from_code(parameters[0])
145
+ map_type_splitted = set(check_map.type.split("_"))
146
+ is_dungeon = self.set_dungeon_status(check_map, map_type_splitted)
147
+ if is_dungeon == False:
148
+ self.current_map = Location.get_location_from_code(parameters[0])
149
+
150
+ event = {
151
+ "type": "update_location",
152
+ "payload": {
153
+ "map": self.current_map.name if self.current_map else "None",
154
+ "dungeon": (
155
+ self.current_dungeon.name if self.current_dungeon else "None"
156
+ ),
157
+ },
158
+ }
159
+ send_event(event)
160
+
161
+ def update_party_member(self, parameters):
162
+ if self.me != None:
163
+ self.party_members.add(self.me.username)
164
+ if parameters[252] == EventCode.PARTY_JOINED.value:
165
+ for member in parameters[5]:
166
+ self.party_members.add(member)
167
+ elif parameters[252] == EventCode.PARTY_DISBANDED.value:
168
+ self.party_members = set()
169
+ elif parameters[252] == EventCode.PARTY_PLAYER_JOINED.value:
170
+ self.party_members.add(parameters[2])
171
+ elif parameters[252] == EventCode.PARTY_PLAYER_LEFT.value:
172
+ if parameters[0] in self.char_id_to_username:
173
+ name = self.char_id_to_username[parameters[0]]
174
+ self.party_members.remove(name)
175
+ event = {
176
+ "type": "update_dps",
177
+ "payload": {"party_members": self.serialize_party_members()},
178
+ }
179
+ send_event(event)
180
+
181
+ def update_dps_meter(self, parameters):
182
+ if 6 in parameters and parameters[6] in self.char_id_to_username:
183
+ username = self.char_id_to_username[parameters[6]]
184
+ if username in self.party_members:
185
+ char: Character = self.characters[username]
186
+ char.handle_health_update(parameters)
187
+ event = {
188
+ "type": "update_dps",
189
+ "payload": {"party_members": self.serialize_party_members()},
190
+ }
191
+ send_event(event)
192
+
193
+ def change_character_equipment(self, parameters):
194
+ if 2 in parameters:
195
+ if parameters[0] in self.char_id_to_username:
196
+ char = self.characters[self.char_id_to_username[parameters[0]]]
197
+ if char.username in self.party_members:
198
+ char.update_equipment(parameters[2])
199
+ event = {
200
+ "type": "update_dps",
201
+ "payload": {"party_members": self.serialize_party_members()},
202
+ }
203
+ send_event(event)
204
+ else:
205
+ self.change_equipment_log[parameters[0]] = parameters[2]
206
+
207
+ def handle_join_response(self, parameters):
208
+ # set my character
209
+
210
+ self.convert_id_to_name(old_id=self.me.id, new_id=parameters[0], char=self.me)
211
+
212
+ self.me.username = parameters[2]
213
+ self.me.guild = parameters[57] if 57 in parameters else ""
214
+ self.me.alliance = parameters[77] if 77 in parameters else ""
215
+ self.characters[self.me.username] = self.me
216
+ if self.me.id in self.change_equipment_log:
217
+ self.me.update_equipment(self.change_equipment_log[self.me.id])
218
+
219
+ self.party_members.add(self.me.username)
220
+
221
+ # set map my character is currently in
222
+ if parameters[8][0] == "@":
223
+ area = parameters[8].split("@")
224
+ if area[1] == "RANDOMDUNGEON":
225
+ check_map = Location.get_location_from_code(area[1])
226
+ self.start_current_dungeon(type=check_map.type, name=check_map.name)
227
+
228
+ event_char = {
229
+ "type": "init_character",
230
+ "payload": {
231
+ "username": self.me.username,
232
+ "fame": self.me.fame_gained,
233
+ "re_spec": self.me.re_spec_gained,
234
+ "silver": self.me.silver_gained,
235
+ "weapon": self.me.equipment[0].image,
236
+ },
237
+ }
238
+ event_map = {
239
+ "type": "update_location",
240
+ "payload": {
241
+ "map": self.current_map.name if self.current_map else "None",
242
+ "dungeon": (
243
+ Dungeon.serialize(self.current_dungeon)
244
+ if self.current_dungeon
245
+ else None
246
+ ),
247
+ },
248
+ }
249
+ send_event(event_map)
250
+ send_event(event_char)
251
+
252
+ def convert_id_to_name(self, old_id, new_id, char: Character):
253
+ if old_id in self.char_id_to_username:
254
+ self.char_id_to_username.pop(old_id) # delete old relative id
255
+ char.id = new_id
256
+ self.char_id_to_username[char.id] = char.username # add new relative id
257
+
258
+ def create_character(
259
+ self,
260
+ id: int,
261
+ username: str,
262
+ guild: str,
263
+ alliance: str,
264
+ equipments: list[str] = [],
265
+ coords: Coords = Coords(0, 0),
266
+ ):
267
+
268
+ # initiate character
269
+ if username not in self.characters:
270
+ char: Character = Character(
271
+ id=id,
272
+ username=username,
273
+ guild=guild,
274
+ alliance=alliance,
275
+ coords=coords,
276
+ )
277
+ char.update_equipment(equipments)
278
+ self.characters[char.username] = char
279
+ self.char_id_to_username[char.id] = char.username
280
+
281
+ # change map
282
+ else:
283
+ char: Character = self.characters[username]
284
+ char.update_equipment(equipments)
285
+ char.coords = coords
286
+ self.convert_id_to_name(old_id=char.id, new_id=id, char=char)
287
+
288
+ def serialize_party_members(self):
289
+ serialized = []
290
+
291
+ total_damage = 0
292
+ total_heal = 0
293
+ for key, value in self.characters.items():
294
+ if key in self.party_members:
295
+ total_damage += value.damage_dealt
296
+ total_heal += value.healing_dealt
297
+
298
+ for key, value in self.characters.items():
299
+ if key in self.party_members:
300
+ if value.equipment != []:
301
+ weapon = Item.serialize(value.equipment[0])["image"]
302
+ data = {
303
+ "username": value.username,
304
+ "damage_dealt": value.damage_dealt,
305
+ "damage_percent": (
306
+ round(value.damage_dealt / total_damage * 100, 2)
307
+ if total_damage > 0
308
+ else 0
309
+ ),
310
+ "healing_dealt": value.healing_dealt,
311
+ "heal_percent": (
312
+ round(value.healing_dealt / total_heal * 100, 2)
313
+ if total_heal > 0
314
+ else 0
315
+ ),
316
+ "weapon": weapon,
317
+ }
318
+ serialized.append(data)
319
+ serialized.sort(key=lambda x: x["damage_dealt"], reverse=True)
320
+ return serialized
321
+
322
+
323
+ world_data = WorldData()
324
+
325
+
326
+ def get_world_data():
327
+ return world_data
Binary file
@@ -0,0 +1 @@
1
+ *{box-sizing:border-box}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}p{margin:0}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}#root,body{margin:auto;display:flex;flex-direction:column;justify-content:start;align-items:center;min-width:320px;min-height:100vh;color:#fff;width:100%}h1{font-size:2em;line-height:1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}._dmgBar_zdqdf_1{background:linear-gradient(135deg,#ff6486,#6486ff);height:6px;border-radius:8px;margin-bottom:2px}._healBar_zdqdf_8{background:linear-gradient(135deg,#64ffde,#64ff90);height:2px;border-radius:4px}._dpsContainer_zdqdf_14{display:flex;flex-direction:column;justify-content:flex-start;width:100%;gap:4px;box-sizing:content-box;padding:16px}._dpsRow_zdqdf_24{display:flex;flex-direction:row;justify-content:space-between;align-items:center}._dpsNumber_zdqdf_31{width:128px;text-align:right}._hidden_zdqdf_36{display:none}._player_zdqdf_40{flex-grow:1}._checkboxColor_zdqdf_44{accent-color:#64d3ff}._container_pkz1i_1{display:flex;flex-direction:column;align-items:center;gap:8px;width:100%;gap:1.5rem}._snackbar_pkz1i_10{position:fixed;right:64px}._stats_pkz1i_15{display:flex;flex-direction:row;align-items:center;gap:.5rem}._options_pkz1i_22{display:flex;flex-direction:row;align-items:center;gap:2rem}._row_pkz1i_29{display:flex;width:100%;justify-content:space-between}._hidden_pkz1i_35{display:none}._dungeonContainer_mlu2u_1{border-radius:1rem;width:100%;padding:2rem;display:flex;flex-direction:column;gap:1rem}._tag_mlu2u_12{background-color:#64d3ff;padding:0 1rem;border-radius:1rem;color:#0f3c4e;font-weight:700}