mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-15 08:25:09 +01:00
Merge branch 'main' of https://github.com/ZeruLight/Erupe into feautre/event-tent
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
"ScreenshotAPIURL": "",
|
"ScreenshotAPIURL": "",
|
||||||
"DeleteOnSaveCorruption": false,
|
"DeleteOnSaveCorruption": false,
|
||||||
"ClientMode": "ZZ",
|
"ClientMode": "ZZ",
|
||||||
|
"QuestCacheExpiry": 300,
|
||||||
"DevMode": true,
|
"DevMode": true,
|
||||||
"DevModeOptions": {
|
"DevModeOptions": {
|
||||||
"AutoCreateAccount": true,
|
"AutoCreateAccount": true,
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ type Config struct {
|
|||||||
DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion
|
DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion
|
||||||
ClientMode string
|
ClientMode string
|
||||||
RealClientMode Mode
|
RealClientMode Mode
|
||||||
|
QuestCacheExpiry int // Number of seconds to keep quest data cached
|
||||||
DevMode bool
|
DevMode bool
|
||||||
|
|
||||||
DevModeOptions DevModeOptions
|
DevModeOptions DevModeOptions
|
||||||
|
|||||||
5
patch-schema/11-event-quest-flags.sql
Normal file
5
patch-schema/11-event-quest-flags.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS flags integer;
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -47,6 +47,10 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.server.erupeConfig.GameplayOptions.SeasonOverride {
|
||||||
|
pkt.Filename = seasonConversion(s, pkt.Filename)
|
||||||
|
}
|
||||||
|
|
||||||
data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
|
data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", s.server.erupeConfig.BinPath, pkt.Filename))
|
s.logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", s.server.erupeConfig.BinPath, pkt.Filename))
|
||||||
@@ -58,6 +62,33 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func seasonConversion(s *Session, questFile string) string {
|
||||||
|
filename := fmt.Sprintf("%s%d", questFile[:6], s.server.Season())
|
||||||
|
|
||||||
|
// Return the seasonal file
|
||||||
|
if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", filename))); err == nil {
|
||||||
|
return filename
|
||||||
|
} else {
|
||||||
|
// Attempt to return the requested quest file if the seasonal file doesn't exist
|
||||||
|
if _, err = os.Stat(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", questFile))); err == nil {
|
||||||
|
return questFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the code reaches this point, it's most likely a custom quest with no seasonal variations in the files.
|
||||||
|
// Since event quests when seasonal pick day or night and the client requests either one, we need to differentiate between the two to prevent issues.
|
||||||
|
var _time string
|
||||||
|
|
||||||
|
if TimeGameAbsolute() > 2880 {
|
||||||
|
_time = "d"
|
||||||
|
} else {
|
||||||
|
_time = "n"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request a d0 or n0 file depending on the time of day. The time of day matters and issues will occur if it's different to the one it requests.
|
||||||
|
return fmt.Sprintf("%s%s%d", questFile[:5], _time, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest)
|
pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest)
|
||||||
var data []byte
|
var data []byte
|
||||||
@@ -77,6 +108,11 @@ func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadQuestFile(s *Session, questId int) []byte {
|
func loadQuestFile(s *Session, questId int) []byte {
|
||||||
|
data, exists := s.server.questCacheData[questId]
|
||||||
|
if exists && s.server.questCacheTime[questId].Add(time.Duration(s.server.erupeConfig.QuestCacheExpiry)*time.Second).After(time.Now()) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
file, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%05dd0.bin", questId)))
|
file, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%05dd0.bin", questId)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -113,14 +149,16 @@ func loadQuestFile(s *Session, questId int) []byte {
|
|||||||
}
|
}
|
||||||
questBody.WriteBytes(newStrings.Data())
|
questBody.WriteBytes(newStrings.Data())
|
||||||
|
|
||||||
|
s.server.questCacheData[questId] = questBody.Data()
|
||||||
|
s.server.questCacheTime[questId] = time.Now()
|
||||||
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, mark uint32
|
var id, mark uint32
|
||||||
var questId int
|
var questId, flags int
|
||||||
var maxPlayers, questType uint8
|
var maxPlayers, questType uint8
|
||||||
rows.Scan(&id, &maxPlayers, &questType, &questId, &mark)
|
rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags)
|
||||||
|
|
||||||
data := loadQuestFile(s, questId)
|
data := loadQuestFile(s, questId)
|
||||||
if data == nil {
|
if data == nil {
|
||||||
@@ -168,7 +206,12 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
|
|||||||
if s.server.erupeConfig.GameplayOptions.SeasonOverride {
|
if s.server.erupeConfig.GameplayOptions.SeasonOverride {
|
||||||
bf.WriteUint8(flagByte & 0b11100000)
|
bf.WriteUint8(flagByte & 0b11100000)
|
||||||
} else {
|
} else {
|
||||||
bf.WriteUint8(flagByte)
|
// Allow for seasons to be specified in database, otherwise use the one in the file.
|
||||||
|
if flags < 0 {
|
||||||
|
bf.WriteUint8(flagByte)
|
||||||
|
} else {
|
||||||
|
bf.WriteUint8(uint8(flags))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bitset Structure Quest Variant 1: b8 UL Fixed, b7 UNK, b6 UNK, b5 UNK, b4 G Rank, b3 HC to UL, b2 Fix HC, b1 Hiden
|
// Bitset Structure Quest Variant 1: b8 UL Fixed, b7 UNK, b6 UNK, b5 UNK, b4 G Rank, b3 HC to UL, b2 Fix HC, b1 Hiden
|
||||||
@@ -192,7 +235,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteUint16(0)
|
bf.WriteUint16(0)
|
||||||
|
|
||||||
rows, _ := s.server.db.Query("SELECT id, COALESCE(max_players, 4) AS max_players, quest_type, quest_id, COALESCE(mark, 0) AS mark FROM event_quests ORDER BY quest_id")
|
rows, _ := s.server.db.Query("SELECT id, COALESCE(max_players, 4) AS max_players, quest_type, quest_id, COALESCE(mark, 0) AS mark, COALESCE(flags, -1) FROM event_quests ORDER BY quest_id")
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
data, err := makeEventQuest(s, rows)
|
data, err := makeEventQuest(s, rows)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -202,18 +245,10 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
totalCount++
|
totalCount++
|
||||||
if _config.ErupeConfig.RealClientMode == _config.F5 {
|
if totalCount > pkt.Offset && len(bf.Data()) < 60000 {
|
||||||
if totalCount > pkt.Offset && len(bf.Data()) < 21550 {
|
returnedCount++
|
||||||
returnedCount++
|
bf.WriteBytes(data)
|
||||||
bf.WriteBytes(data)
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if totalCount > pkt.Offset && len(bf.Data()) < 60000 {
|
|
||||||
returnedCount++
|
|
||||||
bf.WriteBytes(data)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
ps "erupe-ce/common/pascalstring"
|
ps "erupe-ce/common/pascalstring"
|
||||||
@@ -73,6 +74,9 @@ type Server struct {
|
|||||||
name string
|
name string
|
||||||
|
|
||||||
raviente *Raviente
|
raviente *Raviente
|
||||||
|
|
||||||
|
questCacheData map[int][]byte
|
||||||
|
questCacheTime map[int]time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type Raviente struct {
|
type Raviente struct {
|
||||||
@@ -163,6 +167,8 @@ func NewServer(config *Config) *Server {
|
|||||||
state: make([]uint32, 30),
|
state: make([]uint32, 30),
|
||||||
support: make([]uint32, 30),
|
support: make([]uint32, 30),
|
||||||
},
|
},
|
||||||
|
questCacheData: make(map[int][]byte),
|
||||||
|
questCacheTime: make(map[int]time.Time),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mezeporta
|
// Mezeporta
|
||||||
@@ -316,7 +322,6 @@ func (s *Server) BroadcastChatMessage(message string) {
|
|||||||
msgBinChat.Build(bf)
|
msgBinChat.Build(bf)
|
||||||
|
|
||||||
s.BroadcastMHF(&mhfpacket.MsgSysCastedBinary{
|
s.BroadcastMHF(&mhfpacket.MsgSysCastedBinary{
|
||||||
CharID: 0xFFFFFFFF,
|
|
||||||
MessageType: BinaryMessageTypeChat,
|
MessageType: BinaryMessageTypeChat,
|
||||||
RawDataPayload: bf.Data(),
|
RawDataPayload: bf.Data(),
|
||||||
}, nil)
|
}, nil)
|
||||||
@@ -348,7 +353,6 @@ func (s *Server) BroadcastRaviente(ip uint32, port uint16, stage []byte, _type u
|
|||||||
bf.WriteUint16(0) // Unk
|
bf.WriteUint16(0) // Unk
|
||||||
bf.WriteBytes(stage)
|
bf.WriteBytes(stage)
|
||||||
s.WorldcastMHF(&mhfpacket.MsgSysCastedBinary{
|
s.WorldcastMHF(&mhfpacket.MsgSysCastedBinary{
|
||||||
CharID: 0x00000000,
|
|
||||||
BroadcastType: BroadcastTypeServer,
|
BroadcastType: BroadcastTypeServer,
|
||||||
MessageType: BinaryMessageTypeChat,
|
MessageType: BinaryMessageTypeChat,
|
||||||
RawDataPayload: bf.Data(),
|
RawDataPayload: bf.Data(),
|
||||||
|
|||||||
Reference in New Issue
Block a user