From a0970de48c139871dc6474fb112018ccb66c24d8 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 13:02:17 +1100 Subject: [PATCH] review pass for Event Quest cycling --- patch-schema/12-event_quest_cycling.sql | 7 +- server/channelserver/handlers_quest.go | 88 ++++++++++++------------- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/patch-schema/12-event_quest_cycling.sql b/patch-schema/12-event_quest_cycling.sql index cabc928a7..1cd803750 100644 --- a/patch-schema/12-event_quest_cycling.sql +++ b/patch-schema/12-event_quest_cycling.sql @@ -1,7 +1,8 @@ BEGIN; -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS start_time timestamp with time zone NOT NULL DEFAULT (CURRENT_DATE + interval '0 second'); -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS active_duration int DEFAULT 4; -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS inactive_duration int DEFAULT 3; +ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS start_time timestamp with time zone NOT NULL DEFAULT now(); +ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS active_duration int; +ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS inactive_duration int; +UPDATE public.event_quests SET active_duration=NULL, inactive_duration=NULL; END; \ No newline at end of file diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 40fab2721..6db5a0c95 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -230,61 +230,57 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) { return bf.Data(), nil } -func calculateNumberOfCycles(duration time.Duration, lastStartTime time.Time) int { - timeDifference := time.Now().Sub(lastStartTime) - numberOfCycles := int(timeDifference.Nanoseconds() / int64(duration)) - return numberOfCycles -} - func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateQuest) var totalCount, returnedCount uint16 bf := byteframe.NewByteFrame() bf.WriteUint16(0) - currentTime := time.Now() - - // Check the event_quests table to load the quests with rotation system - rows, err := 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), start_time, COALESCE(active_duration, 1) AS active_duration, COALESCE(inactive_duration, 0) AS inactive_duration FROM event_quests ORDER BY quest_id") - if err != nil { - return - } - defer rows.Close() + rows, err := 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), start_time, COALESCE(active_duration, 0) AS active_duration, COALESCE(inactive_duration, 0) AS inactive_duration FROM event_quests ORDER BY quest_id") + if err == nil { + currentTime := time.Now() + tx, _ := s.server.db.Begin() - // Commit event quest changes to a transaction instead of doing it one by one for to help with performance - transaction, _ := s.server.db.Begin() - - for rows.Next() { - var id, mark uint32 - var questId int - var maxPlayers, flags, questType, activeDuration, inactiveDuration uint8 - var startTime time.Time + for rows.Next() { + var id, mark uint32 + var questId, flags, activeDuration, inactiveDuration int + var maxPlayers, questType uint8 + var startTime time.Time - err := rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDuration, &inactiveDuration) - if err != nil { - continue - } - - // Count the number of cycles necessary to align quest with the correct date range. - cycleCount := calculateNumberOfCycles(time.Duration(activeDuration+inactiveDuration)*24*time.Hour, startTime) + err = rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDuration, &inactiveDuration) + if err != nil { + continue + } - // Calculate the rotation time based on start time, active duration, and inactive duration. - rotationTime := startTime.Add(time.Duration(activeDuration+inactiveDuration) * 24 * time.Duration(cycleCount) * time.Hour) - if currentTime.After(rotationTime) { - // take the rotationTime and normalize it to midnight as to align with the ingame message for event quest rotation. - newRotationTime := time.Date(rotationTime.Year(), rotationTime.Month(), rotationTime.Day(), 0, 0, 0, 0, rotationTime.Location()) - newRotationTime = newRotationTime.Add(time.Duration(TimeMidnight().Add(13 * time.Hour).Nanosecond())) + // Use the Event Cycling system + if activeDuration > 0 { + cycleLength := (time.Duration(activeDuration) + time.Duration(inactiveDuration)) * 24 * time.Hour + + // Count the number of full cycles elapsed since the last rotation. + extraCycles := int(currentTime.Sub(startTime) / cycleLength) + + if extraCycles > 0 { + // Calculate the rotation time based on start time, active duration, and inactive duration. + rotationTime := startTime.Add(time.Duration(activeDuration+inactiveDuration) * 24 * time.Hour * time.Duration(extraCycles)) + if currentTime.After(rotationTime) { + // Normalize rotationTime to 12PM JST to align with the in-game events update notification. + newRotationTime := time.Date(rotationTime.Year(), rotationTime.Month(), rotationTime.Day(), 12, 0, 0, 0, TimeAdjusted().Location()) + + _, err = tx.Exec("UPDATE event_quests SET start_time = $1 WHERE id = $2", newRotationTime, id) + if err != nil { + tx.Rollback() // Rollback if an error occurs + break + } + startTime = newRotationTime // Set the new start time so the quest can be used/removed immediately. + } + } - _, err := transaction.Exec("UPDATE event_quests SET start_time = $1 WHERE id = $2", newRotationTime, id) - if err != nil { - transaction.Rollback() // Rollback if an error occurs - break + // Check if the quest is currently active + if currentTime.Before(startTime) || currentTime.After(startTime.Add(time.Duration(activeDuration)*24*time.Hour)) { + break + } } - startTime = newRotationTime // Set the new start time so the quest can be used/removed immediately. - } - // Check if the quest is currently active - if currentTime.After(startTime) && currentTime.Sub(startTime) <= time.Duration(activeDuration)*24*time.Hour { data, err := makeEventQuest(s, rows) if err != nil { continue @@ -301,10 +297,10 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { } } } - } - // Commit transaction so to write to the database. - transaction.Commit() + rows.Close() + tx.Commit() + } type tuneValue struct { ID uint16