1+ package com .nerds .addon .modules ;
2+
3+ import com .mojang .authlib .GameProfile ;
4+ import com .nerds .addon .NerdAddon ;
5+ import meteordevelopment .meteorclient .events .game .GameJoinedEvent ;
6+ import meteordevelopment .meteorclient .events .game .GameLeftEvent ;
7+ import meteordevelopment .meteorclient .events .packets .PacketEvent ;
8+ import meteordevelopment .meteorclient .settings .*;
9+ import meteordevelopment .meteorclient .systems .modules .Module ;
10+ import meteordevelopment .orbit .EventHandler ;
11+ import net .minecraft .client .network .PlayerListEntry ;
12+ import net .minecraft .network .packet .s2c .play .PlayerListS2CPacket ;
13+ import net .minecraft .network .packet .s2c .play .PlayerRemoveS2CPacket ;
14+ import net .minecraft .text .MutableText ;
15+ import net .minecraft .text .Text ;
16+ import net .minecraft .util .Formatting ;
17+
18+ import java .util .List ;
19+ import java .util .UUID ;
20+
21+ public class JoinLeaveNotify extends Module {
22+ private final SettingGroup sgGeneral = settings .getDefaultGroup ();
23+
24+ private final Setting <NotifyMode > mode = sgGeneral .add (new EnumSetting .Builder <NotifyMode >()
25+ .name ("notify-mode" )
26+ .description ("Which notification style to use." )
27+ .defaultValue (NotifyMode .Classic )
28+ .build ()
29+ );
30+
31+ private final Setting <List <String >> players = sgGeneral .add (new StringListSetting .Builder ()
32+ .name ("ignore-list" )
33+ .description ("Players to ignore (name contains)." )
34+ .defaultValue (List .of ())
35+ .build ()
36+ );
37+
38+ private boolean skipJoinListPacket = true ;
39+
40+ public JoinLeaveNotify () {
41+ super (NerdAddon .CATEGORY , "join-leave-notify" , "Notifies you when players join or leave the game." );
42+ }
43+
44+ @ EventHandler
45+ private void onGameJoin (GameJoinedEvent event ) {
46+ skipJoinListPacket = true ;
47+ }
48+
49+ @ EventHandler
50+ private void onGameLeave (GameLeftEvent event ) {
51+ skipJoinListPacket = true ;
52+ }
53+
54+ @ EventHandler
55+ private void onReceivePacket (PacketEvent .Receive event ) {
56+ switch (event .packet ) {
57+ case PlayerListS2CPacket packet -> {
58+ if (!packet .getActions ().contains (PlayerListS2CPacket .Action .ADD_PLAYER )) return ;
59+ if (skipJoinListPacket ) {
60+ skipJoinListPacket = false ;
61+ return ;
62+ }
63+
64+ for (PlayerListS2CPacket .Entry entry : packet .getPlayerAdditionEntries ()) {
65+ if (entry .profile () == null ) continue ;
66+
67+ String name = entry .profile ().name ();
68+ if (shouldIgnore (name )) continue ;
69+ notify (name , true );
70+ }
71+ }
72+ case PlayerRemoveS2CPacket packet -> {
73+ if (mc .getNetworkHandler () == null ) return ;
74+
75+ for (UUID id : packet .profileIds ()) {
76+ PlayerListEntry entry = mc .getNetworkHandler ().getPlayerListEntry (id );
77+ if (entry == null || entry .getProfile () == null ) continue ;
78+
79+ String name = entry .getProfile ().name ();
80+ if (shouldIgnore (name )) continue ;
81+ notify (name , false );
82+ }
83+ }
84+ default -> {}
85+ }
86+ }
87+
88+ private boolean shouldIgnore (String name ) {
89+ if (name == null || name .isBlank ()) return true ;
90+
91+ for (String ignored : players .get ()) {
92+ if (name .contains (ignored )) return true ;
93+ }
94+
95+ return false ;
96+ }
97+
98+ private void notify (String name , boolean joined ) {
99+ switch (mode .get ()) {
100+ case Classic -> notifyClassic (name , joined );
101+ case Modern -> notifyModern (name , joined );
102+ }
103+ }
104+
105+ private void notifyClassic (String name , boolean joined ) {
106+ Text text = Text .literal ("\u00a7 e" + name + (joined ? " joined the game." : " left the game." ));
107+
108+ mc .execute (() -> {
109+ if (mc .player != null ) mc .player .sendMessage (text , false );
110+ });
111+ }
112+
113+ private void notifyModern (String name , boolean joined ) {
114+ MutableText text = Text .literal ("[" )
115+ .formatted (Formatting .GRAY )
116+ .append (Text .literal (joined ? "+" : "-" ).formatted (joined ? Formatting .GREEN : Formatting .RED ))
117+ .append (Text .literal ("] " + name ).formatted (Formatting .GRAY ));
118+
119+ mc .execute (() -> {
120+ if (mc .player != null ) mc .player .sendMessage (text , false );
121+ });
122+ }
123+
124+ public enum NotifyMode {
125+ Classic ,
126+ Modern
127+ }
128+ }
0 commit comments