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
albibong/__init__.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import queue
|
|
2
|
+
import sys
|
|
3
|
+
from time import sleep
|
|
4
|
+
|
|
5
|
+
import webview
|
|
6
|
+
from scapy.all import rdpcap
|
|
7
|
+
|
|
8
|
+
from albibong.classes.logger import Logger
|
|
9
|
+
from albibong.classes.packet_handler import PacketHandler
|
|
10
|
+
from albibong.threads.http_server import HttpServerThread
|
|
11
|
+
from albibong.threads.packet_handler_thread import PacketHandlerThread
|
|
12
|
+
from albibong.threads.sniffer_thread import SnifferThread
|
|
13
|
+
from albibong.threads.websocket_server import get_ws_server
|
|
14
|
+
|
|
15
|
+
logger = Logger(__name__, stdout=True, log_to_file=False)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def read_pcap(path):
|
|
19
|
+
packet_handler = PacketHandler()
|
|
20
|
+
scapy_cap = rdpcap(path)
|
|
21
|
+
for packet in scapy_cap:
|
|
22
|
+
packet_handler.handle(packet)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def sniff():
|
|
26
|
+
_sentinel = object()
|
|
27
|
+
packet_queue = queue.Queue()
|
|
28
|
+
|
|
29
|
+
p = SnifferThread(name="sniffer", out_queue=packet_queue, sentinel=_sentinel)
|
|
30
|
+
|
|
31
|
+
c = PacketHandlerThread(
|
|
32
|
+
name="packet_handler",
|
|
33
|
+
in_queue=packet_queue,
|
|
34
|
+
sentinel=_sentinel,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
p.start()
|
|
38
|
+
c.start()
|
|
39
|
+
|
|
40
|
+
ws_server = get_ws_server()
|
|
41
|
+
ws_server.start()
|
|
42
|
+
|
|
43
|
+
http_server = HttpServerThread(name="http_server")
|
|
44
|
+
http_server.start()
|
|
45
|
+
|
|
46
|
+
# sleep(0.25)
|
|
47
|
+
# with open("../gui/dist/index.html", "r") as html:
|
|
48
|
+
window = webview.create_window(
|
|
49
|
+
"Albibong",
|
|
50
|
+
# "../../gui/dist/index.html",
|
|
51
|
+
url="http://localhost:8000/",
|
|
52
|
+
width=1280,
|
|
53
|
+
height=720,
|
|
54
|
+
zoomable=True,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def on_closing():
|
|
58
|
+
c.stop()
|
|
59
|
+
p.stop()
|
|
60
|
+
ws_server.stop()
|
|
61
|
+
http_server.stop()
|
|
62
|
+
|
|
63
|
+
window.events.closing += on_closing
|
|
64
|
+
|
|
65
|
+
webview.start()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def main():
|
|
69
|
+
if len(sys.argv) > 1:
|
|
70
|
+
ws_server = get_ws_server()
|
|
71
|
+
ws_server.start()
|
|
72
|
+
|
|
73
|
+
http_server = HttpServerThread(name="http_server")
|
|
74
|
+
http_server.start()
|
|
75
|
+
|
|
76
|
+
read_pcap(sys.argv[1])
|
|
77
|
+
else:
|
|
78
|
+
sniff()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from albibong.classes.coords import Coords
|
|
4
|
+
from albibong.classes.item import Item
|
|
5
|
+
from albibong.threads.websocket_server import send_event
|
|
6
|
+
|
|
7
|
+
DIVISOR = 10000
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Character:
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
id: int,
|
|
15
|
+
username: str,
|
|
16
|
+
guild: str,
|
|
17
|
+
alliance: str,
|
|
18
|
+
coords: Coords,
|
|
19
|
+
equipment: list[Item] = [Item.get_item_from_code("0")] * 10,
|
|
20
|
+
):
|
|
21
|
+
self.id = id
|
|
22
|
+
self.username = username
|
|
23
|
+
self.guild = guild
|
|
24
|
+
self.alliance = alliance
|
|
25
|
+
self.coords = coords
|
|
26
|
+
self.fame_gained: int = 0
|
|
27
|
+
self.re_spec_gained: int = 0
|
|
28
|
+
self.silver_gained: int = 0
|
|
29
|
+
self.damage_dealt: int = 0
|
|
30
|
+
self.healing_dealt: int = 0
|
|
31
|
+
self.loot: list[str] = []
|
|
32
|
+
self.equipment = equipment
|
|
33
|
+
|
|
34
|
+
def handle_health_update(self, parameters):
|
|
35
|
+
if 2 in parameters:
|
|
36
|
+
if parameters[2] < 0:
|
|
37
|
+
if parameters[0] != self.id:
|
|
38
|
+
self.damage_dealt += abs(parameters[2])
|
|
39
|
+
else:
|
|
40
|
+
self.healing_dealt += abs(parameters[2])
|
|
41
|
+
|
|
42
|
+
def update_coords(self, parameters):
|
|
43
|
+
if 3 in parameters:
|
|
44
|
+
self.coords = Coords(parameters[3][0], parameters[3][1])
|
|
45
|
+
|
|
46
|
+
def update_fame(self, parameters):
|
|
47
|
+
fame = parameters[2] / DIVISOR
|
|
48
|
+
self.fame_gained += fame
|
|
49
|
+
event = {
|
|
50
|
+
"type": "update_fame",
|
|
51
|
+
"payload": {"username": self.username, "fame_gained": fame},
|
|
52
|
+
}
|
|
53
|
+
send_event(event)
|
|
54
|
+
|
|
55
|
+
def update_re_spec(self, parameters):
|
|
56
|
+
re_spec = parameters[2] / DIVISOR
|
|
57
|
+
self.re_spec_gained += re_spec
|
|
58
|
+
event = {
|
|
59
|
+
"type": "update_re_spec",
|
|
60
|
+
"payload": {"username": self.username, "re_spec_gained": re_spec},
|
|
61
|
+
}
|
|
62
|
+
send_event(event)
|
|
63
|
+
|
|
64
|
+
def update_loot(self, parameters):
|
|
65
|
+
if 3 in parameters and parameters[3] == True:
|
|
66
|
+
if 5 in parameters:
|
|
67
|
+
silver = parameters[5] / DIVISOR
|
|
68
|
+
self.silver_gained += silver
|
|
69
|
+
event = {
|
|
70
|
+
"type": "update_silver",
|
|
71
|
+
"payload": {"username": self.username, "silver_gained": silver},
|
|
72
|
+
}
|
|
73
|
+
send_event(event)
|
|
74
|
+
else:
|
|
75
|
+
self.loot.append(parameters[4])
|
|
76
|
+
|
|
77
|
+
def update_equipment(self, equipments):
|
|
78
|
+
new_eq = []
|
|
79
|
+
if equipments != []:
|
|
80
|
+
for eq in equipments:
|
|
81
|
+
obj = Item.get_item_from_code(str(eq))
|
|
82
|
+
new_eq.append(obj)
|
|
83
|
+
self.equipment = new_eq
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
import uuid
|
|
3
|
+
|
|
4
|
+
DIVISOR = 10000
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Dungeon:
|
|
8
|
+
|
|
9
|
+
def __init__(self, type, name) -> None:
|
|
10
|
+
self.id = uuid.uuid4()
|
|
11
|
+
self.type = type
|
|
12
|
+
self.name = name
|
|
13
|
+
self.tier = 0
|
|
14
|
+
self.fame_gained = 0
|
|
15
|
+
self.silver_gained = 0
|
|
16
|
+
self.re_spec_gained = 0
|
|
17
|
+
self.loot = []
|
|
18
|
+
self.start_time = datetime.now()
|
|
19
|
+
self.time_elapsed = 0
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def serialize(dungeon):
|
|
23
|
+
return {
|
|
24
|
+
"id": str(dungeon.id),
|
|
25
|
+
"type": dungeon.type,
|
|
26
|
+
"name": dungeon.name,
|
|
27
|
+
"tier": dungeon.tier,
|
|
28
|
+
"fame": dungeon.fame_gained,
|
|
29
|
+
"silver": dungeon.silver_gained,
|
|
30
|
+
"re_spec": dungeon.re_spec_gained,
|
|
31
|
+
"date_time": dungeon.start_time.strftime("%a %d %b %Y, %I:%M%p"),
|
|
32
|
+
"time_elapsed": str(dungeon.time_elapsed).split(".")[0],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def serialize_many(dungeons):
|
|
37
|
+
serialized = []
|
|
38
|
+
for key, value in dungeons.items():
|
|
39
|
+
serialized.append(Dungeon.serialize(value))
|
|
40
|
+
return serialized
|
|
41
|
+
|
|
42
|
+
def get_elapsed_time(self):
|
|
43
|
+
end_time = datetime.now()
|
|
44
|
+
self.time_elapsed = end_time - self.start_time
|
|
45
|
+
|
|
46
|
+
def update_fame(self, parameters):
|
|
47
|
+
fame = parameters[2] / DIVISOR
|
|
48
|
+
self.fame_gained += fame
|
|
49
|
+
|
|
50
|
+
def update_re_spec(self, parameters):
|
|
51
|
+
re_spec = parameters[2] / DIVISOR
|
|
52
|
+
self.re_spec_gained += re_spec
|
|
53
|
+
|
|
54
|
+
def update_loot(self, parameters):
|
|
55
|
+
if 3 in parameters and parameters[3] == True:
|
|
56
|
+
silver = parameters[5] / DIVISOR
|
|
57
|
+
self.silver_gained += silver
|
|
58
|
+
else:
|
|
59
|
+
self.loot.append(parameters[4])
|
albibong/classes/item.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
itemsJsonPath = os.path.join(os.path.dirname(__file__), "../resources/items.json")
|
|
5
|
+
with open(itemsJsonPath) as json_file:
|
|
6
|
+
item_data = json.load(json_file)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Item:
|
|
10
|
+
|
|
11
|
+
def __init__(self, id: str, name: str, unique_name: str):
|
|
12
|
+
self.id = id
|
|
13
|
+
self.name = name
|
|
14
|
+
self.unique_name = unique_name
|
|
15
|
+
self.image = (
|
|
16
|
+
"https://render.albiononline.com/v1/item/" + self.unique_name
|
|
17
|
+
if self.unique_name != "None"
|
|
18
|
+
else "../public/No Equipment.png"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def serialize(item):
|
|
23
|
+
return {
|
|
24
|
+
"id": item.id,
|
|
25
|
+
"name": item.name,
|
|
26
|
+
"unique_name": item.unique_name,
|
|
27
|
+
"image": item.image,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def serialize_many(items):
|
|
32
|
+
serialized = []
|
|
33
|
+
for item in items:
|
|
34
|
+
serialized.append(Item.serialize(item))
|
|
35
|
+
return serialized
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def get_item_from_code(cls, code: str):
|
|
39
|
+
item = item_data[code]
|
|
40
|
+
|
|
41
|
+
return cls(id=item["id"], name=item["name"], unique_name=item["unique_name"])
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
mapsJsonPath = os.path.join(os.path.dirname(__file__), "../resources/maps.json")
|
|
5
|
+
with open(mapsJsonPath) as json_file:
|
|
6
|
+
map_data = json.load(json_file)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Location:
|
|
10
|
+
|
|
11
|
+
def __init__(self, id: str, name: str, type: str):
|
|
12
|
+
self.id = id
|
|
13
|
+
self.name = name
|
|
14
|
+
self.type = type
|
|
15
|
+
|
|
16
|
+
def is_black_zone(self):
|
|
17
|
+
if self.type == "OPENPVP_BLACK":
|
|
18
|
+
return True
|
|
19
|
+
elif self.type == "DUNGEON_BLACK":
|
|
20
|
+
return True
|
|
21
|
+
elif self.type == "PASSAGE_BLACK":
|
|
22
|
+
return True
|
|
23
|
+
elif self.type == "TUNNEL":
|
|
24
|
+
return True
|
|
25
|
+
else:
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
def is_red_zone(self):
|
|
29
|
+
if self.type == "OPENPVP_RED":
|
|
30
|
+
return True
|
|
31
|
+
elif self.type == "DUNGEON_RED":
|
|
32
|
+
return True
|
|
33
|
+
elif self.type == "PASSAGE_RED":
|
|
34
|
+
return True
|
|
35
|
+
else:
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
def is_safe_zone(self):
|
|
39
|
+
if self.is_black_zone() == False and self.is_red_zone() == False:
|
|
40
|
+
return True
|
|
41
|
+
else:
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
@classmethod
|
|
45
|
+
def get_location_from_code(cls, code: str):
|
|
46
|
+
location = map_data[code]
|
|
47
|
+
|
|
48
|
+
return cls(id=location["id"], name=location["name"], type=location["type"])
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
|
|
6
|
+
from scapy.all import wrpcap
|
|
7
|
+
|
|
8
|
+
from albibong.photon_packet_parser import EventData, OperationRequest, OperationResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Logger(logging.Logger):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
name,
|
|
15
|
+
stdout=False,
|
|
16
|
+
log_to_file=True,
|
|
17
|
+
ignore_event=False,
|
|
18
|
+
ignore_request=False,
|
|
19
|
+
ignore_response=False,
|
|
20
|
+
):
|
|
21
|
+
super().__init__(name)
|
|
22
|
+
self.ignore_event = ignore_event
|
|
23
|
+
self.ignore_request = ignore_request
|
|
24
|
+
self.ignore_response = ignore_response
|
|
25
|
+
|
|
26
|
+
self.file_timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H%M%S")
|
|
27
|
+
log_filepath = os.path.join(
|
|
28
|
+
os.path.expanduser("~"), f"Albibong/log/log_{self.file_timestamp}.txt"
|
|
29
|
+
)
|
|
30
|
+
os.makedirs(os.path.dirname(log_filepath), exist_ok=True)
|
|
31
|
+
|
|
32
|
+
self.setLevel(logging.DEBUG)
|
|
33
|
+
log_formatter = logging.Formatter("%(message)s")
|
|
34
|
+
|
|
35
|
+
if log_to_file:
|
|
36
|
+
file_handler = logging.FileHandler(log_filepath)
|
|
37
|
+
file_handler.setFormatter(log_formatter)
|
|
38
|
+
file_handler.setLevel(logging.INFO)
|
|
39
|
+
self.addHandler(file_handler)
|
|
40
|
+
|
|
41
|
+
if stdout:
|
|
42
|
+
stdout_handler = logging.StreamHandler()
|
|
43
|
+
stdout_handler.setFormatter(log_formatter)
|
|
44
|
+
stdout_handler.setLevel(logging.INFO)
|
|
45
|
+
self.addHandler(stdout_handler)
|
|
46
|
+
|
|
47
|
+
# Load Event and Operation Code for logging
|
|
48
|
+
eventCodeJsonPath = os.path.join(
|
|
49
|
+
os.path.dirname(__file__), "../resources/event_code.json"
|
|
50
|
+
)
|
|
51
|
+
with open(eventCodeJsonPath) as json_file:
|
|
52
|
+
data = json.load(json_file)
|
|
53
|
+
self.event_code = data
|
|
54
|
+
|
|
55
|
+
operationCodeJsonPath = os.path.join(
|
|
56
|
+
os.path.dirname(__file__), "../resources/operation_code.json"
|
|
57
|
+
)
|
|
58
|
+
with open(operationCodeJsonPath) as json_file:
|
|
59
|
+
data = json.load(json_file)
|
|
60
|
+
self.operation_code = data
|
|
61
|
+
|
|
62
|
+
def get_timestamp(self):
|
|
63
|
+
return datetime.now(timezone.utc).strftime("%H:%M:%S")
|
|
64
|
+
|
|
65
|
+
def log_payload(self, payload):
|
|
66
|
+
if type(payload) == EventData:
|
|
67
|
+
self.log_event(payload)
|
|
68
|
+
elif type(payload) == OperationRequest:
|
|
69
|
+
self.log_request(payload)
|
|
70
|
+
elif type(payload) == OperationResponse:
|
|
71
|
+
self.log_response(payload)
|
|
72
|
+
|
|
73
|
+
def log_dps_meter_state(self, state: bool):
|
|
74
|
+
text = f"{self.get_timestamp()} DPS METER IS {'RUNNING. The damages below this point will be recorded.' if state else 'PAUSED. The damages below this point will NOT be recorded.'}"
|
|
75
|
+
self.info(text)
|
|
76
|
+
print(text)
|
|
77
|
+
|
|
78
|
+
def log_event(self, payload: EventData):
|
|
79
|
+
if self.ignore_event:
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
# Ignore position update, timesync, and guild updates
|
|
83
|
+
if payload.code == 3:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
parameters = payload.parameters
|
|
87
|
+
if 252 in parameters and parameters[252] in {99, 100, 152}:
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
event_code = str(parameters[252]) if 252 in parameters else None
|
|
91
|
+
if event_code in self.event_code:
|
|
92
|
+
event_code = self.event_code[event_code]
|
|
93
|
+
|
|
94
|
+
self.info(f"{self.get_timestamp()} event {event_code}")
|
|
95
|
+
self.info(parameters)
|
|
96
|
+
|
|
97
|
+
def log_request(self, payload: OperationRequest):
|
|
98
|
+
if self.ignore_request:
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
parameters = payload.parameters
|
|
102
|
+
operation_code = str(parameters[253]) if 253 in parameters else None
|
|
103
|
+
if operation_code in self.operation_code:
|
|
104
|
+
operation_code = self.operation_code[operation_code]
|
|
105
|
+
|
|
106
|
+
self.info(f"{self.get_timestamp()} request {operation_code}")
|
|
107
|
+
self.info(parameters)
|
|
108
|
+
|
|
109
|
+
def log_response(self, payload: OperationResponse):
|
|
110
|
+
if self.ignore_response:
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
parameters = payload.parameters
|
|
114
|
+
operation_code = str(parameters[253]) if 253 in parameters else None
|
|
115
|
+
if operation_code in self.operation_code:
|
|
116
|
+
operation_code = self.operation_code[operation_code]
|
|
117
|
+
|
|
118
|
+
self.info(f"{self.get_timestamp()} response {operation_code}")
|
|
119
|
+
self.info(parameters)
|
|
120
|
+
|
|
121
|
+
def log_error_pcap(self, packet):
|
|
122
|
+
wrpcap(f"../pcap/error_{self.file_timestamp}.pcapng", packet, append=True)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import traceback
|
|
3
|
+
|
|
4
|
+
from scapy.all import UDP, Packet
|
|
5
|
+
|
|
6
|
+
from albibong.classes.logger import Logger
|
|
7
|
+
from albibong.classes.world_data import WorldData, get_world_data
|
|
8
|
+
from albibong.photon_packet_parser import (
|
|
9
|
+
EventData,
|
|
10
|
+
OperationRequest,
|
|
11
|
+
OperationResponse,
|
|
12
|
+
PhotonPacketParser,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
logger = Logger(__name__, ignore_request=True)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def log_payload(func):
|
|
19
|
+
@functools.wraps(func)
|
|
20
|
+
def wrapper(*args, **kwargs):
|
|
21
|
+
try:
|
|
22
|
+
payload = func(*args, **kwargs)
|
|
23
|
+
logger.log_payload(payload)
|
|
24
|
+
except:
|
|
25
|
+
print(f"ERROR {func.__name__}: {traceback.format_exc()}")
|
|
26
|
+
|
|
27
|
+
return wrapper
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class PacketHandler:
|
|
31
|
+
def __init__(self):
|
|
32
|
+
self.parser = PhotonPacketParser(
|
|
33
|
+
self.on_event, self.on_request, self.on_response
|
|
34
|
+
)
|
|
35
|
+
self.world_data = get_world_data()
|
|
36
|
+
|
|
37
|
+
@log_payload
|
|
38
|
+
def on_event(self, payload: EventData):
|
|
39
|
+
self.world_data.handle_event(payload.parameters)
|
|
40
|
+
return payload
|
|
41
|
+
|
|
42
|
+
@log_payload
|
|
43
|
+
def on_request(self, payload: OperationRequest):
|
|
44
|
+
self.world_data.handle_request(payload.parameters)
|
|
45
|
+
return payload
|
|
46
|
+
|
|
47
|
+
@log_payload
|
|
48
|
+
def on_response(self, payload: OperationResponse):
|
|
49
|
+
self.world_data.handle_response(payload.parameters)
|
|
50
|
+
return payload
|
|
51
|
+
|
|
52
|
+
def handle(self, packet: Packet):
|
|
53
|
+
try:
|
|
54
|
+
payload = packet[UDP].payload.original
|
|
55
|
+
self.parser.handle_payload(payload)
|
|
56
|
+
except Exception as e:
|
|
57
|
+
if type(e) == KeyboardInterrupt:
|
|
58
|
+
raise e
|
|
59
|
+
|
|
60
|
+
print(f"ERROR HANDLE: {traceback.format_exc()}")
|
|
61
|
+
logger.log_error_pcap(packet)
|