В настоящее время очень сложно найти солидную информацию и реальную помощь в отношении S3PI, тем более, если вы пытаетесь создать программу с использованием S3PI в качестве библиотеки для взаимодействия с файлами пакетов SIMS. Кроме того, библиотека S3PI не находится на GitHub и не имеет здесь репозитория.
По этим причинам я решил создать этот репозиторий для хранения библиотеки S3PI полностью, с примерами кода и советами о том, как правильно его использовать. Кроме того, я собрал здесь всю полезную информацию, которую я нашел в Интернете, связанную с S3PI!
Если вы хотите внести больше информации, пожалуйста, создайте запрос на привлечение или сообщите о нем через вкладку «Проблемы». Я сделаю все возможное, чтобы сохранить этот репозиторий с как можно большим количеством информации и примеров, но если автор S3PI запрашивает его, я возьму этот репозиторий в автономном режиме.
Важный
Вспоминая, что все титры для создания библиотеки S3PI перейдут к невероятному «Питер Л. Джонс»!
«Интерфейс пакета Sims 3» предоставляет основную библиотеку портативного кода, которая «понимает» игровые пакеты SIMS3. Обратите внимание, что (с некоторыми незначительными изменениями) код основного библиотеки также понимает другие форматы игровых пакетов (например, Simcity Online, SIMS4).
Наряду с основной библиотекой находится ряд «оберток», которые обеспечивают основную часть проекта. Они обрабатывают десериализацию и сериализацию данных в пакете (или любом другом источнике).
Дальнейшие инструменты могут использовать эту библиотеку и обертки для манипулирования содержанием данных в файлах пакетов Sims Games.
Обратите внимание, что разработка в этой библиотеке и обертках, предоставленных здесь, теперь закончена.
«S3PI» является аббревиатурой для «интерфейса пакета SIMS3 ™». Он обеспечивает поддержку для доступа к данным в отдельных файлах «пакета», используемых Electronic Arts Sims3 ™ Game. «Пакет» - это файл диска с расширением файла, обычно из -за ».package» (но используются другие расширения). Тем не менее, основной идентификационной функцией, используемой S3PI, является четырех байтового магического печенья в начале файла, который должен быть «DBPF». Кроме того, номер версии формата файла должен быть 2 для Sims 3 ™ (или 3 для Sim City 5 ™, который едва поддерживается).
Обратите внимание, что «защищенные» пакеты (с волшебным печеньем «DBPP») не поддерживаются. Обратите внимание, что «временные» пакеты (с волшебным печеньем «DBBF») в настоящее время не поддерживаются.
S3PI представляет собой набор сборок .NET (документированные ниже и доступны здесь), которые реализуют описания из вики SIMS 3 (с этими страницами альтернативно доступны здесь как вики-Mirror). Обратите внимание, что всегда стоит проверить там, если вы не уверены в чем -то, либо о том, как что -то должно работать, или если вы думаете, что нашли проблему в S3PI, что остается вполне возможным. Ни вики, ни библиотека не всегда правы - действительно, может быть, оба по -разному ошибочны.
Библиотека S3PI поставляется с составленным файлом справки (.CHM), который описывает многое из того, что вам нужно знать. Вы также можете получить доступ к версии этого, здесь. Эта страница пытается дать быстрый обзор, так как библиотека довольно обширная, и может быть сложно понять, что вам нужно знать.
Эта страница разделена на три оставшихся раздела.
После того, как вы поймете, как использовать обертку для доступа к данным в пакете, вам следует обратиться к списку вики вики SIMS3, чтобы увидеть, которые поддерживаются и как получить поддержку (если не часть распределения S3PI).
Кончик
Если у вас есть вопросы без ответа, пожалуйста, не стесняйтесь публиковать здесь на форуме/дискуссиях. Было бы приятно помочь!
Библиотека представляет собой набор DLL .NET Assembly. Если вы, вероятно, будете работать над более чем одним проектом, используя библиотеку, я настоятельно рекомендую поместить их в папку, отдельную от вашего проекта и рабочих пространств решения, но близко в структуре папок. Таким образом, их легко заменить без необходимости обновлять каждый проект.
Чтобы использовать библиотеку из нового проекта, вам сначала нужно знать, какие части библиотеки вы собираетесь использовать. Я сознательно держал зависимые части отдельными, так что вашему проекту необходимо ссылаться только на необходимые DLL, следовательно, снижение вашего проекта в размере. Недостатком является много DLL!
Первое, что нужно заметить, это то, что многие из них являются «обертками» - все с таким именем, как SomethingResource.DLL . Они содержат код, чтобы понять содержимое одного или нескольких ресурсов в файле пакета SIMS 3.
Во -первых, давайте посмотрим на каждую из оставшихся сборок. После этого я предоставлю план того, как начать новый проект. Я закончу некоторые мысли об организации вашей практики.
Примечание
Вы должны согласиться с лицензией GPLV3, прежде чем распространять ваш код. Обратите внимание, что, когда вы ссылаетесь на библиотеку GPLV3, вы по существу повторно используете ее и должны распространять свой код в эквивалентных терминах. Вы можете найти дополнительную информацию на сайте Free Software Foundation.
Когда включить это: всегда - это требуется несколькими другими частями библиотеки.
Резюме: содержит ряд классов, которые напрямую не относятся к «Sims 3» и не имеют ссылок ни на один из типов s3pi.Interfaces . Они могли бы, возможно, полезны для проектов, не использующих оставшуюся часть библиотеки S3PI (следовательно, удерживая ее отдельную).
Дополнительное чтение: ссылаясь на эту сборку, вы получите следующее ...
System.Collections.Generic.AHandlerList<T> EventHandler Аннотация расширение List<T>System.ArgumentLengthException - представляет ошибку в длине аргумента метода.System.Extensions - полезные методы расширения, не предоставленные LINQ (и без отложенного выполнения). (Имя класса сомнительное и может измениться ...)System.Security.Cryptography.FNV32 - Хэш -рутина FNV32System.Security.Cryptography.FNV64 - Хэш -рутина FNV64System.Text.SevenBitString -Читать и написать семибитную кодируемую длину строку в заданном Encoding из или в Stream .System.Security.Cryptography.Sims3PackCRC - Рассчитайте CRC кусочка данных, хранящийся в файле sims3pack. (Хорошо, возможно, у этого нет причин, но с точки зрения кодовых зависимостей, это имеет смысл!) Когда включить это: всегда.
Резюме: Первоначально предназначен для того, чтобы позволить различным настройкам внутренним для библиотеки, заменив DLL. Этого никогда не было.
Дальнейшее чтение: ничего.
Когда включить это: всегда. Это не только требуется самой библиотеке, но и определяет публичный API.
Резюме: предоставляет ряд интерфейсов, абстрактных классов и вспомогательных классов, используемых в библиотеке и обертках, которые определяют публичные методы, предоставленные различными классами библиотеки.
Дальнейшее чтение:
s3pi.Interfaces Документация пространства имен. Обратите внимание, что пространство имен «загрязнено» классами от s3pi.GenericRCOL . Пуристы могут также рассмотреть некоторые из помощников «Загрязнение» ...
Когда включить его: при работе с файлами пакетов SIMS 3.
Резюме: обеспечивает конкретную реализацию абстрактных классов и интерфейсов, определенных в s3pi.Interfaces .
Дальнейшее чтение: ничего.
Когда включить это: при работе с ресурсными обертками.
Резюме: Если вы создаете новые ресурсы или ресурсы для чтения из пакета, это рекомендуемый механизм. Однако альтернативы существуют.
Дальнейшее чтение:
s3pi.WrapperDealer.WrapperDealer - Ответственный за ассоциацию ResourceType в IResourceIndexEntry с конкретным классом («обертка»), который понимает ее или обертку по умолчанию. s3pi.DefaultResource и s3pi.GenericRCOLResource предоставляют основы для понимания того, как использовать ресурс, когда у вас есть ссылка на него.
Когда включить его: если вы хотите сообщества стандартных имен файлов.
Резюме: В начале SIMS 3 сообщество Modding согласилось с установленным форматом для того, как должен быть назван упакованный ресурс, когда он находится вне файла пакета. Эта сборка предоставляет реализацию для библиотеки S3PI.
Дополнительное чтение: s3pi.Extensions Пространство имен. Эта область библиотеки по -прежнему нуждается в правильном документировании.
Когда включить его: когда вы хотите CopyableMessagebox (или VexeException).
Сводка: Эта сборка предоставляет способ отображения сообщений, который позволяет пользователю легко копировать контент. В будущем здесь могут появиться другие общие элементы управления.
Дополнительное чтение: CopyableMessageBox Class, CopyableMessageBoxButtons перечисление и перечисление CopyableMessageBoxIcon .
Когда включить это: когда вы хотите одно из пользовательских элементов управления.
Резюме: Эта сборка предоставляет пользовательские элементы управления, связанные с типами данных в S3PI.
Дополнительное чтение: класс ResourceTypeCombo , класс TGIBlockCombo и класс TGIBlockListEditor . Эта область библиотеки по -прежнему нуждается в правильном документировании.
Когда включить его: когда вы используете DDS -изображения и хотите отобразить их в приложении Winforms.
Резюме: Эта сборка обеспечивает пользовательскую поддержку управления и ресурсов DDS.
Дополнительное чтение: класс DDSPanel и DDSPanel.MaskChannel Перечисление.
Когда включить это: может быть полезно при написании помощника для S3PE.
Резюме: обеспечивает поддержку картирования ресурса с одной или несколькими программами, которые могут быть заинтересованы в таком виде ресурса.
Дополнительное чтение: s3pi.Helpers Пространство имен. Эта область библиотеки по -прежнему нуждается в правильном документировании.
Установите ссылки s3pi.Interfaces необходимые вам на основе предыдущей System.Custom разделения s3pi.Settings Кроме того, вам нужно будет рассмотреть вопрос о том, хотите ли вы ссылаться на конкретные сборки обертки. В большинстве случаев это будет подходящий подход. Ваши ссылки на сборы по умолчанию будут скопированы в папку «Вывод проекта» вместе с вашей программой.
Обратите внимание, что используются определенные дополнительные компоненты, такие как файлы конфигурации, что вам также нужно будет организовать сборку вашего проекта для копирования (если новее) в выводную папку.
Возможно, вы захотите взглянуть на решения S3OC и S3PE Visual Studio, чтобы увидеть, как я это сделал.
S3PI предоставляет ряд классов C# для оказания помощи программам, желающим получить доступ к файлам пакетов SIMS 3 и ресурсам, хранящимися в них. «Основная библиотека» понимает только сам контейнер пакета - она не понимает содержания ресурсов. Это делегировано «оберткам». Обертки связаны с ресурсами, объявляя список ResourceTypes которые они поддерживают. Основная библиотека возвращает экземпляр класса Apporatie Resource в библиотеку «клиент».
Таким образом, у оберток есть две основные цели: предоставить «понимание» содержания одного или нескольких типов ресурсов и сообщить основной библиотеке, какие типы ресурсов они понимают. Обертка может предоставить одну или несколько обработчиков ресурсов, поскольку она считает нужным, но авторам рекомендуется держать разные проблемы, разделенные на разные обертки.
Основная библиотека идентифицирует обертки путем поиска через сборки в папке библиотеки S3PI для тех, кто имеет соответствующий интерфейс.
У WrapperDealer есть интерфейс, который позволяет клиентским приложениям включать и отключать определенные комбинации ResourceType и обертки.
Теперь я включил DefaultResource в документацию по библиотеке S3PI.
Самый простой пример - это приведенный в DefaultResource в распределении источника. Это «ничего не делает» за пределами того, что важно для любой обертки.
Он определяет два класса:
public class DefaultResource : AResource { }
public class DefaultResourceHandler : AResourceHandler { } Сборка, содержащая обертку, должна содержать класс, реализующий AResourceHandler . Этот класс предоставляет IDictionary<Type, List<string>> поиск между классом, который реализует AResource и списком строк, содержащих значения ResourceType . (Используемые строки являются значениями от ResourceType TypedValue отлитого до строки, то есть шестнадцатеричная строка.)
DefaultResource использует «*», чтобы обернуть WrapperDealer знать, что он рад взять все. Не используйте это в своих обертках!
DefaultResource , тогда.
Настоятельно рекомендуется, чтобы у вас был const Int32 recommendedApiVersion = 1; На вершине вашего класса для будущей совместимости. Это позволяет вам «вернуть» API вашей обертки, если вам это нужно. Наверное, не так полезно на практике, хотя.
У вас должна быть недвижимость AApiVersionedFields RecommendedApiVersion .
Конструктор для DefaultResource демонстрирует важный момент - создается новый ресурс, ничего не зная. Он может проверить, что это новое, проверяя, что поток, переданный конструктору, нулевой. Затем он должен создать MemoryStream и заполнить его минимальным допустимым содержанием данных для ресурса.
Вот и все! Вы больше ничего не должны сделать. Конечно, вы еще никому не предоставили повод использовать свою обертку ...
Примечание
После некоторой мысли ImageResource и TextResource считаются устаревшими. Тем не менее, они останутся в библиотеке в обозримом будущем. Несмотря на то, что написано ниже, я больше не считаю хорошей идеей иметь обертку для ресурса, который является всего лишь байтовым потоком.
Подход, принятый для ресурсов DDS, считается более правильным. Ниже приведено, что на дизайн здесь влияет S3PE, а не реализует что -либо, что касается структуры самих данных, которая является целью обертки. Это должно было быть обработано аналогично ресурсам DDS.
Дальнейшим Королевом был дополнение, а затем удаление _VID -ресурсной обертки во время цикла QA, когда было обнаружено, что содержимое было исключительно выводом пользовательского аудиовизуального кодека электронных искусств, а не имел какого -либо полезного расширного содержания.
В заключение: «значение» должно быть просто строкой. Обычно встроенное форматирование создает соответствующий из ваших общественных свойств.
Немного более сложный пример - ImagerSource. Он придерживается модели двух классов:
public class ImageResource : AResource { }
public class ImageResourceHandler : AResourceHandler { }Эта обертка обрабатывает изображения - много разных типов ресурсов просто хранятся файлы PNG89.
Статический конструктор для ImageResourceHandler считывает список всех известных типов ресурсов изображения (из файла в папке, где находится сборка). Затем это используется для заполнения List IDictionary<Type, List<string>> List в конструкторе экземпляра, который затем используется WrapperDealer . Это означает, что легко добавить новые типы ресурсов в список этой обертки поддерживает - просто отредактируйте текстовый файл и добавьте их, не нужно перекомпилировать. (Это такой хороший рисунок, я должен был облегчить повторное использование ...)
Класс ImageResource остается довольно простым. Его конструктор гарантирует, что есть допустимое изображение PNG89, если его пройден нулевый поток. И он предоставляет единое свойство, называемое «значение», которое возвращает System.Drawing.Image . Он не поддерживает сохранение изображений обратно в существующий ресурс.
Свойство Value стоит упомянуть дальше - демо -фронт S3PI Demo (теперь известный как S3PE) проверяет, имеет ли ресурс свойство Value , и, если это так, есть ли у него тип изображений или строковых данных. Он знает, как показать эти два (и эти два, в настоящее время). Возвращение соответствующего может быть полезно при отладке.
Вы заметите, что позиция потока, установленная на ноль, перед использованием - всегда предположим, что она находится в неизвестном состоянии.
Обертка TextResource очень похожа - текстовые ресурсы определяются в файле; Он имеет свойство «значения», возвращая ресурс как строковое значение. Кроме того, он обладает некоторыми текстовыми свойствами, включая доступ к данным как XML. (Было бы лучше дизайна, чтобы иметь XML -обертку в качестве расширения текстовой обертки и обрабатывать только известные файлы XML ...)
Эта обертка обрабатывает один тип ресурса - карта имен пакета. Он предоставляет интерфейс IDictionary<ulong, string> , позволяющий читать и обновлять карту. Это очень простой пример того, как обрабатывать обновления.
Вот как это работает. Это простой пример, но шаблон может быть расширен до более сложных потребностей.
Работа выполнена в ряде мест:
Свойство Stream проверяет, был ли ресурс грязным (т.е. изменился). Если это так, он отбрасывает текущий поток и вызывает UnParse() .
Конструктор экземпляра проверяет нулевый поток и вызывает UnParse() для построения минимального допустимого ресурса.
Метод Parse(Stream s) считывает данные в структуру данных, используемой для манипулирования им - здесь Dictionary<ulong, string> . Поскольку это повторная структура записей различной длины, которая позволяет вставлять данные, не эффективно использовать данные в потоке.
Метод UnParse() экспортирует структуру данных обратно в новый поток, создавая новые объекты, где это необходимо.
Как упомянуто выше, свойство Stream должно знать, был ли ресурс грязным. Реализация интерфейса IDictionary<ulong, string> позаботится об этом, позвонив OnResourceChanged(this, EventArgs.Empty) для операций обновления. Это предоставлено на AResource и устанавливает ресурс на грязные, а также называет ResourceChanged обработчиков всего, что слушает событие.
Catalogresource действительно просто делает идеи в NameMapresource дальше. Он имеет абстрактный класс для связанного набора ресурсов. Я пытался придерживаться последовательной схемы кодирования, чтобы помочь понять, что происходит. Я оставляю это как упражнение читателю, чтобы проработать реализацию, чтобы увидеть, как взаимодействуют все классы. Надеюсь, это должно иметь смысл! (Если нет, я буду в тупике, когда появится ошибка !!)
Это приносит пользу недавним и, хотя относительно простым, есть несколько интересных кусочков. Это также один из обертка, которые я чаще всего консультируюсь с собой, когда пишу новый.
Ресурс RCOL - это нормальный ресурс, как описано выше - с фундаментальным отличием, что он является контейнером для других «ресурсов», известных как блоки RCOL. Каждый блок имеет формат, идентифицированный с помощью четырех символов ("Fourcc" или Tag); Блоки также имеют типы ресурсов. Ресурс RCOL (в пакете) имеет тот же тип, что и первый блок RCOL в (в ресурсе), а ресурс назван в честь этого первого блока RCOL. Некоторые ресурсы RCOL содержат только один блок RCOL; Другие содержат несколько блоков RCOL.
Основная поддержка предоставляется s3pi.GenericRCOLResource . В дополнение к чтению блоков и записи блоков на пакет, ресурсная обертка имеет дополнительные методы для поддержки формата RCOL, и существует реестр обработчиков блоков RCOL.
(Обратите внимание, что термин «чанк» слабо используется, чтобы время от времени ссылаться на блок RCOL ...)
Существует абстрактный класс, ARCOLBlock , который определяет основы. Существует реализация по умолчанию DefaultRCOL , поскольку в реестре не определено никакое другое подходящее обработчик блоков RCOL, что обеспечивает минимальную поддержку.
Помимо расширения ARCOLBlock , а не AResource , задача написания обработчика блоков RCOL очень похожа на написание ресурсной обертки.
Тем не менее, Electronic Arts / Maxis недавно начали усложнять жизнь, поскольку некоторые контейнеры с одним RCOL не совсем соответствуют первоначальному пониманию того, как должен работать контейнер. Имейте в виду это при чтении кода или написании своего собственного.
Во -первых, вам нужно иметь опыт и уже знать, как редактировать файлы пакетов Sims, используя программное обеспечение S3PE. S3PE в основном работает как графический интерфейс для S3PI, который могут использовать общие пользователи. Поэтому можно с уверенностью сказать, что S3PI способен делать все, что может сделать S3PE, и даже больше.
Примечание
S3PE также доступен для загрузки в этом репозитории. И его исполняемый файл, и его исходный код C# и решение Visual Studio.
Зная это, чтобы реализовать S3PI в вашей программе, вам необходимо кодировать так, как если бы ваша программа использовала S3PE для выполнения действия.
Допустим, вы хотите удалить определенный ресурс из файла пакета. Если бы вы использовали S3PE, вы сначала открыли этот файл пакета, поиск ресурса для удаления. Затем вы нажмите клавишу DEL , чтобы удалить этот файл, а затем сохранить. После того, как файл пакета сохранен, вы закроете его.
Если вы делаете это с помощью 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 - это пусковая установка для Sims 3, созданного «Marcos4503». Запуск Dream использует S3PI для реализации различных функций, таких как слияние пакетов, очистка сбережений и другие функции. Вы можете перейти по этой ссылке, чтобы ознакомиться с репозиторием запуска Dream и взглянуть на исходный код для получения дополнительных примеров использования 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 ) ; *** Обратите внимание, что здесь мы могли бы использовать класс WrapperDealer , чтобы S3PI предоставил нам правильную обертку для ресурса, с которым мы работаем, автоматически. Если бы мы использовали там WrapperDealer , S3PI автоматически принесет нам обертку ImageResource , однако, как известно, WrapperDealer несовместима с некоторыми кадрами .NET, такими как сам WPF, вызывая сбои. По этой причине всегда рекомендуется напрямую использовать обертку при работе с ресурсом внутри файла пакета. Если бы мы решили использовать класс 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-значный шестнадцатеричный. Чтобы избежать конфликтов между ресурсами при загрузке игры, каждый ресурс, присутствующий во всех пакетах, загруженных игрой, должен иметь уникальную комбинацию TGI.
Когда вы откроете файл пакета с S3PE, вы можете легко увидеть тип, группу и экземпляр каждого ресурса, присутствующего в открытом пакете. Теперь, когда вы знаете это, имейте в виду, что при редактировании файлов пакетов Sims вы всегда должны убедиться, что ресурсы, которые вы вставляете в файлы пакетов, всегда должны иметь уникальный TGI.
Если у вас есть какие -либо дополнительные вопросы по этому поводу, вы можете прочитать эту статью, о которой говорится и очень хорошо объясняет, что такое конфликты модов, как они встречаются, как их разрешить и т. Д.
Если вы читаете это далеко, вы должны иметь достойное понимание того, что такое S3PI и как его использовать. Если вы хотите получить доступ к старому официальному репозиторию S3PI, вы можете использовать эту ссылку. Вспоминая, что весь кредит за создание библиотеки S3PI идет к Питеру Л. Джонсу.
Репозиторий, созданный Маркосом Томазом