review pass for Event Quest cycling

This commit is contained in:
wish
2023-11-26 13:02:17 +11:00
parent d799932f70
commit a0970de48c
2 changed files with 47 additions and 50 deletions

View File

@@ -1,7 +1,8 @@
BEGIN; 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 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 DEFAULT 4; 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 DEFAULT 3; 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; END;

View File

@@ -230,61 +230,57 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
return bf.Data(), nil 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) { func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateQuest) pkt := p.(*mhfpacket.MsgMhfEnumerateQuest)
var totalCount, returnedCount uint16 var totalCount, returnedCount uint16
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bf.WriteUint16(0) bf.WriteUint16(0)
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() currentTime := time.Now()
tx, _ := s.server.db.Begin()
// 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()
// 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() { for rows.Next() {
var id, mark uint32 var id, mark uint32
var questId int var questId, flags, activeDuration, inactiveDuration int
var maxPlayers, flags, questType, activeDuration, inactiveDuration uint8 var maxPlayers, questType uint8
var startTime time.Time var startTime time.Time
err := rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDuration, &inactiveDuration) err = rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDuration, &inactiveDuration)
if err != nil { if err != nil {
continue continue
} }
// Count the number of cycles necessary to align quest with the correct date range. // Use the Event Cycling system
cycleCount := calculateNumberOfCycles(time.Duration(activeDuration+inactiveDuration)*24*time.Hour, startTime) 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. // 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) rotationTime := startTime.Add(time.Duration(activeDuration+inactiveDuration) * 24 * time.Hour * time.Duration(extraCycles))
if currentTime.After(rotationTime) { if currentTime.After(rotationTime) {
// take the rotationTime and normalize it to midnight as to align with the ingame message for event quest rotation. // Normalize rotationTime to 12PM JST to align with the in-game events update notification.
newRotationTime := time.Date(rotationTime.Year(), rotationTime.Month(), rotationTime.Day(), 0, 0, 0, 0, rotationTime.Location()) newRotationTime := time.Date(rotationTime.Year(), rotationTime.Month(), rotationTime.Day(), 12, 0, 0, 0, TimeAdjusted().Location())
newRotationTime = newRotationTime.Add(time.Duration(TimeMidnight().Add(13 * time.Hour).Nanosecond()))
_, err := transaction.Exec("UPDATE event_quests SET start_time = $1 WHERE id = $2", newRotationTime, id) _, err = tx.Exec("UPDATE event_quests SET start_time = $1 WHERE id = $2", newRotationTime, id)
if err != nil { if err != nil {
transaction.Rollback() // Rollback if an error occurs tx.Rollback() // Rollback if an error occurs
break break
} }
startTime = newRotationTime // Set the new start time so the quest can be used/removed immediately. startTime = newRotationTime // Set the new start time so the quest can be used/removed immediately.
} }
}
// Check if the quest is currently active // Check if the quest is currently active
if currentTime.After(startTime) && currentTime.Sub(startTime) <= time.Duration(activeDuration)*24*time.Hour { if currentTime.Before(startTime) || currentTime.After(startTime.Add(time.Duration(activeDuration)*24*time.Hour)) {
break
}
}
data, err := makeEventQuest(s, rows) data, err := makeEventQuest(s, rows)
if err != nil { if err != nil {
continue continue
@@ -301,10 +297,10 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
} }
} }
} }
}
// Commit transaction so to write to the database. rows.Close()
transaction.Commit() tx.Commit()
}
type tuneValue struct { type tuneValue struct {
ID uint16 ID uint16