Fake Human Entities 1.7.10 + "fake" 1.8

Discussion in 'Spigot Plugin Development' started by Code0, May 22, 2015.

  1. I'm trying to create a plugin that spawns a human entity (using PacketWrapper 1.7.10 - PacketPlayServerNamedEntitySpawn) to create an npc. Then, I listen for interactions with said npc by registering a packetadapater.

    All works, but here's the catch:

    It doesn't work on servers that use spigot 1.7.x but allow 1.8 clients to join.

    I searched around a bit and came to a forum, where someone told someone that he needed to use PacketPlayOutPlayerInfo and send it to everyone, or else 1.8 clients wont render the entity.

    So basically what I'm asking you guys is: How would I go about creating such a Packet and then sending it to everyone, so this plugin works even on 1.7 - 1.8 servers.

    Thank you.
     
  2. Umm... Bump
     
  3. I'm sorry but you're gonna have to help me a lot more.

    I'm not so good at this. I'd like a 80% spoonfeed xP not exact code but exact way of doing it.
     
  4. Well I don't know if reflection is what you need, based on your explanation I think it is, though I can't explain it all in a few moments here. You could google some about the subject, just type in 'Reflection java' or 'Reflection bukkit'
     
  5. Telling me what I should be doing with reflection would help alot (if you're able to :)) Thanks for the help so far!!
     
  6. Well, if you are currently using NMS, you should know it only works for a specific MC version. If you compiled against 1.8, the plugin won't work for 1.7 or protocolhack. Reflection (partially) solves this problem, by not importing but instead looking at available classes and such, it's all quite difficult to explain.
     
  7. I'm not working with nms nor reflection atm. I'm just using ProtocolLib to spawn the entity.

    Now what I'm trying to do is send a packetPlayOutPlayerInfo to all 1.8 clients so they render the entity :)
     
  8. Mhm, then go fiddle around with protocollib docs
     
  9. Anyone else? :)
     
  10. The plugin Herobrine-AI did this, look at the source.
     
  11. try this:
    Main.java
    package com.darkania.npc;
    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerToggleSneakEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    public class Main extends JavaPlugin implements Listener{
    @Override
    public void onEnable() {
    Bukkit.getPluginManager().registerEvents(this, this);
    }


    @EventHandler
    public void onSneak(PlayerToggleSneakEvent event){
    Player player = event.getPlayer();

    if(event.isSneaking()){
    NPC npc = new NPC("BOB", player.getLocation());
    npc.spawn();
    }
    }

    }

    NPC.java
    package com.darkania.npc;
    import java.util.List;
    import java.util.UUID;
    import net.minecraft.server.v1_8_R3.DataWatcher;
    import net.minecraft.server.v1_8_R3.MathHelper;
    import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy;
    import net.minecraft.server.v1_8_R3.PacketPlayOutNamedEntitySpawn;
    import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo;
    import net.minecraft.server.v1_8_R3.WorldSettings.EnumGamemode;
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_8_R3.util.CraftChatMessage;
    import com.mojang.authlib.GameProfile;
    public class NPC extends Reflections {

    int entityID;
    Location location;
    GameProfile gameprofile;


    public NPC(String name,Location location){
    entityID = (int)Math.ceil(Math.random() * 1000) + 2000;
    gameprofile = new GameProfile(UUID.randomUUID(), name);
    this.location = location;
    }

    public void spawn(){
    PacketPlayOutNamedEntitySpawn packet = new PacketPlayOutNamedEntitySpawn();

    setValue(packet, "a", entityID);
    setValue(packet, "b", gameprofile.getId());
    setValue(packet, "c", (int)MathHelper.floor(location.getX() * 32.0D));
    setValue(packet, "d", (int)MathHelper.floor(location.getY() * 32.0D));
    setValue(packet, "e", (int)MathHelper.floor(location.getZ() * 32.0D));
    setValue(packet, "f", (byte) ((int) (location.getYaw() * 256.0F / 360.0F)));
    setValue(packet, "g", (byte) ((int) (location.getPitch() * 256.0F / 360.0F)));
    setValue(packet, "h", 0);
    DataWatcher w = new DataWatcher(null);
    w.a(6,(float)20);
    w.a(10,(byte)127);
    setValue(packet, "i", w);
    addToTablist();
    sendPacket(packet);
    }

    public void destroy(){
    PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] {entityID});
    rmvFromTablist();
    sendPacket(packet);
    }

    public void addToTablist(){
    PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
    PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(gameprofile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(gameprofile.getName())[0]);
    @SuppressWarnings("unchecked")
    List<PacketPlayOutPlayerInfo.PlayerInfoData> players = (List<PacketPlayOutPlayerInfo.PlayerInfoData>) getValue(packet, "b");
    players.add(data);

    setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
    setValue(packet, "b", players);

    sendPacket(packet);
    }

    public void rmvFromTablist(){
    PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
    PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(gameprofile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(gameprofile.getName())[0]);
    @SuppressWarnings("unchecked")
    List<PacketPlayOutPlayerInfo.PlayerInfoData> players = (List<PacketPlayOutPlayerInfo.PlayerInfoData>) getValue(packet, "b");
    players.add(data);

    setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER);
    setValue(packet, "b", players);

    sendPacket(packet);
    }

    }

    Reflections.java
    package com.darkania.npc;
    import java.lang.reflect.Field;
    import net.minecraft.server.v1_8_R3.Packet;
    import org.bukkit.Bukkit;
    import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
    import org.bukkit.entity.Player;
    public class Reflections {
    public void setValue(Object obj,String name,Object value){
    try{
    Field field = obj.getClass().getDeclaredField(name);
    field.setAccessible(true);
    field.set(obj, value);
    }catch(Exception e){}
    }

    public Object getValue(Object obj,String name){
    try{
    Field field = obj.getClass().getDeclaredField(name);
    field.setAccessible(true);
    return field.get(obj);
    }catch(Exception e){}
    return null;
    }

    public void sendPacket(Packet<?> packet,Player player){
    ((CraftPlayer)player).getHandle().playerConnection.sendPacket(packet);
    }

    public void sendPacket(Packet<?> packet){
    for(Player player : Bukkit.getOnlinePlayers()){
    sendPacket(packet,player);
    }
    }

    }


    that will do what you want
     
  12. > "it doesn't work on servers that allow 1.8 clients to join that are spigot 1.7"
    Well, that's your problem. You can either stop using deprecated software or manually construct the packet and send it to netty/stream/nms (can't remember which one is the easiest way you can do with spigot).
     


  13. Code0,May 22, 2015