123 lines
4.0 KiB
Python
123 lines
4.0 KiB
Python
from typing import Any, Sequence
|
|
|
|
from lib.archive import *
|
|
|
|
NO_OP_TYPES = [
|
|
"EPalBaseCampModuleType::Energy",
|
|
"EPalBaseCampModuleType::Medical",
|
|
"EPalBaseCampModuleType::ResourceCollector",
|
|
"EPalBaseCampModuleType::ItemStorages",
|
|
"EPalBaseCampModuleType::FacilityReservation",
|
|
"EPalBaseCampModuleType::ObjectMaintenance",
|
|
]
|
|
|
|
|
|
def decode(
|
|
reader: FArchiveReader, type_name: str, size: int, path: str
|
|
) -> dict[str, Any]:
|
|
if type_name != "MapProperty":
|
|
raise Exception(f"Expected MapProperty, got {type_name}")
|
|
value = reader.property(type_name, size, path, allow_custom=False)
|
|
# module map
|
|
module_map = value["value"]
|
|
for module in module_map:
|
|
module_type = module["key"]
|
|
module_bytes = module["value"]["RawData"]["value"]["values"]
|
|
print(module_type)
|
|
print("".join(f"{b:02x}" for b in module_bytes))
|
|
# module["value"]["RawData"]["value"] = decode_bytes(module_bytes, module_type)
|
|
return value
|
|
|
|
|
|
def pal_item_and_slot_read(reader: FArchiveReader) -> dict[str, Any]:
|
|
return {
|
|
"item_id": {
|
|
# "static_id": reader.fstring(),
|
|
# "dynamic_id": {
|
|
"created_world_id": reader.guid(),
|
|
"local_id_in_created_world": reader.guid(),
|
|
# }
|
|
},
|
|
"slot_id": reader.guid(),
|
|
}
|
|
|
|
|
|
def transport_item_character_info_reader(reader: FArchiveReader) -> dict[str, Any]:
|
|
return {
|
|
"item_infos": reader.tarray,
|
|
"character_location": {
|
|
"x": reader.double(),
|
|
"y": reader.double(),
|
|
"z": reader.double(),
|
|
},
|
|
}
|
|
|
|
|
|
PASSIVE_EFFECT_ENUM = {
|
|
0: "EPalBaseCampPassiveEffectType::None",
|
|
1: "EPalBaseCampPassiveEffectType::WorkSuitability",
|
|
2: "EPalBaseCampPassiveEffectType::WorkHard",
|
|
}
|
|
|
|
|
|
def module_passive_effect_reader(reader: FArchiveReader) -> dict[str, Any]:
|
|
data = {}
|
|
data["type"] = reader.byte()
|
|
if data["type"] not in PASSIVE_EFFECT_ENUM:
|
|
raise Exception(f"Unknown passive effect type {data['type']}")
|
|
elif data["type"] == 1:
|
|
data["work_hard_type"] = reader.byte()
|
|
return data
|
|
|
|
|
|
def decode_bytes(b_bytes: Sequence[int], module_type: str) -> dict[str, Any]:
|
|
reader = FArchiveReader(bytes(b_bytes))
|
|
data = {}
|
|
if module_type in NO_OP_TYPES:
|
|
pass
|
|
elif module_type == "EPalBaseCampModuleType::TransportItemDirector":
|
|
try:
|
|
data["transport_item_character_infos"] = reader.tarray(
|
|
transport_item_character_info_reader
|
|
)
|
|
except Exception as e:
|
|
reader.data.seek(0)
|
|
print(
|
|
f"Warning: Failed to decode transport item director, please report this: {e} ({reader.bytes()})"
|
|
)
|
|
data = {"values": b_bytes}
|
|
elif module_type == "EPalBaseCampModuleType::PassiveEffect":
|
|
try:
|
|
data["passive_effects"] = reader.tarray(module_passive_effect_reader)
|
|
except Exception as e:
|
|
reader.data.seek(0)
|
|
print(
|
|
f"Warning: Failed to decode passive effect, please report this: {e} ({reader.bytes()})"
|
|
)
|
|
data = {"values": b_bytes}
|
|
else:
|
|
print(f"Warning: Unknown base camp module type {module_type}, skipping")
|
|
data["values"] = [b for b in reader.bytes()]
|
|
if not reader.eof():
|
|
raise Exception("Warning: EOF not reached")
|
|
return data
|
|
|
|
|
|
def encode(
|
|
writer: FArchiveWriter, property_type: str, properties: dict[str, Any]
|
|
) -> int:
|
|
if property_type != "MapProperty":
|
|
raise Exception(f"Expected MapProperty, got {property_type}")
|
|
del properties["custom_type"]
|
|
# encoded_bytes = encode_bytes(properties["value"])
|
|
# properties["value"] = {"values": [b for b in encoded_bytes]}
|
|
return writer.property_inner(property_type, properties)
|
|
|
|
|
|
def encode_bytes(p: dict[str, Any]) -> bytes:
|
|
writer = FArchiveWriter()
|
|
writer.byte(p["state"])
|
|
writer.guid(p["id"])
|
|
encoded_bytes = writer.bytes()
|
|
return encoded_bytes
|