ทุกวันนี้มันยากมากที่จะหาข้อมูลที่เป็นของแข็งและความช่วยเหลือที่แท้จริงเกี่ยวกับ S3PI ยิ่งไปกว่านั้นหากคุณพยายามสร้างโปรแกรมโดยใช้ S3PI เป็นไลบรารีเพื่อโต้ตอบกับไฟล์แพ็คเกจ SIMS นอกจากนี้ไลบรารี S3PI ไม่ได้อยู่ใน GitHub และไม่มีที่เก็บที่นี่
ด้วยเหตุผลเหล่านี้ฉันตัดสินใจที่จะสร้างที่เก็บนี้เพื่อจัดเก็บไลบรารี S3PI อย่างครบถ้วนพร้อมตัวอย่างรหัสและเคล็ดลับเกี่ยวกับวิธีการใช้งานอย่างถูกต้อง นอกจากนี้ฉันได้รวบรวมข้อมูลที่เป็นประโยชน์ทั้งหมดที่ฉันพบบนอินเทอร์เน็ตที่เกี่ยวข้องกับ S3PI!
หากคุณต้องการมีส่วนร่วมข้อมูลเพิ่มเติมโปรดสร้างคำขอดึงหรือรายงานผ่านแท็บ "ปัญหา" ฉันจะพยายามอย่างเต็มที่เพื่อให้ที่เก็บข้อมูลนี้มีข้อมูลและตัวอย่างให้มากที่สุดเท่าที่จะทำได้ แต่ถ้าผู้เขียน S3PI ร้องขอมันฉันจะใช้ที่เก็บนี้ออฟไลน์นี้
สำคัญ
จำได้ว่าเครดิตทั้งหมดสำหรับการสร้างห้องสมุด S3PI ไปที่ "Peter L Jones" อย่างไม่น่าเชื่อ!
"Sims 3 Package Interface" จัดเตรียมไลบรารีหลักของรหัสพกพาที่ "เข้าใจ" แพ็คเกจเกม SIMS3 โปรดทราบว่า (ด้วยการปรับแต่งเล็กน้อย) รหัสห้องสมุดหลักยังเข้าใจรูปแบบแพ็คเกจเกมอื่น ๆ (เช่น Simcity Online, Sims4)
พร้อมกับห้องสมุดหลักยังมีจำนวน "wrappers" ที่ให้ส่วนหลักของโครงการ จัดการเหล่านี้ deserialization และการทำให้เป็นอนุกรมของข้อมูลภายในแพ็คเกจ (หรือแหล่งอื่น ๆ )
เครื่องมือเพิ่มเติมสามารถใช้ไลบรารีและ wrappers นี้เพื่อจัดการเนื้อหาข้อมูลของไฟล์แพ็คเกจของเกม SIMS
โปรดทราบว่าการพัฒนาในห้องสมุดและห่อหุ้มที่ให้ไว้ที่นี่เสร็จสิ้นแล้ว
"S3PI" เป็นตัวย่อสำหรับ "Sims3 ™ Package Interface" ให้การสนับสนุนสำหรับการเข้าถึงข้อมูลภายในไฟล์ "แพ็คเกจ" แต่ละไฟล์ที่ใช้โดยเกม Electronic Arts SIMS3 ™ "แพ็คเกจ" เป็นไฟล์ดิสก์ที่มีนามสกุลไฟล์มักจะเป็น ".package" (แต่ใช้ส่วนขยายอื่น ๆ ) อย่างไรก็ตามคุณสมบัติการระบุหลักที่ใช้โดย S3PI คือคุกกี้เวทมนตร์สี่ไบต์ที่จุดเริ่มต้นของไฟล์ซึ่งจะต้องเป็น "DBPF" นอกจากนี้หมายเลขเวอร์ชันรูปแบบไฟล์จะต้องเป็น 2 สำหรับ SIMS 3 ™ (หรือ 3 สำหรับ SIM City 5 ™ซึ่งรองรับแทบจะไม่)
โปรดทราบว่าแพ็คเกจ "ป้องกัน" (พร้อมคุกกี้วิเศษของ "DBPP") ไม่ได้รับการสนับสนุน โปรดทราบว่าแพ็คเกจ "ชั่วคราว" (พร้อมคุกกี้วิเศษของ "DBBF") ไม่ได้รับการสนับสนุนในปัจจุบัน
S3PI เป็นชุดของแอสเซมบลี. NET (บันทึกไว้ด้านล่างและมีอยู่ที่นี่) ที่ใช้คำอธิบายจาก Sims 3 Wiki (พร้อมหน้าเหล่านี้มีให้ที่นี่เป็น Wiki-Mirror) โปรดทราบว่ามันคุ้มค่าที่จะตรวจสอบที่นั่นเสมอหากคุณไม่แน่ใจในบางสิ่งบางอย่างเกี่ยวกับวิธีการทำงานบางอย่างหรือถ้าคุณคิดว่าคุณพบปัญหาใน S3PI ซึ่งยังคงเป็นไปได้มาก ทั้งวิกิและห้องสมุดไม่ถูกต้องเสมอ - แน่นอนอาจเป็นไปได้ว่าทั้งคู่ผิดในรูปแบบที่แตกต่างกัน
ไลบรารี S3PI มาพร้อมกับไฟล์ช่วยเหลือที่รวบรวม (.chm) ซึ่งอธิบายสิ่งที่คุณต้องรู้ คุณยังสามารถเข้าถึงเวอร์ชันนี้ได้ที่นี่ หน้านี้พยายามให้ภาพรวมอย่างรวดเร็วเนื่องจากห้องสมุดค่อนข้างกว้างขวางและอาจเป็นเรื่องยากที่จะหาสิ่งที่คุณต้องรู้
หน้านี้แบ่งออกเป็นสามส่วนที่เหลือ
เมื่อคุณเข้าใจวิธีการใช้ wrapper เพื่อเข้าถึงข้อมูลในแพ็คเกจคุณควรปรึกษารายการประเภทไฟล์ Sims3 Wiki เพื่อดูว่ารองรับและวิธีรับการสนับสนุน (หากไม่ใช่ส่วนหนึ่งของการแจกแจง S3PI)
เคล็ดลับ
หากคุณมีคำถามที่ยังไม่ได้รับคำตอบโปรดโพสต์ที่นี่ในฟอรัม/การอภิปราย จะมีความสุขที่ได้ช่วย!
ห้องสมุดเป็นชุดของแอสเซมบลี. NET หากคุณมีแนวโน้มที่จะทำงานในโครงการมากกว่าหนึ่งโครงการโดยใช้ห้องสมุดฉันขอแนะนำให้วางไว้ในโฟลเดอร์แยกจากพื้นที่ทำงานของโครงการและโซลูชันของคุณ - แต่ใกล้เคียงกับโครงสร้างโฟลเดอร์ของคุณ ด้วยวิธีนี้มันง่ายที่จะแทนที่ทั้งหมดโดยไม่ต้องอัปเดตแต่ละโครงการ
ในการใช้ห้องสมุดจากโครงการใหม่คุณต้องรู้ก่อนว่าคุณจะใช้ส่วนใดส่วนใดของห้องสมุด ฉันจงใจเก็บชิ้นส่วนที่พึ่งพาไว้โดยเจตนาเพื่อให้โครงการของคุณต้องการอ้างอิง DLL ที่ต้องการดังนั้นจึงทำให้โครงการของคุณมีขนาดเท่ากัน ข้อเสียคือมี DLL มากมาย!
สิ่งแรกที่ควรสังเกตคือพวกเขาหลายคนคือ "wrappers" - อะไรก็ได้ที่มีชื่อเช่น SomethingResource.DLL สิ่งเหล่านี้มีรหัสเพื่อทำความเข้าใจเนื้อหาของทรัพยากรอย่างน้อยหนึ่งรายการภายในไฟล์แพ็คเกจ SIMS 3
ก่อนอื่นมาดูชุดประกอบที่เหลือแต่ละครั้ง หลังจากนี้ฉันจะให้โครงร่างของวิธีการเริ่มโครงการใหม่ ฉันจะจบด้วยความคิดบางอย่างเกี่ยวกับการจัดระเบียบวิธีปฏิบัติงานของคุณ
บันทึก
คุณต้องยอมรับใบอนุญาต GPLV3 ก่อนแจกจ่ายรหัสของคุณ ขอให้สังเกตว่าในขณะที่คุณกำลังเชื่อมโยงไปยังไลบรารี GPLV3 คุณจะใช้มันอีกครั้งและต้องกระจายรหัสของคุณภายใต้ข้อกำหนดที่เทียบเท่า คุณสามารถค้นหารายละเอียดเพิ่มเติมเกี่ยวกับเว็บไซต์ของมูลนิธิซอฟต์แวร์ฟรี
เมื่อใดควรรวม: เสมอ - จำเป็นต้องใช้โดยส่วนอื่น ๆ ของห้องสมุด
สรุป: มีจำนวนคลาสที่ไม่เกี่ยวข้องโดยตรงกับ "The Sims 3" และไม่มีการอ้างอิงถึงประเภท s3pi.Interfaces ใด ๆ พวกเขาสามารถใช้งานได้สำหรับโครงการที่ไม่ได้ใช้ส่วนที่เหลือของห้องสมุด S3PI (ดังนั้นจึงแยกมันออก)
การอ่านเพิ่มเติม: โดยการอ้างอิงแอสเซมบลีนี้คุณจะได้รับสิ่งต่อไปนี้ ...
System.Collections.Generic.AHandlerList<T> - นามสกุลนามธรรมของ List<T> ให้ข้อเสนอแนะเกี่ยวกับการอัปเดตรายการผ่าน EventHandler ที่ให้มาSystem.ArgumentLengthException - แสดงถึงข้อผิดพลาดในความยาวของการโต้แย้งกับวิธีการSystem.Extensions - วิธีการขยายที่มีประโยชน์ไม่ได้จัดทำโดย LINQ (และไม่มีการดำเนินการรอการตัดบัญชี) (ชื่อชั้นเรียนน่าสงสัยและอาจเปลี่ยน ... )System.Security.Cryptography.FNV32 - FNV32 HASH ROUTINESystem.Security.Cryptography.FNV64 - FNV64 Hash RoutineSystem.Text.SevenBitString อ่านและเขียนสตริงที่มีความยาวเจ็ดบิตที่เข้ารหัสใน Encoding ที่กำหนดจากหรือไปยัง StreamSystem.Security.Cryptography.Sims3PackCRC - คำนวณ CRC ของชิ้นข้อมูลที่เก็บไว้ในไฟล์ SIMS3PACK (ตกลงเนื้อหานี้ไม่มีเหตุผลอยู่ที่นี่ แต่ในแง่ของการพึ่งพารหัสมันสมเหตุสมผล!) เมื่อใดควรรวม: เสมอ
สรุป: เดิมทีตั้งใจที่จะอนุญาตให้การตั้งค่าต่าง ๆ ภายในห้องสมุดเปลี่ยนไปโดยการเปลี่ยน DLL สิ่งนี้ไม่เคยเกิดขึ้น
การอ่านเพิ่มเติม: ไม่มีอะไร
เมื่อใดควรรวม: เสมอ ไม่เพียง แต่เป็นที่ต้องการของห้องสมุดเท่านั้น แต่ยังกำหนด API สาธารณะ
สรุป: ให้จำนวนอินเทอร์เฟซคลาสนามธรรมและคลาสผู้ช่วยที่ใช้ตลอดห้องสมุดและห่อหุ้มซึ่งกำหนดวิธีการสาธารณะที่จัดทำโดยคลาสห้องสมุดต่างๆ
การอ่านเพิ่มเติม:
s3pi.Interfaces โปรดทราบว่าเนมสเปซเป็น "มลพิษ" โดยชั้นเรียนจาก s3pi.GenericRCOL Purists อาจพิจารณาบางส่วนของผู้ช่วย "มลพิษ" ...
เมื่อใดควรรวม: เมื่อทำงานกับไฟล์แพ็คเกจ Sims 3
สรุป: ให้การใช้งานคอนกรีตของคลาสนามธรรมและอินเทอร์เฟซที่กำหนดไว้ใน s3pi.Interfaces
การอ่านเพิ่มเติม: ไม่มีอะไร
เมื่อใดที่จะรวม: เมื่อทำงานกับ wrappers ทรัพยากร
สรุป: หากคุณกำลังสร้างทรัพยากรใหม่หรือการอ่านทรัพยากรจากแพ็คเกจนี่เป็นกลไกที่แนะนำ อย่างไรก็ตามมีทางเลือกอื่น
การอ่านเพิ่มเติม:
s3pi.WrapperDealer.WrapperDealer - รับผิดชอบในการเชื่อมโยง ResourceType ใน IResourceIndexEntry กับคลาสเฉพาะ ("wrapper") ที่เข้าใจหรือ wrapper เริ่มต้น s3pi.DefaultResource และ s3pi.GenericRCOLResource ให้ข้อมูลพื้นฐานสำหรับการทำความเข้าใจวิธีการใช้ทรัพยากรเมื่อคุณมีการอ้างอิงถึงมัน
เมื่อใดควรรวม: หากคุณต้องการชื่อไฟล์มาตรฐานชุมชน
สรุป: ในช่วงเริ่มต้นของ SIMS 3 ชุมชน Modding ได้ตกลงกันในรูปแบบที่ตั้งไว้สำหรับวิธีการที่ทรัพยากรแพคเกจควรตั้งชื่อเมื่ออยู่นอกไฟล์แพ็คเกจ แอสเซมบลีนี้ให้การใช้งานสำหรับไลบรารี S3PI
การอ่านเพิ่มเติม: s3pi.Extensions NAMESPACE พื้นที่ของห้องสมุดนี้ยังต้องการการจัดทำเอกสารอย่างเหมาะสม
เมื่อใดควรรวม: เมื่อคุณต้องการ CopyableMessageBox (หรือ issueexception)
สรุป: แอสเซมบลีนี้มีวิธีการแสดงข้อความที่อนุญาตให้ผู้ใช้คัดลอกเนื้อหาได้อย่างง่ายดาย ในอนาคตการควบคุมทั่วไปอื่น ๆ อาจปรากฏที่นี่
การอ่านเพิ่มเติม: คลาส CopyableMessageBox , CopyableMessageBoxButtons การแจงนับและการแจงนับ CopyableMessageBoxIcon
เมื่อใดควรรวม: เมื่อคุณต้องการหนึ่งในการควบคุมที่กำหนดเอง
สรุป: แอสเซมบลีนี้ให้การควบคุมแบบกำหนดเองที่เกี่ยวข้องกับชนิดข้อมูลใน S3PI
การอ่านเพิ่มเติม: คลาส ResourceTypeCombo , คลาส TGIBlockCombo และคลาส TGIBlockListEditor พื้นที่ของห้องสมุดนี้ยังต้องการการจัดทำเอกสารอย่างเหมาะสม
เมื่อใดที่ควรรวม: เมื่อคุณใช้ภาพ DDS และต้องการวิธีการแสดงในแอปพลิเคชัน WinForms
สรุป: แอสเซมบลีนี้ให้การควบคุมที่กำหนดเองและการสนับสนุนทรัพยากร DDS
การอ่านเพิ่มเติม: คลาส DDSPanel และ DDSPanel.MaskChannel การแจงนับ
เมื่อใดควรรวม: อาจมีประโยชน์เมื่อเขียนผู้ช่วยสำหรับ S3PE
สรุป: ให้การสนับสนุนสำหรับการแมปทรัพยากรกับหนึ่งโปรแกรมขึ้นไปที่อาจสนใจทรัพยากรประเภทนั้น
การอ่านเพิ่มเติม: s3pi.Helpers เนมสเปซ พื้นที่ของห้องสมุดนี้ยังต้องการการจัดทำเอกสารอย่างเหมาะสม
ตั้งค่าการอ้างอิงที่คุณต้องการตามส่วนก่อนหน้า System.Custom , s3pi.Settings , s3pi.Interfaces และอื่น ๆ นอกจากนี้คุณจะต้องพิจารณาว่าคุณต้องการอ้างอิงชุดประกอบห่อหุ้มเฉพาะหรือไม่ ในกรณีส่วนใหญ่นี่จะเป็นวิธีการที่เหมาะสม แอสเซมบลีที่อ้างอิงของคุณจะถูกคัดลอกไปยังโฟลเดอร์เอาท์พุทโครงการพร้อมกับโปรแกรมของคุณ
โปรดทราบว่ามีส่วนประกอบเพิ่มเติมบางอย่างที่ใช้เช่นไฟล์การกำหนดค่าที่คุณจะต้องจัดเตรียมการสร้างโครงการของคุณเพื่อคัดลอก (ถ้าใหม่กว่า) ไปยังโฟลเดอร์เอาท์พุท
คุณอาจต้องการดูโซลูชัน S3OC และ S3PE Visual Studio เพื่อดูว่าฉันได้ทำอย่างไร
S3PI มีคลาส C# จำนวนหนึ่งเพื่อช่วยเหลือโปรแกรมที่ต้องการเข้าถึงไฟล์แพ็คเกจ SIMS 3 และทรัพยากรที่เก็บไว้ภายใน "ห้องสมุดหลัก" เข้าใจเฉพาะบรรจุภัณฑ์ของตัวเองเท่านั้น - ไม่มีความเข้าใจในเนื้อหาของทรัพยากร ที่ได้รับมอบหมายให้ "wrappers" wrappers เกี่ยวข้องกับทรัพยากรโดยการประกาศรายชื่อ ResourceTypes ที่พวกเขาสนับสนุน ไลบรารีหลักส่งคืนอินสแตนซ์ของคลาสทรัพยากร approriate ไปยังไลบรารี "ไคลเอนต์"
ดังนั้น wrappers มีสองเป้าหมายหลัก: เพื่อให้ "ความเข้าใจ" ของเนื้อหาของประเภททรัพยากรอย่างน้อยหนึ่งประเภทและเพื่อให้ห้องสมุดหลักทราบว่าทรัพยากรประเภทใดที่พวกเขาเข้าใจ wrapper สามารถจัดหาตัวจัดการทรัพยากรอย่างน้อยหนึ่งตัวตามที่เห็นว่าเหมาะสม แต่ผู้เขียนได้รับการสนับสนุนให้เก็บข้อกังวลที่แตกต่างกันซึ่งแยกออกเป็น wrappers ที่แตกต่างกัน
ห้องสมุดหลักระบุ wrappers โดยค้นหาผ่านแอสเซมบลีในโฟลเดอร์ S3PI Library สำหรับผู้ที่มีอินเทอร์เฟซที่เหมาะสม
WrapperDealer มีอินเทอร์เฟซที่ช่วยให้แอปพลิเคชันไคลเอนต์เปิดใช้งานและปิดการใช้งานชุดค่าผสมเฉพาะของ ResourceType และ Wrapper
ตอนนี้ฉันได้รวม DefaultResource ไว้ในเอกสาร S3PI Library
ตัวอย่างที่ง่ายที่สุดคือที่ให้ไว้ใน DefaultResource ในการแจกแจงแหล่งที่มา มัน "ไม่ทำอะไรเลย" นอกเหนือจากสิ่งที่จำเป็นสำหรับเสื้อคลุมใด ๆ
มันกำหนดสองคลาส:
public class DefaultResource : AResource { }
public class DefaultResourceHandler : AResourceHandler { } แอสเซมบลีที่มีเสื้อคลุมจะต้องมีคลาสที่ใช้งาน AResourceHandler คลาสนี้มี IDictionary<Type, List<string>> การค้นหาระหว่างคลาสที่ใช้ AResource และรายการสตริงที่มีค่า ResourceType (สตริงที่ใช้คือค่าจากการพิมพ์ TypedValue ResourceType ไปยังสตริงนั่นคือสตริง hex)
DefaultResource ใช้ "*" เพื่อให้ WrapperDealer รู้ว่ามีความสุขที่ได้รับทุกอย่าง อย่าใช้สิ่งนี้ใน wrappers ของคุณ!
DefaultResource แล้ว
ขอแนะนำอย่างยิ่งที่คุณมี const Int32 recommendedApiVersion = 1; ที่ด้านบนสุดของชั้นเรียนของคุณสำหรับความเข้ากันได้ในอนาคต สิ่งนี้จะช่วยให้คุณสามารถ "เวอร์ชัน" API wrapper ของคุณหากคุณต้องการ แม้ว่าจะไม่ได้มีประโยชน์ในทางปฏิบัติ
คุณต้องมีคุณสมบัติ AApiVersionedFields RecommendedApiVersion
ตัวสร้างสำหรับ DefaultResource แสดงให้เห็นถึงจุดสำคัญ - ทรัพยากรใหม่ถูกสร้างขึ้นโดยไม่รู้ อะไรเลย สามารถตรวจสอบได้ว่าเป็นของใหม่โดยตรวจสอบว่าสตรีมที่ส่งผ่านไปยังตัวสร้างเป็นโมฆะ จากนั้นควรสร้าง MemoryStream และเติมด้วยเนื้อหาข้อมูลขั้นต่ำที่ถูกต้องสำหรับทรัพยากร
แค่ไหน! ไม่มีอะไรที่คุณต้องทำ แน่นอนคุณยังไม่ได้ให้เหตุผลที่จะใช้ wrapper ของคุณ ...
บันทึก
หลังจากความคิดบางอย่าง ImageResource และ TextResource ได้รับการพิจารณาว่าเลิกใช้แล้ว อย่างไรก็ตามพวกเขาจะยังคงอยู่ในห้องสมุดสำหรับอนาคตที่คาดการณ์ได้ แม้จะมีสิ่งที่เขียนไว้ด้านล่าง แต่ฉันไม่คิดว่าจะเป็นความคิดที่ดีอีกต่อไปที่จะมีเสื้อคลุมสำหรับทรัพยากรที่เป็นเพียงกระแสไบต์
วิธีการที่ใช้สำหรับทรัพยากร DDS ถือว่าถูกต้องมากขึ้น ข้อสรุปนั้นระบุไว้ด้านล่างโดยตรง: การออกแบบที่นี่ได้รับอิทธิพลจาก S3PE มากกว่าการใช้สิ่งใด ๆ เกี่ยวกับโครงสร้างของข้อมูลเองซึ่งเป็นจุดประสงค์ของเสื้อคลุม สิ่งนี้ควรได้รับการจัดการในลักษณะเดียวกันกับทรัพยากร DDS
ข้อสรุปเพิ่มเติมคือการเพิ่มจากนั้นการลบ wrapper ทรัพยากร _VID ในระหว่างรอบ QA เมื่อพบว่าเนื้อหานั้นเป็นเอาท์พุทของตัวแปลงสัญญาณภาพอภิปรัชญาอิเล็กทรอนิกส์อิเล็กทรอนิกส์อย่างหมดจดแทนที่จะมีเนื้อหาที่สามารถถอดรหัสได้อย่างมีประโยชน์
โดยสรุป: "ค่า" ควรเป็นสตริง โดยปกติแล้วตัวฟอร์แมตในตัวสร้างสิ่งที่เหมาะสมจากคุณสมบัติสาธารณะของคุณ
ตัวอย่างที่ซับซ้อนกว่าเล็กน้อยคือ ImageResource มันยึดติดกับรุ่นสองคลาส:
public class ImageResource : AResource { }
public class ImageResourceHandler : AResourceHandler { }wrapper นี้จัดการกับรูปภาพ - ประเภททรัพยากรที่แตกต่างกันจำนวนมากถูกเก็บไว้เพียงไฟล์ PNG89
คอนสตรัคเตอร์แบบคงที่สำหรับ ImageResourceHandler อ่านรายการประเภททรัพยากรรูปภาพที่เป็นที่รู้จักทั้งหมด (จากไฟล์ในโฟลเดอร์ที่มีการประกอบอยู่) สิ่งนี้จะถูกใช้เพื่อเติมรายการ IDictionary<Type, List<string>> รายการใน Instance Constructor ซึ่งใช้โดย WrapperDealer ซึ่งหมายความว่าง่ายต่อการเพิ่มประเภททรัพยากรใหม่ในรายการ wrapper นี้รองรับ - เพียงแก้ไขไฟล์ข้อความและเพิ่มพวกเขาไม่จำเป็นต้องคอมไพล์ใหม่ (มันเป็นรูปแบบที่ดีฉันควรทำให้ง่ายต่อการใช้ซ้ำ ... )
คลาส ImageResource ยังคงค่อนข้างง่าย คอนสตรัคเตอร์ของมันทำให้มั่นใจได้ว่ามีภาพ PNG89 ที่ถูกต้องหากผ่านสตรีมโมฆะ และมีคุณสมบัติเดียวที่เรียกว่า "ค่า" ที่ส่งคืน System.Drawing.Image ที่สร้างขึ้นจากข้อมูล PNG89 ไม่รองรับการบันทึกภาพกลับไปยังทรัพยากรที่มีอยู่
คุณสมบัติ Value มีมูลค่าการกล่าวถึงเพิ่มเติม - ส่วนหน้าของ S3PI Demo (ปัจจุบันรู้จักกันในชื่อ S3PE) ตรวจสอบว่าทรัพยากรมีคุณสมบัติ Value หรือไม่และถ้าเป็นเช่นนั้นไม่ว่าจะมีประเภทของข้อมูลภาพหรือสตริง มันรู้วิธีแสดงทั้งสอง (และทั้งสองคนเดียวในปัจจุบัน) การคืนค่าที่เหมาะสมอาจเป็นประโยชน์ในการดีบัก
คุณจะสังเกตเห็นว่าตำแหน่งสตรีมได้รับการตั้งค่าเป็นศูนย์ก่อนการใช้งาน - สมมติว่าอยู่ในสถานะที่ไม่รู้จักเสมอ
Wrapper TextResource นั้นคล้ายกันมาก - ทรัพยากรข้อความถูกกำหนดไว้ในไฟล์ มันมีคุณสมบัติ "ค่า" ที่ส่งคืนทรัพยากรเป็นค่าสตริง นอกจากนี้ยังมีคุณสมบัติเฉพาะข้อความรวมถึงการเข้าถึงข้อมูลเป็น XML (มันจะเป็นการออกแบบที่ดีกว่าที่จะมี wrapper XML เป็นส่วนขยายของ wrapper ข้อความและจัดการไฟล์ XML ที่รู้จักเท่านั้นในนั้น ... )
wrapper นี้จัดการประเภททรัพยากรเดียว - แผนที่ชื่อแพ็คเกจ มันมีอินเทอร์เฟซ IDictionary<ulong, string> ช่วยให้แผนที่สามารถอ่านและอัปเดตได้ มันเป็นตัวอย่างที่ง่ายมากในการจัดการการอัปเดต
นี่คือวิธีการทำงาน นี่เป็นตัวอย่างง่ายๆ แต่รูปแบบสามารถขยายไปสู่ความต้องการที่ซับซ้อนมากขึ้น
งานทำในหลายสถานที่:
คุณสมบัติ Stream ตรวจสอบว่าทรัพยากรนั้นสกปรกหรือไม่ (เช่นเปลี่ยน) ถ้าเป็นเช่นนั้นจะทิ้งสตรีมปัจจุบันและเรียกว่า UnParse()
ตัวสร้างอินสแตนซ์จะตรวจสอบสตรีมโมฆะและเรียกว่า UnParse() เพื่อสร้างทรัพยากรที่ถูกต้องขั้นต่ำ
วิธี Parse(Stream s) อ่านข้อมูลลงในโครงสร้างข้อมูลที่ใช้ในการจัดการ - นี่คือ Dictionary<ulong, string> เนื่องจากนี่เป็นโครงสร้างที่ทำซ้ำของรายการความยาวที่แตกต่างกันซึ่งช่วยให้สามารถแทรกข้อมูลได้จึงไม่มีประสิทธิภาพในการใช้ข้อมูลในสตรีม
เมธอด UnParse() ส่งออกโครงสร้างข้อมูลกลับไปยังสตรีมใหม่สร้างวัตถุใหม่ตามที่จำเป็น
ดังที่ได้กล่าวไว้ข้างต้นคุณสมบัติ Stream จำเป็นต้องรู้ว่าทรัพยากรนั้นสกปรกหรือไม่ การใช้ IDictionary<ulong, string> Interface ดูแลสิ่งนี้โดยการเรียก OnResourceChanged(this, EventArgs.Empty) สำหรับการดำเนินการอัปเดต สิ่งนี้มีให้ใน AResource และตั้งค่าทรัพยากรให้สกปรกรวมทั้งเรียกผู้ดูแล ResourceChanged ของทุกสิ่งที่ฟังเหตุการณ์
Catalogresource เพียงแค่ใช้ความคิดใน Namemapresource ต่อไป มันมีคลาสนามธรรมสำหรับชุดทรัพยากรที่เกี่ยวข้อง ฉันพยายามที่จะรักษารูปแบบการเข้ารหัสที่สอดคล้องกันเพื่อช่วยให้เข้าใจว่าเกิดอะไรขึ้น ฉันปล่อยให้มันเป็นแบบฝึกหัดให้ผู้อ่านทำงานผ่านการดำเนินการเพื่อดูว่าชั้นเรียนทั้งหมดมีปฏิสัมพันธ์กันอย่างไร หวังว่ามันควรจะสมเหตุสมผล! (ถ้าไม่ฉันจะนิ่งงันเมื่อมีข้อบกพร่องขึ้นมา !!)
สิ่งนี้ได้รับประโยชน์จากการเป็นเมื่อเร็ว ๆ นี้และในขณะที่ค่อนข้างง่ายมีบิตที่น่าสนใจ นอกจากนี้ยังเป็นหนึ่งใน wrappers ที่ฉันมักจะปรึกษาตัวเองเมื่อเขียนใหม่
ทรัพยากร RCOL เป็นทรัพยากรปกติตามที่อธิบายไว้ข้างต้น - ด้วยความแตกต่างพื้นฐานที่เป็นคอนเทนเนอร์สำหรับ "ทรัพยากร" อื่น ๆ ที่เรียกว่าบล็อก RCOL แต่ละบล็อกมีรูปแบบที่ระบุโดยรหัสอักขระสี่ตัว ("fourcc" หรือแท็ก); บล็อกยังมีประเภททรัพยากร ทรัพยากร RCOL (ในแพ็คเกจ) มีประเภทเดียวกับบล็อก RCOL แรกใน (ในทรัพยากร) และทรัพยากรได้รับการตั้งชื่อตามบล็อก RCOL แรกนี้ ทรัพยากร RCOL บางตัวมีเพียงบล็อก RCOL เดียวเท่านั้น อื่น ๆ มีหลายบล็อก RCOL
การสนับสนุนขั้นพื้นฐานนั้นจัดทำโดย s3pi.GenericRCOLResource นอกเหนือจากการอ่านบล็อกจากและการเขียนบล็อกไปยังแพ็คเกจแล้ว Wrapper ทรัพยากรยังมีวิธีการเพิ่มเติมเพื่อรองรับรูปแบบ 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-0x0x0a12300000ff0000" จากไฟล์เปิดแพ็คเกจเป็นตัวอย่าง ...
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 เป็นตัวเรียกใช้งานสำหรับ Sims 3 ที่สร้างโดย "Marcos4503" Dream Launcher ใช้ประโยชน์จาก S3PI เพื่อใช้คุณสมบัติต่าง ๆ เช่นการรวมแพ็คเกจการทำความสะอาดบันทึกและฟังก์ชั่นอื่น ๆ คุณสามารถติดตามลิงค์นี้เพื่อตรวจสอบที่เก็บ Dream Launcher และดูที่ซอร์สโค้ดสำหรับตัวอย่างเพิ่มเติมของการใช้ 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 ) ; *** โปรดทราบว่าที่นี่เราสามารถใช้คลาส WrapperDealer เพื่อให้ S3PI จะให้ wrapper ที่ถูกต้องสำหรับทรัพยากรที่เราทำงานด้วยโดยอัตโนมัติ หากเราใช้ WrapperDealer WrapperDealer นั่น S3PI จะนำ Wrapper ImageResource มาให้เราโดยอัตโนมัติ ด้วยเหตุผลนี้ขอแนะนำให้ใช้ wrapper โดยตรงเมื่อทำงานกับทรัพยากรภายในไฟล์แพ็คเกจ หากเราเลือกที่จะใช้คลาส 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 แต่เรายังสามารถใช้ Wrapper CASPartResource โดยตรงเพื่อเข้าถึงทรัพยากร CASP
ตามที่คุณอาจเข้าใจอยู่แล้วไฟล์แพ็คเกจ SIMS เป็นเหมือน "ไฟล์ zip" ซึ่งมีไฟล์อื่น ๆ อีกมากมายภายใน แต่ละไฟล์/ทรัพยากรภายในไฟล์แพ็คเกจมี TGI ที่เกี่ยวข้อง
TGI นั้นเป็นประเภทกลุ่มและอินสแตนซ์ ประเภทและกลุ่มเป็น hexadecimal 8 หลักในขณะที่อินสแตนซ์เป็น hexadecimal 16 หลัก เพื่อหลีกเลี่ยงความขัดแย้งระหว่างทรัพยากรเมื่อโหลดโดยเกมทรัพยากรทุกแห่งที่มีอยู่ในแพ็คเกจทั้งหมดที่โหลดโดยเกมจะต้องมีการรวมกันของ TGI ที่ไม่ซ้ำกัน
เมื่อคุณเปิดไฟล์แพ็คเกจด้วย S3PE คุณสามารถดูประเภทกลุ่มและอินสแตนซ์ของแต่ละทรัพยากรที่มีอยู่ในแพ็คเกจที่เปิดได้อย่างง่ายดาย ตอนนี้คุณรู้สิ่งนี้โปรดทราบว่าในขณะที่แก้ไขไฟล์แพ็คเกจ SIMS คุณควรตรวจสอบให้แน่ใจว่าทรัพยากรที่คุณแทรกลงในไฟล์แพ็คเกจจะต้องมี TGI ที่ไม่ซ้ำกันเสมอ
หากคุณมีคำถามเพิ่มเติมเกี่ยวกับเรื่องนี้คุณสามารถอ่านบทความนี้ซึ่งพูดถึงและอธิบายได้ดีว่า mod มีความขัดแย้งอย่างไรพวกเขาเกิดขึ้นได้อย่างไรวิธีการแก้ไขพวกเขา ฯลฯ
หากคุณอ่านมาไกลขนาดนี้คุณควรมีความเข้าใจที่ดีว่า S3PI คืออะไรและใช้งานได้อย่างไร หากคุณต้องการเข้าถึงที่เก็บ S3PI อย่างเป็นทางการเก่าคุณสามารถใช้ลิงค์นี้ได้ การจดจำว่าเครดิตทั้งหมดสำหรับการสร้างห้องสมุด S3PI ไปที่ Peter L Jones
พื้นที่เก็บข้อมูลที่สร้างขึ้นโดย Marcos Tomaz