├── .github\FUNDING.yml
├── .github\stale.yml
├── .settings
└── org.eclipse.jdt.core.prefs
├── .travis.yml
├── LICENSE
├── pom.xml
├── renovate.json
├── resources
└── plugin.yml
├── settings.xml
└── src
└── org
└── inventivetalent
└── bossbar
├── BossBar.java
├── BossBarAPI.java
├── BossBarPlugin.java
├── BossBarTimer.java
├── EntityBossBar.java
├── PacketBossBar.java
└── reflection
├── AccessUtil.java
├── ClassBuilder.java
├── MathUtil.java
├── NMSClass.java
├── NMUClass.java
└── Reflection.java
/.github\FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: InventivetalentDev
2 | patreon: inventivetalent
3 | custom: ["https://www.paypal.me/inventivetalent", "https://donation.inventivetalent.org"]
4 |
--------------------------------------------------------------------------------
/.github\stale.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InventivetalentDev/BossBarAPI/adc132a0cad8fb89b26893b139a2926c0b52ce3c/.github\stale.yml
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
4 | org.eclipse.jdt.core.compiler.compliance=1.7
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.7
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk8
4 |
5 | script: "mvn deploy --settings settings.xml"
6 | env:
7 | global:
8 | - secure: "FBEvL2TOKKQTWWkGf6yyW049I4F9U3EPbYGavPZY6YxuRHlZEP9livGC2YjFgZrNqdw/iPXaRS9i7j7Gi/Y0BdWYljtAL2RFAP7XqUo2D6VgtLeopShNu3K8KUQxQCwP+ESxgfNoEKXrEd1CGXPhjHT7dr0JquiySgdg+rAs9YVVs7QjrcLGXBB4I9h1vuzB/dxFbaWb16/tFdBJU3WGDoiQsDFfU7YZ2EnBDDJRTSgAw5SpeApE0XQgH+pFuj0vffoUftjqiVv8YJgCgDdIxeie2zrzWA9vPjnagH7kM9/0yS8IrH13/63Qwx4vOYGi9B8NfRpy3Qh8j/vojuGl0qOYOMh016AG+I6YacFemIC3WTVRH9XXq7WTdIoABa5Q3VQadlakuGusF2ydQjI49iHTpHieycDv0DMWBJFZfMXnHW4TXZENQbcVc43LFSx93UoEft7vi3phhZbp64nR79bw8oth/wJPFwND+0LayOqmWZ3i43YvI990aRBkFcJJaaKBL/sEMTn4IN9DBaqkdXNOOR4sP8TTTHBkjI7GOFOIOO/tpWTNeZbCD59YIjv2AIZ068CE9suWO94LvjHEwENuH+gDwUUL8Ogieh4/CmvUb5NVOMBkAIfr8KRP2F0lI0Yl2BuYmo15eWhts3X0GBvX5uGcKVR5L5PjHFwqLHI="
9 | - secure: "U1UDF/PR8lSfhAo6iQtmSdZ0ZDdQ59nNyT3GvbPFmiHNFyVu5WQgj7SzBu9PhtQjxH0bixIeoBnkM6LI8yTkQd2U9bHBXz0nwGaMouke+WXBirIXaYFUI2KvQBL5lqSjYBu/DlgXWqkyyRE/+idWoBPxXuBCMOwrXmh+RwWQGzIIsW8k4L1DssNIBIhz9Y66nIKGhVMcy7leJMvaEdsSRanlKf5gNSoM0AVccfE2MycSusJr+JcIeAF+zRkW0z2s8Gfx55II4bcTsef03mOofZD2LGX4w6ZX4AqGZg6q0owZfL5mXCTLsHzKA1El2wiSDo67YIv9xUVg1B41LnSel5G4d3zKlJFwkHp+3zWqJd++J5IsUzfOVRgc1PImFIfYRCOhAhmfKosAO1huSRrzPCDNICvHOuhOP7ssIqVDv3QWK3ezxYDjX09KA1FSm8uzaQdxBFnBrGITM2bK5nvEmvdgd2huwrA7gjtkvOvOHI1GaglLbBPH7dC+7jhGPY8WooWDNA/wQ8+C90mlOigCyxki9NOhBU2BcWUOhoO6M68YAlQX0wrJ4SQqZvIE8PSoO3V2ZdOd0uBFdcpX+u/8toH8b0RvB8mh9a+X+me+QOza3X7e/FiVnXCRCd46ShkTmb5pzdpy3QQtsIl+4ZAZZI6K7+qsDIsXWImMNn2m4og="
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Haylee Schäfer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 | 4.0.0
31 | org.inventivetalent
32 | bossbarapi
33 | 2.4.3-SNAPSHOT
34 | BossBarAPI
35 |
36 | BossBarAPI_v${project.version}
37 | src
38 |
39 |
40 | src
41 |
42 | **/*.java
43 |
44 |
45 |
46 | resources
47 | true
48 |
49 | plugin.yml
50 | config.yml
51 |
52 |
53 |
54 |
55 |
56 | maven-compiler-plugin
57 | 3.3
58 |
59 | 1.7
60 | 1.7
61 |
62 |
63 |
64 | org.apache.maven.plugins
65 | maven-shade-plugin
66 | 2.4
67 |
68 |
69 | package
70 |
71 | shade
72 |
73 |
74 |
75 |
76 | org.inventivetalent:bossbarapi**
77 | org.inventivetalent:reflectionhelper**
78 | org.inventivetalent:apimanager**
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | inventive-repo
91 | https://repo.inventivetalent.org/content/groups/public/
92 |
93 |
94 | md_5-repo
95 | http://repo.md-5.net/content/repositories/public/
96 |
97 |
98 | spigot-repo
99 | https://hub.spigotmc.org/nexus/content/groups/public/
100 |
101 |
102 | techcable-repo
103 | https://repo.techcable.net/content/groups/public/
104 |
105 |
106 |
107 |
108 | org.spigotmc
109 | spigot-api
110 | 1.12.2-R0.1-SNAPSHOT
111 | provided
112 |
113 |
114 | org.bukkit
115 | bukkit
116 | 1.12.2-R0.1-SNAPSHOT
117 |
118 |
119 | org.inventivetalent
120 | reflectionhelper
121 | 1.14.3-SNAPSHOT
122 |
123 |
124 | org.inventivetalent
125 | apimanager
126 | 1.0.3-SNAPSHOT
127 |
128 |
129 |
130 |
131 |
132 | sonatype-nexus-releases
133 | https://repo.inventivetalent.org/content/repositories/releases/
134 |
135 |
136 | sonatype-nexus-snapshots
137 | https://repo.inventivetalent.org/content/repositories/snapshots/
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ],
5 | "maven": {
6 | "enabled": true
7 | },
8 | "ignoreUnstable": false,
9 | "hostRules": [{
10 | "hostType": "maven",
11 | "endpoint": "https://repo.inventivetalent.org/content/groups/public/"
12 | }]
13 | }
14 |
--------------------------------------------------------------------------------
/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: BossBarAPI
2 | main: org.inventivetalent.bossbar.BossBarPlugin
3 | author: inventivetalent
4 | version: ${project.version}
5 |
6 | loadbefore: [BarAPI]
--------------------------------------------------------------------------------
/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | sonatype-nexus-releases
5 | ${env.CI_DEPLOY_USERNAME}
6 | ${env.CI_DEPLOY_PASSWORD}
7 |
8 |
9 | sonatype-nexus-snapshots
10 | ${env.CI_DEPLOY_USERNAME}
11 | ${env.CI_DEPLOY_PASSWORD}
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/BossBar.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar;
2 |
3 | import org.bukkit.Location;
4 | import org.bukkit.entity.Player;
5 |
6 | import java.util.Collection;
7 |
8 | public interface BossBar {
9 |
10 | /**
11 | * @return The players which can see the BossBar
12 | */
13 | Collection extends Player> getPlayers();
14 |
15 | /**
16 | * Add a player to this BossBar
17 | *
18 | * @param player {@link Player} to add
19 | */
20 | void addPlayer(Player player);
21 |
22 | /**
23 | * Remove a player from this BossBar
24 | *
25 | * @param player {@link Player} to remove
26 | */
27 | void removePlayer(Player player);
28 |
29 | /**
30 | * @return the {@link org.inventivetalent.bossbar.BossBarAPI.Color}
31 | */
32 | BossBarAPI.Color getColor();
33 |
34 | /**
35 | * @param color the new {@link org.inventivetalent.bossbar.BossBarAPI.Color}
36 | */
37 | void setColor(BossBarAPI.Color color);
38 |
39 | /**
40 | * @return the {@link org.inventivetalent.bossbar.BossBarAPI.Style}
41 | */
42 | BossBarAPI.Style getStyle();
43 |
44 | /**
45 | * @param style the new {@link org.inventivetalent.bossbar.BossBarAPI.Style}
46 | */
47 | void setStyle(BossBarAPI.Style style);
48 |
49 | /**
50 | * Modify a property
51 | *
52 | * @param property {@link org.inventivetalent.bossbar.BossBarAPI.Property}
53 | * @param flag whether to enable the property
54 | */
55 | void setProperty(BossBarAPI.Property property, boolean flag);
56 |
57 | /**
58 | * @return the message
59 | */
60 | String getMessage();
61 |
62 | /**
63 | * @param flag whether the BossBar is visible
64 | */
65 | void setVisible(boolean flag);
66 |
67 | /**
68 | * @return whether the BossBar is visible
69 | */
70 | boolean isVisible();
71 |
72 | /**
73 | * @return the progress (0.0 - 1.0)
74 | */
75 | float getProgress();
76 |
77 | /**
78 | * @param progress the new progress (0.0 - 1.0)
79 | */
80 | void setProgress(float progress);
81 |
82 | @Deprecated
83 | float getMaxHealth();
84 |
85 | @Deprecated
86 | void setHealth(float percentage);
87 |
88 | @Deprecated
89 | float getHealth();
90 |
91 | @Deprecated
92 | void setMessage(String message);
93 |
94 | @Deprecated
95 | Player getReceiver();
96 |
97 | @Deprecated
98 | Location getLocation();
99 |
100 | @Deprecated
101 | void updateMovement();
102 | }
103 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/BossBarAPI.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar;
2 |
3 | import net.md_5.bungee.api.chat.BaseComponent;
4 | import net.md_5.bungee.api.chat.TextComponent;
5 | import org.bukkit.Bukkit;
6 | import org.bukkit.Location;
7 | import org.bukkit.entity.Player;
8 | import org.bukkit.event.EventHandler;
9 | import org.bukkit.event.EventPriority;
10 | import org.bukkit.event.Listener;
11 | import org.bukkit.event.player.*;
12 | import org.bukkit.event.server.PluginEnableEvent;
13 | import org.bukkit.plugin.Plugin;
14 | import org.bukkit.scheduler.BukkitRunnable;
15 | import org.inventivetalent.apihelper.API;
16 | import org.inventivetalent.apihelper.APIManager;
17 | import org.inventivetalent.bossbar.reflection.Reflection;
18 | import org.inventivetalent.reflection.minecraft.Minecraft;
19 |
20 | import java.lang.reflect.Method;
21 | import java.util.*;
22 | import java.util.concurrent.ConcurrentHashMap;
23 | import java.util.logging.Logger;
24 |
25 | public class BossBarAPI implements API, Listener {
26 |
27 | protected static final Map> barMap = new ConcurrentHashMap<>();
28 |
29 | public static boolean is1_9 = Minecraft.VERSION.newerThan(Minecraft.Version.v1_9_R1);
30 |
31 | public enum Color {
32 | PINK,
33 | BLUE,
34 | RED,
35 | GREEN,
36 | YELLOW,
37 | PURPLE,
38 | WHITE;
39 | }
40 |
41 | public enum Style {
42 | PROGRESS,
43 | NOTCHED_6,
44 | NOTCHED_10,
45 | NOTCHED_12,
46 | NOTCHED_20;
47 | }
48 |
49 | public enum Property {
50 | DARKEN_SKY,
51 | PLAY_MUSIC,
52 | //This seems to be the only property implemented client-side currently
53 | CREATE_FOG;
54 | }
55 |
56 | /**
57 | * Not compatible with 1.8!
58 | *
59 | * @param players Receivers of the BossBar
60 | * @param message Message of the BossBar (JSON)
61 | * @param color {@link org.inventivetalent.bossbar.BossBarAPI.Color}
62 | * @param style {@link org.inventivetalent.bossbar.BossBarAPI.Style}
63 | * @param progress progress (0.0 - 1.0)
64 | * @param properties {@link org.inventivetalent.bossbar.BossBarAPI.Property}
65 | * @return the new {@link BossBar} instance
66 | */
67 | public static BossBar addBar(Collection players, String message, Color color, Style style, float progress, Property... properties) {
68 | validate1_9();
69 | BossBar bossBar = new PacketBossBar(message, color, style, progress, properties);
70 | for (Player player : players) {
71 | addBarForPlayer(player, bossBar);
72 | }
73 | return bossBar;
74 | }
75 |
76 | /**
77 | * Not compatible with 1.8!
78 | *
79 | * @param players Receivers of the BossBar
80 | * @param component displayed message
81 | * @param color {@link org.inventivetalent.bossbar.BossBarAPI.Color}
82 | * @param style {@link org.inventivetalent.bossbar.BossBarAPI.Style}
83 | * @param progress progress (0.0 - 1.0)
84 | * @param properties {@link org.inventivetalent.bossbar.BossBarAPI.Property}
85 | * @return the new {@link BossBar} instance
86 | */
87 | public static BossBar addBar(Collection players, BaseComponent component, Color color, Style style, float progress, Property... properties) {
88 | validate1_9();
89 | BossBar bossBar = new PacketBossBar(component, color, style, progress, properties);
90 | for (Player player : players) {
91 | addBarForPlayer(player, bossBar);
92 | }
93 | return bossBar;
94 | }
95 |
96 | /**
97 | * Not compatible with 1.8!
98 | *
99 | * @param players Receivers of the BossBar
100 | * @param component displayed message
101 | * @param color {@link org.inventivetalent.bossbar.BossBarAPI.Color}
102 | * @param style {@link org.inventivetalent.bossbar.BossBarAPI.Style}
103 | * @param progress progress (0.0 - 1.0)
104 | * @param timeout time until the bar disappears
105 | * @param interval interval of the "countdown"
106 | * @param properties {@link org.inventivetalent.bossbar.BossBarAPI.Property}
107 | * @return the new {@link BossBar} instance
108 | */
109 | public static BossBar addBar(Collection players, BaseComponent component, Color color, Style style, float progress, int timeout, long interval, Property... properties) {
110 | validate1_9();
111 | final BossBar bossBar = addBar(players, component, color, style, progress, properties);
112 | new BossBarTimer((PacketBossBar) bossBar, progress, timeout).runTaskTimer(BossBarPlugin.instance, interval, interval);
113 | return bossBar;
114 | }
115 |
116 | /**
117 | * Compatible with 1.8
118 | *
119 | * @param player Receiver of the BossBar
120 | * @param component displayed message
121 | * @param color {@link org.inventivetalent.bossbar.BossBarAPI.Color} (1.9-only)
122 | * @param style {@link org.inventivetalent.bossbar.BossBarAPI.Style} (1.9-only)
123 | * @param progress progress (0.0 - 1.0)
124 | * @param properties {@link org.inventivetalent.bossbar.BossBarAPI.Property} (1.9-only)
125 | * @return the new {@link BossBar} instance
126 | * @see #setMessage(Player, String, float)
127 | */
128 | public static BossBar addBar(Player player, BaseComponent component, Color color, Style style, float progress, Property... properties) {
129 | if (is1_9) {
130 | BossBar bossBar = new PacketBossBar(component, color, style, progress, properties);
131 | addBarForPlayer(player, bossBar);
132 | return bossBar;
133 | } else {
134 | setMessage(player, component.toLegacyText(), progress * 100);
135 | return getBossBar(player);
136 | }
137 | }
138 |
139 | /**
140 | * Compatible with 1.8
141 | *
142 | * @param player Receiver of the BossBar
143 | * @param component displayed message
144 | * @param color {@link org.inventivetalent.bossbar.BossBarAPI.Color} (1.9-only)
145 | * @param style {@link org.inventivetalent.bossbar.BossBarAPI.Style} (1.9-only)
146 | * @param progress progress (0.0-1.0)
147 | * @param timeout time until the bar disappears
148 | * @param interval interval of the "countdown"
149 | * @param properties {@link org.inventivetalent.bossbar.BossBarAPI.Property} (1.9-only)
150 | * @return the new {@link BossBar} instance
151 | */
152 | public static BossBar addBar(Player player, BaseComponent component, Color color, Style style, float progress, int timeout, long interval, Property... properties) {
153 | if (is1_9) {
154 | final BossBar bossBar = addBar(player, component, color, style, progress, properties);
155 | new BossBarTimer((PacketBossBar) bossBar, progress, timeout).runTaskTimer(BossBarPlugin.instance, interval, interval);
156 | return bossBar;
157 | } else {
158 | setMessage(player, component.toLegacyText(), progress * 100, timeout);
159 | return getBossBar(player);
160 | }
161 | }
162 |
163 | /**
164 | * Not compatible with 1.8! Adds a BossBar without displaying it to a player
165 | *
166 | * @param component displayed message
167 | * @param color {@link org.inventivetalent.bossbar.BossBarAPI.Color}
168 | * @param style {@link org.inventivetalent.bossbar.BossBarAPI.Style}
169 | * @param progress progress (0.0 - 1.0)
170 | * @param properties {@link org.inventivetalent.bossbar.BossBarAPI.Property}
171 | * @return the new {@link BossBar} instance
172 | */
173 | public static BossBar addBar(BaseComponent component, Color color, Style style, float progress, Property... properties) {
174 | validate1_9();
175 | return new PacketBossBar(component, color, style, progress, properties);
176 | }
177 |
178 | public static Collection getBossBars(Player player) {
179 | if (!barMap.containsKey(player.getUniqueId())) { return new ArrayList<>(); }
180 | return new ArrayList<>(barMap.get(player.getUniqueId()));
181 | }
182 |
183 | protected static void addBarForPlayer(Player player, BossBar bossBar) {
184 | bossBar.addPlayer(player);
185 |
186 | Collection collection = barMap.get(player.getUniqueId());
187 | if (collection == null) { collection = new ArrayList<>(); }
188 | collection.add(bossBar);
189 | barMap.put(player.getUniqueId(), collection);
190 | }
191 |
192 | protected static void removeBarForPlayer(Player player, BossBar bossBar) {
193 | bossBar.removePlayer(player);
194 |
195 | Collection collection = barMap.get(player.getUniqueId());
196 | if (collection != null) {
197 | collection.remove(bossBar);
198 | if (!collection.isEmpty()) {
199 | barMap.put(player.getUniqueId(), collection);
200 | } else {
201 | barMap.remove(player.getUniqueId());
202 | }
203 | }
204 | }
205 |
206 | public static void removeAllBars(Player player) {
207 | for (BossBar bossBar : getBossBars(player)) {
208 | removeBarForPlayer(player, bossBar);
209 | }
210 | }
211 |
212 | //// Deprecated (< 1.9) methods
213 |
214 | /**
215 | * Sets the boss-bar message for the specified player
216 | *
217 | * @param player Receiver of the message
218 | * @param message Message content
219 | */
220 | @Deprecated
221 | public static void setMessage(Player player, String message) {
222 | setMessage(player, message, 100);
223 | }
224 |
225 | /**
226 | * Sets the boss-bar message for the specified player
227 | *
228 | * @param player Receiver of the message
229 | * @param message Message content
230 | * @param percentage Health percentage
231 | */
232 | @Deprecated
233 | public static void setMessage(Player player, String message, float percentage) {
234 | setMessage(player, message, percentage, 0);
235 | }
236 |
237 | /**
238 | * Sets the boss-bar message for the specified player
239 | *
240 | * @param player Receiver of the message
241 | * @param message Message content
242 | * @param percentage Health percentage
243 | * @param timeout Amount of seconds until the bar is removed
244 | */
245 | @Deprecated
246 | public static void setMessage(Player player, String message, float percentage, int timeout) {
247 | setMessage(player, message, percentage, timeout, 100);
248 | }
249 |
250 | /**
251 | * Sets the boss-bar message for the specified player
252 | *
253 | * @param player Receiver of the message
254 | * @param message Message content
255 | * @param percentage Health percentage
256 | * @param timeout Amount of seconds until the bar is removed
257 | * @param minHealth minimum health (100 by default)
258 | */
259 | @Deprecated
260 | public static void setMessage(Player player, String message, float percentage, int timeout, float minHealth) {
261 | if (is1_9) {
262 | removeAllBars(player);
263 | addBar(player, new TextComponent(message), Color.PURPLE, Style.PROGRESS, percentage / 100);
264 | } else {
265 | if (!barMap.containsKey(player.getUniqueId())) {
266 | ArrayList list = new ArrayList<>();
267 | list.add(new EntityBossBar(player, message, percentage, timeout, minHealth));
268 | barMap.put(player.getUniqueId(), list);
269 | }
270 | BossBar bar = ((List) barMap.get(player.getUniqueId())).get(0);
271 | if (!bar.getMessage().equals(message)) {
272 | bar.setMessage(message);
273 | }
274 | float newHealth = percentage / 100F * bar.getMaxHealth();
275 | if (bar.getHealth() != newHealth) {
276 | bar.setHealth(percentage);
277 | }
278 | if (!bar.isVisible()) {
279 | bar.setVisible(true);
280 | }
281 | }
282 | }
283 |
284 | /**
285 | * @param player {@link Player}
286 | * @return The current message of the player's bar
287 | */
288 | @Deprecated
289 | public static String getMessage(Player player) {
290 | BossBar bar = getBossBar(player);
291 | if (bar == null) { return null; }
292 | return bar.getMessage();
293 | }
294 |
295 | /**
296 | * @param player {@link Player} to check
297 | * @return true
if the player has a bar
298 | */
299 | @Deprecated
300 | public static boolean hasBar( Player player) {
301 | return barMap.containsKey(player.getUniqueId());
302 | }
303 |
304 | /**
305 | * Removes the bar of a player
306 | *
307 | * @param player Player to remove
308 | */
309 | @Deprecated
310 | public static void removeBar( Player player) {
311 | BossBar bar = getBossBar(player);
312 | if (bar != null) { bar.setVisible(false); }
313 | removeAllBars(player);
314 | }
315 |
316 | /**
317 | * Changes the displayed health of the bar
318 | *
319 | * @param player {@link Player}
320 | * @param percentage Health percentage
321 | */
322 | @Deprecated
323 | public static void setHealth(Player player, float percentage) {
324 | BossBar bar = getBossBar(player);
325 | if (bar == null) { return; }
326 | bar.setHealth(percentage);
327 | }
328 |
329 | /**
330 | * @param player {@link Player}
331 | * @return The health of the player's bar
332 | */
333 | @Deprecated
334 | public static float getHealth(Player player) {
335 | BossBar bar = getBossBar(player);
336 | if (bar == null) { return -1; }
337 | return bar.getHealth();
338 | }
339 |
340 | /**
341 | * Get the bar for the specified player
342 | *
343 | * @param player {@link Player}
344 | * @return a {@link EntityBossBar} instance if the player has a bar, null
otherwise
345 | */
346 | @Deprecated
347 | public static BossBar getBossBar(Player player) {
348 | if (player == null) { return null; }
349 | List list = ((List) barMap.get(player.getUniqueId()));
350 |
351 | if (list != null && list.size() > 0) {
352 | return list.get(0);
353 | }
354 | return null;
355 | }
356 |
357 | /**
358 | * @return A {@link Collection} of all registered bars
359 | */
360 | @Deprecated
361 | public static Collection getBossBars() {
362 | List list = new ArrayList<>();
363 | for (Collection collection : barMap.values()) {
364 | list.add(((List) collection).get(0));
365 | }
366 | return list;
367 | }
368 |
369 | protected static void sendPacket(Player p, Object packet) {
370 | if (p == null || packet == null) { throw new IllegalArgumentException("player and packet cannot be null"); }
371 | try {
372 | Object handle = Reflection.getHandle(p);
373 | Object connection = Reflection.getField(handle.getClass(), "playerConnection").get(handle);
374 | Reflection.getMethod(connection.getClass(), "sendPacket", Reflection.getNMSClass("Packet")).invoke(connection, new Object[] { packet });
375 | } catch (Exception e) {
376 | }
377 | }
378 |
379 | static void validate1_9() {
380 | if (!is1_9) {
381 | throw new RuntimeException(new UnsupportedOperationException("This method is not compatible with versions < 1.9"));
382 | }
383 | }
384 |
385 | Logger logger = Logger.getLogger("BossBarAPI");
386 |
387 | @Override
388 | public void load() {
389 | }
390 |
391 | @Override
392 | public void init(Plugin plugin) {
393 | APIManager.registerEvents(this, this);
394 | BossBarPlugin.instance = APIManager.getAPIHost(this);
395 | for (Player player : Bukkit.getOnlinePlayers()) {
396 | BossBarAPI.removeAllBars(player);
397 | }
398 | }
399 |
400 | @Override
401 | public void disable(Plugin plugin) {
402 | }
403 |
404 | @EventHandler
405 | public void onPluginEnable(PluginEnableEvent e) {
406 | if ("BarAPI".equals(e.getPlugin().getName()) && Bukkit.getPluginManager().isPluginEnabled("BarAPI")) {
407 | try {
408 | Class> barAPI = Class.forName("me.confuser.barapi.BarAPI");
409 |
410 | Method method = barAPI.getDeclaredMethod("enabled");
411 | method.setAccessible(true);
412 | if ((boolean) method.invoke(null)) {
413 | logger.info("Successfully replaced BarAPI.");
414 | return;
415 | }
416 | } catch (Exception ex) {
417 | }
418 | logger.warning("Failed to replace BarAPI.");
419 | }
420 | }
421 |
422 | @EventHandler(priority = EventPriority.MONITOR)
423 | public void onQuit(PlayerQuitEvent e) {
424 | BossBarAPI.removeBar(e.getPlayer());
425 | }
426 |
427 | @EventHandler(priority = EventPriority.MONITOR)
428 | public void onKick(PlayerKickEvent e) {
429 | BossBarAPI.removeBar(e.getPlayer());
430 | }
431 |
432 | @EventHandler(priority = EventPriority.MONITOR)
433 | public void onTeleport(PlayerTeleportEvent e) {
434 | if (Minecraft.VERSION.olderThan(Minecraft.Version.v1_9_R1)) {
435 | this.handlePlayerTeleport(e.getPlayer(), e.getFrom(), e.getTo());
436 | }
437 | }
438 |
439 | @EventHandler(priority = EventPriority.MONITOR)
440 | public void onRespawn(PlayerRespawnEvent e) {
441 | if (Minecraft.VERSION.olderThan(Minecraft.Version.v1_9_R1)) {
442 | this.handlePlayerTeleport(e.getPlayer(), e.getPlayer().getLocation(), e.getRespawnLocation());
443 | }
444 | }
445 |
446 | protected void handlePlayerTeleport(Player player, Location from, Location to) {
447 | if (!BossBarAPI.hasBar(player)) { return; }
448 | final BossBar bar = BossBarAPI.getBossBar(player);
449 | bar.setVisible(false);
450 | new BukkitRunnable() {
451 |
452 | @Override
453 | public void run() {
454 | bar.setVisible(true);
455 | }
456 | }.runTaskLater(APIManager.getAPIHost(this), 2);
457 | }
458 |
459 | @EventHandler
460 | public void onMove(final PlayerMoveEvent e) {
461 | if (Minecraft.VERSION.olderThan(Minecraft.Version.v1_9_R1)) {
462 | final BossBar bar = BossBarAPI.getBossBar(e.getPlayer());
463 | if (bar != null) {
464 | new BukkitRunnable() {
465 |
466 | @SuppressWarnings("deprecation")
467 | @Override
468 | public void run() {
469 | if (!e.getPlayer().isOnline()) { return; }
470 | bar.updateMovement();
471 | }
472 | }.runTaskLater(APIManager.getAPIHost(this), 0);
473 | }
474 | }
475 | }
476 |
477 | public BossBarAPI() {
478 | }
479 |
480 | }
481 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/BossBarPlugin.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar;
2 |
3 | import org.bukkit.plugin.Plugin;
4 | import org.bukkit.plugin.java.JavaPlugin;
5 | import org.inventivetalent.apihelper.APIManager;
6 |
7 | public class BossBarPlugin extends JavaPlugin {
8 |
9 | protected static Plugin instance;
10 | BossBarAPI apiInstance = new BossBarAPI();
11 |
12 | @Override
13 | public void onLoad() {
14 | APIManager.registerAPI(apiInstance, this);
15 | }
16 |
17 | @Override
18 | public void onEnable() {
19 | instance = this;
20 |
21 | APIManager.initAPI(BossBarAPI.class);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/BossBarTimer.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar;
2 |
3 | import org.bukkit.entity.Player;
4 | import org.bukkit.scheduler.BukkitRunnable;
5 |
6 | public class BossBarTimer extends BukkitRunnable {
7 |
8 | private PacketBossBar bossBar;
9 | final float progressMinus;
10 |
11 | public BossBarTimer(PacketBossBar packetBossBar, float progress, int timeout) {
12 | this.bossBar = packetBossBar;
13 | this.progressMinus = progress / timeout;
14 | }
15 |
16 | @Override
17 | public void run() {
18 | float newProgress = bossBar.getProgress() - progressMinus;
19 | if (newProgress <= 0) {
20 | for (Player player : bossBar.getPlayers()) {
21 | bossBar.removePlayer(player);
22 | }
23 | } else {
24 | bossBar.setProgress(newProgress);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/EntityBossBar.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar;
2 |
3 | import org.bukkit.Location;
4 | import org.bukkit.World;
5 | import org.bukkit.entity.Player;
6 | import org.bukkit.scheduler.BukkitRunnable;
7 | import org.inventivetalent.bossbar.reflection.ClassBuilder;
8 | import org.inventivetalent.bossbar.reflection.NMSClass;
9 | import org.inventivetalent.reflection.minecraft.DataWatcher;
10 |
11 | import java.util.Collection;
12 | import java.util.Collections;
13 | import java.util.Random;
14 | import java.util.UUID;
15 |
16 | import static org.inventivetalent.reflection.minecraft.DataWatcher.V1_9.ValueType.*;
17 |
18 | public class EntityBossBar extends BukkitRunnable implements BossBar {
19 |
20 | protected static int ENTITY_DISTANCE = 32;
21 |
22 | protected final int ID;
23 | protected final UUID uuid;
24 |
25 | protected final Player receiver;
26 | protected String message;
27 | protected float health;
28 | protected float healthMinus;
29 | protected float minHealth = 1;
30 |
31 | protected Location location;
32 | protected World world;
33 | protected boolean visible = false;
34 | protected Object dataWatcher;
35 |
36 | @SuppressWarnings("deprecation")
37 | protected EntityBossBar(Player player, String message, float percentage, int timeout, float minHealth) {
38 | this.ID = new Random().nextInt();
39 | this.uuid = UUID.randomUUID();
40 |
41 | this.receiver = player;
42 | this.message = message;
43 | this.health = percentage / 100F * this.getMaxHealth();
44 | this.minHealth = minHealth;
45 | this.world = player.getWorld();
46 | this.location = this.makeLocation(player.getLocation());
47 |
48 | if (percentage <= minHealth) {
49 | BossBarAPI.removeBar(player);
50 | }
51 |
52 | if (timeout > 0) {
53 | this.healthMinus = this.getMaxHealth() / timeout;
54 | this.runTaskTimer(BossBarPlugin.instance, 20, 20);
55 | }
56 | }
57 |
58 | protected Location makeLocation(Location base) {
59 | return base.getDirection().multiply(ENTITY_DISTANCE).add(base.toVector()).toLocation(this.world);
60 | }
61 |
62 | @Override
63 | public Player getReceiver() {
64 | return receiver;
65 | }
66 |
67 | @Override
68 | public float getMaxHealth() {
69 | return 300;
70 | }
71 |
72 | @SuppressWarnings("deprecation")
73 | @Override
74 | public void setHealth(float percentage) {
75 | this.health = percentage / 100F * this.getMaxHealth();
76 | if (this.health <= this.minHealth) {
77 | BossBarAPI.removeBar(this.receiver);
78 | } else {
79 | this.sendMetadata();
80 | }
81 | }
82 |
83 | @Override
84 | public float getHealth() {
85 | return health;
86 | }
87 |
88 | @Override
89 | public void setMessage(String message) {
90 | this.message = message;
91 | if (this.isVisible()) {
92 | this.sendMetadata();
93 | }
94 | }
95 |
96 | @Override
97 | public Collection extends Player> getPlayers() {
98 | return Collections.singletonList(getReceiver());
99 | }
100 |
101 | @Override
102 | public void addPlayer(Player player) {
103 | }
104 |
105 | @Override
106 | public void removePlayer(Player player) {
107 | setVisible(false);
108 | }
109 |
110 | @Override
111 | public BossBarAPI.Color getColor() {
112 | return null;
113 | }
114 |
115 | @Override
116 | public void setColor(BossBarAPI.Color color) {
117 | }
118 |
119 | @Override
120 | public BossBarAPI.Style getStyle() {
121 | return null;
122 | }
123 |
124 | @Override
125 | public void setStyle(BossBarAPI.Style style) {
126 | }
127 |
128 | @Override
129 | public void setProperty(BossBarAPI.Property property, boolean flag) {
130 | }
131 |
132 | @Override
133 | public String getMessage() {
134 | return message;
135 | }
136 |
137 | @Override
138 | public Location getLocation() {
139 | return this.location;
140 | }
141 |
142 | @SuppressWarnings("deprecation")
143 | @Override
144 | public void run() {
145 | this.health -= this.healthMinus;
146 | if (this.health <= this.minHealth) {
147 | BossBarAPI.removeBar(this.receiver);
148 | } else {
149 | this.sendMetadata();
150 | }
151 | }
152 |
153 | @Override
154 | public void setVisible(boolean flag) {
155 | if (flag == this.visible) { return; }
156 | if (flag) {
157 | this.spawn();
158 | } else {
159 | this.destroy();
160 | }
161 | }
162 |
163 | @Override
164 | public boolean isVisible() {
165 | return this.visible;
166 | }
167 |
168 | @Override
169 | public void setProgress(float progress) {
170 | setHealth(progress * 100);
171 | }
172 |
173 | @Override
174 | public float getProgress() {
175 | return getHealth() / 100;
176 | }
177 |
178 | @Override
179 | public void updateMovement() {
180 | if (!this.visible) { return; }
181 | this.location = this.makeLocation(this.receiver.getLocation());
182 | try {
183 | Object packet = ClassBuilder.buildTeleportPacket(this.ID, this.getLocation(), false, false);
184 | BossBarAPI.sendPacket(this.receiver, packet);
185 | } catch (Exception e) {
186 | e.printStackTrace();
187 | }
188 | }
189 |
190 | protected void updateDataWatcher() {
191 | if (this.dataWatcher == null) {
192 | try {
193 | this.dataWatcher = DataWatcher.newDataWatcher(null);
194 | DataWatcher.setValue(this.dataWatcher, 17, ENTITY_WITHER_a, new Integer(0));
195 | DataWatcher.setValue(this.dataWatcher, 18, ENTITY_WIHER_b, new Integer(0));
196 | DataWatcher.setValue(this.dataWatcher, 19, ENTITY_WITHER_c, new Integer(0));
197 |
198 | DataWatcher.setValue(this.dataWatcher, 20, ENTITY_WITHER_bw, new Integer(1000));// Invulnerable time (1000 = very small)
199 | DataWatcher.setValue(this.dataWatcher, 0, ENTITY_FLAG, Byte.valueOf((byte) (0 | 1 << 5)));
200 | } catch (Exception e) {
201 | throw new RuntimeException(e);
202 | }
203 | }
204 | try {
205 | DataWatcher.setValue(this.dataWatcher, 6, ENTITY_LIVING_HEALTH, this.health);
206 |
207 | DataWatcher.setValue(this.dataWatcher, 10, ENTITY_NAME, this.message);
208 | DataWatcher.setValue(this.dataWatcher, 2, ENTITY_NAME, this.message);
209 |
210 | DataWatcher.setValue(this.dataWatcher, 11, ENTITY_NAME_VISIBLE, (byte) 1);
211 | DataWatcher.setValue(this.dataWatcher, 3, ENTITY_NAME_VISIBLE, (byte) 1);
212 | } catch (Exception e) {
213 | e.printStackTrace();
214 | }
215 | }
216 |
217 | protected void sendMetadata() {
218 | this.updateDataWatcher();
219 | try {
220 | Object metaPacket = ClassBuilder.buildNameMetadataPacket(this.ID, this.dataWatcher, 2, 3, this.message);
221 | BossBarAPI.sendPacket(this.receiver, metaPacket);
222 | } catch (Exception e) {
223 | e.printStackTrace();
224 | }
225 | }
226 |
227 | protected void spawn() {
228 | try {
229 | this.updateMovement();
230 | this.updateDataWatcher();
231 | Object packet = ClassBuilder.buildWitherSpawnPacket(this.ID, this.uuid, this.getLocation(), this.dataWatcher);
232 | BossBarAPI.sendPacket(this.receiver, packet);
233 | this.visible = true;
234 | this.sendMetadata();
235 | this.updateMovement();
236 | } catch (Exception e) {
237 | e.printStackTrace();
238 | }
239 | }
240 |
241 | protected void destroy() {
242 | try {
243 | this.cancel();
244 | } catch (IllegalStateException e) {
245 | }
246 | try {
247 | Object packet = NMSClass.PacketPlayOutEntityDestroy.getConstructor(int[].class).newInstance(new int[] { this.ID });
248 | BossBarAPI.sendPacket(this.receiver, packet);
249 | this.visible = false;
250 | } catch (Exception e) {
251 | e.printStackTrace();
252 | }
253 | }
254 |
255 | }
256 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/PacketBossBar.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar;
2 |
3 | import net.md_5.bungee.api.chat.BaseComponent;
4 | import net.md_5.bungee.chat.ComponentSerializer;
5 | import org.bukkit.Location;
6 | import org.bukkit.entity.Player;
7 | import org.inventivetalent.reflection.resolver.FieldResolver;
8 | import org.inventivetalent.reflection.resolver.MethodResolver;
9 | import org.inventivetalent.reflection.resolver.ResolverQuery;
10 | import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Collection;
14 | import java.util.UUID;
15 |
16 | public class PacketBossBar implements BossBar {
17 |
18 | static NMSClassResolver nmsClassResolver = new NMSClassResolver();
19 |
20 | static Class> PacketPlayOutBoss = nmsClassResolver.resolveSilent("PacketPlayOutBoss");
21 | static Class> PacketPlayOutBossAction = nmsClassResolver.resolveSilent("PacketPlayOutBoss$Action");
22 | static Class> ChatSerializer = nmsClassResolver.resolveSilent("ChatSerializer", "IChatBaseComponent$ChatSerializer");
23 | static Class> BossBattleBarColor = nmsClassResolver.resolveSilent("BossBattle$BarColor");
24 | static Class> BossBattleBarStyle = nmsClassResolver.resolveSilent("BossBattle$BarStyle");
25 |
26 | static FieldResolver PacketPlayOutBossFieldResolver = new FieldResolver(PacketPlayOutBoss);
27 |
28 | static MethodResolver ChatSerializerMethodResolver = new MethodResolver(ChatSerializer);
29 |
30 | private final UUID uuid;
31 | private Collection receivers = new ArrayList<>();
32 | private float progress;
33 | private String message;
34 | private BossBarAPI.Color color;
35 | private BossBarAPI.Style style;
36 | private boolean visible;
37 |
38 | private boolean darkenSky;
39 | private boolean playMusic;
40 | private boolean createFog;
41 |
42 | protected PacketBossBar(String message, BossBarAPI.Color color, BossBarAPI.Style style, float progress, BossBarAPI.Property... properties) {
43 | this.uuid = UUID.randomUUID();
44 |
45 | this.color = color != null ? color : BossBarAPI.Color.PURPLE;
46 | this.style = style != null ? style : BossBarAPI.Style.PROGRESS;
47 | setMessage(message);
48 | setProgress(progress);
49 |
50 | for (BossBarAPI.Property property : properties) {
51 | setProperty(property, true);
52 | }
53 | }
54 |
55 | protected PacketBossBar(BaseComponent message, BossBarAPI.Color color, BossBarAPI.Style style, float progress, BossBarAPI.Property... properties) {
56 | this(ComponentSerializer.toString(message), color, style, progress, properties);
57 | }
58 |
59 | @Override
60 | public Collection extends Player> getPlayers() {
61 | return new ArrayList<>(this.receivers);
62 | }
63 |
64 | @Override
65 | public void addPlayer(Player player) {
66 | if (!this.receivers.contains(player)) {
67 | this.receivers.add(player);
68 | sendPacket(0, player);
69 | BossBarAPI.addBarForPlayer(player, this);
70 | }
71 | }
72 |
73 | @Override
74 | public void removePlayer(Player player) {
75 | if (this.receivers.contains(player)) {
76 | this.receivers.remove(player);
77 | sendPacket(1, player);
78 | BossBarAPI.removeBarForPlayer(player, this);
79 | }
80 | }
81 |
82 | @Override
83 | public BossBarAPI.Color getColor() {
84 | return this.color;
85 | }
86 |
87 | @Override
88 | public void setColor(BossBarAPI.Color color) {
89 | if (color == null) { throw new IllegalArgumentException("color cannot be null"); }
90 | if (color != this.color) {
91 | this.color = color;
92 | sendPacket(4, null);
93 | }
94 | }
95 |
96 | @Override
97 | public BossBarAPI.Style getStyle() {
98 | return this.style;
99 | }
100 |
101 | @Override
102 | public void setStyle(BossBarAPI.Style style) {
103 | if (style == null) { throw new IllegalArgumentException("style cannot be null"); }
104 | if (style != this.style) {
105 | this.style = style;
106 | sendPacket(4, null);
107 | }
108 | }
109 |
110 | @Override
111 | public void setProperty(BossBarAPI.Property property, boolean flag) {
112 | switch (property) {
113 | case DARKEN_SKY:
114 | darkenSky = flag;
115 | break;
116 | case PLAY_MUSIC:
117 | playMusic = flag;
118 | break;
119 | case CREATE_FOG:
120 | createFog = flag;
121 | break;
122 | default:
123 | break;
124 | }
125 | sendPacket(5, null);
126 | }
127 |
128 | @Override
129 | public String getMessage() {
130 | return this.message;
131 | }
132 |
133 | @Override
134 | public void setMessage(String message) {
135 | if (message == null) { throw new IllegalArgumentException("message cannot be null"); }
136 | if (!message.startsWith("{") || !message.endsWith("}")) {
137 | throw new IllegalArgumentException("Invalid JSON");
138 | }
139 | if (!message.equals(this.message)) {
140 | this.message = message;
141 | sendPacket(3, null);
142 | }
143 | }
144 |
145 | @Override
146 | public float getProgress() {
147 | return progress;
148 | }
149 |
150 | @Override
151 | public void setProgress(float progress) {
152 | if (progress > 1) {
153 | progress = progress / 100F;
154 | }
155 | if (progress != this.progress) {
156 | this.progress = progress;
157 | sendPacket(2, null);
158 | }
159 | }
160 |
161 | @Override
162 | public boolean isVisible() {
163 | return this.visible;
164 | }
165 |
166 | @Override
167 | public void setVisible(boolean flag) {
168 | if (flag != this.visible) {
169 | this.visible = flag;
170 | sendPacket(flag ? 0 : 1, null);
171 | }
172 | }
173 |
174 | void sendPacket(int action, Player player) {
175 | try {
176 | Object packet = PacketPlayOutBoss.newInstance();
177 | PacketPlayOutBossFieldResolver.resolve("a").set(packet, this.uuid);
178 | PacketPlayOutBossFieldResolver.resolve("b").set(packet, PacketPlayOutBossAction.getEnumConstants()[action]);
179 | PacketPlayOutBossFieldResolver.resolve("c").set(packet, serialize(this.message));
180 | PacketPlayOutBossFieldResolver.resolve("d").set(packet, this.progress);
181 | PacketPlayOutBossFieldResolver.resolve("e").set(packet, BossBattleBarColor.getEnumConstants()[this.color.ordinal()]);
182 | PacketPlayOutBossFieldResolver.resolve("f").set(packet, BossBattleBarStyle.getEnumConstants()[this.style.ordinal()]);
183 | PacketPlayOutBossFieldResolver.resolve("g").set(packet, this.darkenSky);
184 | PacketPlayOutBossFieldResolver.resolve("h").set(packet, this.playMusic);
185 | PacketPlayOutBossFieldResolver.resolve("i").set(packet, this.createFog);
186 |
187 | if (player != null) {
188 | BossBarAPI.sendPacket(player, packet);
189 | } else {
190 | for (Player player1 : this.getPlayers()) {
191 | BossBarAPI.sendPacket(player1, packet);
192 | }
193 | }
194 | } catch (ReflectiveOperationException e) {
195 | throw new RuntimeException(e);
196 | }
197 | }
198 |
199 | //Deprecated methods
200 |
201 | @Override
202 | public float getMaxHealth() {
203 | return 100F;
204 | }
205 |
206 | @Override
207 | public void setHealth(float percentage) {
208 | setProgress(percentage / 100F);
209 | }
210 |
211 | @Override
212 | public float getHealth() {
213 | return getProgress() * 100F;
214 | }
215 |
216 | @Override
217 | public Player getReceiver() {
218 | return null;
219 | }
220 |
221 | @Override
222 | public Location getLocation() {
223 | return null;
224 | }
225 |
226 | @Override
227 | public void updateMovement() {
228 | }
229 |
230 | static Object serialize(String json) throws ReflectiveOperationException {
231 | return ChatSerializerMethodResolver.resolve(new ResolverQuery("a", String.class)).invoke(null, json);
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/reflection/AccessUtil.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar.reflection;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Method;
5 |
6 | public abstract class AccessUtil {
7 |
8 | /**
9 | * Set a specified Field accessible
10 | *
11 | * @param f Field set accessible
12 | */
13 | public static Field setAccessible(Field f) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
14 | f.setAccessible(true);
15 | Field modifiersField = Field.class.getDeclaredField("modifiers");
16 | modifiersField.setAccessible(true);
17 | modifiersField.setInt(f, f.getModifiers() & 0xFFFFFFEF);
18 | return f;
19 | }
20 |
21 | /**
22 | * Set a specified Method accessible
23 | *
24 | * @param m Method set accessible
25 | */
26 | public static Method setAccessible(Method m) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
27 | m.setAccessible(true);
28 | return m;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/reflection/ClassBuilder.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar.reflection;
2 |
3 | import org.bukkit.Location;
4 | import org.inventivetalent.reflection.minecraft.DataWatcher;
5 | import org.inventivetalent.reflection.minecraft.Minecraft;
6 |
7 | import java.util.UUID;
8 |
9 | import static org.inventivetalent.reflection.minecraft.DataWatcher.V1_9.ValueType.ENTITY_NAME;
10 | import static org.inventivetalent.reflection.minecraft.DataWatcher.V1_9.ValueType.ENTITY_NAME_VISIBLE;
11 |
12 | public abstract class ClassBuilder {
13 |
14 | public static Object buildWitherSpawnPacket(int id, UUID uuid/*UUID*/, Location loc, Object dataWatcher) throws Exception {
15 | Object packet = NMSClass.PacketPlayOutSpawnEntityLiving.newInstance();
16 | if (Minecraft.VERSION.olderThan(Minecraft.Version.v1_9_R1)) {
17 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("a")).set(packet, id);
18 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("b")).set(packet, 64);// TODO: Find correct entity type id
19 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("c")).set(packet, (int) loc.getX());
20 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("d")).set(packet, MathUtil.floor(loc.getY() * 32D));
21 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("e")).set(packet, (int) loc.getZ());
22 |
23 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("i")).set(packet, (byte) MathUtil.d(loc.getYaw() * 256F / 360F));
24 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("j")).set(packet, (byte) MathUtil.d(loc.getPitch() * 256F / 360F));
25 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("k")).set(packet, (byte) MathUtil.d(loc.getPitch() * 256F / 360F));
26 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("l")).set(packet, dataWatcher);
27 | } else {
28 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("a")).set(packet, id);
29 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("b")).set(packet, uuid);
30 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("c")).set(packet, 64);
31 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("d")).set(packet, loc.getX());
32 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("e")).set(packet, loc.getY());
33 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("f")).set(packet, loc.getZ());
34 |
35 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("j")).set(packet, (byte) MathUtil.d(loc.getYaw() * 256F / 360F));
36 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("k")).set(packet, (byte) MathUtil.d(loc.getPitch() * 256F / 360F));
37 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("l")).set(packet, (byte) MathUtil.d(loc.getPitch() * 256F / 360F));
38 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("m")).set(packet, dataWatcher);
39 | }
40 |
41 | return packet;
42 | }
43 |
44 | public static Object buildNameMetadataPacket(int id, Object dataWatcher, int nameIndex, int visibilityIndex, String name) throws Exception {
45 | // dataWatcher = setDataWatcherValue(dataWatcher, nameIndex, name != null ? name : "");// Pass an empty string to avoid exceptions
46 | // dataWatcher = setDataWatcherValue(dataWatcher, visibilityIndex, (byte) (name != null && !name.isEmpty() ? 1 : 0));
47 | DataWatcher.setValue(dataWatcher, nameIndex, ENTITY_NAME, name != null ? name : "");// Pass an empty string to avoid exceptions
48 | DataWatcher.setValue(dataWatcher, visibilityIndex, ENTITY_NAME_VISIBLE, Minecraft.VERSION.olderThan(Minecraft.Version.v1_9_R1) ? (byte) (name != null && !name.isEmpty() ? 1 : 0) : (name != null && !name.isEmpty()));//Byte < 1.9, Boolean >= 1.9
49 | Object metaPacket = NMSClass.PacketPlayOutEntityMetadata.getConstructor(int.class, NMSClass.DataWatcher, boolean.class).newInstance(id, dataWatcher, true);
50 |
51 | return metaPacket;
52 | }
53 |
54 | public static Object updateEntityLocation(Object entity, Location loc) throws Exception {
55 | NMSClass.Entity.getDeclaredField("locX").set(entity, loc.getX());
56 | NMSClass.Entity.getDeclaredField("locY").set(entity, loc.getY());
57 | NMSClass.Entity.getDeclaredField("locZ").set(entity, loc.getZ());
58 | return entity;
59 | }
60 |
61 | // public static Object buildDataWatcher(@Nullable Object entity) throws Exception {
62 | // Object dataWatcher = NMSClass.DataWatcher.getConstructor(NMSClass.Entity).newInstance(entity);
63 | // return dataWatcher;
64 | // }
65 | //
66 | // public static Object buildWatchableObject(int index, Object value) throws Exception {
67 | // return buildWatchableObject(getDataWatcherValueType(value), index, value);
68 | // }
69 | //
70 | // public static Object buildWatchableObject(int type, int index, Object value) throws Exception {
71 | // return NMSClass.WatchableObject.getConstructor(int.class, int.class, Object.class).newInstance(type, index, value);
72 | // }
73 | //
74 | // public static Object setDataWatcherValue(Object dataWatcher, int index, Object value) throws Exception {
75 | // Object type = getDataWatcherValueType(value);
76 | //
77 | // Object map = AccessUtil.setAccessible(NMSClass.DataWatcher.getDeclaredField("dataValues")).get(dataWatcher);
78 | // NMUClass.gnu_trove_map_hash_TIntObjectHashMap.getDeclaredMethod("put", int.class, Object.class).invoke(map, index, buildWatchableObject(type, index, value));
79 | //
80 | // return dataWatcher;
81 | // }
82 | //
83 | // public static Object getDataWatcherValue(Object dataWatcher, int index) throws Exception {
84 | // Object map = AccessUtil.setAccessible(NMSClass.DataWatcher.getDeclaredField("dataValues")).get(dataWatcher);
85 | // Object value = NMUClass.gnu_trove_map_hash_TIntObjectHashMap.getDeclaredMethod("get", int.class).invoke(map, index);
86 | //
87 | // return value;
88 | // }
89 | //
90 | // public static int getWatchableObjectIndex(Object object) throws Exception {
91 | // int index = AccessUtil.setAccessible(NMSClass.WatchableObject.getDeclaredField("b")).getInt(object);
92 | // return index;
93 | // }
94 | //
95 | // public static int getWatchableObjectType(Object object) throws Exception {
96 | // int type = AccessUtil.setAccessible(NMSClass.WatchableObject.getDeclaredField("a")).getInt(object);
97 | // return type;
98 | // }
99 | //
100 | // public static Object getWatchableObjectValue(Object object) throws Exception {
101 | // Object value = AccessUtil.setAccessible(NMSClass.WatchableObject.getDeclaredField("c")).get(object);
102 | // return value;
103 | // }
104 | //
105 | // public static Object getDataWatcherValueType(Object value) {
106 | // int type = 0;
107 | // if (value instanceof Number) {
108 | // if (value instanceof Byte) {
109 | // type = 0;
110 | // } else if (value instanceof Short) {
111 | // type = 1;
112 | // } else if (value instanceof Integer) {
113 | // type = 2;
114 | // } else if (value instanceof Float) {
115 | // type = 3;
116 | // }
117 | // } else if (value instanceof String) {
118 | // type = 4;
119 | // } else if (value != null && value.getClass().equals(NMSClass.ItemStack)) {
120 | // type = 5;
121 | // } else if (value != null && (value.getClass().equals(NMSClass.ChunkCoordinates) || value.getClass().equals(NMSClass.BlockPosition))) {
122 | // type = 6;
123 | // } else if (value != null && value.getClass().equals(NMSClass.Vector3f)) {
124 | // type = 7;
125 | // }
126 | //
127 | // return type;
128 | // }
129 |
130 | public static Object buildArmorStandSpawnPacket(Object armorStand) throws Exception {
131 | Object spawnPacket = NMSClass.PacketPlayOutSpawnEntityLiving.getConstructor(NMSClass.EntityLiving).newInstance(armorStand);
132 | AccessUtil.setAccessible(NMSClass.PacketPlayOutSpawnEntityLiving.getDeclaredField("b")).setInt(spawnPacket, 30);
133 |
134 | return spawnPacket;
135 | }
136 |
137 | public static Object buildTeleportPacket(int id, Location loc, boolean onGround, boolean heightCorrection) throws Exception {
138 | Object packet = NMSClass.PacketPlayOutEntityTeleport.newInstance();
139 | AccessUtil.setAccessible(NMSClass.PacketPlayOutEntityTeleport.getDeclaredField("a")).set(packet, id);
140 | AccessUtil.setAccessible(NMSClass.PacketPlayOutEntityTeleport.getDeclaredField("b")).set(packet, (int) (loc.getX() * 32D));
141 | AccessUtil.setAccessible(NMSClass.PacketPlayOutEntityTeleport.getDeclaredField("c")).set(packet, (int) (loc.getY() * 32D));
142 | AccessUtil.setAccessible(NMSClass.PacketPlayOutEntityTeleport.getDeclaredField("d")).set(packet, (int) (loc.getZ() * 32D));
143 | AccessUtil.setAccessible(NMSClass.PacketPlayOutEntityTeleport.getDeclaredField("e")).set(packet, (byte) (int) (loc.getYaw() * 256F / 360F));
144 | AccessUtil.setAccessible(NMSClass.PacketPlayOutEntityTeleport.getDeclaredField("f")).set(packet, (byte) (int) (loc.getPitch() * 256F / 360F));
145 |
146 | return packet;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/reflection/MathUtil.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar.reflection;
2 |
3 | public abstract class MathUtil {
4 |
5 | public static int floor(double d1) {
6 | int i = (int) d1;
7 | return d1 >= i ? i : i - 1;
8 | }
9 |
10 | public static int d(float f1) {
11 | int i = (int) f1;
12 | return f1 >= i ? i : i - 1;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/reflection/NMSClass.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar.reflection;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | public abstract class NMSClass {
6 |
7 | private static boolean initialized;
8 |
9 | public static Class> Entity;
10 | public static Class> EntityLiving;
11 | public static Class> EntityInsentient;
12 | public static Class> EntityAgeable;
13 | public static Class> EntityHorse;
14 | public static Class> EntityArmorStand;
15 | public static Class> EntityWither;
16 | public static Class> EntityWitherSkull;
17 | public static Class> EntitySlime;
18 | public static Class> World;
19 | public static Class> PacketPlayOutSpawnEntityLiving;
20 | public static Class> PacketPlayOutSpawnEntity;
21 | public static Class> PacketPlayOutEntityDestroy;
22 | public static Class> PacketPlayOutAttachEntity;
23 | public static Class> PacketPlayOutEntityTeleport;
24 | public static Class> PacketPlayOutEntityMetadata;
25 | public static Class> DataWatcher;
26 | public static Class> WatchableObject;
27 | public static Class> ItemStack;
28 | public static Class> ChunkCoordinates;
29 | public static Class> BlockPosition;
30 | public static Class> Vector3f;
31 | public static Class> EnumEntityUseAction;
32 |
33 | static {
34 | if (!initialized) {
35 | for (Field f : NMSClass.class.getDeclaredFields()) {
36 | if (f.getType().equals(Class.class)) {
37 | try {
38 | f.set(null, Reflection.getNMSClassWithException(f.getName()));
39 | } catch (Exception e) {
40 | if (f.getName().equals("WatchableObject")) {
41 | try {
42 | f.set(null, Reflection.getNMSClassWithException("DataWatcher$WatchableObject"));
43 | } catch (Exception e1) {
44 | e1.printStackTrace();
45 | }
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/reflection/NMUClass.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar.reflection;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | public abstract class NMUClass {
6 |
7 | private static boolean initialized;
8 |
9 | public static Class> gnu_trove_map_TIntObjectMap;
10 | public static Class> gnu_trove_map_hash_TIntObjectHashMap;
11 | public static Class> gnu_trove_impl_hash_THash;
12 | public static Class> io_netty_channel_Channel;
13 |
14 | static {
15 | if (!initialized) {
16 | for (Field f : NMUClass.class.getDeclaredFields()) {
17 | if (f.getType().equals(Class.class)) {
18 | try {
19 | String name = f.getName().replace("_", ".");
20 | if (Reflection.getVersion().contains("1_8")) {
21 | f.set(null, Class.forName(name));
22 | } else {
23 | f.set(null, Class.forName("net.minecraft.util." + name));
24 | }
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | }
28 | }
29 | }
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/org/inventivetalent/bossbar/reflection/Reflection.java:
--------------------------------------------------------------------------------
1 | package org.inventivetalent.bossbar.reflection;
2 |
3 | import org.bukkit.Bukkit;
4 |
5 | import java.lang.reflect.Field;
6 | import java.lang.reflect.Method;
7 |
8 | public abstract class Reflection {
9 |
10 | public static String getVersion() {
11 | String name = Bukkit.getServer().getClass().getPackage().getName();
12 | String version = name.substring(name.lastIndexOf('.') + 1) + ".";
13 | return version;
14 | }
15 |
16 | public static Class> getNMSClass(String className) {
17 | String fullName = "net.minecraft.server." + getVersion() + className;
18 | Class> clazz = null;
19 | try {
20 | clazz = Class.forName(fullName);
21 | } catch (Exception e) {
22 | e.printStackTrace();
23 | }
24 | return clazz;
25 | }
26 |
27 | public static Class> getNMSClassWithException(String className) throws Exception {
28 | String fullName = "net.minecraft.server." + getVersion() + className;
29 | Class> clazz = Class.forName(fullName);
30 | return clazz;
31 | }
32 |
33 | public static Class> getOBCClass(String className) {
34 | String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
35 | Class> clazz = null;
36 | try {
37 | clazz = Class.forName(fullName);
38 | } catch (Exception e) {
39 | e.printStackTrace();
40 | }
41 | return clazz;
42 | }
43 |
44 | public static Object getHandle(Object obj) {
45 | try {
46 | return getMethod(obj.getClass(), "getHandle", new Class[0]).invoke(obj, new Object[0]);
47 | } catch (Exception e) {
48 | e.printStackTrace();
49 | }
50 | return null;
51 | }
52 |
53 | public static Field getField(Class> clazz, String name) {
54 | try {
55 | Field field = clazz.getDeclaredField(name);
56 | field.setAccessible(true);
57 | return field;
58 | } catch (Exception e) {
59 | e.printStackTrace();
60 | }
61 | return null;
62 | }
63 |
64 | public static Method getMethod(Class> clazz, String name, Class>... args) {
65 | for (Method m : clazz.getMethods()) {
66 | if (m.getName().equals(name) && (args.length == 0 || ClassListEqual(args, m.getParameterTypes()))) {
67 | m.setAccessible(true);
68 | return m;
69 | }
70 | }
71 | return null;
72 | }
73 |
74 | public static boolean ClassListEqual(Class>[] l1, Class>[] l2) {
75 | boolean equal = true;
76 | if (l1.length != l2.length) { return false; }
77 | for (int i = 0; i < l1.length; i++) {
78 | if (l1[i] != l2[i]) {
79 | equal = false;
80 | break;
81 | }
82 | }
83 | return equal;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------