1+ package net .swofty .type .generic .utility ;
2+
3+ import lombok .Getter ;
4+ import net .minestom .server .MinecraftServer ;
5+ import net .minestom .server .timer .Task ;
6+ import net .minestom .server .timer .TaskSchedule ;
7+ import net .swofty .type .generic .user .HypixelPlayer ;
8+
9+ import java .util .HashMap ;
10+ import java .util .Map ;
11+ import java .util .UUID ;
12+ import java .util .function .BiConsumer ;
13+ import java .util .function .Consumer ;
14+
15+ public class TimedActivityHandler <T extends HypixelPlayer > {
16+ private static final Map <UUID , TimedActivityHandler <?>> ACTIVE_HANDLERS = new HashMap <>();
17+
18+ private final T player ;
19+ private final int countdownSeconds ;
20+ private final int activityDurationSeconds ;
21+ private final BiConsumer <T , Integer > onCountdownTick ;
22+ private final Consumer <T > onActivityStart ;
23+ private final BiConsumer <T , Integer > onActivityTick ;
24+ private final Consumer <T > onActivityComplete ;
25+ private final Consumer <T > onActivityCancelled ;
26+
27+ @ Getter
28+ private ActivityState state = ActivityState .IDLE ;
29+ private int currentCountdown ;
30+ @ Getter
31+ private int elapsedActivityTime ;
32+ private Task scheduledTask ;
33+
34+ public enum ActivityState {
35+ IDLE ,
36+ COUNTING_DOWN ,
37+ IN_PROGRESS ,
38+ COMPLETED ,
39+ CANCELLED
40+ }
41+
42+ private TimedActivityHandler (Builder <T > builder ) {
43+ this .player = builder .player ;
44+ this .countdownSeconds = builder .countdownSeconds ;
45+ this .activityDurationSeconds = builder .activityDurationSeconds ;
46+ this .onCountdownTick = builder .onCountdownTick ;
47+ this .onActivityStart = builder .onActivityStart ;
48+ this .onActivityTick = builder .onActivityTick ;
49+ this .onActivityComplete = builder .onActivityComplete ;
50+ this .onActivityCancelled = builder .onActivityCancelled ;
51+ }
52+
53+ @ SuppressWarnings ("unchecked" )
54+ public static <T extends HypixelPlayer > TimedActivityHandler <T > getActiveHandler (T player ) {
55+ return (TimedActivityHandler <T >) ACTIVE_HANDLERS .get (player .getUuid ());
56+ }
57+
58+ public static boolean hasActiveHandler (HypixelPlayer player ) {
59+ TimedActivityHandler <?> handler = ACTIVE_HANDLERS .get (player .getUuid ());
60+ return handler != null && (handler .state == ActivityState .COUNTING_DOWN || handler .state == ActivityState .IN_PROGRESS );
61+ }
62+
63+ public void start () {
64+ if (state != ActivityState .IDLE ) {
65+ return ;
66+ }
67+
68+ TimedActivityHandler <?> existing = ACTIVE_HANDLERS .get (player .getUuid ());
69+ if (existing != null && (existing .state == ActivityState .COUNTING_DOWN || existing .state == ActivityState .IN_PROGRESS )) {
70+ existing .cancel ();
71+ }
72+
73+ ACTIVE_HANDLERS .put (player .getUuid (), this );
74+ currentCountdown = countdownSeconds ;
75+ elapsedActivityTime = 0 ;
76+
77+ if (countdownSeconds > 0 ) {
78+ state = ActivityState .COUNTING_DOWN ;
79+ scheduleCountdown ();
80+ } else {
81+ startActivity ();
82+ }
83+ }
84+
85+ private void scheduleCountdown () {
86+ scheduledTask = MinecraftServer .getSchedulerManager ().submitTask (() -> {
87+ if (state != ActivityState .COUNTING_DOWN ) {
88+ return TaskSchedule .stop ();
89+ }
90+
91+ if (onCountdownTick != null ) {
92+ onCountdownTick .accept (player , currentCountdown );
93+ }
94+
95+ currentCountdown --;
96+
97+ if (currentCountdown < 0 ) {
98+ startActivity ();
99+ return TaskSchedule .stop ();
100+ }
101+
102+ return TaskSchedule .seconds (1 );
103+ });
104+ }
105+
106+ private void startActivity () {
107+ state = ActivityState .IN_PROGRESS ;
108+ elapsedActivityTime = 0 ;
109+
110+ if (onActivityStart != null ) {
111+ onActivityStart .accept (player );
112+ }
113+
114+ if (activityDurationSeconds > 0 ) {
115+ scheduleActivityTicks ();
116+ }
117+ }
118+
119+ private void scheduleActivityTicks () {
120+ scheduledTask = MinecraftServer .getSchedulerManager ().submitTask (() -> {
121+ if (state != ActivityState .IN_PROGRESS ) {
122+ return TaskSchedule .stop ();
123+ }
124+
125+ elapsedActivityTime ++;
126+
127+ if (onActivityTick != null ) {
128+ onActivityTick .accept (player , elapsedActivityTime );
129+ }
130+
131+ if (elapsedActivityTime >= activityDurationSeconds ) {
132+ complete ();
133+ return TaskSchedule .stop ();
134+ }
135+
136+ return TaskSchedule .seconds (1 );
137+ });
138+ }
139+
140+ public void complete () {
141+ if (state != ActivityState .IN_PROGRESS && state != ActivityState .COUNTING_DOWN ) {
142+ return ;
143+ }
144+
145+ state = ActivityState .COMPLETED ;
146+
147+ if (scheduledTask != null ) {
148+ scheduledTask .cancel ();
149+ scheduledTask = null ;
150+ }
151+
152+ if (onActivityComplete != null ) {
153+ onActivityComplete .accept (player );
154+ }
155+
156+ ACTIVE_HANDLERS .remove (player .getUuid ());
157+ }
158+
159+ public void cancel () {
160+ if (state != ActivityState .COUNTING_DOWN && state != ActivityState .IN_PROGRESS ) {
161+ return ;
162+ }
163+
164+ state = ActivityState .CANCELLED ;
165+
166+ if (scheduledTask != null ) {
167+ scheduledTask .cancel ();
168+ scheduledTask = null ;
169+ }
170+
171+ if (onActivityCancelled != null ) {
172+ onActivityCancelled .accept (player );
173+ }
174+
175+ ACTIVE_HANDLERS .remove (player .getUuid ());
176+ }
177+
178+ public int getRemainingTime () {
179+ if (state == ActivityState .COUNTING_DOWN ) {
180+ return currentCountdown ;
181+ } else if (state == ActivityState .IN_PROGRESS ) {
182+ return activityDurationSeconds - elapsedActivityTime ;
183+ }
184+ return 0 ;
185+ }
186+
187+ public boolean isCountingDown () {
188+ return state == ActivityState .COUNTING_DOWN ;
189+ }
190+
191+ public boolean isInProgress () {
192+ return state == ActivityState .IN_PROGRESS ;
193+ }
194+
195+ public boolean isActive () {
196+ return state == ActivityState .COUNTING_DOWN || state == ActivityState .IN_PROGRESS ;
197+ }
198+
199+ public static <T extends HypixelPlayer > Builder <T > builder (T player ) {
200+ return new Builder <>(player );
201+ }
202+
203+ public static class Builder <T extends HypixelPlayer > {
204+ private final T player ;
205+ private int countdownSeconds = 5 ;
206+ private int activityDurationSeconds = 0 ;
207+ private BiConsumer <T , Integer > onCountdownTick ;
208+ private Consumer <T > onActivityStart ;
209+ private BiConsumer <T , Integer > onActivityTick ;
210+ private Consumer <T > onActivityComplete ;
211+ private Consumer <T > onActivityCancelled ;
212+
213+ private Builder (T player ) {
214+ this .player = player ;
215+ }
216+
217+ public Builder <T > countdownSeconds (int seconds ) {
218+ this .countdownSeconds = seconds ;
219+ return this ;
220+ }
221+
222+ public Builder <T > activityDurationSeconds (int seconds ) {
223+ this .activityDurationSeconds = seconds ;
224+ return this ;
225+ }
226+
227+ public Builder <T > onCountdownTick (BiConsumer <T , Integer > callback ) {
228+ this .onCountdownTick = callback ;
229+ return this ;
230+ }
231+
232+ public Builder <T > onActivityStart (Consumer <T > callback ) {
233+ this .onActivityStart = callback ;
234+ return this ;
235+ }
236+
237+ public Builder <T > onActivityTick (BiConsumer <T , Integer > callback ) {
238+ this .onActivityTick = callback ;
239+ return this ;
240+ }
241+
242+ public Builder <T > onActivityComplete (Consumer <T > callback ) {
243+ this .onActivityComplete = callback ;
244+ return this ;
245+ }
246+
247+ public Builder <T > onActivityCancelled (Consumer <T > callback ) {
248+ this .onActivityCancelled = callback ;
249+ return this ;
250+ }
251+
252+ public TimedActivityHandler <T > build () {
253+ return new TimedActivityHandler <>(this );
254+ }
255+ }
256+ }
0 commit comments