albibong 1.0.7__tar.gz → 1.1.0__tar.gz

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 (75) hide show
  1. {albibong-1.0.7 → albibong-1.1.0}/.gitignore +2 -0
  2. {albibong-1.0.7 → albibong-1.1.0}/PKG-INFO +2 -1
  3. {albibong-1.0.7 → albibong-1.1.0}/pyproject.toml +4 -2
  4. albibong-1.1.0/src/albibong/__init__.py +147 -0
  5. albibong-1.1.0/src/albibong/classes/dungeon.py +66 -0
  6. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/__init__.py +10 -0
  7. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_character_equipment_changed.py +2 -10
  8. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_party.py +6 -13
  9. albibong-1.1.0/src/albibong/classes/event_handler/handle_operation_change_cluster.py +38 -0
  10. albibong-1.1.0/src/albibong/classes/event_handler/handle_operation_farmable_harvest.py +17 -0
  11. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_operation_join.py +2 -25
  12. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/world_data_utils.py +68 -25
  13. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/item.py +19 -4
  14. albibong-1.1.0/src/albibong/classes/location.py +151 -0
  15. albibong-1.1.0/src/albibong/gui_dist/assets/index-C4r00CBk.js +168 -0
  16. albibong-1.1.0/src/albibong/gui_dist/assets/index-DKbORdbN.css +1 -0
  17. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/index.html +2 -2
  18. albibong-1.1.0/src/albibong/models/models.py +12 -0
  19. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/requirements.txt +1 -0
  20. albibong-1.1.0/src/albibong/resources/items_by_unique_name.json +55282 -0
  21. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/resources/maps.json +259 -259
  22. albibong-1.1.0/src/albibong/threads/__init__.py +0 -0
  23. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/threads/websocket_server.py +64 -41
  24. albibong-1.0.7/src/albibong/__init__.py +0 -89
  25. albibong-1.0.7/src/albibong/classes/dungeon.py +0 -59
  26. albibong-1.0.7/src/albibong/classes/event_handler/handle_operation_change_cluster.py +0 -43
  27. albibong-1.0.7/src/albibong/classes/location.py +0 -20
  28. albibong-1.0.7/src/albibong/gui_dist/assets/index-DZvgNqlG.css +0 -1
  29. albibong-1.0.7/src/albibong/gui_dist/assets/index-Dt6hyZiS.css +0 -1
  30. albibong-1.0.7/src/albibong/gui_dist/assets/index-E7pha23k.js +0 -161
  31. albibong-1.0.7/src/albibong/gui_dist/assets/index-WIuC9Mnh.js +0 -161
  32. {albibong-1.0.7 → albibong-1.1.0}/LICENSE +0 -0
  33. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/__main__.py +0 -0
  34. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/assets/boom_small.mp3 +0 -0
  35. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/__init__.py +0 -0
  36. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/character.py +0 -0
  37. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/coords.py +0 -0
  38. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_health.py +0 -0
  39. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_in_combat_state_update.py +0 -0
  40. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_new_character.py +0 -0
  41. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_other_grabbed_loot.py +0 -0
  42. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_update_fame.py +0 -0
  43. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_event_update_re_spec_points.py +0 -0
  44. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/event_handler/handle_operation_move.py +0 -0
  45. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/logger.py +0 -0
  46. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/packet_handler.py +0 -0
  47. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/utils.py +0 -0
  48. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/classes/world_data.py +0 -0
  49. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/Albibong.png +0 -0
  50. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/No Equipment.png +0 -0
  51. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/fame.png +0 -0
  52. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/re_spec.png +0 -0
  53. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/silver.png +0 -0
  54. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/gui_dist/vite.svg +0 -0
  55. {albibong-1.0.7/src/albibong/threads → albibong-1.1.0/src/albibong/models}/__init__.py +0 -0
  56. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/__init__.py +0 -0
  57. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/command_type.py +0 -0
  58. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/crc_calculator.py +0 -0
  59. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/event_data.py +0 -0
  60. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/message_type.py +0 -0
  61. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/number_serializer.py +0 -0
  62. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/operation_request.py +0 -0
  63. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/operation_response.py +0 -0
  64. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/photon_packet_parser.py +0 -0
  65. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/protocol16_deserializer.py +0 -0
  66. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/protocol16_type.py +0 -0
  67. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/photon_packet_parser/segmented_packet.py +0 -0
  68. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/resources/EventCode.py +0 -0
  69. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/resources/OperationCode.py +0 -0
  70. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/resources/event_code.json +0 -0
  71. /albibong-1.0.7/src/albibong/resources/items.json → /albibong-1.1.0/src/albibong/resources/items_by_id.json +0 -0
  72. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/resources/operation_code.json +0 -0
  73. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/threads/http_server.py +0 -0
  74. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/threads/packet_handler_thread.py +0 -0
  75. {albibong-1.0.7 → albibong-1.1.0}/src/albibong/threads/sniffer_thread.py +0 -0
