forked from ScriptedEvents/ScriptedEvents
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCountdownModule.cs
More file actions
150 lines (123 loc) · 4.76 KB
/
CountdownModule.cs
File metadata and controls
150 lines (123 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
namespace ScriptedEvents.API.Modules
{
using System;
using System.Collections.Generic;
using Exiled.API.Features;
using MEC;
using ScriptedEvents.Structures;
using UnityEngine;
/// <summary>
/// Module that controls showing countdowns to players.
/// </summary>
public class CountdownModule : SEModule
{
public override string Name => "CountdownModule";
/// <summary>
/// Gets or sets the main coroutine handle.
/// </summary>
public CoroutineHandle? MainHandle { get; set; }
/// <summary>
/// Gets a <see cref="Dictionary{TKey, TValue}"/> of active countdowns.
/// </summary>
public Dictionary<Player, Countdown> Countdowns { get; } = new();
/// <summary>
/// Gets the default countdown text.
/// </summary>
public string BroadcastString => MainPlugin.Singleton.Config.CountdownString ?? "Countdown";
/// <summary>
/// Begins the countdown coroutine.
/// </summary>
public override void Init()
{
base.Init();
Exiled.Events.Handlers.Server.RestartingRound += OnRestarting;
Exiled.Events.Handlers.Server.WaitingForPlayers += WaitingForPlayers;
}
public override void Kill()
{
base.Kill();
Exiled.Events.Handlers.Server.RestartingRound -= OnRestarting;
Exiled.Events.Handlers.Server.WaitingForPlayers -= WaitingForPlayers;
}
public void OnRestarting()
{
if (MainHandle is not null && MainHandle.Value.IsRunning)
{
Timing.KillCoroutines(MainHandle.Value);
MainHandle = null;
Countdowns.Clear();
}
}
public void WaitingForPlayers()
{
MainHandle = Timing.RunCoroutine(InternalCoroutine());
}
/// <summary>
/// Given a <see cref="TimeSpan"/>, returns a pretty string format.
/// </summary>
/// <param name="time">The time span.</param>
/// <returns>String format.</returns>
public static string Display(TimeSpan time)
{
int seconds = Mathf.RoundToInt((float)time.TotalSeconds);
if (seconds <= 60)
return Mathf.RoundToInt((float)time.TotalSeconds).ToString();
string secondsStr = time.Seconds.ToString();
if (secondsStr.Length == 1)
{
secondsStr = $"0{secondsStr}";
}
if (time.TotalHours < 1)
return $"{time.Minutes}:{secondsStr}";
string minStr = time.Minutes.ToString();
if (minStr.Length == 1)
{
minStr = $"0{minStr}";
}
if (time.TotalDays < 1)
return $"{time.Hours}:{minStr}:{secondsStr}";
string hourStr = time.Hours.ToString();
if (hourStr.Length == 1)
{
hourStr = $"0{hourStr}";
}
return $"{time.Days}:{hourStr}:{minStr}:{secondsStr}";
}
/// <summary>
/// Adds a countdown to a player.
/// </summary>
/// <param name="player">The player to count down for.</param>
/// <param name="text">The text to show.</param>
/// <param name="ts">The time on the countdown.</param>
/// <param name="source">The script that started the countdown.</param>
public void AddCountdown(Player player, string text, TimeSpan ts, Script source = null)
{
if (Countdowns.ContainsKey(player))
Countdowns.Remove(player);
Countdown ct = new(player, text, (int)ts.TotalSeconds, source);
Countdowns.Add(player, ct);
player.ClearBroadcasts();
player.Broadcast(1, BroadcastString.Replace("{TEXT}", ct.Text).Replace("{TIME}", Display(ts)));
}
private IEnumerator<float> InternalCoroutine()
{
while (true)
{
if (Round.IsEnded)
break;
foreach (Player ply in Player.List)
{
if (!Countdowns.TryGetValue(ply, out Countdown ct))
continue;
if (!ct.Expired)
{
ply.ClearBroadcasts();
ply.Broadcast(1, BroadcastString.Replace("{TEXT}", ct.Text).Replace("{TIME}", Display(ct.TimeLeft)));
}
}
yield return Timing.WaitForSeconds(1);
}
MainHandle = null;
}
}
}