Beispiel #1
0
def get_named_pio(shop: ParameterIO, shop_type: str) -> ParameterIO:
    named_pio = ParameterIO()
    shop_keys = EXT_PARAMS[shop_type]

    for table_key, table_obj in shop.objects.items():
        if table_key.hash == oead.aamp.Name("Header").hash:
            tablenames = ParameterObject()
            named_pio.objects["TableNames"] = ParameterObject()
            tablenum = table_obj.params["TableNum"].v
            for idx in range(1, tablenum + 1):
                table_name = str(table_obj.params[f"Table{idx:02}"].v)
                tablenames.params[oead.aamp.Name(table_name)] = table_name
            named_pio.objects["TableNames"] = tablenames
            continue
        table_max = table_obj.params["ColumnNum"].v
        table_obj_new = ParameterList()
        for idx in range(1, table_max + 1):
            if shop_type == "brecipe":
                entry_key = "%02d" % idx
            elif shop_type == "bshop":
                entry_key = "%03d" % idx
            else:
                raise KeyError(shop_type)
            entry_value = ParameterObject()
            try:
                for curr_shop_key in shop_keys:
                    no_shop_key = curr_shop_key + entry_key
                    entry_value.params[curr_shop_key] = table_obj.params[
                        no_shop_key]
            except KeyError:
                continue
            table_obj_new.objects[str(
                entry_value.params["ItemName"].v)] = entry_value
        named_pio.lists[table_key] = table_obj_new
    return named_pio
Beispiel #2
0
def shop_merge(base: ParameterIO, ext: str, adds: ParameterList,
               rems: ParameterList) -> ParameterIO:
    base_sorted = get_named_pio(base, ext)
    base_sorted = util.pio_subtract(base_sorted, rems)
    base_sorted = util.pio_merge(base_sorted, adds)

    if ext == "bshop":
        fix_itemsorts(base_sorted)

    merged = ParameterIO()
    merged.objects["Header"] = ParameterObject()
    merged.objects["Header"].params["TableNum"] = Parameter(
        len(base_sorted.lists))
    table_no = 1
    for table_key, table_list in base_sorted.lists.items():
        merged.objects["Header"].params[f"Table{table_no:02}"] = Parameter(
            base_sorted.objects["TableNames"].params[table_key].v)
        table_no += 1
        merged_table_obj = ParameterObject()
        merged_table_obj.params["ColumnNum"] = Parameter(
            len(table_list.objects))
        for _, item_obj in table_list.objects.items():
            if ext == "brecipe":
                entry_key = "%02d" % (item_obj.params["ItemSort"].v + 1)
            elif ext == "bshop":
                entry_key = "%03d" % (item_obj.params["ItemSort"].v + 1)
            else:
                raise KeyError(ext)
            for param_key in EXT_PARAMS[ext]:
                param_name = param_key + entry_key
                merged_table_obj.params[param_name] = item_obj.params[
                    param_key]
        merged.objects[table_key] = merged_table_obj
    return merged
Beispiel #3
0
def make_shopdata(pio: ParameterIO) -> ParameterList:
    shopdata = ParameterList()
    tables: List[Parameter] = [
        str(t.v) for _, t in pio.objects["Header"].params.items() if is_string(t)
    ]
    if not tables:
        raise InvalidDataError("A shop file is invalid: has no tables")
    shopdata.objects["TableNames"] = ParameterObject()
    for table in tables:
        table_plist = ParameterList()
        shopdata.objects["TableNames"].params[table] = Parameter(FixedSafeString64(table))
        table_hash = crc32(table.encode())
        items: Dict[str, List[int]] = {
            str(p.v): [k.hash, i]
            for i, (k, p) in enumerate(pio.objects[table_hash].params.items())
            if is_string(p)
        }
        for item in items.keys():
            item_no = int(
                name_table.get_name(items[item][0], items[item][1], table_hash).replace(
                    "ItemName", ""
                )
            )
            item_obj = ParameterObject()
            for shop_key in shop_keys:
                try:
                    item_obj.params[shop_key] = pio.objects[table_hash].params[
                        f"{shop_key}{item_no:03d}"
                    ]
                except KeyError:
                    raise KeyError(f"{shop_key}{item_no:03d}")
            table_plist.objects[item] = item_obj
        if table_plist.objects:
            shopdata.lists[table_hash] = table_plist
    return shopdata
