Skip to content

Instantly share code, notes, and snippets.

@backspace119
Last active August 29, 2015 14:03
Show Gist options
  • Save backspace119/b6fca3006e7371547d56 to your computer and use it in GitHub Desktop.
Save backspace119/b6fca3006e7371547d56 to your computer and use it in GitHub Desktop.
modified version of ftblaster's boss bar api
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