[SOLVED] Disguise as a Creeper

Discussion in 'Plugin Development' started by SnowGears, Aug 2, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    SnowGears

    All I want to do is make it look like I am a creeper to everyone else in my server.

    I KNOW THERE IS DISGUISECRAFT AND MOBDISGUISE.

    All I want is the creeper portion of that code and I have been looking through the source code and can't figure out how it is done.

    All I need is to be able to turn the effect of being a creeper on and off at different times and I can figure the rest out on my own.

    If anyone could please help me out with this I would really appreciate it. Its the last touch my plugin needs. Thanks!
     
  2. Offline

    michaelb10297

    https://github.com/joey23art/MobDisguise/tree/master/src/me/desmin88/mobdisguise that is the source code for the plugin if you go under command if you look

    Code:
    package me.desmin88.mobdisguise.commands;
    import me.desmin88.mobdisguise.MobDisguise;
    import me.desmin88.mobdisguise.utils.MobIdEnum;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    public class MDCommand implements CommandExecutor {
    @SuppressWarnings("unused")
    private final MobDisguise plugin;
    public MDCommand(MobDisguise instance) {
    this.plugin = instance;
    }
    public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
    if (sender instanceof Player) {
    Player s = (Player) sender;
     
    if (args.length == 0) { // Undisguising, player types /md
    if(!MobDisguise.disList.contains(s.getName())) {
    s.sendMessage(MobDisguise.pref + "You are not disguised, so you can't undisguise!");
    return true;
    }
    MobDisguise.pu.undisguiseToAll(s);
    MobDisguise.disList.remove(s.getName());
    MobDisguise.playerMobId.put(s.getName(), null);
    MobDisguise.playerEntIds.remove(Integer.valueOf(s.getEntityId()));
    s.sendMessage(MobDisguise.pref + "You have been changed back to human form!");
    return true;
    }
     
    if (args[0].equalsIgnoreCase("types")) { // They want to know valid types of mobs
    s.sendMessage(MobDisguise.pref + MobIdEnum.types);
    return true;
    }
    if (args[0].equalsIgnoreCase("stats")) { // They want to know they're current disguing status
    boolean disguised = MobDisguise.disList.contains(s.getName());
    if(!disguised){
    s.sendMessage(MobDisguise.pref + "You are currently NOT disguised!");
    return true;
    }
    else {
    Integer inte = (Integer) MobDisguise.playerMobId.get(s.getName()).intValue();
    String mobtype = MobIdEnum.getTypeFromByte(inte);
    s.sendMessage(MobDisguise.pref + "You are currently disguised as a " + mobtype);
    return true;
    }
     
    }
     
    if(args.length == 1) { // Means they're trying to disguise
    String mobtype = args[0].toLowerCase();
    if (!MobIdEnum.map.containsKey(mobtype)) {
    s.sendMessage(MobDisguise.pref + "Invalid mob type!");
    return true;
    }
    if(MobDisguise.perm && !s.isOp()){
    if(!s.hasPermission("mobdisguise." + mobtype) ) {
    s.sendMessage(MobDisguise.pref + "You don't have permission for this mob!");
    return true;
    }
    }
    if(!MobDisguise.perm && !s.isOp()) {
    s.sendMessage(MobDisguise.pref + "You are not an OP and perms are disabled!");
    return true;
    }
    if (!MobDisguise.cfg.getBoolean("BlackList." + mobtype, true)) {
    s.sendMessage(MobDisguise.pref + "This mob type has been restricted!");
    return true;
    }
    [COLOR=#ff0000]****************************Look Here**************************************[/COLOR]
    MobDisguise.disList.add(s.getName());
    MobDisguise.playerMobId.put(s.getName(), (byte) MobIdEnum.map.get(mobtype).intValue());
    MobDisguise.playerEntIds.add(Integer.valueOf(s.getEntityId()));
    MobDisguise.pu.disguiseToAll(s);
    s.sendMessage(MobDisguise.pref + "You have been disguised as a " + args[0].toLowerCase() + "!");
    return true;
     
    }
    }
    return false;
    }
    }
    
    its gets mobtype from a enum under utils/MobIdEnum.java
     
  3. Offline

    SnowGears

    michaelb10297

    That doesn't really help me though... there is nothing there about disguising as a creeper, it is all generic and I have tried reading through all that source code but it is so complicated... What packets do I need to hide and show in order to achieve turning into a creeper? Can you please give me an example to get me on the right track?
     
  4. Offline

    michaelb10297

    what program do you use for coding eclipse/netbeans?
     
  5. Offline

    SnowGears

    eclipse
     
  6. Offline

    hawkfalcon

    ^^
     
  7. Offline

    ZeusAllMighty11

    It's not as simple as you think. You have to destroy packets sent from the server saying you are a default Player Entity, and you have to create it and force it to think you are a creeper entity.
     
    r0306 likes this.
  8. Offline

    michaelb10297

    i can't figure out how to do that i know that the packet id for creepers are 50
     
  9. Offline

    SnowGears

    I know its not simple. Thats why I am asking here. I was hoping someone would have some sort of experience with this and be able to help me "carve out the creeper code" to use with my plugin basically.
     
  10. Offline

    r0306

    Tooner101
    This is an extensive plugin so I will only touch into the basics:
    The first three methods are just the packets to send. The disguiseCreeper() method puts the two packets together and sends them to all players on the server.

    First send the destroy packet to remove the player entity:
    Code:
    public Packet29DestroyEntity destroyEntity(Entity entity)
    {
    return new Packet29DestroyEntity(entity.getEntityId());
    }
    Then send the spawn creeper packet:
    Code:
    public DataWatcher field;
    public Packet24MobSpawn spawnMob(Location location, int id) throws FieldNotFoundException
     
    Packet24MobSpawn packet = new Packet24MobSpawn()
    {
    packet.a = id; //Entity UDID
    packet.b = 50; //id for creeper
    packet.c = Math.floor(loc.getX() * 32d);
    packet.d = Math.floor(loc.getY() * 32d);
    packet.e = Math.floor(loc.getZ() * 32d);
    packet.f = (byte) loc.getYaw();
    packet.g = (byte) loc.getPitch();
    packet.h = packet.f;
     
    Field metadata = packet.getClass().getDeclaredField("i");
    metadata.setAccessible(true);
    metadata.set(packet, field);
     
    return packet;
    }
    
    Now send mob movements:
    Code:
    public Packet33RelEntityMoveLook movePacket(Location move, int id)
    {
    Packet33RelEntityMoveLook packet = new Packet33RelEntityMoveLook();
    packet.a = id;
    packet.b = (byte) move.getX();
    packet.c = (byte) move.getY();
    packet.d = (byte) move.getZ();
    packet.e = (byte) move.getYaw();
    packet.f = (byte) move.getPitch();
     
    return packet;
    }
    
    Now to put it all together, you will have to send the packets to every player on the server:
    Call this method to disguise player as creeper.
    Code:
    private static int id = 1000000;
    public static HashMap<String, Integer> ids = new HashMap<String, Integer>
     
    public void disguiseCreeper(Player player)
    {
      int id = this.id++;
      Location location = player.getLocation();
      for (Player p : Bukkit.getOnlinePlayers())
      {
      ((CraftPlayer)p).getHandle().netServerHandler.sendPacket(destroyEntity(player));
      ((CraftPlayer)p).getHandle().netServerHandler.sendPacket(spawnMob(location, id);
      }
    ids.put(player.getName(), id);
    }
      
    Add a listener that listens to player movements and send the updates to all players.
    Code:
    @EventHandler
    public void onMove(PlayerMoveEvent event)
    {
      Player player = event.getPlayer();
      if (ids.containsKey(player.getName())
      {
        for (Player p : Bukkit.getOnlinePlayers())
        {
            ((CraftPlayer)p).getHandle().netServerHandler.sendPacket(movePacket(event.getTo(), ids.get(player.getName())));
        }
      }
    }
        
     
  11. Offline

    SnowGears

    r0306

    Thanks a lot!

    I talked to the developer of DisguiseCraft and he referred me to the DisguiseCraft API which you can hook into any plugin and it works great! Thanks a lot though, I might try this way later if I have problems or the API is not updated for 1.3
     
  12. Offline

    r0306

    Tooner101
    Np. I integrated this into my plugin even though I knew there was the DisguiseCraft API because it makes it much more convenient when the plugin doesn't have dependencies. I hook into the API when DisguiseCraft is detected but when it's not, the plugin defaults to using its native disguise system.
     
    Tooner101 likes this.
  13. Offline

    SnowGears

    r0306
    hey since I have you could you tell me why my plugin only works in the main world and not nether or end? I think it has something to do with player.getWorld() or something but I'm not sure where to implement it.
     
  14. Offline

    r0306

  15. I tried your code but I get a java.lang.reflect.InvocationTargetException on this line:

    return new Packet29DestroyEntity(entity.getEntityId());

    Here is the full method

    public static Packet29DestroyEntity destroyEntity(Entity entity){
    return new Packet29DestroyEntity(entity.getEntityId());
    }


    Thanks
    Keir

    EDIT: Here is some more of the stack trace

    Caused by: java.lang.NoSuchMethodError: net.minecraft.server.Packet29DestroyEntity.<init>(I)V
    1:53:22 PM [SEVERE]at com.github.zathrus_writer.commandsex.helpers.Disguise.destroyEntity(Disguise.java:21)
    1:53:22 PM [SEVERE]at com.github.zathrus_writer.commandsex.helpers.Disguise.disguise(Disguise.java:63)
    1:53:22 PM [SEVERE]at com.github.zathrus_writer.commandsex.commands.Command_cex_disguise.run(Command_cex_disguise.java:117)
    1:53:22 PM [SEVERE]... 22 more
     
  16. Offline

    r0306

    iKeirNez
    I've never seen that exception before but after searching it up, this is what I got:

    Thrown to indicate an exception occurred in an invoked method within the target VM.

    Not sure what to make of it either.

    Maybe try this:
    Code:
    public static Packet29DestroyEntity destroyEntity(Entity entity){
    int id = entity.getEntityId();
    Packet29DestroyEntity packet = new Packet29DestroyEntity();
    packet.a = id;
    return packet;
    }
     
  17. Hmm, I'm getting a NoSuchFieldError now for packet.a, even although I don't get any errors in Eclipse
     
  18. Offline

    r0306

    iKeirNez
    Are you running this on the server or off of Eclipse?
     
  19. Offline

    CorrieKay

    From my experience with reflection, an InvocationTargetException is thrown whenever youre using reflection to do something, and an exception is thrown. its sorta like a wrapper around another exception.
    edit: actually, thats exactly what it is.
    "InvocationTargetException is a checked exception that wraps an exception thrown by an invoked method or constructor."

    Heres how i "decode" them

    The field must have changed then. It happens all the time unfortunately, due to the obfuscated nature of the deeper code.
     
  20. Thanks also if the field changed then is there anyway to find out what it changed to and then use that?
     
  21. Offline

    CorrieKay

    Not easily. Find the class that holds the field, and try to find the new "name" of the field :\
     
  22. Offline

    SnowGears

    I am using the disguiseCraft API for my plugin and now it will not load because of this error:

    org.bukkit.plugin.UnknownDependencyException: DisguiseCraft

    It was working last night.... How do I fix this?
     
  23. Offline

    CorrieKay

    "Thrown when attempting to load an invalid Plugin file" says their jdocs
     
  24. Offline

    SnowGears

    So what does that mean? Because it was working last night... does that mean something in my plugin.yml is wrong
     
  25. Offline

    CorrieKay

    Not sure, but it wouldnt hurt to check..
     
  26. Offline

    SnowGears

    Well its the exact same as it was last night when it was working so I have no idea...
     
  27. Is DisguiseCraft still installed?

    Sounds impossible if the field name has changed.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 27, 2016
  28. Offline

    SnowGears

    That was it.... okay dang that sucks. Do you know how to do what r0306 was talking about where I can detect if they have DisguiseCraft installed? Because I do not want to have to depend on another plugin but will use it if its there
     
  29. Offline

    ZeusAllMighty11

    I thought you have to have the depends for the plugin you're using the API off of.
     
  30. Offline

    SnowGears

    I thought you did too but from what r0306 said : "I integrated this into my plugin even though I knew there was the DisguiseCraft API because it makes it much more convenient when the plugin doesn't have dependencies. I hook into the API when DisguiseCraft is detected but when it's not, the plugin defaults to using its native disguise system."
    It sounds like its possible
     
Thread Status:
Not open for further replies.

Share This Page