오늘날 S3PI를 SIMS 패키지 파일과 상호 작용하기 위해 S3PI를 라이브러리로 사용하는 프로그램을 만들려고하는 경우 S3PI에 대한 견고한 정보와 실제 도움을 찾기가 매우 어렵습니다. 또한 S3PI 라이브러리는 GitHub에 있지 않으며 여기에는 저장소가 없습니다.
이러한 이유로, 나는 코드 예제와 올바르게 사용하는 방법에 대한 팁과 함께 S3PI 라이브러리를 전체적으로 저장하기 위해이 저장소를 만들기로 결정했습니다. 또한 S3PI와 관련된 인터넷에서 찾은 모든 유용한 정보를 여기에 컴파일했습니다!
자세한 정보를 제공하려면 풀 요청을 작성하거나 "문제"탭을 통해보고하십시오. 나는 가능한 한 많은 정보와 예제 로이 저장소를 유지하기 위해 최선을 다할 것이지만, S3PI의 저자가 요청하면이 저장소를 오프라인으로 취할 것입니다.
중요한
S3PI 라이브러리 제작에 대한 모든 크레딧은 놀라운 "Peter L Jones"로 이동한다는 것을 기억하십시오!
"Sims 3 패키지 인터페이스"는 SIMS3 게임 패키지를 "이해하는"휴대용 코드의 핵심 라이브러리를 제공합니다. (일부 조정과 함께) 핵심 라이브러리 코드는 다른 게임 패키지 형식 (예 : SIMCity Online, SIMS4)도 이해합니다.
핵심 라이브러리와 함께 프로젝트의 주요 부분을 제공하는 많은 "포장지"가 있습니다. 이들은 패키지 (또는 다른 소스) 내에서 데이터의 사산화 및 직렬화를 처리합니다.
추가 도구는이 라이브러리와 포장지를 사용하여 SIMS 게임의 패키지 파일의 데이터 컨텐츠를 조작 할 수 있습니다.
여기에 제공된이 라이브러리 및 포장지의 개발이 이제 완료되었습니다.
"S3PI"는 "SIMS3 ™ 패키지 인터페이스"의 약어입니다. Electronic Arts Sims3 ™ 게임에서 사용하는 개별 "패키지"파일 내에서 데이터에 액세스 할 수 있도록 지원합니다. "패키지"는 일반적으로 ".package"의 파일 확장자가있는 디스크 파일입니다 (그러나 다른 확장자가 사용됨). 그러나 S3PI에서 사용하는 주요 식별 기능은 파일 시작시 4 바이트 마술 쿠키이며 "DBPF"여야합니다. 또한 파일 형식 버전 번호는 Sims 3 ™의 경우 2이어야합니다 (또는 Sim City 5 ™의 경우 3 개는 거의 지원되지 않습니다).
"보호 된"패키지 ( "DBPP"의 마술 쿠키 포함)는 지원되지 않습니다. "임시"패키지 ( "DBBF"의 마술 쿠키 포함)는 현재 지원되지 않습니다.
S3PI는 Sims 3 Wiki의 설명을 구현하는 .NET 어셈블리 세트 (아래에 문서화되어 있으며 여기에서 사용할 수 있음)입니다 (이 페이지는 여기에서 Wiki-Mirror로 사용할 수 있음). 무언가가 어떻게 작동 해야하는지 또는 S3PI에서 문제를 발견했다고 생각하는 경우에 대해 항상 확인할 가치가 있습니다. 위키 나 도서관은 항상 옳지 않습니다. 실제로, 둘 다 다른 방식으로 잘못 될 수 있습니다.
S3PI 라이브러리에는 컴파일 된 도움말 파일 (.chm)이 함께 제공되는 많은 것을 설명하는 것의 많은 부분을 설명합니다. 여기에서 버전에 액세스 할 수도 있습니다. 이 페이지는 라이브러리가 꽤 광범위하고 알아야 할 것이 무엇인지 까다로울 수 있기 때문에 빠른 개요를 제공하려고합니다.
이 페이지는 나머지 세 부분으로 나뉩니다.
래퍼를 사용하여 패키지에서 데이터에 액세스하는 방법을 이해 한 후에는 SIMS3 Wiki 파일 유형 목록을 참조하여 지원되는 파일 유형 목록과 지원 방법 (S3PI 배포의 일부가 아닌 경우)을 확인해야합니다.
팁
답이없는 질문이 있으시면 여기 포럼/토론에 게시하십시오. 도와 드리겠습니다!
라이브러리는 .NET 어셈블리 DLL 세트입니다. 라이브러리를 사용하여 둘 이상의 프로젝트에서 작업 할 가능성이 있다면 프로젝트 및 솔루션 작업 공간과 별도로 폴더에 넣는 것이 좋습니다. 그러나 폴더 구조에 가깝습니다. 이렇게하면 각 프로젝트를 업데이트하지 않고도 쉽게 교체 할 수 있습니다.
새 프로젝트에서 라이브러리를 사용하려면 먼저 사용할 라이브러리의 일부를 알아야합니다. 의도적으로 종속 부품을 별도로 보관하여 프로젝트가 필요한 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 -FNV32 해시 루틴System.Security.Cryptography.FNV64 -FNV64 해시 루틴System.Text.SevenBitString 주어진 Encoding 에서 Stream 으로 인코딩 된 7 비트 인코딩 된 길이 완화 된 문자열을 읽고 씁니다.System.Security.Cryptography.Sims3PackCRC SIMS3PACK 파일에 저장된 데이터 청크의 CRC를 계산합니다. (좋아요, 아마도 이것은 여기에있을 이유가 없지만 코드 종속성 측면에서 의미가 있습니다!) 포함시기 : 항상.
요약 : 원래 DLL을 교체하여 라이브러리 내부의 다양한 설정을 변경할 수 있도록했습니다. 이것은 결코 일어나지 않았습니다.
추가 독서 : 아무것도.
포함시기 : 항상. 라이브러리 자체가 필요할뿐만 아니라 공개 API를 정의합니다.
요약 : 라이브러리 및 포장지 전체에 사용되는 여러 인터페이스, 추상 클래스 및 도우미 클래스를 제공하여 다양한 라이브러리 클래스에서 제공하는 공개 방법을 정의합니다.
추가 읽기 :
s3pi.Interfaces 네임 스페이스 문서. 네임 스페이스는 s3pi.GenericRCOL 의 클래스에 의해 "오염"됩니다. 순수 주의자들은 또한 일부 도우미 계급 "오염"을 고려할 수도 있습니다.
포함시기 : Sims 3 패키지 파일과 함께 작업 할 때.
요약 : s3pi.Interfaces 에 정의 된 추상 클래스 및 인터페이스의 구체적인 구현을 제공합니다.
추가 독서 : 아무것도.
포함시기 : 자원 랩퍼와 함께 작업 할 때.
요약 : 패키지에서 새로운 자원을 만들거나 리소스를 읽는 경우 권장 메커니즘입니다. 그러나 대안이 존재합니다.
추가 읽기 :
s3pi.WrapperDealer.WrapperDealer IResourceIndexEntry 의 ResourceType 특정 클래스 ( "래퍼")와 연결하는 것 또는 기본 래퍼를 이해하는 책임을 맡고 있습니다. s3pi.DefaultResource 및 s3pi.GenericRCOLResource 자원을 참조하면 자원을 사용하는 방법을 이해하기위한 기본 사항을 제공합니다.
포함시기 : 커뮤니티 표준 파일 이름을 원하는 경우.
요약 : Sims 3이 시작될 때, Modding Community는 패키지 파일 외부에서 패키지 리소스의 이름을 지정하는 방법에 대한 정해진 형식에 동의했습니다. 이 어셈블리는 S3PI 라이브러리의 구현을 제공합니다.
추가 읽기 : s3pi.Extensions 네임 스페이스. 라이브러리 의이 영역은 여전히 제대로 문서화되어야합니다.
포함시기 : CopyableMessageBox (또는 issuesexception)를 원할 때.
요약 : 이 어셈블리는 사용자가 컨텐츠를 쉽게 복사 할 수있는 메시지를 표시하는 방법을 제공합니다. 앞으로 다른 일반적인 통제가 여기에 나타날 수 있습니다.
추가 읽기 : CopyableMessageBox 클래스, CopyableMessageBoxButtons 열거 및 CopyableMessageBoxIcon 열거.
포함시기 : 사용자 정의 컨트롤 중 하나를 원할 때.
요약 : 이 어셈블리는 S3PI의 데이터 유형과 관련된 사용자 정의 컨트롤을 제공합니다.
추가 읽기 : ResourceTypeCombo 클래스, TGIBlockCombo 클래스 및 TGIBlockListEditor 클래스. 라이브러리 의이 영역은 여전히 제대로 문서화되어야합니다.
포함시기 : DDS 이미지를 사용하고 Winforms 응용 프로그램에 표시하는 방법을 원할 때.
요약 : 이 어셈블리는 사용자 정의 제어 및 DDS 리소스 지원을 제공합니다.
추가 읽기 : DDSPanel class 및 DDSPanel.MaskChannel 열거.
포함시기 : S3PE에 대한 도우미를 쓸 때 유용 할 수 있습니다.
요약 : 리소스를 이러한 종류의 리소스에 관심이있을 수있는 하나 이상의 프로그램에 리소스 매핑을 지원합니다.
추가 읽기 : s3pi.Helpers helpers 네임 스페이스. 라이브러리 의이 영역은 여전히 제대로 문서화되어야합니다.
이전 섹션 System.Custom , s3pi.Settings , s3pi.Interfaces 등을 기반으로 필요한 참조를 설정하십시오. 또한 특정 래퍼 어셈블리를 참조할지 여부를 고려해야합니다. 대부분의 경우 이것은 적절한 접근법이 될 것입니다. 참조 된 어셈블리는 기본적으로 프로그램과 함께 프로젝트 출력 폴더에 복사됩니다.
구성 파일과 같은 특정 추가 구성 요소가 있으므로 프로젝트 빌드가 출력 폴더에 (최신 인 경우) 복사하도록 배열해야합니다.
S3OC 및 S3PE Visual Studio 솔루션을보고 내가 어떻게했는지 확인하고 싶을 수도 있습니다.
S3PI는 SIMS 3 패키지 파일 및 그 내부에 저장된 리소스에 액세스하려는 프로그램을 지원하는 여러 C# 클래스를 제공합니다. "핵심 라이브러리"는 패키지 컨테이너 자체 만 이해합니다. 자원의 내용을 이해하지 못합니다. 그것은 "포장지"로 위임됩니다. 래퍼는 지원하는 ResourceTypes 목록을 선언하여 리소스와 관련이 있습니다. Core Library는 Abtoriate Resource 클래스의 인스턴스를 라이브러리 "클라이언트"로 반환합니다.
따라서 포장지에는 두 가지 주요 목표가 있습니다. 하나 이상의 리소스 유형의 컨텐츠에 대한 "이해"를 제공하고 핵심 라이브러리에 이해하는 리소스 유형을 알려줍니다. 래퍼는 적합하다고 생각되는 하나 이상의 리소스 핸들러를 제공 할 수 있지만 저자는 다른 래퍼로 다른 문제를 분리하는 것이 좋습니다.
핵심 라이브러리는 적절한 인터페이스를 가진 사람들을 위해 S3PI 라이브러리 폴더의 어셈블리를 검색하여 랩퍼를 식별합니다.
WrapperDealer 에는 클라이언트 응용 프로그램이 ResourceType 및 래퍼의 특정 조합을 활성화하고 비활성화 할 수있는 인터페이스가 있습니다.
이제 S3PI 라이브러리 문서에 DefaultResource 포함 시켰습니다.
가장 간단한 예는 소스 분포에서 DefaultResource 에 제공된 예입니다. 그것은 모든 포장지에 필수적인 것 이상으로 "아무것도하지 않습니다".
두 개의 클래스를 정의합니다.
public class DefaultResource : AResource { }
public class DefaultResourceHandler : AResourceHandler { } 래퍼가 포함 된 어셈블리에는 AResourceHandler 구현하는 클래스가 포함되어야합니다. 이 클래스는 AResource 구현하는 클래스와 ResourceType 값을 포함하는 문자열 목록 간의 IDictionary<Type, List<string>> 조회를 제공합니다. (사용 된 문자열은 TypedValue ResourceType 의 문자열로 값을 획득 한 문자열입니다.)
DefaultResource "*"를 사용하여 WrapperDealer 모든 것을 취하는 것이 기쁘다는 것을 알 수 있습니다. 랩퍼에 이것을 사용하지 마십시오!
그렇다면 DefaultResource .
const Int32 recommendedApiVersion = 1; 미래의 호환성을 위해 수업의 최상위에. 필요하면 래퍼의 API를 "버전"할 수 있습니다. 그러나 실제로는 그렇게 유용하지 않을 것입니다.
AApiVersionedFields RecommendedApiVersion 사항이 있어야합니다.
DefaultResource 의 생성자는 중요한 점을 보여줍니다. 새로운 리소스가 아무것도 아는 새로운 리소스가 만들어집니다. 스트림이 생성자로 전달 된 스트림이 NULL인지 확인하여 새로운 것을 확인할 수 있습니다. 그런 다음 MemoryStream 생성하고 리소스의 최소 유효한 데이터 컨텐츠로 채워야합니다.
그게 다야! 당신이해야 할 다른 일은 없습니다. 물론, 당신은 아직 래퍼를 사용할 이유를 누구에게도 제공하지 않았습니다 ...
메모
어떤 생각 이후, ImageResource 와 TextResource 더 이상 사용되지 않는 것으로 간주됩니다. 그러나 그들은 가까운 미래를 위해 도서관에 남아있을 것입니다. 아래에 쓰여진 내용에도 불구하고, 나는 더 이상 바이트 스트림 인 리소스를위한 래퍼를 갖는 것이 좋지 않다고 생각합니다.
DDS 리소스에 대한 접근 방식은 더 정확한 것으로 간주됩니다. 코롤리는 아래에 직접 언급되어 있습니다. 여기의 설계는 래퍼의 목적 인 데이터 자체의 구조와 관련하여 무엇이든 구현하는 대신 S3PE의 영향을 받았습니다. 이것은 DDS 리소스와 유사한 방식으로 처리되어야합니다.
추가적인 코롤로리는 QA주기 동안 _VID 자원 래퍼를 제거하는 것이 었습니다.
결론적으로 : "value"는 단지 문자열이어야합니다. 일반적으로, 내장 된 Formatter는 공개 속성에서 적절한 것을 구축합니다.
약간 더 복잡한 예는 ImageResource입니다. 두 클래스 모델을 고수합니다.
public class ImageResource : AResource { }
public class ImageResourceHandler : AResourceHandler { }이 래퍼는 이미지를 처리합니다. 다양한 리소스 유형은 단순히 PNG89 파일로 저장됩니다.
ImageResourceHandler 의 정적 생성자는 알려진 모든 이미지 리소스 유형 (어셈블리가있는 폴더의 파일에서)의 목록을 읽습니다. 그런 다음 인스턴스 생성자에 목록 IDictionary<Type, List<string>> 목록을 채우고 WrapperDealer 가 사용합니다. 즉,이 래퍼가 지원하는 목록에 새 리소스 유형을 쉽게 추가 할 수 있습니다. 텍스트 파일을 편집하고 추가 할 필요가 없습니다. (정말 좋은 패턴입니다. 재사용하기가 더 쉬워 졌을 것입니다 ...)
ImageResource 클래스는 여전히 간단합니다. 생성자는 NULL 스트림을 통과하면 유효한 PNG89 이미지가 있는지 확인합니다. 또한 PNG89 데이터에서 생성 된 System.Drawing.Image 를 반환하는 "value"라는 단일 속성을 제공합니다. 기존 리소스로 이미지 저장을 지원하지 않습니다.
Value 속성은 더 언급 할 가치 Value 있습니다. 그것은 그 두 가지를 표시하는 방법을 알고 있습니다 (그리고 현재 두 사람 만). 적절한 것을 반환하면 디버깅에 유용 할 수 있습니다.
사용하기 전에 스트림 위치가 0으로 설정되는 것을 알 수 있습니다. 항상 알 수없는 상태에 있다고 가정합니다.
TextResource 래퍼는 매우 유사합니다. 텍스트 리소스는 파일에 정의됩니다. 자원을 문자열 값으로 반환하는 "값"속성이 있습니다. 또한 XML로 데이터에 액세스하는 것을 포함하여 텍스트 별 속성이 있습니다. (XML 래퍼를 텍스트 래퍼의 확장으로 사용하고 알려진 XML 파일 만 처리하는 것이 더 나은 디자인입니다 ...)
이 래퍼는 단일 리소스 유형 인 패키지 이름 맵을 처리합니다. 맵을 읽고 업데이트 할 수있는 IDictionary<ulong, string> 인터페이스를 제공합니다. 업데이트를 처리하는 방법의 매우 간단한 예입니다.
작동 방식은 다음과 같습니다. 이것은 간단한 예이지만 패턴은보다 복잡한 요구로 확장 될 수 있습니다.
작업은 여러 곳에서 이루어집니다.
Stream 속성은 리소스가 더러워 졌는지 여부를 확인합니다 (즉, 변경). 그렇다면 현재 스트림을 폐기하고 UnParse() 호출합니다.
인스턴스 생성자는 NULL 스트림을 점검하고 UnParse() 호출하여 최소 유효한 리소스를 구성합니다.
Parse(Stream s) 메소드는 데이터를 조작하는 데 사용되는 데이터 구조로 데이터를 읽습니다. 여기서 Dictionary<ulong, string> . 이것은 데이터를 삽입 할 수있는 다양한 길이 항목의 반복 구조이므로 스트림에서 데이터를 사용하는 것이 효율적이지 않습니다.
UnParse() 메소드는 데이터 구조를 새 스트림으로 다시 내보내어 필요한 경우 새 개체를 만듭니다.
위에서 언급했듯이 Stream 속성은 자원이 더러워 졌는지 알아야합니다. 우드 업데이트 작업을 위해 OnResourceChanged(this, EventArgs.Empty) 호출함으로써 IDictionary<ulong, string> 인터페이스의 구현이이를 처리합니다. 이것은 AResource 에 제공되며 리소스를 Dirty로 설정하고 이벤트를 듣고있는 모든 것의 ResourceChanged 핸들러를 호출합니다.
Catalogresource는 실제로 Namemapresource에서 아이디어를 더 취합니다. 관련 리소스 세트에 대한 추상 클래스가 있습니다. 나는 무슨 일이 일어나고 있는지 이해하기 위해 일관된 코딩 패턴을 유지하려고 노력했습니다. 나는 모든 수업이 어떻게 상호 작용하는지 알아보기 위해 구현을 통해 일하기 위해 독자에게 연습으로 남겨 둡니다. 잘만되면 이해가되기를 바랍니다! (그렇지 않다면, 버그가 나오면 그무가 생길 것입니다 !!)
이것은 최근의 이점이 있으며, 상대적으로 단순하지만 흥미로운 비트가 있습니다. 또한 새로운 포장지 중 하나입니다. 새 작품을 쓸 때 가장 자주 스스로 상담합니다.
RCOL 리소스는 위에서 설명한대로 정상적인 리소스입니다. RCOL 블록으로 알려진 다른 "리소스"의 컨테이너라는 근본적인 차이가 있습니다. 각 블록은 4 개의 문자 코드 ( "Fourcc"또는 Tag)로 식별 된 형식을 갖습니다. 블록에는 자원 유형도 있습니다. RCOL 리소스 (패키지의)는 (리소스에서) 첫 번째 RCOL 블록과 동일한 유형을 가지며 리소스의 첫 번째 RCOL 블록의 이름을 따서 명명되었습니다. 일부 RCOL 자원은 단일 RCOL 블록 만 포함합니다. 다른 것들에는 여러 개의 RCOL 블록이 포함되어 있습니다.
기본 지원은 s3pi.GenericRCOLResource 에서 제공합니다. 리소스 래퍼에는 패키지에 블록을 읽고 블록을 읽는 것 외에도 RCOL 형식을 지원하는 추가 방법이 있으며 RCOL 블록 핸들러 레지스트리가 있습니다.
( "청크"라는 용어는 때때로 RCOL 블록을 참조하는 데 느슨하게 사용됩니다 ...)
기초를 정의하는 추상 클래스 인 ARCOLBlock 이 있습니다. 레지스트리에 다른 일치하는 RCOL 블록 핸들러가 정의되지 않은 경우 기본 구현 DefaultRCOL 이 있습니다.
AResource 대신 ARCOLBlock 확장하는 것 외에 RCOL 블록 핸들러를 작성하는 작업은 리소스 래퍼 작성과 매우 유사합니다.
그러나 전자 예술 / Maxis는 최근 일부 단일 Rcol 컨테이너가 컨테이너의 작동 방식에 대한 원래의 이해를 정확히 부여하지 않는다는 점에서 인생을 조금 더 어렵게하기 시작했습니다. 코드를 읽거나 직접 쓸 때 이것을 알고 있어야합니다.
먼저 S3PE 소프트웨어를 사용하여 경험이 필요하고 이미 SIMS 패키지 파일을 편집하는 방법을 알고 있습니다. S3PE는 기본적으로 일반 사용자가 사용할 수있는 S3PI의 그래픽 인터페이스로 작동합니다. 따라서 S3PI는 S3PE가 할 수있는 모든 일을 할 수 있다고 말하는 것이 안전합니다.
메모
S3PE는이 저장소에서도 다운로드 할 수 있습니다. 실행 파일과 C# 소스 코드 및 Visual Studio 솔루션이 모두 있습니다.
이를 알면 프로그램에서 S3PI를 구현하려면 프로그램이 S3PE를 사용하여 작업을 수행하는 것처럼 코드를 코딩해야합니다.
패키지 파일에서 특정 리소스를 삭제하려고한다고 가정 해 봅시다. S3PE를 사용하는 경우 먼저 해당 패키지 파일을 열고 자원을 검색하여 삭제하십시오. 그런 다음 DEL 키를 눌러 해당 파일을 삭제 한 다음 저장합니다. 패키지 파일이 저장되면 닫을 것입니다.
S3PE를 사용 하여이 작업을 수행하는 경우 S3PI를 사용하여 동일한 작업을 수행하는 경우 프로그램이 동일한 단계를 수행해야합니다. 아래 샘플 코드를 참조하여 리소스 삭제 "0x00B2D882-0X000000-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 Repository를 확인하고 소스 코드를 살펴보고 S3PI 사용의 더 많은 예를 살펴보십시오. Dream Launcher는 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 리소스에 액세스하지만 CASP 자원에 직접 액세스하기 위해 래퍼 CASPartResource 직접 사용할 수도 있습니다.
이미 이해했듯이 Sims 패키지 파일은 "zip 파일"과 같습니다. 패키지 파일 내부의 각 파일/리소스에는 관련 TGI가 있습니다.
TGI는 기본적으로 유형, 그룹 및 인스턴스입니다. 유형과 그룹은 8 자리 16 진수이고 인스턴스는 16 자라쪽으로 16 자라입니다. 게임에서로드 할 때 자원 간의 충돌을 피하려면 게임에서로드 된 모든 패키지에 존재하는 모든 리소스에는 고유 한 TGI 조합이 있어야합니다.
S3PE로 패키지 파일을 열면 열린 패키지에있는 각 리소스의 유형, 그룹 및 인스턴스를 쉽게 볼 수 있습니다. 이를 알았으므로 Sims 패키지 파일을 편집하는 동안 항상 패키지 파일에 삽입되는 리소스에 항상 고유 한 TGI가 있어야합니다.
이것에 대해 더 이상 질문이 있다면,이 기사를 읽을 수 있습니다.이 기사는 MOD 충돌이 어떤 것인지, 어떻게 발생하는지, 해결 방법 등을 설명하는이 기사를 읽을 수 있습니다.
지금까지 읽었다면 S3PI가 무엇인지, 사용 방법에 대해 잘 이해해야합니다. 이전 공식 S3PI 저장소에 액세스하려면이 링크를 사용할 수 있습니다. S3PI 라이브러리를 만드는 데 대한 모든 크레딧은 Peter L Jones에게 간다는 것을 기억합니다.
Marcos Tomaz가 만든 저장소