Beispiel #4
0
 def __init__(self,
              def_name: str,
              type: str,
              name: str = "",
              group: str = ""):
     super().__init__()
     defs = util.get_ai_defs()
     key = ("AIs" if type == "ai" else
            "Actions" if type == "action" else "Behaviors"
            if type == "behavior" else "Querys" if type == "query" else "")
     if def_name in defs[key]:
         ai_def = defs[key][def_name]
         self.lists = {}
         self.objects = {crc32(b"Def"): ParameterObject()}
         self.objects["Def"].params["ClassName"] = Parameter(
             oead.FixedSafeString32(def_name))
         self.objects["Def"].params["Name"] = Parameter(name)
         self.objects["Def"].params["GroupName"] = Parameter(group)
         if "childs" in ai_def:
             self.objects["ChildIdx"] = ParameterObject()
             for child in ai_def["childs"]:
                 self.objects["ChildIdx"].params[child] = Parameter(
                     oead.S32(-1))
         if "StaticInstParams" in ai_def:
             self.objects["SInst"] = ParameterObject()
             for sinst in ai_def["StaticInstParams"]:
                 if "Value" in sinst:
                     val = sinst["Value"]
                 else:
                     val = _param_type_map[sinst["Type"]]()
                 self.objects["SInst"].params[sinst["Name"]] = Parameter(
                     val)
     else:
         raise ValueError(f"{def_name} is not a valid AI")
Beispiel #5
0
 def diff_pobj(pobj: ParameterObject,
               ref_pobj: ParameterObject) -> ParameterObject:
     diff = ParameterObject()
     for param, value in pobj.params.items():
         if param not in ref_pobj.params or ref_pobj.params[param] != value:
             diff.params[param] = value
     return diff
Beispiel #6
0
 def _to_pobj(self, obj) -> ParameterObject:
     if isinstance(obj, ParameterObject):
         return obj
     pobj = ParameterObject()
     if "params" in obj and obj["params"]:
         for param, val in obj["params"].items():
             if param.isnumeric():
                 pobj.params[int(param)] = self.object_hook(val)
             else:
                 pobj.params[param] = self.object_hook(val)
     return pobj
Beispiel #7
0
    def generate_diff(self, mod_dir: Path,
                      modded_files: List[Union[Path, str]]) -> ParameterIO:
        print("Logging changes to shop files...")
        diffs = ParameterIO()
        file_names = ParameterObject()
        for file in [
                file for file in modded_files
                if Path(file).suffix in EXT_FOLDERS
        ]:
            try:
                mod_bytes = util.get_nested_file_bytes(
                    str(mod_dir) + "/" + str(file))
                nests = str(file).split("//", 1)
                try:
                    ref_path = str(util.get_game_file(Path(
                        nests[0]))) + "//" + nests[1]
                except FileNotFoundError:
                    continue
                try:
                    ref_bytes = util.get_nested_file_bytes(ref_path)
                except AttributeError:
                    continue
                shop_type = str(file).split(".")[-1]

                mod_pio = get_named_pio(ParameterIO.from_binary(mod_bytes),
                                        shop_type)
                ref_pio = get_named_pio(ParameterIO.from_binary(ref_bytes),
                                        shop_type)

                file_names.params[oead.aamp.Name(file).hash] = Parameter(file)
                diffs.lists[file] = gen_diffs(ref_pio, mod_pio)
            except (KeyError, AttributeError) as err:
                raise err
        diffs.objects["Filenames"] = file_names
        return diffs
Beispiel #8
0
 def merge_addres(plist: ParameterList, other_plist: ParameterList):
     bfres: List[str] = []
     for _, pobj in plist.objects.items():
         bfres.append(str(pobj.params["Anim"].v))
     for _, other_pobj in other_plist.objects.items():
         bfres.append(str(other_pobj.params["Anim"].v))
     for i, v in enumerate(list(dict.fromkeys(bfres))):
         key = f"AddRes_{i}"
         if not key in plist.objects:
             plist.objects[key] = ParameterObject()
         plist.objects[key].params["Anim"] = Parameter(FixedSafeString64(v))
