DREAMFIRE Docs ← Back to site
Loading...
Searching...
No Matches
DreamScoreboard.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.DreamScoreboard;
25
26import com.dreamfirestudios.dreamcore.DreamCore;
27import com.dreamfirestudios.dreamcore.DreamJava.DreamClassID;
28import lombok.Getter;
29import org.bukkit.Bukkit;
30import org.bukkit.entity.Player;
31import org.bukkit.scoreboard.DisplaySlot;
32import org.bukkit.scoreboard.Objective;
33import org.bukkit.scoreboard.Scoreboard;
34
35import java.util.ArrayList;
36import java.util.Collections;
37import java.util.List;
38
64public class DreamScoreboard extends DreamClassID {
65 private Scoreboard scoreboard;
66 private List<DreamScoreboardLines> frames = new ArrayList<>();
67 private int frameIndex = 0;
68
70 @Getter private final List<Player> viewers = new ArrayList<>();
72 @Getter private boolean paused = true;
73 private boolean sidebarInitialized = false;
74
80 public boolean isPlayerViewing(Player player) {
81 return player != null && viewers.contains(player);
82 }
83
92 public void addPlayer(Player player){
93 if (player == null || isPlayerViewing(player)) return;
94
95 // fire cancellable event and honor it
97 if (event.isCancelled()) return;
98
99 player.setScoreboard(scoreboard);
100 viewers.add(player);
101 }
102
111 public void removePlayer(Player player) {
112 if (player == null || !isPlayerViewing(player)) return;
113
115 if (event.isCancelled()) return;
116
117 if (Bukkit.getScoreboardManager() != null) {
118 player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
119 }
120 viewers.remove(player);
121 }
122
126 public void clearViewers() {
127 // copy to avoid CME
128 for (Player p : new ArrayList<>(viewers)) removePlayer(p);
129 }
130
135 public void displayNextFrame() {
136 if (frames.isEmpty() || viewers.isEmpty() || paused) return;
137
138 ensureSidebarCreated();
139
140 final DreamScoreboardLines current = frames.get(frameIndex);
141 current.UpdateLine(scoreboard);
142
143 frameIndex = (frameIndex + 1) % frames.size();
144 }
145
150 public void setPaused(boolean paused) {
151 this.paused = paused;
152 }
153
157 private void ensureSidebarCreated() {
158 if (sidebarInitialized) return;
159
160 // create a stable objective id; unique per-board
161 final String objectiveId = "sb_" + getClassID().toString().replace("-", "").substring(0, 12);
162 Objective existing = scoreboard.getObjective(DisplaySlot.SIDEBAR);
163 if (existing == null) {
164 // use the first frame to create teams/entries
165 frames.get(0).CreateLine(scoreboard, objectiveId);
166 }
167 sidebarInitialized = true;
168 }
169
170 // -------- builder --------
171
177
181 public static class PulseScoreboardBuilder {
182 private final List<Player> initialPlayers = new ArrayList<>();
183 private final List<DreamScoreboardLines> frames = new ArrayList<>();
184 private boolean startPaused = true;
185
199 if (frame == null || repeatFrames <= 0)
200 throw new IllegalArgumentException("frame cannot be null and repeatFrames must be > 0");
201 for (int i = 0; i < repeatFrames; i++) frames.add(frame);
202 return this;
203 }
204
210 public PulseScoreboardBuilder addPlayer(Player... players){
211 if (players != null) Collections.addAll(initialPlayers, players);
212 return this;
213 }
214
220 public PulseScoreboardBuilder paused(boolean paused) {
221 this.startPaused = paused;
222 return this;
223 }
224
239 public DreamScoreboard create(boolean replaceExisting){
240 DreamScoreboard board = new DreamScoreboard();
241 // create backing board
242 if (Bukkit.getScoreboardManager() == null)
243 throw new IllegalStateException("ScoreboardManager is not ready");
244 board.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
245 board.frames = new ArrayList<>(frames);
246 board.paused = startPaused;
247
248 // fire created event
249 new ScoreboardCreatedEvent(board);
250
251 // attach viewers
252 initialPlayers.forEach(board::addPlayer);
253
254 // register in core (if you keep a registry)
255 return DreamCore.DreamScoreboards.put(board.getClassID(), board);
256 }
257 }
258}
static final LinkedHashMap< UUID, DreamScoreboard > DreamScoreboards
Represents a single “frame” of a sidebar scoreboard: a title plus a set of numbered lines.
void UpdateLine(Scoreboard scoreboard)
Back-compat. Use updateSidebar(Scoreboard).
Builder for assembling a scoreboard with frames and initial viewers.
PulseScoreboardBuilder addLineHolder(DreamScoreboardLines frame, int repeatFrames)
Adds a frame multiple times to extend its on-screen duration.
PulseScoreboardBuilder addPlayer(Player... players)
Adds one or more players as initial viewers.
PulseScoreboardBuilder paused(boolean paused)
Sets the initial paused state.
DreamScoreboard create(boolean replaceExisting)
Builds the scoreboard, fires ScoreboardCreatedEvent, and adds initial viewers.
Manages an animated sidebar scoreboard composed of multiple frames.
void clearViewers()
Removes all viewers from this scoreboard.
void removePlayer(Player player)
Removes a player from viewing this scoreboard.
static PulseScoreboardBuilder builder()
Creates a builder for constructing a DreamScoreboard.
void displayNextFrame()
Advances the animated scoreboard by one frame.
void addPlayer(Player player)
Adds a player as a viewer of this scoreboard.
boolean isPlayerViewing(Player player)
Checks whether a player is currently viewing this scoreboard.
void setPaused(boolean paused)
Sets the paused state for animation.
Fired when a DreamScoreboard is created via the builder.
Fired before a player is added as a viewer of a DreamScoreboard.
Fired before a player is removed from viewing a DreamScoreboard.