11package com .github .crashdemons .aztectabcompleter ;
22
3-
4- import com .mojang .brigadier .tree .RootCommandNode ;
5- import com .mojang .brigadier .tree .CommandNode ;
6-
7-
8- import com .comphenix .protocol .PacketType ;
9- import com .comphenix .protocol .ProtocolLibrary ;
10- import com .comphenix .protocol .ProtocolManager ;
11- import com .comphenix .protocol .events .ListenerPriority ;
12- import static com .comphenix .protocol .events .ListenerPriority .HIGH ;
13- import com .comphenix .protocol .events .PacketAdapter ;
14- import com .comphenix .protocol .events .PacketContainer ;
15- import com .comphenix .protocol .events .PacketEvent ;
163import com .github .crashdemons .aztectabcompleter .filters .FilterArgs ;
174import com .github .crashdemons .aztectabcompleter .filters .FilterSet ;
18- import com .github .crashdemons .util .Pair ;
19- import java .lang .reflect .InvocationTargetException ;
20- import java .net .InetSocketAddress ;
21- import java .time .LocalDateTime ;
22- import java .util .Collection ;
23- import java .util .Iterator ;
24- import java .util .concurrent .ConcurrentHashMap ;
25- import org .bukkit .Bukkit ;
265import org .bukkit .command .Command ;
276import org .bukkit .command .CommandSender ;
287import org .bukkit .entity .Player ;
298import org .bukkit .event .EventHandler ;
309import org .bukkit .event .EventPriority ;
3110import org .bukkit .event .Listener ;
3211import org .bukkit .event .player .PlayerCommandSendEvent ;
33- import org .bukkit .event .player .PlayerJoinEvent ;
3412import org .bukkit .event .player .PlayerLoginEvent ;
3513import org .bukkit .plugin .java .JavaPlugin ;
36- import org .bukkit .scheduler .BukkitRunnable ;
37- import org .bukkit .scheduler .BukkitTask ;
3814
3915/*
4016 * To change this license header, choose License Headers in Project Properties.
4925public class AZTabPlugin extends JavaPlugin implements Listener {
5026 //internal variables
5127 private static final int TPS = 20 ;
52- private ProtocolManager protocolManager ;
5328 private FilterSet filters ;
5429
5530 //runtime behavior variables
5631 public volatile boolean loaded = false ;
5732 private volatile boolean ready = false ;
5833
59- private ConcurrentHashMap <InetSocketAddress ,Pair <LocalDateTime ,PacketContainer >> packetQueue = new ConcurrentHashMap <>();
60- //don't store Player from packet event since it will be a "temporary" player object that doesn't support every method.
61-
62- private BukkitTask expireQueueEntriesTask =null ;
63- private BukkitTask sendQueueEntriesTask =null ;
64-
65- private long expirationSeconds =60 ;
66- private long expirationInterval =60 ;
67- private long tryUnsentPacketsInterval =10 ;
34+
6835
6936 private boolean kickEarlyJoins =true ;
7037 private String kickMessage ="The server is still loading - check back in a moment!" ;
7138
72- private boolean sendPacket (Player playerDestination , PacketContainer packet ){
73- if (playerDestination ==null ) return false ;
74- if (!playerDestination .isOnline ()) return false ;
75- String name = playerDestination .getName ();
76- if (name ==null ) name = "[null]" ;
77- try {
78- log ("Sending commands to " +name );
79- ProtocolLibrary .getProtocolManager ().sendServerPacket (playerDestination , packet , false );//send packet - disable further filtering.
80- return true ;
81- }catch (IllegalArgumentException e ){
82- log ("Problem sending packet to " + name +" " +playerDestination .getUniqueId ());
83- }catch (InvocationTargetException e ){
84- e .printStackTrace ();
85- }
86- return false ;
87- }
8839
8940 public AZTabPlugin () {
9041 filters = new FilterSet (this );
@@ -102,21 +53,15 @@ private void loadConfig(){
10253
10354 kickEarlyJoins = getConfig ().getBoolean ("kick-early-joins" );
10455 kickMessage = getConfig ().getString ("kick-message" );
105- expirationSeconds = getConfig ().getLong ("queue-expiration-seconds" );
106- expirationInterval = getConfig ().getLong ("queue-expiration-check-seconds" );
107- tryUnsentPacketsInterval =getConfig ().getLong ("queue-try-unsent-seconds" );
108- log ("commands queue unsent retry time: " +tryUnsentPacketsInterval +"s" );
109- log ("commands queue expiration time: " +expirationSeconds +"s" );
110- log ("commands queue check interval: " +expirationInterval +"s" );
56+
11157 }
11258
11359
11460 // Fired when plugin is disabled
11561 @ Override
11662 public void onDisable () {
11763 log ("Disabling..." );
118- if (expireQueueEntriesTask !=null ) expireQueueEntriesTask .cancel ();
119- if (sendQueueEntriesTask !=null ) sendQueueEntriesTask .cancel ();
64+
12065 loaded =false ;
12166 log ("Disabed." );
12267 }
@@ -125,36 +70,13 @@ public void onDisable() {
12570 public void onLoad () {
12671 log ("Loading... v" +this .getDescription ().getVersion ());
12772 loadConfig ();
128- log ("Loaded config." );
129- protocolManager = ProtocolLibrary .getProtocolManager ();
13073 loaded =true ;
131-
132- createInitialCommandsFilter ();
133- log ("Created filter." );
74+ log ("Loaded config." );
13475 }
13576 @ Override
13677 public void onEnable () {
13778 log ("Enabling... v" +this .getDescription ().getVersion ());
13879 getServer ().getPluginManager ().registerEvents (this , this );
139- if (expireQueueEntriesTask !=null ) expireQueueEntriesTask .cancel ();
140- if (sendQueueEntriesTask !=null ) sendQueueEntriesTask .cancel ();
141- expireQueueEntriesTask = new BukkitRunnable () {
142- public void run () {
143- LocalDateTime now = LocalDateTime .now ();
144- packetQueue .entrySet ().removeIf ((entry )->entry .getValue ().getKey ().plusSeconds (expirationSeconds ).isBefore (LocalDateTime .now ())
145- );
146- }
147- }.runTaskTimer (this ,expirationInterval *TPS ,expirationInterval *TPS );
148- sendQueueEntriesTask = new BukkitRunnable () {
149- public void run () {
150- Bukkit .getOnlinePlayers ().stream ().forEach (
151- (player ) -> {
152- if (player ==null ) return ;
153- processQueueFor (player );
154- }
155- );
156- }
157- }.runTaskTimer (this ,tryUnsentPacketsInterval *TPS ,tryUnsentPacketsInterval *TPS );
15880 loaded =true ;
15981 ready = true ;
16082 log ("Enabled." );
@@ -178,8 +100,11 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
178100 @ EventHandler (priority =EventPriority .HIGH )
179101 public void onCommandSuggestion (PlayerCommandSendEvent event ){
180102 Player player = event .getPlayer ();
103+ if (player .hasPermission ("aztectabcompleter.bypass" )) return ;
181104 if (!ready ){
182105 event .getCommands ().clear ();
106+ }else {
107+ event .getCommands ().removeIf ( entry -> !filters .filter (new FilterArgs (player ,entry )).isAllowed );
183108 }
184109 }
185110
@@ -193,93 +118,5 @@ public void onPlayerLogin(PlayerLoginEvent event){
193118 }
194119 }
195120 }
196-
197- @ EventHandler (priority =EventPriority .HIGH )
198- public void onPlayerJoin (PlayerJoinEvent event ){
199- //log("playerjoinevent");
200- if (!loaded ) return ;
201- if (!ready ) return ;
202- Player player = event .getPlayer ();
203- //log("trying packets for joined player");
204- processQueueFor (player );
205- }
206-
207- private void processQueueFor (Player playerDestination ){
208- if (!ready ) return ;//don't process queued packets until completely enabled!
209- if (playerDestination ==null ) return ;
210- InetSocketAddress addr = playerDestination .getAddress ();
211- String name = playerDestination .getName ();
212- if (addr ==null ) return ;
213- //log("Player joined: "+uuid);
214- boolean bypassFiltering =playerDestination .hasPermission ("aztectabcompleter.bypass" );
215- Pair <LocalDateTime ,PacketContainer > record = packetQueue .remove (addr );
216- if (record ==null ) return ;
217- PacketContainer packet = record .getValue ();
218- if (packet ==null ) return ;
219- PacketContainer packet_filtered ;
220- if (bypassFiltering ){
221- packet_filtered =packet ;
222- //log("player "+name+" is exempt from command filtering");
223- }else {
224- packet_filtered =filterPacketFor (playerDestination ,packet );
225- //log("filtered packet for player "+name);
226- }
227- sendPacket (playerDestination ,packet_filtered );
228- }
229- private boolean queuePacketFor (Player playerDestination , PacketContainer epacket ){
230- InetSocketAddress addr = playerDestination .getAddress ();
231- if (addr ==null ){
232- getLogger ().warning ("Could not queue packet for player with null address: " +playerDestination .toString ());
233- return false ;
234- }
235- packetQueue .put (addr , new Pair <LocalDateTime ,PacketContainer >(LocalDateTime .now (),epacket ));
236- //log("Queued commands for "+uuid);
237- return true ;
238- }
239-
240- private PacketContainer filterPacketFor (Player playerDestination , PacketContainer epacket ){
241- //the new Commands packet syntax contains a RootNode object containing multiple CommandNode objects inside in the form of a list
242- //CommandNode is difficult to construct, so instead we just selectively remove them from the collection.
243- RootCommandNode rcn = epacket .getSpecificModifier (RootCommandNode .class ).read (0 );//get the Root object
244- //this.plugin.getLogger().info("RCN Name: "+rcn.getName());
245- //this.plugin.getLogger().info("RCN Usage: "+rcn.getUsageText());
246- @ SuppressWarnings ("unchecked" )
247- Collection <CommandNode <Object >> children = rcn .getChildren ();
248- //this.plugin.getLogger().info("RCN Children: "+children.size());
249- Iterator <CommandNode <Object >> iterator = children .iterator ();
250- while (iterator .hasNext ()) {
251- CommandNode <Object > cn = iterator .next ();
252- //this.plugin.getLogger().info(" CN Name: "+cn.getName());
253- //this.plugin.getLogger().info(" CN Usage: "+cn.getUsageText());
254- if (!filters .filter (new FilterArgs (playerDestination ,cn .getName ())).isAllowed )
255- iterator .remove ();
256- }
257- PacketContainer packet = new PacketContainer (PacketType .Play .Server .COMMANDS );
258- packet .getSpecificModifier (RootCommandNode .class ).write (0 , rcn );//write the modified root object into a new packet
259- return packet ;
260- }
261-
262- private void createInitialCommandsFilter (){
263- protocolManager .addPacketListener (new PacketAdapter (this , ListenerPriority .HIGHEST , new PacketType [] { PacketType .Play .Server .COMMANDS }) {
264-
265- @ Override
266- public void onPacketSending (PacketEvent event ) {
267- AZTabPlugin pl = (AZTabPlugin ) this .plugin ;
268-
269- if (!pl .loaded ) return ;
270- event .setCancelled (true );//prevent default tabcomplete
271- Player playerDestination = event .getPlayer ();
272- if (playerDestination ==null ) return ;
273-
274- //pl.log("Intercepted Commands packet, filtering...");
275-
276- PacketContainer epacket = event .getPacket ();//get the outgoing spigot packet containing the command list
277- queuePacketFor (playerDestination ,epacket );
278-
279-
280- }
281-
282- });
283- }
284121
285122}
0 commit comments