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)
currentTime := time.Now() 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()
// Check the event_quests table to load the quests with rotation system for rows.Next() {
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") var id, mark uint32
if err != nil { var questId, flags, activeDuration, inactiveDuration int
return var maxPlayers, questType uint8
} var startTime time.Time
defer rows.Close()
// Commit event quest changes to a transaction instead of doing it one by one for to help with performance err = rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDuration, &inactiveDuration)
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
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)
// 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()))
_, err := transaction.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 continue
break }
// 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.
}
}
// 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) 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