Emote API

Overview

LabyMod users can play clientside an emote for all other players on the minecraft server. Minecraft servers can also force-play emotes for specific player's using the plugin messages.

Warning

This works only for NPC's and not for real players.

Requirements

Explanation

Servers can make NPC's do emotes. To prevent abuse, this does not work for real players. To enforce this, emotes can only be forced for players that have the second half of their UUID entirely being 0 (-> 64 least significant bits are 0, or the second long value equals 0) You therefore need to spawn them with a uuid like this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public void forceEmote( UUID npcUUID, int emoteId ) {
    // List of all forced emotes
    JsonArray array = new JsonArray();

    // Emote and target NPC
    JsonObject forcedEmote = new JsonObject();
    forcedEmote.put( "uuid", npcUUID );
    forcedEmote.put( "emote_id", emoteId );
    array.add(forcedEmote);

    // Send to LabyMod using the API
    LabyModPlugin.getInstance().sendServerMessage( player, "emote_api", array );
}

Spawn valid NPC for emotes

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
private void example() { 
    // Create NPC uuid with least significant bits set to 0
    UUID uuid = new UUID(random.nextLong(), 0);

    // Add NPC to the tablist
    GameProfile gameProfile = new GameProfile(uuid, "NPC");
    addPlayerToTablist(gameProfile, gameProfile.getName());

    // Spawn the entity in the world (Maybe with a little delay of few ticks)
    spawnPlayerInWorld(1337, uuid, location);

    // Play hello emote (Another delay here)
    forceEmote(uuid.getUniqueId(), 4);
}

private void spawnPlayerInWorld( int entityId, UUID uuid, Location location ) {
    PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacket( PacketType.Play.Server.NAMED_ENTITY_SPAWN );

    // Entity id and uuid
    packet.getIntegers().write( 0, entityId );
    packet.getUUIDs().write( 0, uuid );

    // Location
    packet.getIntegers().write( 1, ( int ) Math.floor( location.getX() * 32D ) );
    packet.getIntegers().write( 2, ( int ) Math.floor( location.getY() * 32D ) );
    packet.getIntegers().write( 3, ( int ) Math.floor( location.getZ() * 32D ) );
    packet.getBytes().write( 0, ( byte ) ( location.getYaw() * 256F / 360F ) );
    packet.getBytes().write( 1, ( byte ) ( location.getPitch() * 256F / 360F ) );

    packet.getIntegers().write( 4, ( int ) 0 /* Item in hand id */ );

    // Data watcher for second skin layer
    WrappedDataWatcher watcher = new WrappedDataWatcher();
    watcher.setObject( 0, ( byte ) 0 );
    watcher.setObject( 10, ( byte ) 127 );
    packet.getDataWatcherModifier().write( 0, watcher );

    // Send packet to all players
    for ( Player player : Bukkit.getOnlinePlayers() ) {
        ProtocolLibrary.getProtocolManager().sendServerPacket( player, packet );
    }
}

private void addPlayerToTablist( GameProfile gameProfile, String displayName ) {
    PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacket( PacketType.Play.Server.PLAYER_INFO );

    // Write action type
    packet.getPlayerInfoAction().write( 0, EnumWrappers.PlayerInfoAction.ADD_PLAYER );

    // Write gameprofile
    WrappedGameProfile wrappedProfile = WrappedGameProfile.fromHandle( gameProfile );
    EnumWrappers.NativeGameMode nativeGameMode = EnumWrappers.NativeGameMode.fromBukkit( GameMode.SURVIVAL );
    packet.getPlayerInfoDataLists().write( 0, Collections.singletonList( new PlayerInfoData( wrappedProfile, 20, nativeGameMode, WrappedChatComponent.fromText( displayName ) ) ) );

    // Send packet to all players
    for ( Player player : Bukkit.getOnlinePlayers() ) {
        ProtocolLibrary.getProtocolManager().sendServerPacket( player, packet );
    }
}

Example emote id's

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
2: Backflip
3: Dab
4: Hello
5: Bow thanks
6: Hype
7: Tryingtofly
8: Infinity sit
11: Zombie
13: Hula Hoop
14: Calling
15: Facepalm
18: Brush your shoulders
19: Split
20: Salute
22: Balarina
31: Handstand
32: Helicopter
33: Holy
34: Waveover
36: Deeper deeper
37: Karate
38: Moonwalk
40: Freezing
41: Jubilation
43: Turtle
45: Headspin
46: Infinity Dab
47: Chicken
49: The Floss
50: The mega thrust
51: The cleaner
52: Bridge
53: Milk the cow
54: Rurik
55: Wave
57: Money rain
59: The pointer
60: Frightening
61: Sad
62: Air guitar
63: Witch
69: Left
70: Right
74: Buuuh
75: Spitting bars
76: Count money
77: Hug
78: Applause
79: Boxing
83: Shoot
84: The pointing man
85: Heart
86: Near the fall
89: Waiting
92: Praise your item
93: Look
97: I love you
98: Sarcastic clap
101: You
105: Head on wall
112: Balance
113: Levelup
114: Take the L
121: My idol
122: Airplane
124: Eagle
126: Job well done
128: Elephant
130: Present
131: Eyes on you
133: Bow down
134: Maneki-neko
135: Conductor
136: Didi challenge
137: Snow Angle
138: Snowball
139: Sprinkler
140: Calculated
141: One-armed handstand
142: Eat
143: Shy
145: Sit-Ups
146: Breakdance
148: Mindblow
149: Fall
150: T Pose
153: Jumping Jack
154: Backstoke
156: Ice-Hockey
157: Look at fireworks
158: Finish the tree
159: Ice-Skating
161: Fancy Feet
162: Ronaldo
163: True Heart
164: Pumpernickel
166: Baby Shark
167: Open present
170: Dj
173: Sneeze