Skip to content

Commit 8cc61de

Browse files
author
ny
committed
bug fix, add fallback for actor attr when winapi error
1 parent 9f92652 commit 8cc61de

3 files changed

Lines changed: 46 additions & 16 deletions

File tree

ff_draw/mem/actor.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import typing
44
import glm
55
from nylib.utils.win32 import memory as ny_mem
6-
from .utils import direct_mem_property
6+
from .utils import direct_mem_property, WinAPIError
77

88
if typing.TYPE_CHECKING:
99
from . import XivMem
@@ -26,8 +26,13 @@ def actor(self):
2626

2727
def __iter__(self):
2828
"""id,param,remain,source_id"""
29-
for i in range(30):
30-
yield status_struct.unpack(ny_mem.read_bytes(self.handle, self.address + 8 + (i * status_struct.size), status_struct.size))
29+
try:
30+
for i in range(30):
31+
yield status_struct.unpack(
32+
ny_mem.read_bytes(self.handle, self.address + 8 + (i * status_struct.size), status_struct.size)
33+
)
34+
except WinAPIError:
35+
pass
3136

3237
def _iter_filter(self, status_id: int, source_id=0):
3338
for status_id_, param, remain, source_id_ in self:
@@ -105,7 +110,10 @@ def __init__(self, handle, address):
105110

106111
@property
107112
def name(self):
108-
return ny_mem.read_string(self.handle, self.address + self.offsets.name, 68)
113+
try:
114+
return ny_mem.read_string(self.handle, self.address + self.offsets.name, 68)
115+
except WinAPIError:
116+
return ''
109117

110118
id = direct_mem_property(ctypes.c_uint)
111119
base_id = direct_mem_property(ctypes.c_uint)
@@ -132,17 +140,28 @@ def pos(self):
132140

133141
@property
134142
def target_id(self):
135-
return ny_mem.read_uint(self.handle, self.address + (self.offsets.pc_target_id if self.actor_type == 1 else self.offsets.b_npc_target_id))
143+
try:
144+
return ny_mem.read_uint(self.handle, self.address + (
145+
self.offsets.pc_target_id if self.actor_type == 1 else self.offsets.b_npc_target_id
146+
))
147+
except WinAPIError:
148+
return 0
136149

137150
@property
138151
def can_select(self):
139-
if ny_mem.read_byte(self.handle, self.address + self.offsets.status_flag) & 0b110 != 0b110: return False
140-
return ny_mem.read_uint(self.handle, self.address + self.offsets.hide_flag) >> 11 == 0
152+
try:
153+
if ny_mem.read_byte(self.handle, self.address + self.offsets.status_flag) & 0b110 != 0b110: return False
154+
return ny_mem.read_uint(self.handle, self.address + self.offsets.hide_flag) >> 11 == 0
155+
except WinAPIError:
156+
return False
141157

142158
@property
143159
def is_visible(self):
144-
p_draw_object = ny_mem.read_address(self.handle, self.address + self.offsets.draw_object)
145-
return ny_mem.read_byte(self.handle, p_draw_object + 0x88) & 1
160+
try:
161+
p_draw_object = ny_mem.read_address(self.handle, self.address + self.offsets.draw_object)
162+
return ny_mem.read_byte(self.handle, p_draw_object + 0x88) & 1 > 0
163+
except WinAPIError:
164+
return False
146165

147166
@property
148167
def status(self):
@@ -157,7 +176,8 @@ def __init__(self, main: 'XivMem'):
157176
self.handle = main.handle
158177
self.base_address = main.scanner.find_point('4c ? ? * * * * 89 ac cb')[0]
159178
self.sorted_table_address = self.base_address + main.scanner.find_val('4e ? ? ? * * * * 41 ? ? ? 3b ? 73')[0]
160-
self.sorted_count_address = self.base_address + main.scanner.find_val('44 ? ? * * * * 45 ? ? 41 ? ? ? 48 ? ? 78')[0]
179+
self.sorted_count_address = self.base_address + \
180+
main.scanner.find_val('44 ? ? * * * * 45 ? ? 41 ? ? ? 48 ? ? 78')[0]
161181
self.me_ptr = main.scanner.find_point('48 ? ? * * * * 49 39 87')[0]
162182
if main.game_version >= (6, 3, 0):
163183
Actor.offsets = ActorOffsets630
@@ -204,7 +224,9 @@ def get_actor_by_id(self, actor_id):
204224
# error occurred, maybe just game update
205225
return
206226
aid = a.id
207-
if aid < actor_id:
227+
if not aid:
228+
continue
229+
elif aid < actor_id:
208230
left = idx + 1
209231
elif aid > actor_id:
210232
right = idx - 1

ff_draw/mem/utils.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,31 @@
33
import typing
44

55
from nylib.utils.win32 import memory as ny_mem
6+
from nylib.utils.win32.exception import WinAPIError
67

78
_addr_size = ctypes.sizeof(ctypes.c_void_p)
89
_T = typing.TypeVar('_T')
910

1011

1112
class direct_mem_property:
12-
def __init__(self, _type, offset_key=None):
13+
def __init__(self, _type, offset_key=None, default=0):
1314
self.type = _type
1415
self.offset_key = offset_key
16+
self.default = default
1517

1618
def __set_name__(self, owner, name):
1719
if not self.offset_key:
1820
self.offset_key = name
1921

2022
def __get__(self, instance, owner) -> 'float | int | direct_mem_property':
2123
if instance is None: return self
22-
if not (addr := instance.address): raise AttributeError('Instance is None')
23-
return ny_mem.read_memory(instance.handle, self.type, addr + getattr(instance.offsets, self.offset_key)).value
24+
if not (addr := instance.address): return self.default
25+
try:
26+
return ny_mem.read_memory(
27+
instance.handle, self.type,
28+
addr + getattr(instance.offsets, self.offset_key)).value
29+
except WinAPIError:
30+
return self.default
2431

2532

2633
def get_hwnd(pid):
@@ -43,7 +50,8 @@ def get_game_version_info(file_name):
4350
with open(file_name, 'rb') as f: base_data = f.read()
4451
match = re.search(r"/\*{5}ff14\*{6}rev\d+_(\d{4})/(\d{2})/(\d{2})".encode(), base_data)
4552
game_build_date: str = f"{match.group(1).decode()}.{match.group(2).decode()}.{match.group(3).decode()}.0000.0000"
46-
match = re.search(r'(\d{3})\\trunk\\prog\\client\\Build\\FFXIVGame\\x64-Release\\ffxiv_dx11.pdb'.encode(), base_data)
53+
match = re.search(r'(\d{3})\\trunk\\prog\\client\\Build\\FFXIVGame\\x64-Release\\ffxiv_dx11.pdb'.encode(),
54+
base_data)
4755
game_version: tuple[int, int, int] = tuple(b - 48 for b in match.group(1))
4856
return game_version, game_build_date
4957

ff_draw/sniffer/message_dump.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def parse(cls, file_name: pathlib.Path | str, pno_dir: pathlib.Path | str):
5555
zone_client_pno_map = simple.load_pno_map(pno_dir / 'ZoneClientIpc.csv', game_build_date, enums.ZoneClient)
5656

5757
while True:
58-
if not (header_bytes := buf.read(20)): break
58+
if not (header_bytes := buf.read(24)): break
5959

6060
scope, proto_no, fix_value, source_id, size, timestamp_ms = struct.unpack(b'BHiIIQ', header_bytes)
6161
data = buf.read(size)

0 commit comments

Comments
 (0)