Skip to content

Instantly share code, notes, and snippets.

@odensc
Created January 15, 2014 23:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odensc/8446511 to your computer and use it in GitHub Desktop.
Save odensc/8446511 to your computer and use it in GitHub Desktop.
Fake Wither boss using ProtocolLib and PacketWrapper
package yourpackage.yourthingy;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.packetwrapper.WrapperPlayServerEntityMetadata;
import com.comphenix.packetwrapper.WrapperPlayServerEntityDestroy;
import com.comphenix.packetwrapper.WrapperPlayServerSpawnEntityLiving;
/**
* A "fake" wither.
* Originally by Comphenix, edited for 1.7 by thesbros
* @author Comphenix, thesbros
*/
public class FakeWither
{
public static final byte INVISIBLE = 0x20;
// Just a guess
private static final int HEALTH_RANGE = 80 * 80;
// Next entity ID
private static int NEXT_ID = 6000;
private static final int METADATA_WITHER_HEALTH = 6;
// Metadata indices
private static final int METADATA_FLAGS = 0;
private static final int METADATA_NAME = 10;
private static final int METADATA_SHOW_NAME = 11;
// Unique ID
private int id = NEXT_ID++;
// Default health
private int health = 300;
private boolean visible;
private String customName;
private boolean created;
private Location location;
private ProtocolManager manager;
public FakeWither(Location location, ProtocolManager manager)
{
this.location = location;
this.manager = manager;
}
public int getHealth()
{
return health;
}
public void setHealth(int health)
{
// Update the health of the entity
if (created)
{
WrappedDataWatcher watcher = new WrappedDataWatcher();
watcher.setObject(METADATA_WITHER_HEALTH, (float) health);
sendMetadata(watcher);
}
this.health = health;
}
public void setVisible(boolean visible)
{
// Make visible or invisible
if (created)
{
WrappedDataWatcher watcher = new WrappedDataWatcher();
watcher.setObject(METADATA_FLAGS, visible ? (byte)0 : INVISIBLE);
sendMetadata(watcher);
}
this.visible = visible;
}
public void setCustomName(String name)
{
if (created)
{
WrappedDataWatcher watcher = new WrappedDataWatcher();
if (name != null)
{
watcher.setObject(METADATA_NAME, name);
watcher.setObject(METADATA_SHOW_NAME, (byte) 1);
}
else
{
// Hide custom name
watcher.setObject(METADATA_SHOW_NAME, (byte) 0);
}
// Only players nearby when this is sent will see this name
sendMetadata(watcher);
}
this.customName = name;
}
private void sendMetadata(WrappedDataWatcher watcher)
{
WrapperPlayServerEntityMetadata update = new WrapperPlayServerEntityMetadata();
update.setEntityId(id);
update.setEntityMetadata(watcher.getWatchableObjects());
broadcastPacket(update.getHandle(), true);
}
public int getId()
{
return id;
}
public void create()
{
WrapperPlayServerSpawnEntityLiving spawnEntity = new WrapperPlayServerSpawnEntityLiving();
WrappedDataWatcher watcher = new WrappedDataWatcher();
watcher.setObject(METADATA_FLAGS, visible ? (byte)0 : INVISIBLE);
watcher.setObject(METADATA_WITHER_HEALTH, (float) health);
if (customName != null)
{
watcher.setObject(METADATA_NAME, customName);
watcher.setObject(METADATA_SHOW_NAME, (byte) 1);
}
spawnEntity.setEntityID(id);
spawnEntity.setType(EntityType.WITHER);
spawnEntity.setX(location.getX());
spawnEntity.setY(location.getY());
spawnEntity.setZ(location.getZ());
spawnEntity.setMetadata(watcher);
broadcastPacket(spawnEntity.getHandle(), true);
created = true;
}
public void destroy()
{
if (!created)
{
throw new IllegalStateException("Cannot kill a killed entity.");
}
WrapperPlayServerEntityDestroy destroy = new WrapperPlayServerEntityDestroy();
destroy.setEntities(new int[] {id});
broadcastPacket(destroy.getHandle(), false);
created = false;
}
private void broadcastPacket(PacketContainer packet, boolean onlyNearby)
{
for (Player player : Bukkit.getServer().getOnlinePlayers())
{
// Must be within the range
if (!onlyNearby || player.getLocation().distanceSquared(location) < HEALTH_RANGE)
{
try
{
manager.sendServerPacket(player, packet);
}
catch (InvocationTargetException e)
{
Bukkit.getLogger().log(Level.WARNING, "Cannot send " + packet + " to " + player, e);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment