Exemple #1
0
    public override void Awake()
    {
        if (!settings.loadMods)
        {
            return;
        }
        var needRescan = false;

        needRescan |= CanonizeZip();
        needRescan |= CanonizeCsv();
        needRescan |= CopyABdata();
        if (needRescan)
        {
            print("VFS changed; rescanning");
            LoadedAssetBundle.GCBundles();
            Vfs.Rescan(true);
            Vfs.Save();
        }
    }
Exemple #2
0
    public bool CanonizeZip()
    {
        var target = Dir.mod;

        print("Unzipping mods into " + Path.GetFullPath(target));
        var  zipdir     = Dir.root + "mods";
        bool needRescan = false;

        LoadedAssetBundle.GCBundles();
        foreach (var zipfn in Directory.GetFiles(zipdir, "*.zip", SearchOption.AllDirectories))
        {
            var modname = Path.GetFileNameWithoutExtension(zipfn);
            //print("@ " + modname);
            if (Directory.Exists(target + modname))
            {
                continue;
            }
            needRescan = true;
            print("Extracting " + Path.GetFileName(zipfn));
            using (var fs = File.Open(zipfn, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var zip  = new ZipFile(fs);
                var guid = modname;

                // pick guid from manifest if its there
                var manifest = zip.GetEntry("manifest.xml");
                if (manifest != null)
                {
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(Encoding.UTF8.GetString(entry2bytes(zip, manifest)).StripBOM());
                    guid = doc.SelectSingleNode("//guid").InnerText;
                }
                foreach (ZipEntry entry in zip)
                {
                    if (!entry.IsFile)
                    {
                        continue;
                    }
                    var efn = entry.Name;
                    if (efn.ToLower().EndsWith("manifest.xml"))
                    {
                        continue;
                    }

                    if (efn.StartsWith("abdata/"))
                    {
                        efn = efn.Substring(7);
                    }

                    var prefix   = "list/characustom/";
                    var basename = Path.GetFileNameWithoutExtension(efn);
                    var bytes    = entry2bytes(zip, entry);

                    // make the cat manifest csv canonical
                    if (efn.StartsWith(prefix) && efn.EndsWith(".csv"))
                    {
                        var str      = Encoding.UTF8.GetString(bytes);
                        var ex       = ScriptableObject.CreateInstance <ExcelData>().Import(CSV.ParseCSV(str));
                        var firstrow = ex.list.First().list;
                        var cat      = -1;
                        var dist     = 0;
                        if (firstrow.Count == 1)
                        {
                            try
                            {
                                cat  = int.Parse(ex[0, 0].Trim());
                                dist = int.Parse(ex[1, 0].Trim());
                                ex.list.RemoveRange(0, 3);
                            }
                            catch (System.Exception exc) {
                                print(exc.Message);
                                print(ex[0, 0]);
                                print(ex[1, 0]);
                            };
                        }
                        else
                        {
                            try
                            {
                                cat = int.Parse(basename.Split('_')[0]);
                            }
                            catch { };
                        }
                        // if we can't figure out the category, bail on this csv
                        if (cat == -1)
                        {
                            print(zipfn + " unzip failed");
                            continue;
                        }
                        efn   = $"{prefix}{dist:D2}_{guid}/{cat}_{basename}.csv";
                        bytes = ex.Marshal().AddBOM().ToBytes();
                    }

                    // if it is a hardmod, check that the contents of the bundle fully match the file overriden.
                    var hardab   = Dir.abdata + efn;
                    var oldefn   = efn;
                    int nmissing = 0;
                    efn = target + modname + "/" + efn;
                    Directory.CreateDirectory(Path.GetDirectoryName(efn));
                    bool nukecab = true;
                    if (efn.EndsWith(".unity3d") && File.Exists(hardab))
                    {
                        // if it overwrites in its entirety, do not nuke the cab as deps amy point to it
                        nukecab = false;
                        var ab = AssetBundle.LoadFromMemory(bytes);
                        if (ab == null)
                        {
                            print($"WARNING: {efn} failed to load, skipping.");
                            continue;
                        }
                        var abnames = new HashSet <string>(ab.GetAllAssetNames().Select((x) => Path.GetFileNameWithoutExtension(x)).ToList());
                        ab.Unload(true);

                        var origab = AssetBundle.LoadFromFile(hardab);
                        if (origab == null)
                        {
                            goto skip2;
                        }

                        // Now load the original and check the replacement has all its assets
                        foreach (var ass in origab.GetAllAssetNames())
                        {
                            var shass = Path.GetFileNameWithoutExtension(ass);
                            if (!abnames.Contains(shass))
                            {
                                //print($"WARNING: {Path.GetFileName(efn)}: {shass} is missing {oldefn}");
                                nmissing++;
                            }
                        }
                        origab.Unload(true);

                        // missing assets; nuke cab
                        if (nmissing > 0)
                        {
                            nukecab = true;
                        }
                    }
skip2:

                    //print(".. Extracted " + efn);
                    if (nmissing != 0)
                    {
                        efn = Directory.GetParent(efn).FullName + "/+" + Path.GetFileName(efn);
                    }
                    if (efn.EndsWith(".unity3d"))
                    {
                        using (var fo = File.Create(efn))
                            if (Vfs.Repack(new MemoryStream(bytes), fo, nukecab | sideloader_compat))
                            {
                                bytes = null;
                            }
                    }
                    if (bytes != null)
                    {
                        File.WriteAllBytes(efn, bytes);
                    }
                }
            }
        }
        print("Done");
        return(needRescan);
    }
Exemple #3
0
    public static void dumpassets()
    {
        print("Dumping all text serializable assets");
        var dumpdir   = Dir.mod + "!base/";
        var mainass   = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "Assembly-CSharp");
        var dumpables = mainass.GetExportedTypes().Where(t => typeof(IDumpable).IsAssignableFrom(t));
        var basedir   = Dir.abdata;

        print($"Found {dumpables.Count()} types.");
        LoadedAssetBundle.GCBundles();
        foreach (var bpath in Directory.GetFiles(Dir.abdata + subdir, "*.unity3d", SearchOption.AllDirectories))
        {
            var bundle = bpath.Replace("\\", "/");
            var abname = bundle.Substring(Dir.abdata.Length);
            if (abname.Contains("--"))
            {
                continue;
            }
            var lab = AssetBundle.LoadFromFile(bundle);
            if (lab == null)
            {
                continue;
            }
            foreach (var longname in lab.GetAllAssetNames())
            {
                var    dir   = bundle.Remove(bundle.LastIndexOf('.')).Substring(Dir.abdata.Length);
                byte[] bytes = null;
                var    name  = Path.GetFileName(longname).ToLower();
                var    bname = Path.GetFileNameWithoutExtension(name);
                string ext   = name.Substring(bname.Length).ToLower();
                if (ext != ".asset" && ext != ".txt" && ext != ".bytes" && ext != "")
                {
                    //print("skip");
                    continue;
                }
                var ass = lab.LoadAsset(bname);
                if (ass == null)
                {
                    print("Failed to load ", ass);
                    continue;
                }
                var ta = ass as UnityEngine.TextAsset;
                var da = ass as IDumpable;
                //print(ass.GetType());
                if (ta != null)
                {
                    if (bname.StartsWith("cf_anmshape"))
                    {
                        print(name);
                        var si = new AnimationKeyInfo();
                        si.LoadInfo(new MemoryStream(ta.bytes));
                        bytes = si.Marshal().ToBytes();
                        ext   = ".csv";
                    }
                    else
                    if (abname.Contains("list/characustom/"))
                    {
                        var chd = MessagePackSerializer.Deserialize <ChaListData>(ta.bytes);
                        bytes = chd.Marshal().ToBytes();
                        bname = chd.categoryNo + "_" + bname;
                        var disa = $"{chd.distributionNo:00}";
                        var disb = Path.GetFileName(dir);
                        dir = dir.Remove(dir.LastIndexOf('/') + 1) + disa + ((disa != disb)?("_" + disb):"");
                        ext = ".csv";
                    }
                    else
                    if (name.ToLower().EndsWith(".txt"))
                    {
                        bytes = ta.text.StripBOM().ToBytes();
                        ext   = ".lst";
                    }
                    else
                    {
                        var test = ta.text.Replace("\r", "").Split('\n');
                        if (test.Length > 2 && (test[0].Split('\t').Length == test[1].Split('\t').Length) && test[0].Split('\t').Length >= 2)
                        {
                            bytes = ta.text.StripBOM().ToBytes();
                            ext   = ".lst";
                        }
                        else
                        {
                            if (abname.Contains("h/list") && bname.StartsWith("kh") && ext == ".bytes")
                            {
                                var ikd = new MotionIKData();
                                ikd.Read(new MemoryStream(ta.bytes));
                                bytes = ikd.Marshal().ToBytes();
                                ext   = "." + ikd.GetFileExt();
                            }
                            else
                            {
                                print("Uknown " + bname);
                            }
                        }
                    }
                }
                else if (ass is IDumpable)
                {
                    ext = "." + da.GetFileExt();
                    try {
                        bytes = da.Marshal().ToBytes();
                    } catch (Exception ex)
                    {
                        print("Something went wrong");
                        print(bpath);
                        print(bname);
                        print(ex);
                    }
                }

                if (bytes != null)
                {
                    var ddir = dumpdir + dir;
                    Directory.CreateDirectory(ddir);
                    var dst = ddir + "/" + bname + ext;
                    File.WriteAllBytes(dst, bytes);
                    //print("Dumping " + dst.Substring(Dir.root.Length) + " of type " + ass.GetType().Name);
                }
            }
            lab.Unload(true);
        }
    }