Created
January 15, 2014 23:02
Fake Wither boss using ProtocolLib and PacketWrapper
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 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