Created
April 7, 2014 21:08
-
-
Save aadnk/10056453 to your computer and use it in GitHub Desktop.
Filter entity flag metadata. See http://dev.bukkit.org/bukkit-plugins/protocollib/forum/65015-how-to-set-invisiblity-potion-only-for-one-team/
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 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