1111import java .util .ArrayList ;
1212import java .util .Arrays ;
1313import java .util .Collection ;
14+ import java .util .Collections ;
1415import java .util .HashMap ;
1516import java .util .LinkedList ;
1617import java .util .List ;
2223import java .util .concurrent .CompletableFuture ;
2324import java .util .concurrent .ConcurrentHashMap ;
2425import java .util .concurrent .ExecutionException ;
26+ import java .util .concurrent .TimeUnit ;
27+ import java .util .concurrent .TimeoutException ;
2528import java .util .concurrent .atomic .AtomicLong ;
2629import java .util .zip .DataFormatException ;
2730
@@ -86,7 +89,9 @@ public class InteractiveChatBungee extends Plugin implements Listener {
8689 private Map <Integer , Byte []> incomming = new HashMap <>();
8790
8891 private Map <UUID , List <String >> forwardedMessages = new ConcurrentHashMap <>();
89- private Map <Integer , UUID > requestedMessages = new ConcurrentHashMap <>();
92+ private Map <UUID , UUID > requestedMessages = new ConcurrentHashMap <>();
93+
94+ private Map <UUID , List <UUID >> requestedMessageProcesses = new ConcurrentHashMap <>();
9095
9196 public static List <String > parseCommands = new ArrayList <>();
9297
@@ -163,6 +168,8 @@ public void onReceive(PluginMessageEvent event) {
163168 if (!event .getTag ().equals ("interchat:main" )) {
164169 return ;
165170 }
171+
172+ event .setCancelled (true );
166173
167174 SocketAddress senderServer = event .getSender ().getSocketAddress ();
168175
@@ -193,28 +200,66 @@ public void onReceive(PluginMessageEvent event) {
193200 ByteArrayDataInput input = ByteStreams .newDataInput (CompressionUtils .decompress (data ));
194201 switch (packetId ) {
195202 case 0x08 :
196- int requestId = input . readInt ();
203+ UUID messageId = DataTypeIO . readUUID ( input );
197204 String component = DataTypeIO .readString (input , StandardCharsets .UTF_8 );
198- UUID uuid = requestedMessages .get (requestId );
199- if (uuid != null ) {
200- Chat chatPacket = new Chat (component + "<QUxSRUFEWVBST0NFU1NFRA==>" );
201- UserConnection userConnection = (UserConnection ) getProxy ().getPlayer (uuid );
202- ChannelWrapper channelWrapper ;
203- Field channelField = null ;
204-
205- try {
206- channelField = userConnection .getClass ().getDeclaredField ("ch" );
207- channelField .setAccessible (true );
208- channelWrapper = (ChannelWrapper ) channelField .get (userConnection );
209- } catch (NoSuchFieldException | IllegalAccessException e ) {
210- throw new RuntimeException (e );
211- } finally {
212- if (channelField != null ) {
213- channelField .setAccessible (false );
205+ UUID playerUUID = requestedMessages .get (messageId );
206+ List <UUID > messageQueue = requestedMessageProcesses .get (playerUUID );
207+
208+ //ProxyServer.getInstance().getConsole().sendMessage(new TextComponent(messageId.toString() + " <- " + component));
209+
210+ if (playerUUID != null && messageQueue != null ) {
211+ new Thread (new Runnable () {
212+ @ Override
213+ public void run () {
214+ CompletableFuture <Void > future = new CompletableFuture <Void >();
215+ new Thread (new Runnable () {
216+ @ Override
217+ public void run () {
218+ while (true ) {
219+ if (messageQueue .indexOf (messageId ) == 0 ) {
220+ future .complete (null );
221+ break ;
222+ }
223+ if (future .isDone ()) {
224+ break ;
225+ }
226+ try {
227+ TimeUnit .MILLISECONDS .sleep (10 );
228+ } catch (InterruptedException e ) {
229+ e .printStackTrace ();
230+ }
231+ }
232+ }
233+ }).start ();
234+
235+ try {
236+ future .get (delay + 2000 , TimeUnit .MILLISECONDS );
237+ } catch (InterruptedException | ExecutionException | TimeoutException e ) {}
238+ if (!future .isDone ()) {
239+ future .complete (null );
240+ }
241+
242+ Chat chatPacket = new Chat (component + "<QUxSRUFEWVBST0NFU1NFRA==>" );
243+ UserConnection userConnection = (UserConnection ) getProxy ().getPlayer (playerUUID );
244+ ChannelWrapper channelWrapper ;
245+ Field channelField = null ;
246+
247+ try {
248+ channelField = userConnection .getClass ().getDeclaredField ("ch" );
249+ channelField .setAccessible (true );
250+ channelWrapper = (ChannelWrapper ) channelField .get (userConnection );
251+ } catch (NoSuchFieldException | IllegalAccessException e ) {
252+ throw new RuntimeException (e );
253+ } finally {
254+ if (channelField != null ) {
255+ channelField .setAccessible (false );
256+ }
257+ }
258+
259+ messageQueue .remove (messageId );
260+ channelWrapper .write (chatPacket );
214261 }
215- }
216-
217- channelWrapper .write (chatPacket );
262+ }).start ();
218263 }
219264 break ;
220265 case 0x09 :
@@ -495,6 +540,8 @@ public void write(ChannelHandlerContext channelHandlerContext, Object obj, Chann
495540 public void onPlayerConnected (PostLoginEvent event ) {
496541 ProxiedPlayer player = event .getPlayer ();
497542 forwardedMessages .put (player .getUniqueId (), new ArrayList <>());
543+ List <UUID > messageQueue = Collections .synchronizedList (new LinkedList <>());
544+ requestedMessageProcesses .put (player .getUniqueId (), messageQueue );
498545
499546 UserConnection userConnection = (UserConnection ) player ;
500547 ChannelWrapper channelWrapper ;
@@ -522,11 +569,14 @@ public void write(ChannelHandlerContext channelHandlerContext, Object obj, Chann
522569 if (packet .getMessage ().contains ("<QUxSRUFEWVBST0NFU1NFRA==>" )) {
523570 packet .setMessage (packet .getMessage ().replace ("<QUxSRUFEWVBST0NFU1NFRA==>" , "" ));
524571 } else {
572+ UUID messageId = UUID .randomUUID ();
573+ messageQueue .add (messageId );
574+ //ProxyServer.getInstance().getConsole().sendMessage(new TextComponent(messageId.toString() + " -> " + packet.getMessage()));
525575 new Timer ().schedule (new TimerTask () {
526576 @ Override
527577 public void run () {
528578 try {
529- requestMessageProcess (player , packet .getMessage ());
579+ requestMessageProcess (player , packet .getMessage (), messageId );
530580 } catch (IOException e ) {
531581 e .printStackTrace ();
532582 }
@@ -540,12 +590,10 @@ public void run() {
540590 });
541591 }
542592
543- private void requestMessageProcess (ProxiedPlayer player , String component ) throws IOException {
593+ private void requestMessageProcess (ProxiedPlayer player , String component , UUID messageId ) throws IOException {
544594 ByteArrayDataOutput output = ByteStreams .newDataOutput ();
545-
546- int requestId = random .nextInt ();
547595
548- output . writeInt ( requestId );
596+ DataTypeIO . writeUUID ( output , messageId );
549597 DataTypeIO .writeUUID (output , player .getUniqueId ());
550598 DataTypeIO .writeString (output , component , StandardCharsets .UTF_8 );
551599
@@ -572,7 +620,7 @@ private void requestMessageProcess(ProxiedPlayer player, String component) throw
572620 pluginMessagesCounter .incrementAndGet ();
573621 }
574622
575- requestedMessages .put (requestId , player .getUniqueId ());
623+ requestedMessages .put (messageId , player .getUniqueId ());
576624 }
577625
578626 @ EventHandler
@@ -660,6 +708,7 @@ private void requestAliasesMapping(ServerInfo server) throws IOException {
660708 @ EventHandler
661709 public void onLeave (PlayerDisconnectEvent event ) {
662710 forwardedMessages .remove (event .getPlayer ().getUniqueId ());
711+ requestedMessageProcesses .remove (event .getPlayer ().getUniqueId ());
663712 new Timer ().schedule (new TimerTask () {
664713 @ Override
665714 public void run () {
0 commit comments