Sim File Maid

How it Works

Please Note: This document is a work in progress. It is always in a state of "doneness", but never in a state of "completeness". It will be added to as I have time.

Introduction

Sim File Maid is a fairly complex program. This page is not intended for general users, but rather technically-minded people who are interested in The Maid's logic. Six very important things you need to know BEFORE reading this:

1) This information can certainly be used to create or enhance competing products- I really don't care. Sim File Maid is the best program out that I've found that does what she does. If that changes tomorrow I don't really care. I've had contact with over 3000 distinct Maid users as of this writing, and have done some degree of technical support for well over half of them. I'd love to offload that to someone else. In the meantime, however, I love the Sims community (in general) and will continue to support The Maid until I can point to a viable alternative.

2) This document is actually a first-step to open sourcing The Maid. In the end, The Maid will be open source. It's too powerful of a tool NOT to be integrated into other programs. Not today, but soon.

3) There will most likely be a lot of thought maps, wild ramblings, and otherwise incoherent babble in this document. Deal. It's all relevant on some level.

4) Some of my wild ramblings and otherwise incoherent babbling will be abstract, and thus be language/implementation -neutral, others will be targetted at Visual Basic programmers and as such will use Visual Basic notation. As such, even some programmers who don't understand VB may be left blinking their eyes at my notations.

5) I hate Windows. It is, however, the operating system where nearly all of my games are as it is the most largely supported platform for games. I say this because some of you "real" programmers out there will scoff at my use of Visual Basic instead of a "more better" language like Visual C++ or Java- Well, I have two words for you (kids, cover your eyes and ears now): Fuck you. Visual Basic is the best Rapid-Application Development interface for Windows programs, period. I would much rather be programming Perl or C/C++ in a vi session on my Linux box, but I'm afraid that the market size for Sim File Maid on Linux/UN*X is pretty small.

6) Nothing in here may be relevant by the time you read it. It's current as of this writing, that's all I can guarantee.

Table of Contents

Overview

The largest technical misconception about The Maid is that it's complicated. This myth may be inspired in part by the first sentance of the introduction- "Sim File Maid is a fairly complex program." The Maid is conceptually very simple. The complications were introduced when I decided to make The Maid "easy to use" by the "Sims-using community". No offense to anyone, but the "Sims-using community" is one of the lowest-tech communities I've ever been involved with (and also, by far, the warmest and nicest). Some of these users have problems turning on their computers! Obviously, this makes supporting a program difficult, especially a free one. Out of the several thousand "problem reports" I've gotten since The Maid burst into the popular mainstream, only a very small handful were legitimate problems with The Maid- Most were user-problems. In fact, all of the "Maid-related" problems are noted in the ChangeLog, usually with credit to the person who reported it.

The Maid, in essence, does the following:

"The Lawn" ("Installing" Files into The Sims)

That's it... Essentially.

"The Rack" ("Converting" Skins to be "Buyable" downtown)

My Object Classes

The first big eye-roller I have to warn you about is my use of 3 home-brewed object classes. The below sections regarding these object classes do not reflect all of the class members, just the exposed members that I thought were pertinent to understanding their function and use.

MArray

This is my generic "array object" class. MArray, in fact, means "Matt's Array". It has a number of members such as Pop, Push, Shift and Unshift (which if you've ever programmed in Perl makes a lot of sense) as well as a "size" element. This object makes dealing with arrays much more palatable as it does all of the work for you.

Public Sub Initialize(initialValue As Variant, Optional commandDropFormatFlag As Boolean = False)

This subroutine is used to initially populate an MArray with data from a Variant array. The commandDropFormatFlag is used when the Variant array is in the same format as the Command function returns (command line arguments passed to a program at run-time).

Public Function See(ByVal Element As Long) As Variant

Given the position of an item in the array, this function returns that item.

Public Sub Change(ByVal Element As Long, ByVal datum As Variant)

Given the position of an item in the array and some datum, replace the existing item with datum.

Public Sub Unshift(ByVal datum As Variant)

"Unshift" is a Perl function that is used to add an item (datum) to the beginning of an array (instead of the end, like a "Push"). I like it, so it's here.

Public Function Shift() As Variant

"Shift" is a Perl function that is used to remove and return an item from the beginning of an array (instead of the end, like a "Pop"). I like it, so it's here.

Public Sub Push(ByVal datum As Variant)

"Push" is a typical array/stack fuction to add an item (datum) to the end of an array.

Public Function Pop() As Variant

"Pop" is a typical array/stack function to remove and return and item (datum) from the end of an array.

Public Sub Reverse()

As the name implies, this function merely reverses (or inverts) the position of each element in an array. So the first would be the last, etc.

Public Function Give() as Variant

Sometimes one really does need a Variant array. This function does exactly that- Returns the Variant array itself.

Hash

Once again exposing my love of Perl, I needed a hash (associative array), so I implemented it as an object class. The Hash is actually a pair of MArrays, one containing keys and the othe values. As such, the Hash class requires the MArray. The "K=V format" mentioned below is actually "Key = Value".

Public Sub Initialize(ByRef initialValue As Variant)

This subroutine allows the Hash to be populated by a Variant array of elements in the "K=V" format.

Public Sub Update(ByRef newVal As Variant)

Given a Varian in K=V format, the existing Key is updated with the Value, or a new one is created if one does not already exist.

Public Function Value(ByVal Key As String) As Variant

Given a keyname, the value is returned.

Public Function Pop() As Variant

Returns the last K=V element.

Public Sub Push(ByVal vValue As Variant)

Adds a K=V value onto the Hash.

Public Sub Change(ByVal Key As Variant, ByVal vValue As Variant)

Given a separate Key and Value, the value of Key is changed to vValue. Key must exist. NOTE: I do not know why I implemented this function. It was probably implemented before I created "Update" which does this and better.

Public Function SeePair(ByVal Element As Integer) As Variant

Given the position of a K=V in the Hash, return the K=V.

Public Function GetKeys() As MArray

One of the coolest hash-manipulation function in Perl is "keys", which simply returns an array containing all of the key names. This function returns an MArray of all of the keys.

LanguagePack

This object class was formed to allow dynamic, modular "language pack" support. I uses the Hash object class. The "K=V format" mentioned below is actually "Key = Value".

Public Sub Initialize(initialValue As Variant)

Allows a language pack to be populated by a Variant array of elements in K=V format. The first two elements of the Variant array are assumed to be the name of language and the name of the author (translator) respectively.

Public Sub Update(newVal As Variant)

Given a K=V, either update the Value associated with the Key, or create a new entry if the Key does not exist.

Public Function SeeByName(Key As String) As Variant

This may very well be the worst name function I've ever written. I don't know what I was thinking. This is the same as the Hash's "Value" function.

Public Property Get Name() As String

Returns the name of the language.

Public Property Get author() As String

Returns the author's (translator's) name and optionally e-mail address.

Public Function Pop() As Variant

Returns the K=V from the end of the Hash.

Public Function ProperString(Key As String, Optional v1 As String = "", Optional v2 As String = "", Optional v3 As String = "") As String

Another horribly named function. Some times I astonish myself with my idiocy. This function, given a Key and upto three optional strings, returns the Value with up to the first three elipses (...) replaced with each of the optional strings in sequence. This, if the Value was "I ... my ..." and v1="ate" and v2="cat", the string returned would be "I ate my cat". And no, I did not eat my cat. I don't even have a cat. And no, it's not because I ate it.

Public Sub Push(vValue As Variant)

Adds K=V to the end of the Hash.

Public Function See(Element As Integer) As Variant

Given the position of a K=V in the Hash, return the K=V.

Public Sub Change(Key As Variant, vValue As Variant)

Give a Key and it's new Value, update it. Key must exist. This is a predecessor to Update and I don't know why it is still even here. Nostalgia I guess.

Some Functions to Care About

The file SimFileMaidMod.mod contains a myriad of functions for use with The Maid.

Function Get_SimsPath() As String

This function uses rules and heuristics to try and ascertain where The Sims is installed. It returns the path.

Function Make_Temp() As String

Temp folders are an integral part of how The Maid works, as such this function creates a randomly named, non-existant folder and returns it's path

Sub Kill_Temp(kpath As String)

Given a path, kill the contents of the folder, and then the folder itself. Special sanity checks are in place so it will only delete folders created with Make_Temp.

Function Do_ZipFile(ZipFilePath As String) As Integer

Ah yes, the thing that makes The Maid cool- Her ability to handle Zip files. This function takes a Zip file, unzips it to a temp folde (via Make_Temp) iterates over the contents of that folder using Handle_File (below), calls Kill_Temp and then returns the number of unzipped files it "installed".

Function Handle_FileCopy(srcPath As String, destPath As String)

Quite simply, it copys one file onto another according to rules.

Function Handle_File(filePath As String) As Integer

This is a heavy rule-based function that does the Right Thing (tm) based on the file name or extension or other heuristics. It calls Handle_FileCopy or Do_ZipFile as necessary.

Sub Load_Language()

Someone once said to me, "The Maid is the coolest thing in the World, too bad a lot of non-English speaking people can't use it easily." Well, that depressed me. So for the 2.0 release, I developed a "language pack" format, created a class module based on it (See the LanguagePack class), removed nearly all of my user-viewable strings and moved them into an English language pack. This allows infinite scalability in language. You can view the languages that The Maid is officially supported on by looking at the Sim File Maid homepage at the language names surrounding the logo banner.

Anyhow, this function does two things- First it loads the English language pack, and then it updates the language pack stored in memory with whichever language is selected. This way if a translation isn't available (yet) for a particular phrase, it will still be displayed in English.

Sub Check_Updates(Optional Interactive As Boolean = False)

After dealing with an ever-growing "The Maid Updates" e-mail list, beginning with the 2.1 release, I decided that The Maid should update herself so I don't have to manage the over 42,000 accounts on the list. As such, this subroutine checks my website for update, and optionally starts the download process. See the "Get Updates" page for more details. If the Interactive flag is set, the function will alert the user if there are no more recent updates, else it exits ssilently.

Sim File Maid is not supported or endorsed by Maxis or Electronic Arts. Although if they'd like to use/improve/distribute/support/endorse it, I'd be happy to work with them on such an endeavour. But I'm not begging or anything. Really. Just sayin'.