Beispiel #9
0
 def make_bshop(plist: ParameterList) -> ParameterIO:
     bshop = ParameterIO()
     bshop.type = "xml"
     tables: List[str] = [
         str(t.v) for _, t in plist.objects["TableNames"].params.items()
     ]
     bshop.objects["Header"] = ParameterObject()
     bshop.objects["Header"].params["TableNum"] = Parameter(len(tables))
     for i, table in enumerate(tables, 1):
         table_hash = crc32(table.encode())
         bshop.objects["Header"].params[f"Table{i:02d}"] = Parameter(
             FixedSafeString64(table)
         )
         table_pobj = ParameterObject()
         table_pobj.params["ColumnNum"] = Parameter(
             len(plist.lists[table_hash].objects)
         )
         for j, item in enumerate(
             [item for _, item in plist.lists[table_hash].objects.items()], 1
         ):
             table_pobj.params[f"ItemSort{j:03d}"] = Parameter(j - 1)
             for shop_key in shop_keys:
                 table_pobj.params[f"{shop_key}{j:03d}"] = item.params[shop_key]
         if table_pobj.params:
             bshop.objects[table_hash] = table_pobj
     return bshop
Beispiel #10
0
def gen_diffs(ref: ParameterIO, mod: ParameterIO) -> ParameterList:
    diffs = ParameterList()
    tablenames_key = oead.aamp.Name("TableNames")
    # generate additions, modifications
    additions = nand_pio_into_plist(ref, mod)
    if len(additions.lists) != 0:
        additions.objects[tablenames_key] = ParameterObject()
        add_names = additions.objects[tablenames_key]
        mod_names = mod.objects[tablenames_key]
        for table_key in additions.lists.keys():
            add_names.params[table_key] = mod_names.params[table_key]
    diffs.lists["Additions"] = additions
    # generate deletions
    removals = nand_pio_into_plist(mod, ref)
    if len(removals.lists) != 0:
        removals.objects[tablenames_key] = ParameterObject()
        rem_names = removals.objects[tablenames_key]
        ref_names = ref.objects[tablenames_key]
        for table_key in removals.lists.keys():
            rem_names.params[table_key] = ref_names.params[table_key]
    diffs.lists["Removals"] = removals
    return diffs
Beispiel #11
0
 def merge_asdefine(plist: ParameterList, other_plist: ParameterList):
     defs: Dict[str, str] = {}
     for _, pobj in plist.objects.items():
         defs[str(pobj.params["Name"].v)] = pobj.params["Filename"].v
     for _, other_pobj in other_plist.objects.items():
         defs[str(
             other_pobj.params["Name"].v)] = other_pobj.params["Filename"].v
     for i, (k, v) in enumerate(defs.items()):
         key = f"ASDefine_{i}"
         if not key in plist.objects:
             plist.objects[key] = ParameterObject()
         plist.objects[key].params["Name"] = Parameter(FixedSafeString64(k))
         plist.objects[key].params["Filename"] = Parameter(v)
Beispiel #12
0
 def diff_addres(addres: ParameterList,
                 ref_addres: ParameterList) -> ParameterList:
     diff = ParameterList()
     bfres: List[str] = []
     for _, pobj in addres.objects.items():
         bfres.append(pobj.params["Anim"].v)
     for _, ref_pobj in ref_addres.objects.items():
         try:
             bfres.remove(ref_pobj.params["Anim"].v)
         except ValueError:
             continue
     for i, v in enumerate(bfres):
         key = f"AddRes_{i}"
         diff.objects[key] = ParameterObject()
         diff.objects[key].params["Anim"] = Parameter(v)
     return diff
Beispiel #13
0
    def generate_diff(self, mod_dir: Path, modded_files: List[Union[str,
                                                                    Path]]):
        print("Detecting general changes to AAMP files...")
        aamps = {
            m
            for m in modded_files
            if isinstance(m, str) and m[m.rindex("."):] in (
                util.AAMP_EXTS -
                HANDLED) and "Dummy" not in m and "CDungeon" not in m
        }
        if not aamps:
            return None

        consolidated: Dict[str, Any] = {}
        for aamp in aamps:
            util.dict_merge(
                consolidated,
                reduce(
                    lambda res, cur: {cur: res if res is not None else {}
                                      },  # type: ignore
                    reversed(aamp.split("//")),
                    None,
                ),
            )
        this_pool = self._pool or Pool(maxtasksperchild=500)
        results = this_pool.starmap(partial(get_aamp_diffs, tmp_dir=mod_dir),
                                    list(consolidated.items()))
        if not self._pool:
            this_pool.close()
            this_pool.join()
        del consolidated
        del aamps

        diffs = ParameterIO()
        diffs.objects["FileTable"] = ParameterObject()
        i: int = 0
        for file, diff in sorted(
            (k, v) for r in [r for r in results if r is not None]
                for k, v in r.items()):
            diffs.objects["FileTable"].params[f"File{i}"] = Parameter(file)
            diffs.lists[file] = diff
            i += 1
        return diffs
