Skip to content

Instantly share code, notes, and snippets.

@aadnk
Created April 7, 2014 21:08
Show Gist options
  • Save aadnk/10056453 to your computer and use it in GitHub Desktop.
Save aadnk/10056453 to your computer and use it in GitHub Desktop.
package com.comphenix.example;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.google.common.base.Preconditions;
public abstract class EntityFlagFilter {
public static final int ENTITY_ON_FIRE = 1 << 0;
public static final int ENTITY_CROUCHED = 1 << 1;
public static final int ENTITY_SPRINTING = 1 << 3;
public static final int ENTITY_CONSUMING = 1 << 4;
public static final int ENTITY_INVISIBLE = 1 << 5;
// Packet listening
private ProtocolManager manager;
private PacketListener packetListener;
private boolean closed;
public EntityFlagFilter(Plugin plugin) {
packetListener = new PacketAdapter(plugin, WrapperPlayServerEntityMetadata.TYPE) {
@Override
public void onPacketSending(PacketEvent event) {
EntityFlagFilter.this.onPacketSending(event);
}
};
}
/**
* Register the current entity flag filter.
*/
public void register() {
Preconditions.checkState(!closed, "Filter has been closed.");
manager = ProtocolLibrary.getProtocolManager();
manager.addPacketListener(packetListener);
}
/**
* Refresh the flag value of a given entity by resending the value.
* <p>
* This will allow {@link #filterFlag(Player, Entity)} to process it again.
* @param entity - entity to refresh.
* @throws RuntimeException If we cannot send the packet.
*/
public void updateEntity(Entity entity) {
Preconditions.checkState(!closed, "Filter has been closed.");
Byte flag = WrappedDataWatcher.getEntityWatcher(entity).getByte(0);
// It doesn't matter much
if (flag == null) {
flag = 0;
}
// Create the packet we will transmit
WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata();
WrappedDataWatcher watcher = new WrappedDataWatcher();
watcher.setObject(0, flag);
packet.setEntityId(entity.getEntityId());
packet.setEntityMetadata(watcher.getWatchableObjects());
// Broadcast the packet
for (Player observer : manager.getEntityTrackers(entity)) {
try {
manager.sendServerPacket(observer, packet.getHandle());
} catch (Exception e) {
throw new RuntimeException("Cannot send packet " + packet.getHandle() + " to " + observer, e);
}
}
}
private void onPacketSending(PacketEvent event) {
WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata(event.getPacket());
Entity entity = packet.getEntity(event);
Byte input = null;
// Find the flag value
for (WrappedWatchableObject object : packet.getEntityMetadata()) {
if (object.getIndex() == 0) {
input = (Byte) object.getValue();
break;
}
}
if (input != null) {
// Allow our filter to process it
int filtered = filterFlag(event.getPlayer(), entity, input);
// Clone and update changes
if (filtered != input) {
packet = new WrapperPlayServerEntityMetadata(packet.getHandle().deepClone());
WrappedDataWatcher watcher = new WrappedDataWatcher(packet.getEntityMetadata());
watcher.setObject(0, (byte)filtered);
event.setPacket(packet.getHandle());
}
}
}
/**
* Invoked whenever a given player is about to be informed of an entities flag values.
* @param observer - the observing Minecraft client.
* @param observed - the observed entity.
* @param flagValues - the flag values that is currently about to be observed.
* @return The flag values that will be observed.
*/
protected abstract int filterFlag(Player observer, Entity observed, int flagValues);
/**
* Close and clean up the current filter.
*/
public void close() {
if (!closed) {
manager.removePacketListener(packetListener);
manager = null;
closed = true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment