最近では、S3PIに関する強固な情報と真のヘルプを見つけることは非常に困難です。S3PIを使用してライブラリとしてSIMSパッケージファイルとやり取りするプログラムを作成しようとしている場合は、さらに困難です。さらに、S3PIライブラリはGitHub上にないため、ここにはリポジトリがありません。
これらの理由から、私はこのリポジトリを作成して、S3PIライブラリ全体を完全に保存することにしました。コードの例とそれを正しく使用する方法についてのヒントを使用しました。さらに、S3PIに関連するインターネットで見つけたすべての有用な情報をここにまとめました!
より多くの情報を提供したい場合は、[問題]タブを介してプルリクエストを作成するか、報告してください。私はこのリポジトリをできる限り多くの情報と例で維持するために最善を尽くしますが、S3PIの著者がそれを要求した場合、このリポジトリをオフラインにします。
重要
S3PIライブラリの作成のためのすべてのクレジットが信じられないほどの「Peter L Jones」に行くことを思い出してください!
「SIMS 3パッケージインターフェイス」は、SIMS3ゲームパッケージを「理解」するポータブルコードのコアライブラリを提供します。 (いくつかのマイナーな調整を使用して)コアライブラリコードは、他のゲームパッケージ形式も理解していることに注意してください(例:SimCity Online、SIMS4)。
コアライブラリとともに、プロジェクトの主要な部分を提供する多くの「ラッパー」があります。これらは、パッケージ内(またはその他のソース)内のデータの敏arializializationとシリアル化を処理します。
さらにツールは、このライブラリとラッパーを使用して、SIMSゲームのパッケージファイルのデータコンテンツを操作できます。
ここで提供されるこのライブラリとラッパーの開発が完了したことに注意してください。
「S3PI」は、「SIMS3™パッケージインターフェイス」の頭字語です。 Electronic Arts SIMS3™ゲームで使用される個々の「パッケージ」ファイル内のデータへのアクセスをサポートします。 「パッケージ」は、通常「パッケージ」のファイル拡張子を備えたディスクファイルです(ただし、他の拡張機能が使用されます)。ただし、S3PIで使用される主な識別機能は、ファイルの開始時の4バイトマジッククッキーです。これは「DBPF」でなければなりません。さらに、ファイル形式のバージョン番号は、Sims 3™の場合は2でなければなりません(または、Sim City 5™の場合は3つありません。これはほとんどサポートされていません)。
「保護された」パッケージ(「DBPP」のマジッククッキーを使用)はサポートされていません。 「DBBF」の魔法のクッキーを使用して、「一時的な」パッケージは現在サポートされていないことに注意してください。
S3PIは、Sims 3 Wikiの説明を実装する.NETアセンブリのセット(以下に文書化されています)です(これらのページはWiki-Mirrorとしてここで入手可能)。何かがうまくいくべきか、何かがどのように機能するか、またはS3PIで問題を見つけたと思うかについて、何かが不明であるかどうかは常にそこにチェックする価値があることに注意してください。ウィキも図書館も常に正しいことではありません - 確かに、両方が異なる方法で間違っていることがあります。
S3PIライブラリには、あなたが知っておくべきことの多くを説明するコンパイルされたヘルプファイル(.CHM)が付属しています。ここで、これのバージョンにアクセスすることもできます。このページは、ライブラリがかなり広範囲であり、あなたが知っておくべきことを扱うのが難しいかもしれないため、簡単な概要を説明しようとします。
このページは、残りの3つのセクションに分割されます。
ラッパーを使用してパッケージ内のデータにアクセスする方法を理解したら、ファイルタイプのSIMS3 Wikiリストを参照して、サポートされているものとサポートを取得する方法を確認する必要があります(S3PIディストリビューションの一部ではない場合)。
ヒント
未回答の質問がある場合は、ここにフォーラム/ディスカッションに投稿してください。助けてくれるでしょう!
ライブラリは、.NETアセンブリDLLのセットです。ライブラリを使用して複数のプロジェクトに取り組む可能性が高い場合は、プロジェクトやソリューションワークスペースとは別のフォルダーにそれらを置くことを強くお勧めしますが、フォルダー構造に近いことです。このようにして、各プロジェクトを更新することなく、それらすべてを簡単に交換できます。
新しいプロジェクトからライブラリを使用するには、最初に使用するライブラリのどの部分を知る必要があります。私は、プロジェクトが必要なDLLを参照する必要があるように、依存部品を故意に分離したままにしているため、プロジェクトをサイズに抑えています。欠点は、DLLがたくさんあることです!
最初に気付くのは、それらの多くが「ラッパー」であるSomethingResource.DLLことです。これらには、Sims 3パッケージファイル内の1つ以上のリソースのコンテンツを理解するためのコードが含まれています。
まず、残りの各アセンブリを見てみましょう。この後、新しいプロジェクトを開始する方法の概要を提供します。私はあなたの労働慣行を整理することについていくつかの考えで終わります。
注記
コードを配布する前に、GPLV3ライセンスに同意する必要があります。 GPLV3ライブラリにリンクしているため、本質的にそれを再利用しており、同等の条件でコードを配布する必要があることに注意してください。 Free Software Foundationのサイトで詳細を見つけることができます。
いつそれを含めるか:常に - それはライブラリの他のいくつかの部分に必要です。
概要: 「The Sims 3」に直接関係しておらず、 s3pi.Interfacesタイプのいずれにも参照されていない多くのクラスが含まれています。彼らは、S3PIライブラリの残りの部分を使用しないプロジェクトにおそらく役立つ可能性があります(したがって、それを別々に保ちます)。
さらに読む:このアセンブリを参照することで、次のことを取得します...
System.Collections.Generic.AHandlerList<T> - 補足されたEventHandlerを介してリストの更新に関するフィードバックを提供するList<T>の要約拡張。System.ArgumentLengthExceptionメソッドの引数の長さのエラーを表します。System.Extensions LINQによって提供されない有用な拡張メソッド(および繰延実行なし)。 (クラス名は疑わしいもので、変化する可能性があります...)System.Security.Cryptography.FNV32 -fnv32ハッシュルーチンSystem.Security.Cryptography.FNV64 -fnv64ハッシュルーチンSystem.Text.SevenBitStringまたはStreamからの特定のEncodingで、7ビットエンコードされた長さが埋められた文字列を読み取り、書き込みます。System.Security.Cryptography.Sims3PackCRC SIMS3Packファイルに保存されているデータチャンクのCRCを計算します。 (OK、これにはおそらくここにいる理由はありませんが、コードの依存関係に関しては理にかなっています!) いつそれを含めるか:常に。
概要:もともと、DLLを交換することにより、ライブラリの内部のさまざまな設定を変更することを目的としています。これは決して起こりませんでした。
さらに読む:何もない。
いつそれを含めるか:常に。ライブラリ自体が必要とするだけでなく、パブリックAPIを定義します。
概要:さまざまなライブラリクラスが提供するパブリック方法を定義するライブラリとラッパー全体で使用される多数のインターフェイス、抽象クラス、およびヘルパークラスを提供します。
さらに読む:
s3pi.Interfaces名空間ドキュメント。名前空間は、 s3pi.GenericRCOLのクラスによって「汚染」されていることに注意してください。純粋主義者はまた、ヘルパークラスの「汚染」の一部を考慮するかもしれません...
それを含める時期: Sims 3パッケージファイルを使用するとき。
概要: s3pi.Interfacesで定義されている抽象クラスとインターフェイスの具体的な実装を提供します。
さらに読む:何もない。
それを含める時期:リソースラッパーで作業するとき。
概要:新しいリソースを作成したり、パッケージからリソースを読んでいる場合、これが推奨されるメカニズムです。ただし、代替案は存在します。
さらに読む:
s3pi.WrapperDealer.WrapperDealer IResourceIndexEntryのResourceTypeを特定のクラス(「ラッパー」)に関連付けるか、デフォルトのラッパーを理解する責任があります。 s3pi.DefaultResourceおよびs3pi.GenericRCOLResource 、リソースを参照したら、リソースを使用する方法を理解するための基本を提供します。
いつ含めるか:コミュニティ標準ファイル名が必要な場合。
概要: Sims 3の開始時に、Moddingコミュニティは、パッケージファイルの外側にパッケージ化されたリソースをどのように命名するかについての設定形式に同意しました。このアセンブリは、S3PIライブラリの実装を提供します。
さらに読み取り: s3pi.Extensions namespace。ライブラリのこの領域は、まだ適切に文書化する必要があります。
いつ含めるか: CopyAbleMessageBox(またはIssuesException)が必要な場合。
概要:このアセンブリは、ユーザーがコンテンツを簡単にコピーできるメッセージを表示する方法を提供します。将来的には、他の一般的なコントロールがここに表示される場合があります。
さらに読み取り: CopyableMessageBoxクラス、 CopyableMessageBoxButtons Enumeration、Cop CopyableMessageBoxIcon列挙。
いつ含めるか:カスタムコントロールの1つが必要な場合。
概要:このアセンブリは、S3PIのデータ型に関連するカスタムコントロールを提供します。
さらなる読み取り: ResourceTypeComboクラス、 TGIBlockComboクラス、 TGIBlockListEditorクラス。ライブラリのこの領域は、まだ適切に文書化する必要があります。
それを含める時期: DDS画像を使用し、WinFormsアプリケーションでそれらを表示する方法が必要な場合。
概要:このアセンブリは、カスタムコントロールとDDSのリソースサポートを提供します。
さらなる読み取り: DDSPanelクラスとDDSPanel.MaskChannel列挙。
いつ含めるか: S3PEのヘルパーを書くときに役立つ場合があります。
概要:そのようなリソースに関心のある1つ以上のプログラムにリソースをマッピングするためのサポートを提供します。
さらに読み取り: s3pi.Helpersの名前空間。ライブラリのこの領域は、まだ適切に文書化する必要があります。
前のセクションSystem.Custom 、 s3pi.Settings 、 s3pi.Interfacesなどに基づいて必要な参照を設定します。さらに、特定のラッパーアセンブリを参照するかどうかを検討する必要があります。ほとんどの場合、これは適切なアプローチになります。参照されているアセンブリは、デフォルトでは、プログラムとともにプロジェクト出力フォルダーにコピーされます。
構成ファイルなど、特定の追加コンポーネントが使用されていることに注意してください。これは、プロジェクトのビルドを出力フォルダーにコピーするためにアレンジする必要があることに注意してください。
S3OCおよびS3PE Visual Studio Solutionsを見て、私がそれをどのように行ったかを確認することをお勧めします。
S3PIは、SIMS 3パッケージファイルとその中に保存されているリソースにアクセスしたいプログラムを支援するための多くのC#クラスを提供します。 「コアライブラリ」は、パッケージコンテナ自体のみを理解しています。リソースの内容を理解していません。それは「ラッパー」に委任されます。ラッパーは、サポートするResourceTypesのリストを宣言することにより、リソースに関連付けられています。コアライブラリは、ApproRiate Resourceクラスのインスタンスをライブラリ「クライアント」に返します。
したがって、ラッパーには2つの主な目的があります。1つ以上のリソースタイプのコンテンツの「理解」を提供し、コアライブラリにどのリソースタイプを理解しているかを知らせることです。ラッパーは、適切と思われる1つ以上のリソースハンドラーを提供できますが、著者はさまざまな懸念をさまざまなラッパーに分けておくことが奨励されています。
コアライブラリは、適切なインターフェイスを持つ人をS3PIライブラリフォルダーのアセンブリを検索することにより、ラッパーを識別します。
WrapperDealerには、クライアントアプリケーションがResourceTypeとラッパーの特定の組み合わせを有効にして無効にできるインターフェイスを備えています。
S3PIライブラリのドキュメントにDefaultResourceを含めました。
最も簡単な例は、ソース分布のDefaultResourceで与えられたことです。ラッパーにとって不可欠なことを超えて、「何もしません」。
2つのクラスを定義します。
public class DefaultResource : AResource { }
public class DefaultResourceHandler : AResourceHandler { }ラッパーを含むアセンブリには、 AResourceHandler実装するクラスが含まれている必要があります。このクラスは、 AResource実装するクラス間のIDictionary<Type, List<string>>ルックアップと、 ResourceType値を含む文字列のリストを提供します。 (使用される文字列は、 TypedValue ResourceTypeキャストされた弦からの値、つまり16進ストリングです。)
DefaultResource 「*」を使用して、 WrapperDealerすべてを取ることが喜んでいることを知らせます。ラッパーでこれを使用しないでください!
その後、 DefaultResource 。
const Int32 recommendedApiVersion = 1;将来の互換性のためにクラスのトップで。これにより、必要に応じてラッパーのAPIを「バージョン」することができます。しかし、実際にはそれほど役に立たないでしょう。
AApiVersionedFields RecommendedApiVersionプロパティが必要です。
DefaultResourceのコンストラクターは重要なポイントを示しています -何も知らない新しいリソースが作成されます。コンストラクターに渡されたストリームがnullであることを確認することで、新しいことを確認できます。次に、 MemoryStreamを作成し、リソースの最小有効なデータコンテンツを入力する必要があります。
それでおしまい!あなたがしなければならないことは他に何もありません。もちろん、あなたはまだあなたのラッパーを使用する理由を誰にも提供していません...
注記
いくつかの考えの後、 ImageResourceとTextResource非推奨と見なされます。しかし、それらは近い将来に図書館に残ります。以下に書いていることにもかかわらず、私はもはやバイトストリームであるリソースのラッパーを持つことをお勧めしません。
DDSリソースのために採用されたアプローチは、より正確であると見なされます。結果は以下に直接記載されています。ここのデザインは、ラッパーの目的であるデータ自体の構造に関して何かを実装するのではなく、S3PEの影響を受けました。これは、DDSリソースと同様の方法で処理されるべきでした。
さらに、コンテンツが有用な解読可能なコンテンツを持つのではなく、カスタム電子芸術の視聴覚コーデックの出力であることが発見されたQAサイクル中に、 _VIDリソースラッパーの追加と削除が追加されました。
結論として:「値」は文字列である必要があります。通常、組み込みのフォーマッタは、公共のプロパティから適切なものを構築します。
少し複雑な例は、ImageResourceです。 2つのクラスモデルに固執します。
public class ImageResource : AResource { }
public class ImageResourceHandler : AResourceHandler { }このラッパーは画像を処理します - さまざまなリソースタイプには、単にPNG89ファイルが保存されます。
ImageResourceHandlerの静的コンストラクターは、すべての既知の画像リソースタイプのリストを読み取ります(アセンブリがあるフォルダー内のファイルから)。これは、List IDictionary<Type, List<string>> list in astance constructor WrapperDealerリストを設定するために使用されます。これは、このラッパーがサポートするリストに新しいリソースタイプを簡単に追加できることを意味します。テキストファイルを編集して追加するだけで、再コンパイルする必要はありません。 (それはとても良いパターンです、私はそれを再利用しやすくするべきでした...)
ImageResourceクラスはかなり単純なままです。そのコンストラクターは、ヌルストリームを渡すと有効なPNG89画像があることを保証します。また、PNG89データから作成されたSystem.Drawing.Imageを返す「値」と呼ばれる単一のプロパティを提供します。既存のリソースへの画像の保存をサポートするものではありません。
Valueプロパティはさらに言及する価値があります - S3PIデモフロントエンド(現在はS3PEとして知られています)は、リソースにValueプロパティがあるかどうか、もしそうなら、画像の種類または文字列データがあるかどうかをチェックします。これら2つ(そして現在、これら2つだけ)を表示する方法を知っています。適切なものを返すことは、デバッグに役立ちます。
使用前にストリームの位置がゼロに設定されていることに気付くでしょう - 常に未知の状態にあると仮定します。
TextResourceラッパーは非常に似ています。テキストリソースはファイルで定義されています。リソースを文字列値として返す「値」プロパティがあります。さらに、XMLとしてデータへのアクセスなど、テキスト固有のプロパティがあります。 (XMLラッパーをテキストラッパーの拡張機能として持つ方が、既知のXMLファイルのみを処理する方が良いでしょう...)
このラッパーは、単一のリソースタイプ - パッケージ名マップを処理します。 IDictionary<ulong, string> interfaceを提供し、マップを読み取りおよび更新できるようにします。これは、更新を処理する方法の非常に簡単な例です。
これがどのように機能しますか。これは簡単な例ですが、パターンはより複雑なニーズに拡張できます。
作業は多くの場所で行われます:
Streamプロパティは、リソースが汚れているかどうかを確認します(つまり、変更されました)。もしそうなら、それは現在のストリームを破棄し、 UnParse()を呼び出します。
インスタンスコンストラクターはnullストリームをチェックし、 UnParse()を呼び出して最小有効なリソースを構築します。
Parse(Stream s)メソッドは、データを操作に使用するデータ構造に読み取ります。ここではDictionary<ulong, string> 。これは、データを挿入できるようにするさまざまな長さエントリの繰り返し構造であるため、ストリーム内のデータを使用するのは効率的ではありません。
UnParse()メソッドは、データ構造を新しいストリームに戻し、必要に応じて新しいオブジェクトを作成します。
上記のように、 Streamプロパティは、リソースが汚れているかどうかを知る必要があります。 IDictionary<ulong, string> interfaceの実装は、更新操作のためにOnResourceChanged(this, EventArgs.Empty)呼び出すことでこれを処理します。これはAResourceで提供されており、リソースを汚れたものに設定するだけでなく、イベントを聞いているもののResourceChanged Handlersを呼び出します。
Catalogresourceは、本当にNamemapresourceでアイデアをさらに取り上げています。関連するリソースセットの抽象クラスがあります。私は、何が起こっているのかを理解するために、一貫したコーディングのパターンを維持しようとしました。読者に演習として、実装を通じて作業して、すべてのクラスがどのように相互作用しているかを確認します。うまくいけば、それは理にかなっているはずです! (そうでない場合、バグが出たときに困惑します!!)
これには最近であるという利点があり、比較的単純ですが、いくつかの興味深いビットがあります。また、新しいものを書くときに私が最もよく相談するラッパーの1つです。
RCOLリソースは、上記のように、RCOLブロックと呼ばれる他の「リソース」のコンテナであるという根本的な違いを伴う通常のリソースです。各ブロックには、4文字のコード(「4cc」またはタグ)によって識別される形式があります。ブロックにはリソースタイプもあります。 RCOLリソース(パッケージ内)は、(リソース内)の最初のRCOLブロックと同じタイプで、リソースはこの最初のRCOLブロックにちなんで命名されています。一部のRCOLリソースには、単一のRCOLブロックのみが含まれています。その他には複数のRCOLブロックが含まれています。
基本的なサポートは、 s3pi.GenericRCOLResourceによって提供されます。リソースラッパーには、ブロックからブロックを読み取り、ブロックを書き込み、RCOL形式をサポートする追加の方法があり、RCOLブロックハンドラーのレジストリがあります。
(「チャンク」という用語は、時々RCOLブロックを参照するために大まかに使用されていることに注意してください...)
基本を定義する抽象クラス、 ARCOLBlockがあります。デフォルトの実装、 DefaultRCOLがあります。これは、レジストリで他の一致するRCOLブロックハンドラーが定義されていないため、最小限のサポートを提供します。
AResourceではなくARCOLBlock拡張する以外に、RCOLブロックハンドラーを作成するタスクは、リソースラッパーの作成に非常に似ています。
ただし、電子芸術 /マキシは最近、一部のシングルRCOLコンテナがコンテナがどのように機能するかについての当初の理解に正確に適合していないという点で、人生を少し難しくし始めています。コードを読んだり自分で書いたりするときは、これに注意してください。
まず、S3PEソフトウェアを使用して、SIMSパッケージファイルを編集する方法を既に知っている必要があります。 S3PEは基本的に、一般的なユーザーが使用できるS3PIのグラフィカルインターフェイスとして機能します。したがって、S3PIはS3PEができることなど、さらに多くのことを行うことができると言っても安全です。
注記
S3PEは、このリポジトリからもダウンロードできます。実行可能ファイルとC#ソースコードとVisual Studioソリューションの両方。
これを知って、プログラムにS3PIを実装するには、プログラムがアクションを実行するためにS3PEを使用しているかのようにコーディングする必要があります。
パッケージファイルから特定のリソースを削除する必要があるとしましょう。 S3PEを使用している場合は、最初にそのパッケージファイルを開き、リソースを検索して削除します。次に、 DEL Keyを押してそのファイルを削除してから保存します。パッケージファイルが保存されると、閉じます。
S3PEを使用してこれを行う場合、S3PIを使用してこの同じアクションを実行する場合、プログラムは同じ手順を実行する必要があります。以下のサンプルコードを参照して、リソースを削除するアクション「0x00B2D882-0X00000000-0X0A12300000FF0000」を例として、例として...
using s3pi ;
using s3pi . Interfaces ;
using s3pi . Package ;
//Open the package
IPackage package = Package . OpenPackage ( 0 , "C:/Folder/someFile.package" , true ) ;
//Search the resource "0x00B2D882-0x00000000-0x0A12300000FF0000" inside the package
foreach ( IResourceIndexEntry item in package . GetResourceList )
{
//Get current entrie resource TGI
string typeHex = GetLongConvertedToHexStr ( item . ResourceType , 8 ) ;
string groupHex = GetLongConvertedToHexStr ( item . ResourceGroup , 8 ) ;
string instanceHex = GetLongConvertedToHexStr ( item . Instance , 16 ) ;
//If is the target resource, delete it
if ( typeHex == "0x00B2D882" && groupHex == "0x00000000" && instanceHex == "0x0A12300000FF0000" )
package . DeleteResource ( item ) ;
}
//Save the changes
package . SavePackage ( ) ;
//Close the package
Package . ClosePackage ( 0 , package ) ; 重要
作業が完了した後、常に開いたパッケージファイルを閉じることが非常に重要です。
注記
Dream Launcherは、「Marcos4503」によって作成されたSims 3のランチャーです。 Dream Launcherは、S3PIを使用して、パッケージのマージ、セーブのクリーンアップ、その他の機能など、さまざまな機能を実装しています。このリンクに従って、Dream Launcherリポジトリをチェックして、S3PI使用の例についてはソースコードをご覧ください。ドリームランチャーは、プログラミング言語としてC#を使用して作成されました。
using s3pi ;
using s3pi . Interfaces ;
using s3pi . Package ;
//Creates a new Package that will receive the resources from 2 other Packages
IPackage finalPackage = Package . NewPackage ( 0 ) ;
//Open the Package 1 and copy all resources to the final package
IPackage package1 = Package . OpenPackage ( 0 , "C:/Folder/package1.package" , false ) ;
foreach ( IResourceIndexEntry item in package1 . GetResourceList )
finalPackage . AddResource ( item , ( package1 as APackage ) . GetResource ( item ) , true ) ;
Package . ClosePackage ( 0 , package1 ) ;
//Open the Package 2 and copy all resources to the final package
IPackage package2 = Package . OpenPackage ( 0 , "C:/Folder/package2.package" , false ) ;
foreach ( IResourceIndexEntry item in package2 . GetResourceList )
finalPackage . AddResource ( item , ( package2 as APackage ) . GetResource ( item ) , true ) ;
Package . ClosePackage ( 0 , package2 ) ;
//Enable compression for all viable resources of final merged package (the same way S3PE does)
foreach ( IResourceIndexEntry item in finalPackage . GetResourceList )
item . Compressed = ( ushort ) ( ( item . Filesize != item . Memsize ) ? 0xFFFF : 0x0000 ) ;
//Saves the final Package, result of the merge
finalPackage . SaveAs ( "C:/Folder/finalFile.package" ) ;
Package . ClosePackage ( 0 , finalPackage ) ; using s3pi ;
using s3pi . Interfaces ;
using s3pi . Package ;
//Open a .nhd save file
IPackage nhdSaveFile = Package . OpenPackage ( 0 , "C:/Folder/saveFile.nhd" , false ) ;
//Search inside the package, by the first thumbnail of type "SNAP" (or hex type "0x6B6D837E")
foreach ( IResourceIndexEntry item in nhdSaveFile . GetResourceList )
if ( GetLongConvertedToHexStr ( item . ResourceType , 8 ) == "0x6B6D837E" )
{
//Get the base stream for this resource
Stream aPackageStream = ( nhdSaveFile as APackage ) . GetResource ( item ) ;
//Get the base resource using the "ImageResource" s3pi wrapper***
IResource baseResource = ( IResource ) ( new ImageResource . ImageResource ( 0 , aPackageStream ) ) ;
//Get the bitmap from base resource stream
BitmapImage bitmapImage = new BitmapImage ( ) ;
bitmapImage . BeginInit ( ) ;
bitmapImage . StreamSource = baseResource . Stream ;
bitmapImage . CacheOption = BitmapCacheOption . OnLoad ;
bitmapImage . EndInit ( ) ;
bitmapImage . Freeze ( ) ;
//... continue ...//
//Cancel the search
break ;
}
//Close the save file
Package . ClosePackage ( 0 , nhdSaveFile ) ; ***ここでは、S3PIが自動的に作業しているリソースの正しいラッパーを提供するように、 WrapperDealerクラスを使用できることに注意してください。そこでWrapperDealer使用した場合、S3PIは自動的にImageResourceラッパーをもたらしますが、 WrapperDealer 、WPF自体などのいくつかの.NETフレームワークと互換性があり、クラッシュを引き起こすことが知られています。このため、パッケージファイル内のリソースを使用する場合は、常にラッパーを直接使用することをお勧めします。画像を取得するためにWrapperDealerクラスを使用することを選択した場合、コードスニペットは次のようになります...
//...
//Get the resource using WrapperDealer
IResource resource = WrapperDealer . GetResource ( 0 , nhdSaveFile , item , true ) ;
//Get the bitmap from base resource stream
BitmapImage bitmapImage = new BitmapImage ( ) ;
bitmapImage . BeginInit ( ) ;
bitmapImage . StreamSource = resource . Stream ;
bitmapImage . CacheOption = BitmapCacheOption . OnLoad ;
bitmapImage . EndInit ( ) ;
bitmapImage . Freeze ( ) ;
//... using s3pi ;
using s3pi . Interfaces ;
using s3pi . Package ;
//Open a package that contains a CASP resource
IPackage openedPackage = Package . OpenPackage ( 0 , "C:/Folder/clothes.package" , true ) ;
//Search the first CASP (or hex type 0x034AEECB) resource inside the package
foreach ( IResourceIndexEntry item in openedPackage . GetResourceList )
if ( GetLongConvertedToHexStr ( item . ResourceType , 8 ) == "0x034AEECB" )
{
//Get the CASP stream
Stream caspStream = WrapperDealer . GetResource ( 1 , openedPackage , item , true ) . Stream ;
//Get the CASP resource
CASPartResource . CASPartResource sourceCASpart = new CASPartResource . CASPartResource ( 1 , caspStream ) ;
//Allow this CASP for Random Sims
sourceCaspart . ClothingCategory |= CASPartResource . ClothingCategoryFlags . ValidForRandom ;
//Disallow this CASP for Random Sims
sourceCaspart . ClothingCategory &= ~ CASPartResource . ClothingCategoryFlags . ValidForRandom ;
//Delete the old CASP resource
openedPackage . DeleteResource ( item ) ;
//Add the new modified resource
openedPackage . AddResource ( ( ( IResourceKey ) item ) , ( ( AResource ) sourceCaspart ) . Stream , true ) ;
//Release streams
caspStream . Dispose ( ) ;
caspStream . Close ( ) ;
( ( AResource ) sourceCaspart ) . Stream . Dispose ( ) ;
( ( AResource ) sourceCaspart ) . Stream . Close ( ) ;
}
//Save the package and close it
openedPackage . SavePackage ( ) ;
Package . ClosePackage ( 0 , openedPackage ) ; 注記
ここでは、 WrapperDealerを使用してCASPリソースにアクセスしますが、ラッパーCASPartResourceを使用してCASPリソースにアクセスすることもできます。
おそらくすでに理解しているように、Simsパッケージファイルは「zipファイル」のようなもので、その内部に他のいくつかのファイルが含まれています。パッケージファイル内の各ファイル/リソースには、それに関連付けられたTGIがあります。
TGIは基本的にタイプ、グループ、インスタンスです。タイプとグループは8桁の16進数ですが、インスタンスは16桁の16進数です。ゲームによってロードされたときのリソース間の競合を回避するために、ゲームによってロードされたすべてのパッケージに存在するすべてのリソースには、独自のTGIの組み合わせが必要です。
S3PEでパッケージファイルを開くと、開いたパッケージに存在する各リソースのタイプ、グループ、インスタンスを簡単に確認できます。これがわかったので、Simsパッケージファイルを編集する際には、パッケージファイルに挿入するリソースに常に一意のTGIが必要であることを常に確認する必要があります。
これについてさらに質問がある場合は、この記事を読むことができます。これは、modの競合、それらがどのように発生するか、それらを解決する方法などについて非常によく説明します。
ここまで読んだことがあるなら、S3PIとは何か、それをどのように使用するかを適切に理解する必要があります。古い公式S3PIリポジトリにアクセスする場合は、このリンクを使用できます。 S3PIライブラリを作成したことのすべてのクレジットは、Peter L Jonesに寄付されることを思い出してください。
Marcos Tomazによって作成されたリポジトリ