Add item basetype parsing

This commit is contained in:
2023-10-22 13:03:38 +02:00
parent 643784af52
commit e99d93a6a0
2 changed files with 50 additions and 3 deletions

View File

@@ -1,7 +1,12 @@
import json
import os
from bitarray import bitarray from bitarray import bitarray
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
_data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
_basetype_map = None
class Quality(Enum): class Quality(Enum):
LOW = 1 LOW = 1
@@ -73,10 +78,16 @@ class Item:
nameword2: int | None = None nameword2: int | None = None
runeword_id: int | None = None runeword_id: int | None = None
personal_name: str | None = None personal_name: str | None = None
defense: int | None = None
durability: int | None = None
max_durability: int | None = None
sockets: int | None = None
quantity: int | None = None
def print(self, indent=5, with_raw=False): def print(self, indent=5, with_raw=False):
properties = [] properties = []
print(" " * indent, self.kind) kind_name = lookup_basetype(self.kind)["name"]
print(" " * indent, f"{kind_name} ({self.kind})")
if self.lvl: if self.lvl:
print(" " * indent, f"ilvl {self.lvl}") print(" " * indent, f"ilvl {self.lvl}")
if self.is_simple: if self.is_simple:
@@ -117,3 +128,11 @@ class Item:
print(" " * indent, txtbits(bits)) print(" " * indent, txtbits(bits))
print("") print("")
print("") print("")
def lookup_basetype(code: str) -> dict:
global _basetype_map
if _basetype_map is None:
with open(os.path.join(_data_path, "items.json")) as f:
_basetype_map = json.load(f)
return _basetype_map[code]

View File

@@ -2,7 +2,7 @@ import struct
from bitarray import bitarray from bitarray import bitarray
from bitarray.util import ba2int from bitarray.util import ba2int
from d2warehouse.stash import Stash, StashTab from d2warehouse.stash import Stash, StashTab
from d2warehouse.item import Affix, Item, LowQualityType, Quality from d2warehouse.item import Affix, Item, LowQualityType, Quality, lookup_basetype
import d2warehouse.huffman as huffman import d2warehouse.huffman as huffman
STASH_TAB_MAGIC = b"\x55\xAA\x55\xAA" STASH_TAB_MAGIC = b"\x55\xAA\x55\xAA"
@@ -154,7 +154,9 @@ def parse_item(data: bytes) -> tuple[bytes, Item]:
else: else:
personalized_end = runeword_end personalized_end = runeword_end
extended_byte_size = int((personalized_end + 7) / 8) item, itemtype_end = parse_basetype_data(bits[personalized_end:], item)
extended_byte_size = int((itemtype_end + 7) / 8)
print("extended size", extended_byte_size) print("extended size", extended_byte_size)
item.raw_data = data[:] item.raw_data = data[:]
@@ -265,6 +267,32 @@ def parse_personalization(bits: bitarray) -> tuple[str, int]:
return output, ptr + 1 return output, ptr + 1
def parse_basetype_data(bits: bitarray, item: Item) -> tuple[Item, int]:
cls = lookup_basetype(item.kind)["class"]
ptr = 0
if cls == "armor":
item.defense = ba2int(bits[0:10]) + 10
ptr += 10
if cls in ["armor", "weapon"]:
item.max_durability = ba2int(bits[ptr : ptr + 8])
item.durability = ba2int(bits[ptr : ptr + 8])
ptr += 16
if item.is_socketed:
item.sockets = ba2int(bits[ptr : ptr + 4])
ptr += 4
if cls == "tome":
ptr += 5 # unknown field
if cls in ["tome", "stackable"]:
item.quality = ba2int(bits[ptr : ptr + 9])
ptr += 9
return item, ptr
def parse_items(data: bytes) -> list[Item]: def parse_items(data: bytes) -> list[Item]:
data = parse_fixed(data, ITEM_DATA_MAGIC) data = parse_fixed(data, ITEM_DATA_MAGIC)
data, num = parse_u16(data) data, num = parse_u16(data)