DREAMFIRE Docs ← Back to site
Loading...
Searching...
No Matches
DreamBossBar.java
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) 2025 Dreamfire Studio
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24package com.dreamfirestudios.dreamcore.DreamBossBar;
25
26import com.dreamfirestudios.dreamcore.DreamCore;
27import com.dreamfirestudios.dreamcore.DreamJava.DreamClassID;
28import lombok.Getter;
29import org.bukkit.Bukkit;
30import org.bukkit.boss.BarFlag;
31import org.bukkit.boss.BossBar;
32import org.bukkit.entity.Player;
33
34import java.util.*;
35
53public class DreamBossBar extends DreamClassID {
54 private List<DreamBossBarData> frames;
55 private BarFlag[] barFlags;
56 @Getter private BossBar bossBar;
57 private int currentFrameIndex;
58 @Getter private boolean bossBarPaused = true;
59 private final List<UUID> viewers = new ArrayList<>();
60
67 public boolean isPlayer(Player player){
68 if (player == null) throw new IllegalArgumentException("Player cannot be null.");
69 return viewers.contains(player.getUniqueId());
70 }
71
75 public void resetBossBar(){
76 if (frames == null || frames.isEmpty()) return;
77 currentFrameIndex = 0;
78 var first = frames.get(0);
79 if (bossBar == null) {
80 bossBar = Bukkit.createBossBar(first.safeTitle(null), first.barColor(), first.barStyle(), barFlags);
81 } else {
82 bossBar.setTitle(first.safeTitle(null));
83 bossBar.setColor(first.barColor());
84 bossBar.setStyle(first.barStyle());
85 bossBar.setProgress(first.clampedProgress());
86 }
87 }
88
91 public void addPlayer(Player... players){
92 if (players == null) return;
93 for (var p : players) {
94 if (p != null) addPlayer(p);
95 }
96 }
97
103 public void addPlayer(Player player) {
104 if (player == null) throw new IllegalArgumentException("Player cannot be null.");
105 var id = player.getUniqueId();
106 if (viewers.contains(id)) return;
107 if (new BossBarPlayerAddedEvent(this, player).isCancelled()) return;
108 ensureBossBarInitialized();
109 bossBar.addPlayer(player);
110 viewers.add(id);
111 }
112
118 public void removePlayer(Player player){
119 if (player == null) throw new IllegalArgumentException("Player cannot be null.");
120 var id = player.getUniqueId();
121 if (!viewers.contains(id)) return;
122 new BossBarPlayerRemovedEvent(this, player);
123 if (bossBar != null) bossBar.removePlayer(player);
124 viewers.remove(id);
125 }
126
130 public void removeAllPlayers(){
131 if (viewers.isEmpty()) return;
132 // Create a copy to avoid ConcurrentModificationException
133 List<UUID> copy = new ArrayList<>(viewers);
134 for (var uuid : copy){
135 var player = Bukkit.getPlayer(uuid);
136 if (player != null) removePlayer(player);
137 }
138 }
139
143 public void displayNextFrame(){
144 if (frames == null || frames.isEmpty() || viewers.isEmpty() || bossBarPaused) return;
145 ensureBossBarInitialized();
146
147 var frame = frames.get(currentFrameIndex);
148 for (var uuid : viewers){
149 var player = Bukkit.getPlayer(uuid);
150 if (player == null) continue;
151 frame.DisplayBarData(bossBar, player);
152 }
153
154 new BossBarFrameAdvancedEvent(this, currentFrameIndex);
155 currentFrameIndex = (currentFrameIndex + 1) % frames.size();
156 }
157
159 public void pause(){
160 if (!bossBarPaused){
161 bossBarPaused = true;
162 new BossBarPausedEvent(this);
163 }
164 }
165
167 public void play(){
168 if (bossBarPaused){
169 bossBarPaused = false;
170 new BossBarStartedEvent(this);
171 }
172 }
173
179 bossBarPaused = true;
180 new BossBarStoppedEvent(this);
182 return DreamCore.DreamBossBars.remove(getClassID());
183 }
184
188 private void ensureBossBarInitialized() {
189 if (bossBar != null) return;
190 if (frames == null || frames.isEmpty()) {
191 bossBar = Bukkit.createBossBar("", org.bukkit.boss.BarColor.WHITE, org.bukkit.boss.BarStyle.SOLID, barFlags);
192 return;
193 }
194 var first = frames.get(0);
195 bossBar = Bukkit.createBossBar(first.safeTitle(null), first.barColor(), first.barStyle(), barFlags);
196 bossBar.setProgress(first.clampedProgress());
197 }
198
202 public static final class Builder {
203 private final List<DreamBossBarData> frames = new ArrayList<>();
204 private final List<Player> players = new ArrayList<>();
205
213 public Builder dreamfireBossBarData(DreamBossBarData barData, int numberOfFrames) {
214 if (barData == null) throw new IllegalArgumentException("Bar data cannot be null.");
215 if (numberOfFrames <= 0) throw new IllegalArgumentException("Number of frames must be > 0.");
216 for (int i = 0; i < numberOfFrames; i++) frames.add(barData);
217 return this;
218 }
219
223 public Builder players(Player... toAdd) {
224 if (toAdd == null) return this;
225 for (var p : toAdd) if (p != null) players.add(p);
226 return this;
227 }
228
239 public DreamBossBar build(BarFlag... barFlags) {
240 if (frames.isEmpty()) throw new IllegalArgumentException("Boss bar frames must not be empty.");
241 var dbb = new DreamBossBar();
242 dbb.frames = new ArrayList<>(frames);
243 dbb.barFlags = (barFlags == null ? new BarFlag[0] : barFlags.clone());
244 dbb.resetBossBar();
245 players.forEach(dbb::addPlayer);
246 return DreamCore.DreamBossBars.put(dbb.getClassID(), dbb);
247 }
248 }
249}
Fired after a DreamBossBar applies a frame to its viewers.
Builder players(Player... toAdd)
Adds players to be attached at build time.
Builder dreamfireBossBarData(DreamBossBarData barData, int numberOfFrames)
Adds a frame repeated numberOfFrames times.
DreamBossBar build(BarFlag... barFlags)
Builds (or reuses) a DreamBossBar and registers it with the core.
Animated boss bar with viewer management and frame sequencing.
void displayNextFrame()
Advances to the next frame and updates the bar for all viewers.
void addPlayer(Player... players)
Adds one or more players to the boss bar.
void pause()
Pauses the animation (no frame progression).
void addPlayer(Player player)
Adds a single player to the boss bar.
void play()
Resumes the animation (frame progression continues).
boolean isPlayer(Player player)
Checks if the player currently has this boss bar.
void removePlayer(Player player)
Removes a player from the boss bar.
void removeAllPlayers()
Removes all players from the boss bar.
void resetBossBar()
Resets the bar back to frame 0 and reinitializes the underlying BossBar.
DreamBossBar stop()
Stops the boss bar, removes viewers, and unregisters from the core registry.
static final LinkedHashMap< UUID, DreamBossBar > DreamBossBars
record DreamBossBarData(BarColor barColor, BarStyle barStyle, double barProgress, Function< Player, String > messageProvider)
Immutable data for a single boss bar frame.