Solved Change player to snowman

Discussion in 'Plugin Development' started by perwin, Feb 17, 2013.

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

    perwin

    Hello,
    I have a problem with creating a plugin which will allow player to change to the snowman.
    Here is my code:
    Code:java
    1. public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    2. if(command.getName().equalsIgnoreCase("snowman") && args.length == 0 && sender instanceof Player) {
    3. this.change((Player) sender);
    4. return true;
    5. }
    6. return false;
    7. }
    8.  
    9. private void change(Player player) {
    10. for(Player p : this.getServer().getOnlinePlayers()) {
    11. CraftPlayer cp = (CraftPlayer) p;
    12. cp.getHandle().playerConnection.sendPacket(destroyEntity(player));
    13. cp.getHandle().playerConnection.sendPacket(mobSpawn(player));
    14. }
    15. }
    16.  
    17. private Packet24MobSpawn mobSpawn(Player player) {
    18. DataWatcher metadata = new DataWatcher();
    19.  
    20. Location loc = player.getLocation();
    21. Packet24MobSpawn packet = new Packet24MobSpawn();
    22.  
    23. packet.a = player.getEntityId();
    24. packet.b = 97;
    25. packet.c = MathHelper.floor(loc.getX() *32D);
    26. packet.d = MathHelper.floor(loc.getY() *32D);
    27. packet.e = MathHelper.floor(loc.getZ() *32D);
    28. packet.f = ((byte)(int)((int)loc.getYaw() * 256.0F / 360.0F));
    29. packet.g = ((byte)(int)(loc.getPitch() * 256.0F / 360.0F));
    30. packet.h = packet.f;
    31.  
    32. try {
    33. Field metadataField = packet.getClass().getDeclaredField("s");
    34. metadataField.setAccessible(true);
    35. metadataField.set(packet, metadata);
    36. } catch(Exception e) {
    37. e.printStackTrace();
    38. return null;
    39. }
    40.  
    41. return packet;
    42. }
    43.  
    44. private Packet29DestroyEntity destroyEntity(Player player) {
    45. return new Packet29DestroyEntity(player.getEntityId());
    46. }

    But when I type command /snowman it kicks me from the server and client crashes with error:
    (I attached full crash report to this thread here.)
    Can anyone help me with solving this problem? I don't want to use some created API for this, I want to have my own code.
    Thank you very much.
     

    Attached Files:

  2. Offline

    Comphenix

    Reinventing the wheel isn't necessarily a bad idea - after all, you will certainly learn a lot from the experience, but I would recommend keeping the product private until you're positive you've ironed out all the faulty code. Invalid packets will, as you've noticed, often crash the client, and you have to be prepared to read the stack trace and find the corresponding lines of code in the obfuscated source code.

    So, in this example, you have a NullPointerException in the following line of code (download JD-GUI and see for yourself):
    Code:java
    1.  
    2. // public class co extends ef
    3. // or Packet24MobSpawn
    4. public List c() {
    5. if (this.t == null) {
    6. this.t = this.s.c(); // line 97
    7. }
    8. return this.t;
    9. }
    10.  

    So, for some reason, t (List<WatchableObject>) is NULL on the client side.

    This should tell you to look into how Minecraft reads and (most importantly) writes the t list. As it turns out, this is done in a static method in DataWatcher:
    Code:java
    1.  
    2. public void a(DataOutputStream paramDataOutputStream) {
    3. this.e.readLock().lock();
    4. for (WatchableObject localWatchableObject : this.c.values()) {
    5. a(paramDataOutputStream, localWatchableObject);
    6. }
    7. this.e.readLock().unlock();
    8.  
    9. paramDataOutputStream.writeByte(127);
    10. }
    11.  


    The read method (which loads the t List) looks like this:
    Code:java
    1.  
    2. public static List a(DataInputStream paramDataInputStream)
    3. {
    4. ArrayList localArrayList = null;
    5.  
    6. int i = paramDataInputStream.readByte();
    7.  
    8. while (i != 127)
    9. // etc.
    10. }
    11. return localArrayList;
    12. }
    13.  

    Do you see it? If the DataWatcher is empty, the resulting List in the client side is NULL, which the client cannot handle.

    So, you should set a value in the DataWatcher to something. There's a list of them here. I'd recommend setting index 0 (byte) to 0.[/quote]
     
  3. Offline

    perwin

    Thank you very much! I added this line:
    Code:java
    1. metadata.a(0, Byte.valueOf((byte) 0));

    And the problem is gone! :)
    But there's another problem... when I turn into the snowman, I can't move... could anyone help me with this issue please? I can't catch PlayerMoveEvent so I can't send move packets...

    Great, I solved this problem too. The problem was that I was sending destroying packets to myself too.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
Thread Status:
Not open for further replies.

Share This Page