@@ -7,6 +7,8 @@ dump/
7
7
  log/
8
8
  pcap/
9
9
  .vscode
10
+ src/*.db
11
+ *.db
10
12
 
11
13
  ### macOS ###
12
14
  # General
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: albibong
3
- Version: 1.0.7
3
+ Version: 1.1.0
4
4
  Summary: A cross-platform Albion Online damage, fame, and dungeon tracker
5
5
  Project-URL: Homepage, https://github.com/imjangkar/albibong
6
6
  Project-URL: Issues, https://github.com/imjangkar/albibong/issues
@@ -10,6 +10,7 @@ Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: >=3.10
13
+ Requires-Dist: peewee==3.17.6
13
14
  Requires-Dist: pywebview==5.1
14
15
  Requires-Dist: scapy==2.5.0
15
16
  Requires-Dist: websockets==12.0
@@ -11,7 +11,8 @@ exclude = [
11
11
  "/tests",
12
12
  "/gui",
13
13
  "/readme_screenshots",
14
- "/README.md"
14
+ "/README.md",
15
+ "/*.db"
15
16
  ]
16
17
 
17
18
  [project.scripts]
@@ -19,7 +20,7 @@ albibong = "albibong:main"
19
20
 
20
21
  [project]
21
22
  name = "albibong"
22
- version = "1.0.7"
23
+ version = "1.1.0"
23
24
  authors = [
24
25
  { name="imjangkar", email="imjangkar@gmail.com" },
25
26
  ]
@@ -34,6 +35,7 @@ dependencies = [
34
35
  "scapy==2.5.0",
35
36
  "websockets==12.0",
36
37
  "pywebview==5.1",
38
+ "peewee==3.17.6",
37
39
  ]
38
40
 
39
41
  [project.urls]
@@ -0,0 +1,147 @@
1
+ import json
2
+ import os
3
+ import queue
4
+ import random
5
+ import socket
6
+ import sys
7
+ import uuid
8
+ from datetime import datetime, timedelta
9
+ from pathlib import Path
10
+ from time import sleep
11
+
12
+ import webview
13
+ from scapy.all import rdpcap
14
+
15
+ from albibong.classes.dungeon import Dungeon
16
+ from albibong.classes.location import Island
17
+ from albibong.classes.logger import Logger
18
+ from albibong.classes.packet_handler import PacketHandler
19
+ from albibong.models.models import db
20
+ from albibong.threads.http_server import HttpServerThread
21
+ from albibong.threads.packet_handler_thread import PacketHandlerThread
22
+ from albibong.threads.sniffer_thread import SnifferThread
23
+ from albibong.threads.websocket_server import get_ws_server
24
+
25
+ logger = Logger(__name__, stdout=True, log_to_file=False)
26
+ PORT = random.randrange(8500, 8999)
27
+
28
+ home_dir = os.path.expanduser("~")
29
+ DUNGEON_DB = f"{home_dir}/Albibong/list_dungeon.json"
30
+ SQLITE_DB = f"{home_dir}/Albibong/Albibong.db"
31
+
32
+
33
+ def read_pcap(path):
34
+ packet_handler = PacketHandler()
35
+ scapy_cap = rdpcap(path)
36
+ for packet in scapy_cap:
37
+ packet_handler.handle(packet)
38
+
39
+
40
+ def sniff(useWebview):
41
+ _sentinel = object()
42
+ packet_queue = queue.Queue()
43
+
44
+ p = SnifferThread(name="sniffer", out_queue=packet_queue, sentinel=_sentinel)
45
+
46
+ c = PacketHandlerThread(
47
+ name="packet_handler",
48
+ in_queue=packet_queue,
49
+ sentinel=_sentinel,
50
+ )
51
+
52
+ p.start()
53
+ c.start()
54
+
55
+ ws_server = get_ws_server()
56
+ ws_server.start()
57
+
58
+ def get_end_time(str, start_time):
59
+ timer = str.split(":")
60
+ seconds = int(timer[0]) * 3600 + int(timer[1]) * 60 + int(timer[2])
61
+ return timedelta(seconds=seconds) + start_time
62
+
63
+ if Path(SQLITE_DB).is_file() == False:
64
+ db.connect()
65
+ db.create_tables([Dungeon, Island])
66
+ if Path(DUNGEON_DB).is_file() == True:
67
+ # convert json db to sqlite db
68
+ json_data = json.load(open(DUNGEON_DB))
69
+
70
+ for dungeon in json_data:
71
+ start_time = datetime.strptime(
72
+ dungeon["date_time"], "%a %d %b %Y, %I:%M%p"
73
+ )
74
+ type_splitted = set(dungeon["type"].split("_"))
75
+
76
+ if "CORRUPTED" in type_splitted:
77
+ converted_type = "CORRUPTED DUNGEON"
78
+ elif "HARDCORE" in type_splitted:
79
+ converted_type = "HARDCORE EXPEDITION"
80
+ elif "10V10" in type_splitted:
81
+ converted_type = "HELLGATE 10V10"
82
+ elif "5V5" in type_splitted:
83
+ converted_type = "HELLGATE 5V5"
84
+ elif "2V2" in type_splitted:
85
+ converted_type = "HELLGATE 2V2"
86
+ elif "DUNGEON" in type_splitted:
87
+ converted_type = "STATIC DUNGEON"
88
+ elif "RANDOMDUNGEON" in type_splitted:
89
+ converted_type = "SPAWN DUNGEON"
90
+ Dungeon.create(
91
+ type=converted_type,
92
+ name=dungeon["name"],
93
+ tier=dungeon["tier"],
94
+ fame=dungeon["fame"],
95
+ silver=dungeon["silver"],
96
+ re_spec=dungeon["re_spec"],
97
+ start_time=start_time,
98
+ end_time=get_end_time(dungeon["time_elapsed"], start_time),
99
+ )
100
+
101
+ db.connect(reuse_if_open=True)
102
+
103
+ if useWebview:
104
+
105
+ sock = socket.socket()
106
+ sock.bind(("", 0))
107
+ port = sock.getsockname()[1]
108
+ sock.close()
109
+
110
+ http_server = HttpServerThread(name="http_server", port=port)
111
+ http_server.start()
112
+
113
+ window = webview.create_window(
114
+ "Albibong",
115
+ url=f"http://localhost:{port}/",
116
+ width=1280,
117
+ height=720,
118
+ zoomable=True,
119
+ )
120
+
121
+ def on_closing():
122
+ c.stop()
123
+ p.stop()
124
+ ws_server.stop()
125
+ http_server.stop()
126
+ db.close()
127
+
128
+ window.events.closing += on_closing
129
+
130
+ webview.start()
131
+ else:
132
+ try:
133
+ while True:
134
+ sleep(100)
135
+ except KeyboardInterrupt as e:
136
+ p.stop()
137
+ ws_server.stop()
138
+
139
+
140
+ def main(useWebview=True):
141
+ if len(sys.argv) > 1:
142
+ ws_server = get_ws_server()
143
+ ws_server.start()
144
+
145
+ read_pcap(sys.argv[1])
146
+ else:
147
+ sniff(useWebview)
@@ -0,0 +1,66 @@
1
+ import uuid
2
+ from datetime import datetime
3
+
4
+ from peewee import *
5
+ from playhouse.sqlite_ext import JSONField
6
+
7
+ from albibong.models.models import BaseModel
8
+
9
+ DIVISOR = 10000
10
+
11
+
12
+ class Dungeon(BaseModel):
13
+
14
+ id = UUIDField(unique=True, default=uuid.uuid4)
15
+ type = CharField()
16
+ name = CharField()
17
+ tier = IntegerField(default=0)
18
+ fame = FloatField(default=0)
19
+ silver = FloatField(default=0)
20
+ re_spec = FloatField(default=0)
21
+ start_time = DateTimeField(default=datetime.now)
22
+ end_time = DateTimeField(null=True, default=None)
23
+ meter = JSONField(default=dict)
24
+
25
+ @staticmethod
26
+ def serialize(dungeon):
27
+ return {
28
+ "id": str(dungeon.id),
29
+ "type": dungeon.type,
30
+ "name": dungeon.name,
31
+ "tier": dungeon.tier,
32
+ "fame": dungeon.fame,
33
+ "silver": dungeon.silver,
34
+ "re_spec": dungeon.re_spec,
35
+ "date_time": dungeon.start_time.strftime("%a %d %b %Y, %I:%M%p"),
36
+ "time_elapsed": (
37
+ str(dungeon.end_time - dungeon.start_time).split(".")[0]
38
+ if dungeon.end_time
39
+ else ""
40
+ ),
41
+ "meter": dungeon.meter,
42
+ }
43
+
44
+ def set_end_time(self):
45
+ self.end_time = datetime.now()
46
+
47
+ def update_fame(self, parameters):
48
+ fame = parameters[2] / DIVISOR
49
+ self.fame += fame
50
+
51
+ def update_re_spec(self, parameters):
52
+ re_spec = parameters[2] / DIVISOR
53
+ self.re_spec += re_spec
54
+
55
+ def update_loot(self, parameters):
56
+ if 3 in parameters and parameters[3] == True:
57
+ silver = parameters[5] / DIVISOR
58
+ self.silver += silver
59
+
60
+ def update_meter(self, party):
61
+ self.meter = party
62
+
63
+ @staticmethod
64
+ def get_all_dungeon():
65
+ query = Dungeon.select().order_by(Dungeon.start_time.desc())
66
+ return [Dungeon.serialize(dungeon) for dungeon in query]
@@ -30,6 +30,10 @@ from albibong.classes.event_handler.handle_operation_change_cluster import (
30
30
  handle_operation_change_cluster,
31
31
  )
32
32
  from albibong.classes.event_handler.handle_operation_join import handle_operation_join
33
+ from albibong.classes.event_handler.handle_operation_farmable_harvest import (
34
+ handle_operation_farmable_harvest,
35
+ handle_operation_farmable_finish_grown_item,
36
+ )
33
37
  from albibong.classes.event_handler.handle_operation_move import handle_operation_move
34
38
  from albibong.classes.world_data import WorldData
35
39
  from albibong.resources.EventCode import EventCode
@@ -84,6 +88,12 @@ class EventHandler:
84
88
  self.response_handler[OperationCode.CHANGE_CLUSTER.value] = (
85
89
  handle_operation_change_cluster
86
90
  )
91
+ self.response_handler[OperationCode.FARMABLE_FINISH_GROWN_ITEM.value] = (
92
+ handle_operation_farmable_finish_grown_item
93
+ )
94
+ self.response_handler[OperationCode.FARMABLE_HARVEST.value] = (
95
+ handle_operation_farmable_harvest
96
+ )
87
97
 
88
98
  def on_request(self, world_data: WorldData, parameters):
89
99
  if REQUEST_TYPE_PARAMETER not in parameters:
@@ -1,5 +1,5 @@
1
+ from albibong.classes.event_handler.world_data_utils import WorldDataUtils
1
2
  from albibong.classes.world_data import WorldData
2
- from albibong.threads.websocket_server import send_event
3
3
 
4
4
 
5
5
  def handle_event_character_equipment_changed(world_data: WorldData, parameters):
@@ -11,14 +11,6 @@ def handle_event_character_equipment_changed(world_data: WorldData, parameters):
11
11
  ]
12
12
  if char.username in world_data.party_members:
13
13
  char.update_equipment(parameters[2])
14
- ws_update_character_equipment(world_data)
14
+ WorldDataUtils.ws_update_damage_meter(world_data)
15
15
  else:
16
16
  world_data.change_equipment_log[parameters[0]] = parameters[2]
17
-
18
-
19
- def ws_update_character_equipment(world_data: WorldData):
20
- event = {
21
- "type": "update_dps",
22
- "payload": {"party_members": world_data.serialize_party_members()},
23
- }
24
- send_event(event)
@@ -1,21 +1,22 @@
1
1
  from uuid import UUID
2
+
3
+ from albibong.classes.event_handler.world_data_utils import WorldDataUtils
2
4
  from albibong.classes.world_data import WorldData
3
- from albibong.threads.websocket_server import send_event
4
5
 
5
6
 
6
7
  def handle_event_party_joined(world_data: WorldData, parameters):
7
8
  world_data.party_members = set(parameters[5])
8
- ws_update_party_member(world_data)
9
+ WorldDataUtils.ws_update_damage_meter(world_data)
9
10
 
10
11
 
11
12
  def handle_event_party_disbanded(world_data: WorldData, parameters):
12
13
  world_data.party_members = {world_data.me.username}
13
- ws_update_party_member(world_data)
14
+ WorldDataUtils.ws_update_damage_meter(world_data)
14
15
 
15
16
 
16
17
  def handle_event_party_player_joined(world_data: WorldData, parameters):
17
18
  world_data.party_members.add(parameters[2])
18
- ws_update_party_member(world_data)
19
+ WorldDataUtils.ws_update_damage_meter(world_data)
19
20
 
20
21
 
21
22
  def handle_event_party_player_left(world_data: WorldData, parameters):
@@ -27,12 +28,4 @@ def handle_event_party_player_left(world_data: WorldData, parameters):
27
28
  # self out party
28
29
  if name == world_data.me.username:
29
30
  world_data.party_members = {world_data.me.username}
30
- ws_update_party_member(world_data)
31
-
32
-
33
- def ws_update_party_member(world_data: WorldData):
34
- event = {
35
- "type": "update_dps",
36
- "payload": {"party_members": world_data.serialize_party_members()},
37
- }
38
- send_event(event)
31
+ WorldDataUtils.ws_update_damage_meter(world_data)
@@ -0,0 +1,38 @@
1
+ from albibong.classes.event_handler.world_data_utils import WorldDataUtils
2
+ from albibong.classes.location import Island, Location
3
+ from albibong.classes.world_data import WorldData
4
+ from albibong.threads.websocket_server import send_event
5
+
6
+
7
+ def handle_operation_change_cluster(world_data: WorldData, parameters):
8
+ world_data.change_equipment_log = {}
9
+
10
+ if type(world_data.current_map).__name__ == "Island":
11
+ WorldDataUtils.set_island_status(
12
+ current_island=world_data.current_map, parameters=parameters
13
+ )
14
+
15
+ if 1 in parameters:
16
+ check_map = Location.get_location_from_code(parameters[1])
17
+ map_type_splitted = set(check_map.type.split(" "))
18
+ WorldDataUtils.set_dungeon_status(world_data, check_map, map_type_splitted)
19
+
20
+ if "ISLAND" in map_type_splitted:
21
+ island = Island.get_island_from_code(parameters[1])
22
+ island.name = f"{parameters[2]}'s {island.name}"
23
+ world_data.current_map = island
24
+ elif "HIDEOUT" in map_type_splitted:
25
+ hideout = Location.get_location_from_code(parameters[1])
26
+ hideout.name = f"{parameters[2]}'s {hideout.name}"
27
+ world_data.current_map = hideout
28
+
29
+ elif 0 in parameters:
30
+ check_map = Location.get_location_from_code(parameters[0])
31
+ map_type_splitted = set(check_map.type.split(" "))
32
+ is_dungeon = WorldDataUtils.set_dungeon_status(
33
+ world_data, check_map, map_type_splitted
34
+ )
35
+ if is_dungeon == False:
36
+ world_data.current_map = Location.get_location_from_code(parameters[0])
37
+
38
+ WorldDataUtils.ws_update_location(world_data)
@@ -0,0 +1,17 @@
1
+ from albibong.classes.world_data import WorldData
2
+
3
+
4
+ def handle_operation_farmable_harvest(world_data: WorldData, parameters):
5
+ if type(world_data.current_map).__name__ == "Island":
6
+ for i in range(len(parameters[0])):
7
+ world_data.current_map.add_crop(
8
+ unique_name=parameters[0][i], quantity=parameters[1][i]
9
+ )
10
+
11
+
12
+ def handle_operation_farmable_finish_grown_item(world_data: WorldData, parameters):
13
+ if type(world_data.current_map).__name__ == "Island":
14
+ for i in range(len(parameters[0])):
15
+ world_data.current_map.add_animal(
16
+ unique_name=parameters[0][i], quantity=parameters[1][i]
17
+ )
@@ -43,8 +43,8 @@ def handle_operation_join(world_data: WorldData, parameters):
43
43
  )
44
44
 
45
45
  ws_init_character(world_data)
46
- ws_update_location(world_data)
47
- ws_update_dps(world_data)
46
+ WorldDataUtils.ws_update_location(world_data)
47
+ WorldDataUtils.ws_update_damage_meter(world_data)
48
48
 
49
49
 
50
50
  def ws_init_character(world_data: WorldData):
@@ -59,26 +59,3 @@ def ws_init_character(world_data: WorldData):
59
59
  },
60
60
  }
61
61
  send_event(event)
62
-
63
-
64
- def ws_update_location(world_data: WorldData):
65
- event = {
66
- "type": "update_location",
67
- "payload": {
68
- "map": world_data.current_map.name if world_data.current_map else "None",
69
- "dungeon": (
70
- Dungeon.serialize(world_data.current_dungeon)
71
- if world_data.current_dungeon
72
- else None
73
- ),
74
- },
75
- }
76
- send_event(event)
77
-
78
-
79
- def ws_update_dps(world_data: WorldData):
80
- event = {
81
- "type": "update_dps",
82
- "payload": {"party_members": world_data.serialize_party_members()},
83
- }
84
- send_event(event)
@@ -1,38 +1,65 @@
1
- from collections import deque
2
1
  import json
3
2
  import os
3
+ from collections import deque
4
+ from datetime import datetime
4
5
 
5
6
  from albibong.classes.character import Character
6
7
  from albibong.classes.dungeon import Dungeon
7
- from albibong.classes.location import Location
8
+ from albibong.classes.location import Island, Location
8
9
  from albibong.classes.utils import Utils
9
10
  from albibong.classes.world_data import WorldData
10
11
  from albibong.threads.websocket_server import send_event
11
12
 
12
- FILENAME = os.path.join(os.path.expanduser("~"), "Albibong/list_dungeon.json")
13
- os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
13
+ LIST_DUNGEON = os.path.join(os.path.expanduser("~"), "Albibong/list_dungeon.json")
14
+ os.makedirs(os.path.dirname(LIST_DUNGEON), exist_ok=True)
15
+ LIST_ISLAND = os.path.join(os.path.expanduser("~"), "Albibong/list_island.json")
16
+ os.makedirs(os.path.dirname(LIST_ISLAND), exist_ok=True)
14
17
 
15
18
 
16
19
  class WorldDataUtils:
17
20
 
18
- def end_current_dungeon(world_data: WorldData):
19
- if world_data.current_dungeon:
20
- list_dungeon = deque()
21
-
22
- try:
23
- with open(FILENAME) as json_file:
24
- list_dungeon = deque(json.load(json_file))
25
- except:
26
- pass
27
-
28
- world_data.current_dungeon.get_elapsed_time()
29
- list_dungeon.appendleft(Dungeon.serialize(world_data.current_dungeon))
30
-
31
- with open(FILENAME, "w") as json_file:
32
- json.dump(list(list_dungeon), json_file)
21
+ def save_current_island(current_map: Island):
22
+ current_map.save(force_insert=True)
23
+ WorldDataUtils.ws_update_total_harvest_by_date(
24
+ Island.get_total_harvest_by_date()
25
+ )
26
+ WorldDataUtils.ws_update_island(Island.get_all_island())
27
+
28
+ def set_island_status(current_island: Island, parameters):
29
+ check_map = (
30
+ Location.get_location_from_code(parameters[1])
31
+ if 1 in parameters
32
+ else Location.get_location_from_code(parameters[0])
33
+ )
34
+ check_map_name = (
35
+ f"{parameters[2]}'s {check_map.name}" if 2 in parameters else check_map.name
36
+ )
37
+ if current_island.name != check_map_name:
38
+ if current_island.crops != {} or current_island.animals != {}:
39
+ WorldDataUtils.save_current_island(current_island)
40
+
41
+ def ws_update_total_harvest_by_date(payload):
42
+ event = {
43
+ "type": "update_total_harvest_by_date",
44
+ "payload": payload,
45
+ }
46
+ send_event(event)
33
47
 
34
- WorldDataUtils.ws_update_dungeon(list(list_dungeon))
48
+ def ws_update_island(list_island: list):
49
+ event = {
50
+ "type": "update_island",
51
+ "payload": {"list_island": list_island},
52
+ }
53
+ send_event(event)
35
54
 
55
+ def end_current_dungeon(world_data: WorldData):
56
+ if world_data.current_dungeon:
57
+ world_data.current_dungeon.set_end_time()
58
+ world_data.current_dungeon.update_meter(
59
+ world_data.serialize_party_members()
60
+ )
61
+ world_data.current_dungeon.save(force_insert=True)
62
+ WorldDataUtils.ws_update_dungeon(Dungeon.get_all_dungeon())
36
63
  world_data.current_dungeon = None
37
64
 
38
65
  def ws_update_dungeon(list_dungeon: list):
@@ -45,14 +72,14 @@ class WorldDataUtils:
45
72
  @staticmethod
46
73
  def start_current_dungeon(world_data: WorldData, type: str, name: str):
47
74
  if world_data.current_dungeon == None:
48
- new_dungeon = Dungeon(type, name)
75
+ new_dungeon = Dungeon(type=type, name=name)
49
76
  world_data.current_dungeon = new_dungeon
50
77
 
51
78
  @staticmethod
52
79
  def set_dungeon_status(
53
80
  world_data: WorldData, check_map: Location, map_type_splitted: set
54
81
  ):
55
- if "EXPEDITION" in map_type_splitted:
82
+ if "EXPEDITION" in map_type_splitted or "HELLGATE" in map_type_splitted:
56
83
  WorldDataUtils.start_current_dungeon(
57
84
  world_data, type=check_map.type, name=check_map.name
58
85
  )
@@ -102,11 +129,27 @@ class WorldDataUtils:
102
129
  else:
103
130
  char.update_heal_dealt(nominal)
104
131
 
105
- WorldDataUtils.ws_update_damage_heal(world_data)
132
+ WorldDataUtils.ws_update_damage_meter(world_data)
106
133
 
107
- def ws_update_damage_heal(world_data: WorldData):
134
+ def ws_update_damage_meter(world_data: WorldData):
108
135
  event = {
109
- "type": "update_dps",
136
+ "type": "update_damage_meter",
110
137
  "payload": {"party_members": world_data.serialize_party_members()},
111
138
  }
112
139
  send_event(event)
140
+
141
+ def ws_update_location(world_data: WorldData):
142
+ event = {
143
+ "type": "update_location",
144
+ "payload": {
145
+ "map": (
146
+ world_data.current_map.name if world_data.current_map else "None"
147
+ ),
148
+ "dungeon": (
149
+ world_data.current_dungeon.name
150
+ if world_data.current_dungeon
151
+ else "None"
152
+ ),
153
+ },
154
+ }
155
+ send_event(event)
@@ -1,9 +1,16 @@
1
1
  import json
2
2
  import os
3
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)
4
+ itemsByIdJsonPath = os.path.join(
5
+ os.path.dirname(__file__), "../resources/items_by_id.json"
6
+ )
7
+ itemsByUniqueNameJsonPath = os.path.join(
8
+ os.path.dirname(__file__), "../resources/items_by_unique_name.json"
9
+ )
10
+ with open(itemsByIdJsonPath) as json_file:
11
+ items_by_id = json.load(json_file)
12
+ with open(itemsByUniqueNameJsonPath) as json_file:
13
+ items_by_unique_name = json.load(json_file)
7
14
 
8
15
 
9
16
  class Item:
@@ -17,6 +24,7 @@ class Item:
17
24
  if self.unique_name != "None"
18
25
  else "/No Equipment.png"
19
26
  )
27
+ self.quantity = 0
20
28
 
21
29
  @staticmethod
22
30
  def serialize(item):
@@ -25,6 +33,7 @@ class Item:
25
33
  "name": item.name,
26
34
  "unique_name": item.unique_name,
27
35
  "image": item.image,
36
+ "quantity": item.quantity,
28
37
  }
29
38
 
30
39
  @staticmethod
@@ -36,6 +45,12 @@ class Item:
36
45
 
37
46
  @classmethod
38
47
  def get_item_from_code(cls, code: str):
39
- item = item_data[code]
48
+ item = items_by_id[code]
49
+
50
+ return cls(id=item["id"], name=item["name"], unique_name=item["unique_name"])
51
+
52
+ @classmethod
53
+ def get_item_from_unique_name(cls, unique_name: str):
54
+ item = items_by_unique_name[unique_name]
40
55
 
41
56
  return cls(id=item["id"], name=item["name"], unique_name=item["unique_name"])