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.
- albibong/__init__.py +82 -0
- albibong/classes/__init__.py +0 -0
- albibong/classes/character.py +83 -0
- albibong/classes/coords.py +9 -0
- albibong/classes/dungeon.py +59 -0
- albibong/classes/item.py +41 -0
- albibong/classes/location.py +48 -0
- albibong/classes/logger.py +122 -0
- albibong/classes/packet_handler.py +61 -0
- albibong/classes/world_data.py +327 -0
- albibong/gui_dist/No Equipment.png +0 -0
- albibong/gui_dist/assets/index-BFSx0nua.css +1 -0
- albibong/gui_dist/assets/index-DAndaN_4.js +161 -0
- albibong/gui_dist/fame.png +0 -0
- albibong/gui_dist/index.html +14 -0
- albibong/gui_dist/re_spec.png +0 -0
- albibong/gui_dist/silver.png +0 -0
- albibong/gui_dist/vite.svg +1 -0
- albibong/photon_packet_parser/__init__.py +4 -0
- albibong/photon_packet_parser/command_type.py +7 -0
- albibong/photon_packet_parser/crc_calculator.py +16 -0
- albibong/photon_packet_parser/event_data.py +4 -0
- albibong/photon_packet_parser/message_type.py +6 -0
- albibong/photon_packet_parser/number_serializer.py +22 -0
- albibong/photon_packet_parser/operation_request.py +4 -0
- albibong/photon_packet_parser/operation_response.py +6 -0
- albibong/photon_packet_parser/photon_packet_parser.py +168 -0
- albibong/photon_packet_parser/protocol16_deserializer.py +302 -0
- albibong/photon_packet_parser/protocol16_type.py +23 -0
- albibong/photon_packet_parser/segmented_packet.py +5 -0
- albibong/resources/EventCode.py +579 -0
- albibong/resources/OperationCode.py +499 -0
- albibong/resources/event_code.json +577 -0
- albibong/resources/items.json +54035 -0
- albibong/resources/maps.json +3565 -0
- albibong/resources/operation_code.json +497 -0
- albibong/threads/__init__.py +0 -0
- albibong/threads/http_server.py +60 -0
- albibong/threads/packet_handler_thread.py +32 -0
- albibong/threads/sniffer_thread.py +27 -0
- albibong/threads/websocket_server.py +168 -0
- albibong-1.0.0.dist-info/METADATA +15 -0
- albibong-1.0.0.dist-info/RECORD +46 -0
- albibong-1.0.0.dist-info/WHEEL +4 -0
- albibong-1.0.0.dist-info/entry_points.txt +2 -0
- 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}
|