Beispiel #14
0
    def generate_diff(self, mod_dir: Path, modded_files: List[Union[str,
                                                                    Path]]):
        print("Detecting general changes to AAMP files...")
        aamps = {
            m
            for m in modded_files
            if isinstance(m, str) and m[m.rindex("."):] in (util.AAMP_EXTS -
                                                            HANDLED)
        }
        if not aamps:
            return None

        consolidated = {}
        for aamp in aamps:
            util.dict_merge(
                consolidated,
                reduce(
                    lambda res, cur: {cur: res} if res is not None else [cur],
                    reversed(aamp.split("//")),
                    None,
                ),
            )
        this_pool = self._pool or Pool()
        results = this_pool.starmap(partial(get_aamp_diffs, tmp_dir=mod_dir),
                                    list(consolidated.items()))
        if not self._pool:
            this_pool.close()
            this_pool.join()
        del consolidated
        del aamps

        diffs = ParameterIO()
        diffs.objects["FileTable"] = ParameterObject()
        i: int = 0
        for result in results:
            if not result:
                continue
            for file, diff in result.items():
                diffs.objects["FileTable"].params[f"File{i}"] = Parameter(file)
                diffs.lists[file] = diff
                i += 1
        return diffs
Beispiel #15
0
 def diff_asdefine(asdef: ParameterList,
                   ref_asdef: ParameterList) -> ParameterList:
     diff = ParameterList()
     defs: Dict[str, str] = {}
     for _, pobj in asdef.objects.items():
         defs[str(pobj.params["Name"].v)] = str(pobj.params["Filename"].v)
     for _, ref_pobj in ref_asdef.objects.items():
         try:
             if (defs[str(ref_pobj.params["Name"].v)] == str(
                     ref_pobj.params["Filename"].v)):
                 defs.pop(str(ref_pobj.params["Name"].v))
         except (ValueError, KeyError):
             continue
     for i, (k, v) in enumerate(defs.items()):
         key = f"ASDefine_{i}"
         diff.objects[key] = ParameterObject()
         diff.objects[key].params["Name"] = Parameter(FixedSafeString64(k))
         diff.objects[key].params["Filename"] = Parameter(
             FixedSafeString64(v))
     return diff
Beispiel #16
0
 def merge_pobj(pobj: ParameterObject, other_pobj: ParameterObject):
     for param, value in other_pobj.params.items():
         pobj.params[param] = value
Beispiel #17
0
def _dict_to_drop(drop_dict: dict) -> ParameterIO:
    pio = ParameterIO()
    pio.type = "xml"
    header = ParameterObject()
    header.params["TableNum"] = Parameter(len(drop_dict))
    for i, table in enumerate(drop_dict.keys()):
        header.params[f"Table{i + 1:02}"] = Parameter(
            oead.FixedSafeString64(table))
    pio.objects["Header"] = header
    for i, (table, contents) in enumerate(drop_dict.items()):
        header.params[f"Table{i:02}"] = table
        table_obj = ParameterObject()
        table_obj.params["RepeatNumMin"] = Parameter(
            contents["repeat_num_min"])
        table_obj.params["RepeatNumMax"] = Parameter(
            contents["repeat_num_max"])
        table_obj.params["ApproachType"] = Parameter(contents["approach_type"])
        table_obj.params["OccurrenceSpeedType"] = Parameter(
            contents["occurrence_speed_type"])
        table_obj.params["ColumnNum"] = Parameter(len(contents["items"]))
        for idx, item in enumerate(contents["items"]):
            table_obj.params[f"ItemName{idx + 1:02}"] = Parameter(
                oead.FixedSafeString64(item))
            table_obj.params[f"ItemProbability{idx + 1:02}"] = Parameter(
                contents["items"][item])
        pio.objects[table] = table_obj
    return pio