Skip to content

Instantly share code, notes, and snippets.

@aadnk
Last active December 4, 2018 17:03
Show Gist options
  • Select an option

  • Save aadnk/5278938 to your computer and use it in GitHub Desktop.

Select an option

Save aadnk/5278938 to your computer and use it in GitHub Desktop.
April fools. Flip zombies and chickens.
package com.comphenix.flipmobs;
import java.util.List;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.plugin.java.JavaPlugin;
import com.comphenix.protocol.Packets;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ConnectionSide;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
public class FlipMobPlugin extends JavaPlugin {
private int SPAWN_MOB_TYPE = 1;
@Override
public void onEnable() {
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
manager.addPacketListener(
new PacketAdapter(this, ConnectionSide.SERVER_SIDE,
Packets.Server.MOB_SPAWN, Packets.Server.ENTITY_METADATA) {
@Override
public void onPacketSending(PacketEvent event) {
if (event.getPacketID() == Packets.Server.MOB_SPAWN) {
handleMobSpawn(event.getPacket());
} else {
handleMetadata(event.getPlayer().getWorld(), event.getPacket());
}
}
});
}
private void handleMobSpawn(PacketContainer packet) {
StructureModifier<Integer> ints = packet.getIntegers();
StructureModifier<WrappedDataWatcher> watchers = packet.getDataWatcherModifier();
int originalType = ints.read(SPAWN_MOB_TYPE);
int translatedType = translateType(originalType);
EntityType type = EntityType.fromId(originalType);
if (originalType != translatedType) {
WrappedDataWatcher watcher = watchers.read(0);
if (watcher != null && checkDatawatcher(type, watcher)) {
// It must be cloned
watcher = watcher.deepClone();
processDatawatcher(type, watcher);
watchers.write(0, watcher);
}
// Change the mob type
ints.write(SPAWN_MOB_TYPE, translatedType);
}
}
private void handleMetadata(World world, PacketContainer packet) {
List<WrappedWatchableObject> list = packet.getWatchableCollectionModifier().read(0);
WrappedDataWatcher watcher = new WrappedDataWatcher(list);
if (watcher.getObject(12) != null) {
Entity entity = packet.getEntityModifier(world).read(0);
// Update watchables
if (checkDatawatcher(entity.getType(), watcher)) {
processDatawatcher(entity.getType(), watcher);
packet.getWatchableCollectionModifier().
write(0, watcher.getWatchableObjects());
}
}
}
/**
* Determine if we need to process the data watcher.
* @param type - entity type.
* @param watcher - the watcher type.
*/
private boolean checkDatawatcher(EntityType type, WrappedDataWatcher watcher) {
return (type == EntityType.CHICKEN && watcher.getObject(12) instanceof Integer) ||
(type == EntityType.ZOMBIE && watcher.getObject(12) instanceof Byte);
}
private void processDatawatcher(EntityType type, WrappedDataWatcher watcher) {
// Ensure that we're sending the correct data type
if (type == EntityType.CHICKEN)
setNewObject(watcher, 12, watcher.getInteger(12).byteValue());
else if (type == EntityType.ZOMBIE)
setNewObject(watcher, 12, watcher.getByte(12).intValue());
}
private void setNewObject(WrappedDataWatcher watcher, int index, Object value) {
watcher.removeObject(index);
watcher.setObject(index, value);
}
private int translateType(int type) {
if (type == EntityType.ZOMBIE.getTypeId())
return EntityType.CHICKEN.getTypeId();
else if (type == EntityType.CHICKEN.getTypeId())
return EntityType.ZOMBIE.getTypeId();
else
return type;
}
}
@frdmn

frdmn commented Apr 2, 2013

Copy link
Copy Markdown

Thank you for the update. 1.0.1 seems to work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment