refactor Quest Enumeration

This commit is contained in:
wish
2023-07-18 21:40:42 +10:00
parent c6618b7688
commit 2ae42d59af

View File

@@ -98,45 +98,8 @@ func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} }
func readOriginalPointers(pointer int64, quest []byte) []byte { func loadQuestFile(s *Session, questFile string) []byte {
fileBytes := byteframe.NewByteFrameFromBytes(quest) file, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", questFile)))
fileBytes.SetLE()
fileBytes.Seek(pointer, 0)
questMeta := struct {
pointers []int64
strings [][]byte
}{
make([]int64, 8),
make([][]byte, 8),
}
for i := 0; i < 8; i++ {
questMeta.pointers[i] = int64(fileBytes.ReadUint32())
}
for i := 0; i < 8; i++ {
fileBytes.Seek(questMeta.pointers[i], 0)
questMeta.strings[i] = fileBytes.ReadNullTerminatedBytes()
}
newPointers := byteframe.NewByteFrame()
newPointers.SetLE()
for i := 0; i < 8; i++ {
length := 352
for j := 0; j < i; j++ {
length += len(questMeta.strings[j]) + 1
}
newPointers.WriteUint32(uint32(length))
}
for i := 0; i < 8; i++ {
newPointers.WriteNullTerminatedBytes(questMeta.strings[i])
}
ps.Uint8(newPointers, "", true) // Unused developer comment section?
return newPointers.Data()
}
func loadQuestFile(s *Session, questId string) []byte {
file, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", questId)))
if err != nil { if err != nil {
return nil return nil
} }
@@ -144,30 +107,50 @@ func loadQuestFile(s *Session, questId string) []byte {
decrypted := decryption.UnpackSimple(file) decrypted := decryption.UnpackSimple(file)
fileBytes := byteframe.NewByteFrameFromBytes(decrypted) fileBytes := byteframe.NewByteFrameFromBytes(decrypted)
fileBytes.SetLE() fileBytes.SetLE()
fileBytes.Seek(int64(fileBytes.ReadInt32()), io.SeekStart) fileBytes.Seek(int64(fileBytes.ReadUint32()), 0)
// The 320 bytes directly following the data pointer must go directly into the event's body, after the header and before the string pointers. // The 320 bytes directly following the data pointer must go directly into the event's body, after the header and before the string pointers.
questBody := byteframe.NewByteFrameFromBytes(fileBytes.ReadBytes(320)) questBody := byteframe.NewByteFrameFromBytes(fileBytes.ReadBytes(320))
questBody.SetLE() questBody.SetLE()
questBody.Seek(40, io.SeekStart) // Find the master quest string pointer
strings := readOriginalPointers(int64(questBody.ReadUint32()), decrypted) questBody.Seek(40, 0)
fileBytes.Seek(int64(questBody.ReadUint32()), 0)
// Overwrite it
questBody.WriteUint32(320)
questBody.Seek(0, 2) questBody.Seek(0, 2)
questBody.WriteBytes(strings)
// Rewrite the quest strings and their pointers
var tempString []byte
newStrings := byteframe.NewByteFrame()
tempPointer := 352
for i := 0; i < 8; i++ {
temp := int64(fileBytes.Index())
fileBytes.Seek(int64(fileBytes.ReadUint32()), 0)
tempString = fileBytes.ReadNullTerminatedBytes()
fileBytes.Seek(temp, 0)
questBody.WriteUint32(uint32(tempPointer + len(tempString) + 1))
tempPointer += len(tempString) + 1
newStrings.WriteNullTerminatedBytes(tempString)
}
questBody.WriteBytes(newStrings.Data())
return questBody.Data() return questBody.Data()
} }
func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) { func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
var id int32 var id uint32
var questId uint16 var questId int
var maxPlayers, questType, mark uint8 var maxPlayers, questType, mark uint8
rows.Scan(&id, &maxPlayers, &questType, &questId, &mark) rows.Scan(&id, &maxPlayers, &questType, &questId, &mark)
bf := byteframe.NewByteFrame() data := loadQuestFile(s, fmt.Sprintf("%05dd0", questId))
bf.SetLE() if data == nil {
return nil, fmt.Errorf("failed to load quest file")
}
// Reconstructing the event-header itself. A lot of the data is not actually necessary for the quest to operate normally. bf := byteframe.NewByteFrame()
bf.WriteInt32(id) bf.WriteUint32(id)
bf.WriteInt32(0) bf.WriteUint32(0)
bf.WriteUint8(0) // Indexer bf.WriteUint8(0) // Indexer
bf.WriteUint8(maxPlayers) bf.WriteUint8(maxPlayers)
bf.WriteUint8(questType) bf.WriteUint8(questType)
@@ -175,23 +158,9 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
bf.WriteUint16(0) bf.WriteUint16(0)
bf.WriteUint32(0) bf.WriteUint32(0)
bf.WriteUint16(0) bf.WriteUint16(0)
bf.WriteUint16(0) bf.WriteUint16(uint16(len(data)))
data := loadQuestFile(s, fmt.Sprintf("%05d", questId)+"d0")
if data == nil {
return nil, fmt.Errorf("failed to load quest file")
}
bf.WriteBytes(data) bf.WriteBytes(data)
ps.Uint8(bf, "", true) // What is this string for?
// Update the checksum at pos 21, the checksum is determined the total length of the file minus 553 turned into a single byte.
bf.Seek(21, io.SeekStart)
bf.WriteUint8(uint8(len(bf.Data()) - 553))
// Overwrite the string-pointer at 62 to point at 320. This is always 320 and does not count the 22 from the event header.
bf.Seek(62, io.SeekStart)
bf.WriteInt16(320)
return bf.Data(), nil return bf.Data(), nil
} }
@@ -215,7 +184,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
if err != nil { if err != nil {
continue continue
} else { } else {
if len(data) > 850 || len(data) < 400 { if len(data) > 896 || len(data) < 352 {
continue continue
} else { } else {
totalCount++ totalCount++