Last active
August 29, 2015 14:03
-
-
Save backspace119/b6fca3006e7371547d56 to your computer and use it in GitHub Desktop.
modified version of ftblaster's boss bar api
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package YOUR.PACKAGE.HERE; | |
import java.lang.reflect.Field; | |
import java.util.HashMap; | |
import java.util.Map; | |
import net.minecraft.server.v1_7_R3.DataWatcher; | |
import net.minecraft.server.v1_7_R3.EntityPlayer; | |
import net.minecraft.server.v1_7_R3.Packet; | |
import net.minecraft.server.v1_7_R3.PacketPlayInClientCommand; | |
import net.minecraft.server.v1_7_R3.PacketPlayOutSpawnEntityLiving; | |
import net.minecraft.server.v1_7_R3.PacketPlayOutEntityDestroy; | |
import net.minecraft.server.v1_7_R3.PacketPlayOutEntityMetadata; | |
import org.bukkit.Bukkit; | |
import org.bukkit.ChatColor; | |
import org.bukkit.Location; | |
import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer; | |
import org.bukkit.entity.EntityType; | |
import org.bukkit.entity.Player; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import org.bukkit.scheduler.BukkitRunnable; | |
//IMPORTANT: REMEMBER TO CHANGE YOUR.PACKAGE.HERE TO THE CORRESPONDING PACKAGE YOU | |
//DROP THIS IN. | |
// Original code by chasechocolate | |
// Modified by ftbastler for Minecraft 1.7 | |
// cleaned and edited by backspace119 | |
public class BarAPI { | |
public static final int ENTITY_ID = 1234; | |
private static JavaPlugin plugin; | |
private static HashMap<String, Boolean> hasHealthBar = new HashMap<String, Boolean>(); | |
private static Map<Player, Integer> percentageMap = new HashMap<Player, Integer>(); | |
private static Map<Player, Boolean> stopPercentage = new HashMap<Player, Boolean>(); | |
public static void sendPacket(Player player, Packet packet){ | |
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); | |
entityPlayer.playerConnection.sendPacket(packet); | |
} | |
/** | |
* CALL THIS BEFORE DOING ANYTHING. PASS IN AN INSTANCE TO YOUR PLUGIN | |
* @param plugin | |
*/ | |
public static void init(JavaPlugin plugin) | |
{ | |
BarAPI.plugin = plugin; | |
} | |
public static Field getField(Class<?> cl, String field_name){ | |
try { | |
Field field = cl.getDeclaredField(field_name); | |
return field; | |
} catch (SecurityException e) { | |
e.printStackTrace(); | |
} catch (NoSuchFieldException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
//Accessing packets | |
@SuppressWarnings("deprecation") | |
public static PacketPlayOutSpawnEntityLiving getMobPacket(String text, Location loc){ | |
PacketPlayOutSpawnEntityLiving mobPacket = new PacketPlayOutSpawnEntityLiving(); | |
try { | |
Field a = getField(mobPacket.getClass(), "a"); | |
a.setAccessible(true); | |
a.set(mobPacket, (int) ENTITY_ID); | |
Field b = getField(mobPacket.getClass(), "b"); | |
b.setAccessible(true); | |
b.set(mobPacket, (byte) EntityType.WITHER.getTypeId()); | |
Field c = getField(mobPacket.getClass(), "c"); | |
c.setAccessible(true); | |
c.set(mobPacket, (int) Math.floor(loc.getBlockX() * 32.0D)); | |
Field d = getField(mobPacket.getClass(), "d"); | |
d.setAccessible(true); | |
d.set(mobPacket, (int) Math.floor(loc.getBlockY() * 32.0D)); | |
Field e = getField(mobPacket.getClass(), "e"); | |
e.setAccessible(true); | |
e.set(mobPacket, (int) Math.floor(loc.getBlockZ() * 32.0D)); | |
Field f = getField(mobPacket.getClass(), "f"); | |
f.setAccessible(true); | |
f.set(mobPacket, (byte) 0); | |
Field g = getField(mobPacket.getClass(), "g"); | |
g.setAccessible(true); | |
g.set(mobPacket, (byte) 0); | |
Field h = getField(mobPacket.getClass(), "h"); | |
h.setAccessible(true); | |
h.set(mobPacket, (byte) 0); | |
Field i = getField(mobPacket.getClass(), "i"); | |
i.setAccessible(true); | |
i.set(mobPacket, (byte) 0); | |
Field j = getField(mobPacket.getClass(), "j"); | |
j.setAccessible(true); | |
j.set(mobPacket, (byte) 0); | |
Field k = getField(mobPacket.getClass(), "k"); | |
k.setAccessible(true); | |
k.set(mobPacket, (byte) 0); | |
} catch (IllegalArgumentException e1) { | |
e1.printStackTrace(); | |
} catch (IllegalAccessException e1) { | |
e1.printStackTrace(); | |
} | |
DataWatcher watcher = getWatcher(text, 300); | |
try{ | |
Field t = PacketPlayOutSpawnEntityLiving.class.getDeclaredField("l"); | |
t.setAccessible(true); | |
t.set(mobPacket, watcher); | |
} catch(Exception ex){ | |
ex.printStackTrace(); | |
} | |
return mobPacket; | |
} | |
public static PacketPlayOutEntityDestroy getDestroyEntityPacket(){ | |
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(); | |
Field a = getField(packet.getClass(), "a"); | |
a.setAccessible(true); | |
try { | |
a.set(packet, new int[]{ENTITY_ID}); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} | |
return packet; | |
} | |
public static PacketPlayOutEntityMetadata getMetadataPacket(DataWatcher watcher){ | |
PacketPlayOutEntityMetadata metaPacket = new PacketPlayOutEntityMetadata(); | |
Field a = getField(metaPacket.getClass(), "a"); | |
a.setAccessible(true); | |
try { | |
a.set(metaPacket, (int) ENTITY_ID); | |
} catch (IllegalArgumentException e1) { | |
e1.printStackTrace(); | |
} catch (IllegalAccessException e1) { | |
e1.printStackTrace(); | |
} | |
try{ | |
Field b = PacketPlayOutEntityMetadata.class.getDeclaredField("b"); | |
b.setAccessible(true); | |
b.set(metaPacket, watcher.c()); | |
} catch(Exception e){ | |
e.printStackTrace(); | |
} | |
return metaPacket; | |
} | |
public static PacketPlayInClientCommand getRespawnPacket(){ | |
PacketPlayInClientCommand packet = new PacketPlayInClientCommand(); | |
Field a = getField(packet.getClass(), "a"); | |
a.setAccessible(true); | |
try { | |
a.set(packet, (int) 1); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} | |
return packet; | |
} | |
public static DataWatcher getWatcher(String text, int health){ | |
DataWatcher watcher = new DataWatcher(null); | |
watcher.a(0, (Byte) (byte) 0x20); //Flags, 0x20 = invisible | |
watcher.a(6, (Float) (float) health); | |
watcher.a(10, (String) text); //Entity name | |
watcher.a(11, (Byte) (byte) 1); //Show name, 1 = show, 0 = don't show | |
//watcher.a(16, (Integer) (int) health); //Wither health, 300 = full health | |
return watcher; | |
} | |
//Other methods | |
/** | |
* use the bar as a simple text display. | |
* @param text | |
* @param player | |
*/ | |
public static void displayTextBar(String text, final Player player){ | |
if(plugin == null) return; | |
createBar(player, text); | |
new BukkitRunnable(){ | |
@Override | |
public void run(){ | |
destroyBar(player); | |
} | |
}.runTaskLater(plugin, 120L); | |
} | |
/** | |
* after we're finished with the bar (either from our countdown | |
* or the percentage handler reached 100 (or was stopped) ) | |
* call this to remove the bar from the players HUD | |
* @param player | |
*/ | |
public static void destroyBar(Player player) | |
{ | |
PacketPlayOutEntityDestroy destroyEntityPacket = getDestroyEntityPacket(); | |
sendPacket(player, destroyEntityPacket); | |
hasHealthBar.put(player.getName(), false); | |
} | |
/** | |
* creates a bar with the text given. Use this before | |
* starting to send data about the bar (like a percentage) | |
* @param player | |
* @param text | |
*/ | |
public static void createBar(Player player, String text) | |
{ | |
PacketPlayOutSpawnEntityLiving mobPacket = getMobPacket(text, player.getLocation()); | |
sendPacket(player, mobPacket); | |
hasHealthBar.put(player.getName(), true); | |
} | |
static ChatColor percentageColor = ChatColor.GREEN; | |
/** | |
* A dev-controlled percentage bar. The only automation is the | |
* update procedure. The dev must use setPercentage() to keep the | |
* display updated and, once the percentage is 100, the bar will destroy | |
* itself and briefly display the endText | |
* This should be used in the case of the bar being a "percentage complete" | |
* bar or the like | |
* | |
* @author backspace119 | |
* @param text text to display above the bar | |
* @param player | |
* @param percentage | |
* @param appendPercentage if true the percentage will be appended to the end of the text | |
* @param appendEndPercentage if true the percentage will be appended when the bar is finished, whether it | |
* finished through automation or through being cancelled | |
*/ | |
public static void displayPercentageBar(String text, String endText,final Player player, int percentage, boolean appendPercentage, boolean appendEndPercentage) | |
{ | |
if(plugin == null) return; | |
stopPercentage.put(player, false); | |
setPercentage(player, percentage); | |
final String dText = appendPercentage ? appendPercentage(text, percentage):text; | |
createBar(player, text); | |
final String dEndText = appendEndPercentage ? appendPercentage(endText, percentage): endText; | |
new BukkitRunnable(){ | |
@Override | |
public void run() | |
{ | |
if(getPercentage(player) >= 100 || getStop(player)) { | |
destroyBar(player); | |
createBar(player, dEndText); | |
new BukkitRunnable(){ | |
@Override | |
public void run() | |
{ | |
destroyBar(player); | |
} | |
}.runTaskLater(plugin, 60L); | |
this.cancel(); | |
} | |
setBarHealth(player, getPercentage(player) * 3, dText); | |
} | |
}.runTaskTimer(plugin, 10L, 10L); | |
} | |
public static void stopPercentage(Player player) | |
{ | |
stopPercentage.put(player, true); | |
} | |
public static boolean getStop(Player player) | |
{ | |
return stopPercentage.get(player); | |
} | |
public static void setPercentage(Player player, int percentage) | |
{ | |
percentageMap.put(player, percentage); | |
} | |
public static int getPercentage(Player player) | |
{ | |
return percentageMap.get(player); | |
} | |
/** | |
* set the color of the percentage appended to the bar if appendPercentage is true in displayPercentageBar() | |
* default color is Green. | |
* @param pColor | |
*/ | |
public static void setPercentageColor(ChatColor pColor) | |
{ | |
percentageColor = pColor; | |
} | |
private static String appendPercentage(String message, int percentage) | |
{ | |
return message + percentageColor + " - " + percentage + "%"; | |
} | |
/** | |
* This sets the bars "health fill" amount. 300 is full, 0 is empty. | |
* @param player | |
* @param health | |
* @param text text that is on the bar to set health on | |
*/ | |
public static void setBarHealth(Player player, int health, String text) | |
{ | |
DataWatcher watcher = getWatcher(text, health); | |
PacketPlayOutEntityMetadata metaPacket = getMetadataPacket(watcher); | |
sendPacket(player, metaPacket); | |
} | |
/** | |
* used internally, the extra parameter healthAdd determines the amount of health | |
* to add or subtract each second and the delay is for the update speed in ticks. | |
* @param text | |
* @param completeText | |
* @param player | |
* @param healthAdd | |
* @param delay | |
* @param loadUp | |
*/ | |
public static void displayLoadingBar(final String text, final String completeText, final Player player, final int healthAdd, final long delay, final boolean loadUp){ | |
if(plugin == null) return; | |
createBar(player, text); | |
new BukkitRunnable(){ | |
int health = (loadUp ? 0 : 300); | |
@Override | |
public void run(){ | |
//fires if time is left on the "loading bar" loop | |
if((loadUp ? health < 300 : health > 0)){ | |
setBarHealth(player, health, text); | |
if(loadUp){ | |
health += healthAdd; | |
} else { | |
health -= healthAdd; | |
} | |
//fires once the bar is done loading, cleans up the bar and | |
//puts the "complete text" on the bar for the player to see | |
} else { | |
//this code will remain uncleaned until I find out | |
//whether the order of these lines is important-backspace119 | |
DataWatcher watcher = getWatcher(text, (loadUp ? 300 : 0)); | |
PacketPlayOutEntityMetadata metaPacket = getMetadataPacket(watcher); | |
PacketPlayOutEntityDestroy destroyEntityPacket = getDestroyEntityPacket(); | |
sendPacket(player, metaPacket); | |
sendPacket(player, destroyEntityPacket); | |
hasHealthBar.put(player.getName(), false); | |
//Complete text | |
createBar(player, completeText); | |
setBarHealth(player,300, completeText); | |
new BukkitRunnable(){ | |
@Override | |
public void run(){ | |
destroyBar(player); | |
} | |
}.runTaskLater(plugin, 40L); | |
this.cancel(); | |
} | |
} | |
}.runTaskTimer(plugin, delay, delay); | |
} | |
/** | |
* Use this to display a loading bar to the player with the given delay. | |
* @param text text to show before load is complete | |
* @param completeText text to show after load is complete | |
* @param player | |
* @param secondsDelay | |
* @param loadUp load towards left ("up") if true, right if false | |
*/ | |
public static void displayLoadingBar(final String text, final String completeText, final Player player, final int secondsDelay, final boolean loadUp){ | |
final int healthChangePerSecond = 300 / secondsDelay; | |
displayLoadingBar(text, completeText, player, healthChangePerSecond, 20L, loadUp); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment