Replies: 5 (Who?), Viewed: 6202 times.
Test Subject
Original Poster
#1 Old 28th Dec 2017 at 3:55 PM
Default Help working with packages utilizing s4pi in .net
After spending hours and hours organizing, repacking, and troubleshooting my custom content, I've decided to write my own CC Management tool that takes features from 3 or 4 current tools and puts them all together with an intelligent back end to help users maintain best practices for CC management with as little time and effort as possible. However, this post isn't meant as an advertisement for my now 3 day old piece of software, but looking for some answers that will help me get that tool to a place that I can share it with people sooner.

Currently the biggest hurdle I'm running into is something that sounds very simple. I'm trying to open a .package, and read the name(s), category, and tuning data of the content within the package. I have managed to get a .package file open and extract some data, but it's a very bull in a china shop kind of way just reading the raw string values (if they exist) of the resources in the package's ResourceList. Eventually I'll want to be able to interpret, modify, and merge .package files within my code, but right now I really just want to get the catalog entry data (Name/Type (CAS,Build,Buy)/Category ect...) and any available xml tuning data.
Ms. Byte
staff: moderator
#2 Old 28th Dec 2017 at 7:30 PM Last edited by CmarNYC : 29th Dec 2017 at 12:45 PM.
The process is basically: Open the package, get the TGI-based index entries of the resource(s) you want, then use the specific wrapper for those resource(s) to read them and get the values you want from them. You have to know what you're looking for; you can't just read resources and then do stuff depending on what they are. (Edit: Since the index entry includes the type ID you can use that to determine what wrapper to use if necessary.) What you typically do is have a list of the resource types you want and search the package for them.

This is all in C#, which s4pi is written in.

First make sure you've set up the references correctly:

You always include s4pi.Interfaces and System.Custom from the s4pi set of dlls. Also s4pi.Package if you're working with packages.

I've included s4pi.CatalogResource which handles catalog resources including CBLK, CCOL, CFEN, CFLR, CFLT, CFND, CFRZ, CFTR, COBJ, CPLT, CRAL, CRPT, CRTR, CSPN, CSTL, CSTR, CTPT, CWAL, STRM, and ObjectDefinition (OBJD). For other types of resources you'd have to include references for the wrappers that handle them.

For catalog objects and CAS parts you also have to include the common property tags resource - s4pi.Resource.Commons - and the xml file which contains the latest list of property tags. Copy the xml file into your project and include it, and set it to be copied to the project output:

With all that done, here's the code for a very simple demo of reading a custom object package:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using CatalogResource;
using s4pi.Interfaces;
using s4pi.Package;

namespace s4piDemo
public partial class Form1 : Form
public Form1()

private void button1_Click(object sender, EventArgs e)
//open package
OpenFileDialog dialog = new OpenFileDialog();
dialog.DefaultExt = "package";
if (dialog.ShowDialog() != DialogResult.OK) return;
Package pack = (Package)Package.OpenPackage(1, dialog.FileName);

//search for COBJ resources
Predicate<IResourceIndexEntry> predCOBJ = r => r.ResourceType == 0x319E4F1D;
List<IResourceIndexEntry> COBJentries = pack.FindAll(predCOBJ);

//loop through results, reading each COBJ and its associated OBJD and writing selected values to a string
string results = "";
foreach (IResourceIndexEntry irie in COBJentries)
COBJResource cobj = new COBJResource(1, pack.GetResource(irie));
//get associated OBJD resource
Predicate<IResourceIndexEntry> predOBJD = r => r.ResourceType == 0xC0DB5AE7 & r.Instance == irie.Instance;
IResourceIndexEntry OBJDentry = pack.Find(predOBJD);
ObjectDefinitionResource objd = new ObjectDefinitionResource(1, pack.GetResource(OBJDentry));
results += objd.Name + ", ";
foreach (CatalogResource.Common.CatalogTag t in cobj.CommonBlock.Tags)
results += t.Value + ", ";
results += Environment.NewLine;

//display results

And results:

I've attached the latest xml file for convenience. Updates can be downloaded from the s4pi source code on Github:

Hope this helps!
Download - please read all instructions before downloading any files!
File Type: zip (23.4 KB, 23 downloads) - View custom content

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
Test Subject
Original Poster
#3 Old 29th Dec 2017 at 4:38 AM
Excellent! I was able to convert your code over to VB.Net (what I'm writing in because it's what I'm comfortable with) and reproduce your behavior inside of my application. this gives me a lot to work with for a bit, thank you so much I'm sure I'll be back in the future with additional questions.

Thanks again, It's highly unlikely I would have been able to stumble upon figuring that out on my own.
Test Subject
Original Poster
#4 Old 29th Dec 2017 at 5:11 AM
Alright so, kind of a non-sequitur here, but, spinning through one of my objects, it appears to have some tags that shouldn't be here.

I know that viewing sculptures in my game is currently completely broken, and I'm wondering if the presence of those BuyCat related tags are what's breaking it, or is that sort of value to be expected?
One horse disagreer of the Apocalypse
#5 Old 29th Dec 2017 at 9:36 AM
There are quite a lot of silly bugs left in by EA so it's perfectly possible you have stumbled across some there. Why not experiment and see if changing those fixes what you have been seeing?

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Ms. Byte
staff: moderator
#6 Old 29th Dec 2017 at 12:27 PM
I know very little about objects so can't really say, but from what I've seen inappropriate tags in CAS parts are ignored in-game.

Glad you got the example working!

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
Back to top