Palworld-co-op-to-server-fix/lib/rawdata/base_camp_module.py

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