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 dataclasses import dataclass
from enum import Enum
_data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
_basetype_map = None
class Quality(Enum):
LOW = 1
@@ -73,10 +78,16 @@ class Item:
nameword2: int | None = None
runeword_id: int | 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):
properties = []
print(" " * indent, self.kind)
kind_name = lookup_basetype(self.kind)["name"]
print(" " * indent, f"{kind_name} ({self.kind})")
if self.lvl:
print(" " * indent, f"ilvl {self.lvl}")
if self.is_simple:
@@ -117,3 +128,11 @@ class Item:
print(" " * indent, txtbits(bits))
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.util import ba2int
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
STASH_TAB_MAGIC = b"\x55\xAA\x55\xAA"
@@ -154,7 +154,9 @@ def parse_item(data: bytes) -> tuple[bytes, Item]:
else:
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)
item.raw_data = data[:]
@@ -265,6 +267,32 @@ def parse_personalization(bits: bitarray) -> tuple[str, int]:
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]:
data = parse_fixed(data, ITEM_DATA_MAGIC)
data, num = parse_u16(data)