Example #1
0
 def add_flags_from_Hash(self, name: str, data: Hash) -> None:
     is_revival = bool("revival" in name)
     for ftype, flags in data.items():
         for flag in flags:
             self._store[ftype][flag["HashValue"].v] = FLAG_MAPPING[ftype](
                 flag, revival=is_revival)
             self._orig_store[ftype][
                 flag["HashValue"].v] = FLAG_MAPPING[ftype](
                     flag, revival=is_revival)
Example #2
0
 def add_flags_from_Hash(self,
                         name: str,
                         data: Hash,
                         overwrite_ok: bool = True) -> None:
     is_revival = bool("revival" in name)
     for ftype, flags in data.items():
         for flag in flags:
             hash = flag["HashValue"].v
             if hash in self._store[ftype] and not overwrite_ok:
                 continue
             self._store[ftype][hash] = FLAG_MAPPING[ftype](
                 flag, revival=is_revival)
Example #3
0
    def perform_merge(self):
        force = self._options.get("force", False)
        glog_path = util.get_master_modpack_dir() / "logs" / "gamedata.log"

        modded_entries = self.consolidate_diffs(self.get_all_diffs())
        if not modded_entries:
            print("No gamedata merging necessary.")
            if glog_path.exists():
                glog_path.unlink()
            if (util.get_master_modpack_dir() / "logs" / "gamedata.sarc").exists():
                (util.get_master_modpack_dir() / "logs" / "gamedata.sarc").unlink()
            return
        if glog_path.exists() and not force:
            with glog_path.open("r") as l_file:
                if xxhash.xxh64_hexdigest(str(modded_entries)) == l_file.read():
                    print("No gamedata merging necessary.")
                    return

        print("Loading stock gamedata...")
        gamedata = consolidate_gamedata(get_stock_gamedata())
        merged_entries = {
            data_type: Hash({entry["DataName"]: entry for entry in entries})
            for data_type, entries in gamedata.items()
        }
        del gamedata

        print("Merging changes...")
        for data_type in {d for d in merged_entries if d in modded_entries}:
            util.dict_merge(
                merged_entries[data_type],
                modded_entries[data_type]["add"],
                shallow=True,
            )
            for entry in modded_entries[data_type]["del"]:
                try:
                    del merged_entries[data_type][entry]
                except KeyError:
                    continue

        merged_entries = Hash(
            {
                data_type: oead.byml.Array([value for _, value in entries.items()])
                for data_type, entries in merged_entries.items()
            }
        )
        print("Creating and injecting new gamedata.sarc...")
        new_gamedata = oead.SarcWriter(
            endian=oead.Endianness.Big
            if util.get_settings("wiiu")
            else oead.Endianness.Little
        )
        for data_type in merged_entries:
            num_files = ceil(len(merged_entries[data_type]) / 4096)
            for i in range(num_files):
                end_pos = (i + 1) * 4096
                if end_pos > len(merged_entries[data_type]):
                    end_pos = len(merged_entries[data_type])
                new_gamedata.files[f"/{data_type}_{i}.bgdata"] = oead.byml.to_binary(
                    Hash({data_type: merged_entries[data_type][i * 4096 : end_pos]}),
                    big_endian=util.get_settings("wiiu"),
                )
        new_gamedata_bytes = new_gamedata.write()[1]
        del new_gamedata
        util.inject_file_into_sarc(
            "GameData/gamedata.ssarc",
            util.compress(new_gamedata_bytes),
            "Pack/Bootup.pack",
            create_sarc=True,
        )
        (util.get_master_modpack_dir() / "logs").mkdir(parents=True, exist_ok=True)
        (util.get_master_modpack_dir() / "logs" / "gamedata.sarc").write_bytes(
            new_gamedata_bytes
        )

        print("Updating RSTB...")
        rstable.set_size(
            "GameData/gamedata.sarc",
            rstable.calculate_size("GameData/gamedata.sarc", new_gamedata_bytes),
        )
        del new_gamedata_bytes

        glog_path.parent.mkdir(parents=True, exist_ok=True)
        with glog_path.open("w", encoding="utf-8") as l_file:
            l_file.write(xxhash.xxh64_hexdigest(str(modded_entries)))
Example #4
0
 def find_name(item: Hash) -> str:
     for k, v in item.items():
         if "name" in k.lower():
             return v
     else:
         return ""
Example #5
0
 def consolidate_diffs(self, diffs: list):
     a_diffs = Hash()
     for mod_diff in diffs:
         for file, diff in mod_diff.items():
             # a_map = Map(*file.split("_"))
             if file not in a_diffs:
                 a_diffs[file] = Array()
             a_diffs[file].append(diff)
     c_diffs = Hash()
     for file, mods in a_diffs.items():
         c_diffs[file] = Hash({
             "Objs":
             Hash({
                 "add":
                 Array(),
                 "mod":
                 Hash(),
                 "del":
                 Array([
                     oead.U32(h) for h in set([
                         hash_id.v for hashes in [
                             mod["Objs"]["del"] for mod in mods
                             if "Objs" in mod and "del" in mod["Objs"]
                         ] for hash_id in hashes
                     ])
                 ]),
             }),
             "Rails":
             Hash({
                 "add":
                 Array(),
                 "mod":
                 Hash(),
                 "del":
                 Array([
                     oead.U32(h) for h in set([
                         hash_id.v for hashes in [
                             mod["Rails"]["del"] for mod in mods
                             if "Rails" in mod and "del" in mod["Rails"]
                         ] for hash_id in hashes
                     ])
                 ]),
             }),
         })
         for mod in [m for m in mods if "Objs" in m and "mod" in m["Objs"]]:
             for hash_id, actor in mod["Objs"]["mod"].items():
                 c_diffs[file]["Objs"]["mod"][hash_id] = actor
         for mod in [
                 m for m in mods if "Rails" in m and "mod" in m["Rails"]
         ]:
             for hash_id, actor in mod["Rails"]["mod"].items():
                 c_diffs[file]["Rails"]["mod"][hash_id] = actor
         add_obj_hashes = []
         add_rail_hashes = []
         for mod in reversed(mods):
             if "add" in mod["Objs"]:
                 for actor in mod["Objs"]["add"]:
                     if actor["HashId"] not in add_obj_hashes:
                         add_obj_hashes.append(actor["HashId"])
                         c_diffs[file]["Objs"]["add"].append(actor)
             if "add" in mod["Rails"]:
                 for actor in mod["Rails"]["add"]:
                     if actor["HashId"] not in add_rail_hashes:
                         add_rail_hashes.append(actor["HashId"])
                         c_diffs[file]["Rails"]["add"].append(actor)
     return c_diffs