Hi there! You are currently browsing as a guest. Why not create an account? Then you get less ads, can thank creators, post feedback, keep a list of your favourites, and more!
Field Researcher
Original Poster
#1 Old 19th Nov 2015 at 7:16 AM
Default s4pi Help Wanted: Importing Resources
I think it's time I finally added support for .package files to my modding tools. The only problem is, I was unable to find a tutorial even after searching Google. I also searched for a tutorial on s3pi since it would likely be similar, but still no luck. I'm assuming any tutorial that existed was deleted along with SimLogical.

So I have a very beginner question: how do you open a package file (or create a new one), import resources and then save it?

I know adding a resource requires setting a TGI key and adding a stream, but I couldn't figure out how to define a TGI key object, let alone use it.
Advertisement
One horse disagreer of the Apocalypse
#2 Old 19th Nov 2015 at 9:13 AM
I think there are guides to s3pi still in existence. Did you check out the sourceforge account for it? Try that and I will have a look also

Have you got the s4pe and/or s4pi solution set up? Just looking at how s4pe does it will get you going. It's all open source licence so you can use the code or libraries direct, provided your own tools are open source also.

Edit: There is some documentation for s3pi here: http://s3pi.sourceforge.net/

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Ms. Byte (Deceased)
#3 Old 19th Nov 2015 at 8:01 PM Last edited by CmarNYC : 19th Nov 2015 at 8:16 PM.
If you need some specific examples, these might help.

Code:
using s4pi.Interfaces;
using s4pi.Package;


Create a package:

Code:
Package newPack = (Package)Package.NewPackage(0);


Open a package:

Code:
            try
            {
                Package package = (Package)Package.OpenPackage(0, packagePathString, readwriteBool);
            }
            catch
            {
                MessageBox.Show("Unable to read valid package data from " + packagePathString);
            }


Save, SaveAs, and Dispose:

Code:
newPack.SavePackage();
newPack.SaveAs(savePathString);
newPack.Dispose();


Find and read one resource: (in this case a DST image)

Code:
                   Predicate<IResourceIndexEntry> iRes = r => r.ResourceType == ResourceTypeUint &
                                            r.ResourceGroup == ResourceGroupUint &
                                            r.Instance == ResourceInstanceUlong;
                    IResourceIndexEntry rRes = package.Find(iRes);
                    if (rRes != null)
                    {
                        DSTResource dst = new DSTResource(0, package.GetResource(rRes));
                    }


Find all resources with a specified type:

Code:
                    Predicate<IResourceIndexEntry> iRes = r => r.ResourceType == ResourceTypeUint;
                    List<IResourceIndexEntry> rRes = package.FindAll(iRes);


Write a resource and turn on compression:

Code:
            TGIBlock rResNew = new TGIBlock(0, null, newTGIType, newTGIGroup, newTGIInstance);
            IResourceIndexEntry irieRes = package.AddResource(rResNew, resourceMemoryStream, rejectDupsBool);
            if (irieRes != null) irieRes.Compressed = (ushort)0x5A42;


And after a ridiculous amount of time struggling to figure out how to use the package.ReplaceResource method, I came up with this code which seems to work:

Code:
        private void ReplaceResource(Package package, IResourceIndexEntry keyToReplace, MemoryStream ms)
        {
            IResource res = new Resource(0, ms);
            package.ReplaceResource(keyToReplace, res);
        }

        internal class Resource : AResource
        {
            internal Resource(int APIversion, Stream s) : base(APIversion, s) { }

            public override int RecommendedApiVersion
            {
                get { return 1; }
            }

            protected override Stream UnParse()
            {
                return this.stream;
            }
        }


I fiddled with the code a little for simplification so I can't guarantee I didn't break something.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
Original Poster
#4 Old 19th Nov 2015 at 9:55 PM
@Inge - Thanks for the help! It took hours to find exactly what I need to use, but I eventually ended up succeeding.

@CmarNYC - I already figured it out before reading your post, but thanks anyway! My current code creates new package files and imports files, but if I ever need to learn how to do anything else, like opening existing packages and resources or replacing them, I'll come back to your post.

For anyone else reading this who needs a solution, this is the test code I'm currently using, which worked as expected:

Code:
            // create the package
            NewPackage = Package.NewPackage(0);

            // create resource
            // resource key
            TGIN tgin = new TGIN();
            tgin.ResType = 0x0333406C;
            tgin.ResGroup = 0x00000000;
            tgin.ResInstance = 0x000000000001AE5C;
            IResourceKey rk = (TGIBlock)tgin;

            // create memory stream
            FileStream fs = new FileStream("Projects\\Debug\\TestMod\\Export\\S4_78559E9E_00000000_000000000001AE5C.xml", FileMode.OpenOrCreate, FileAccess.Read);
            MemoryStream ms = new MemoryStream();
            fs.CopyTo(ms);

            // add resource
            IResourceIndexEntry rie = NewPackage.AddResource(rk, ms, true);
            rie.Compressed = 0x5A42;

            // save the package
            NewPackage.SaveAs("Test.package");


I haven't tried importing multiple resources yet, but that probably won't require any special steps that aren't just regular C# programming.

EDIT: Here are the using directives the code used:

Code:
using s4pi.Package;
using s4pi.Interfaces;
using s4pi.Extensions;
using System.IO;
Back to top