:>1.0.1 Fix EaglerXBukkitAPI on newer server versions

This commit is contained in:
lax1dude 2024-09-24 20:29:36 -07:00
parent ec1ab8ece3
commit 12b8177f5e
9 changed files with 112 additions and 22 deletions

View File

@ -34,16 +34,28 @@ public class EaglerXBukkitAPIListener implements Listener, PluginMessageListener
@Override @Override
public void onPluginMessageReceived(String channel, Player player, byte[] data) { public void onPluginMessageReceived(String channel, Player player, byte[] data) {
if(EaglerBackendRPCProtocol.CHANNEL_NAME.equals(channel)) { PlayerDataObj dataObj;
PlayerDataObj dataObj = PlayerDataObj.getForPlayer(player); switch(channel) {
case EaglerBackendRPCProtocol.CHANNEL_NAME:
case EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN:
dataObj = PlayerDataObj.getForPlayer(player);
if(dataObj != null) { if(dataObj != null) {
dataObj.firePluginMsgRecievedInternal(data); dataObj.firePluginMsgRecievedInternal(data);
} }
}else if(EaglerBackendRPCProtocol.CHANNEL_NAME_READY.equals(channel)) { break;
PlayerDataObj dataObj = PlayerDataObj.getForPlayer(player); case EaglerBackendRPCProtocol.CHANNEL_NAME_READY:
dataObj = PlayerDataObj.getForPlayer(player);
if(dataObj != null) { if(dataObj != null) {
dataObj.firePluginReadyMsgRecieved(); dataObj.firePluginReadyMsgRecieved(false);
} }
break;
case EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN:
dataObj = PlayerDataObj.getForPlayer(player);
if(dataObj != null) {
dataObj.firePluginReadyMsgRecieved(true);
}
default:
break;
} }
} }

View File

@ -5,8 +5,10 @@ import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.bukkit.Server;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.messaging.Messenger;
import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol;
import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.PlayerDataObj; import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.PlayerDataObj;
@ -44,10 +46,30 @@ public class EaglerXBukkitAPIPlugin extends JavaPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
EaglerXBukkitAPIListener ls = new EaglerXBukkitAPIListener(); EaglerXBukkitAPIListener ls = new EaglerXBukkitAPIListener();
getServer().getPluginManager().registerEvents(ls, this); Server svr = getServer();
getServer().getMessenger().registerOutgoingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME); svr.getPluginManager().registerEvents(ls, this);
getServer().getMessenger().registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME, ls); Messenger msgr = svr.getMessenger();
getServer().getMessenger().registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_READY, ls); boolean registerLegacy = !isPost_v1_13();
if(registerLegacy) {
try {
msgr.registerOutgoingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME);
}catch(Throwable t) {
registerLegacy = false;
}
}
if(!registerLegacy) {
getLogger().warning("Note: Only the modernized plugin channel names can be used for this server!");
getLogger().warning("Make sure to set \"use_modernized_channel_names: true\" in bungee/velocity plugin settings.yml");
}
msgr.registerOutgoingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN);
if(registerLegacy) {
msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME, ls);
}
msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN, ls);
if(registerLegacy) {
msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_READY, ls);
}
msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN, ls);
if(timeoutHandler == null) { if(timeoutHandler == null) {
timeoutHandler = new Timer("EaglerXBukkitAPI: Timeout cleanup thread"); timeoutHandler = new Timer("EaglerXBukkitAPI: Timeout cleanup thread");
timeoutHandler.scheduleAtFixedRate(new TimerTask() { timeoutHandler.scheduleAtFixedRate(new TimerTask() {
@ -83,4 +105,15 @@ public class EaglerXBukkitAPIPlugin extends JavaPlugin {
return instance.getLogger(); return instance.getLogger();
} }
private boolean isPost_v1_13() {
String[] ver = getServer().getVersion().split("[\\.\\-]");
if(ver.length >= 2) {
try {
return Integer.parseInt(ver[0]) >= 1 || Integer.parseInt(ver[1]) >= 13;
}catch(NumberFormatException ex) {
}
}
return false;
}
} }

View File

@ -5,7 +5,8 @@ import java.util.concurrent.Executor;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.SameThreadExecutor;
/** /**
* Copyright (c) 2024 lax1dude. All Rights Reserved. * Copyright (c) 2024 lax1dude. All Rights Reserved.
@ -24,13 +25,11 @@ import com.google.common.util.concurrent.MoreExecutors;
*/ */
public interface IEaglerRPCFuture<V> extends ListenableFuture<V> { public interface IEaglerRPCFuture<V> extends ListenableFuture<V> {
public static final Executor SAME_THREAD_EXECUTOR = MoreExecutors.sameThreadExecutor();
/** /**
* Warning: Futures.addCallback is recommended! * Warning: Futures.addCallback is recommended!
*/ */
default void addListener(Runnable runnable) { default void addListener(Runnable runnable) {
addListener(runnable, SAME_THREAD_EXECUTOR); addListener(runnable, SameThreadExecutor.SAME_THREAD_EXECUTOR);
} }
default void addCallback(FutureCallback<V> runnable, Executor executor) { default void addCallback(FutureCallback<V> runnable, Executor executor) {
@ -38,7 +37,7 @@ public interface IEaglerRPCFuture<V> extends ListenableFuture<V> {
} }
default void addCallback(FutureCallback<V> runnable) { default void addCallback(FutureCallback<V> runnable) {
Futures.addCallback(this, runnable, SAME_THREAD_EXECUTOR); Futures.addCallback(this, runnable, SameThreadExecutor.SAME_THREAD_EXECUTOR);
} }
void setExpiresMSFromNow(int millis); void setExpiresMSFromNow(int millis);

View File

@ -79,13 +79,13 @@ public class EaglerXBukkitImpl implements IEaglerXBukkitAPI {
sendHello = data.hasRecievedReady; sendHello = data.hasRecievedReady;
} }
if(sendHello) { if(sendHello) {
sendHelloPacket(player); sendHelloPacket(data.pluginChName, player);
} }
return data.openFuture; return data.openFuture;
} }
protected static void sendHelloPacket(Player player) { protected static void sendHelloPacket(String channel, Player player) {
player.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), EaglerBackendRPCProtocol.CHANNEL_NAME, HelloPacketFactory.BASE_HELLO_PACKET); player.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), channel, HelloPacketFactory.BASE_HELLO_PACKET);
} }
protected static EaglerXBukkitImpl createFromHandshakeInternal(PlayerDataObj playerDataObj, SPacketRPCEnabledSuccess pkt) { protected static EaglerXBukkitImpl createFromHandshakeInternal(PlayerDataObj playerDataObj, SPacketRPCEnabledSuccess pkt) {
@ -362,7 +362,7 @@ public class EaglerXBukkitImpl implements IEaglerXBukkitAPI {
.warning("[" + playerObj.getName() + "] Packet type " + packet.getClass().getSimpleName() .warning("[" + playerObj.getName() + "] Packet type " + packet.getClass().getSimpleName()
+ " was the wrong length after serialization: " + ret.length + " != " + len); + " was the wrong length after serialization: " + ret.length + " != " + len);
} }
playerObj.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), EaglerBackendRPCProtocol.CHANNEL_NAME, ret); playerObj.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), playerDataObj.pluginChName, ret);
} }
protected EaglerBackendRPCPacket decodePacket(byte[] data) throws IOException { protected EaglerBackendRPCPacket decodePacket(byte[] data) throws IOException {

View File

@ -41,6 +41,8 @@ public class PlayerDataObj {
public final Player player; public final Player player;
public String pluginChName = null;
public volatile boolean hasRecievedReady = false; public volatile boolean hasRecievedReady = false;
public volatile boolean isSupported = true; public volatile boolean isSupported = true;
public volatile EaglerXBukkitImpl currentAPI = null; public volatile EaglerXBukkitImpl currentAPI = null;
@ -60,12 +62,13 @@ public class PlayerDataObj {
this.player = player; this.player = player;
} }
public void firePluginReadyMsgRecieved() { public void firePluginReadyMsgRecieved(boolean modern) {
synchronized(this) { synchronized(this) {
if(!hasRecievedReady) { if(!hasRecievedReady) {
hasRecievedReady = true; hasRecievedReady = true;
pluginChName = modern ? EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN : EaglerBackendRPCProtocol.CHANNEL_NAME;
if(openFuture != null) { if(openFuture != null) {
EaglerXBukkitImpl.sendHelloPacket(player); EaglerXBukkitImpl.sendHelloPacket(pluginChName, player);
} }
} }
} }
@ -121,7 +124,7 @@ public class PlayerDataObj {
if(pkt.selectedRPCProtocol != EaglerBackendRPCProtocol.V1.vers) { if(pkt.selectedRPCProtocol != EaglerBackendRPCProtocol.V1.vers) {
try { try {
// send raw CPacketRPCDisabled // send raw CPacketRPCDisabled
player.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), EaglerBackendRPCProtocol.CHANNEL_NAME, new byte[] { 0x03 }); player.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), pluginChName, new byte[] { 0x03 });
}finally { }finally {
apiFuture.fireExceptionInternal(new EaglerRPCException("Server tried to select an unsupported protocol: " + pkt.selectedRPCProtocol)); apiFuture.fireExceptionInternal(new EaglerRPCException("Server tried to select an unsupported protocol: " + pkt.selectedRPCProtocol));
} }

View File

@ -0,0 +1,40 @@
package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl;
import java.util.concurrent.Executor;
import com.google.common.util.concurrent.MoreExecutors;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class SameThreadExecutor {
public static final Executor SAME_THREAD_EXECUTOR;
static {
Executor fuck;
try {
fuck = (Executor) MoreExecutors.class.getDeclaredMethod("newDirectExecutorService").invoke(null);
}catch(Throwable t) {
try {
fuck = (Executor) MoreExecutors.class.getDeclaredMethod("sameThreadExecutor").invoke(null);
}catch(Throwable t2) {
throw new RuntimeException("Google fucked up!", t2);
}
}
SAME_THREAD_EXECUTOR = fuck;
}
}

View File

@ -1,5 +1,5 @@
name: EaglercraftXBukkitAPI name: EaglercraftXBukkitAPI
version: 1.0.0 version: 1.0.1
main: net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.EaglerXBukkitAPIPlugin main: net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.EaglerXBukkitAPIPlugin
description: Official EaglercraftX API for Bukkit servers description: Official EaglercraftX API for Bukkit servers
author: lax1dude author: lax1dude

View File

@ -63,6 +63,9 @@ public enum EaglerBackendRPCProtocol {
public static final String CHANNEL_NAME = "EAG|1.8-RPC"; public static final String CHANNEL_NAME = "EAG|1.8-RPC";
public static final String CHANNEL_NAME_READY = "EAG|1.8-Ready"; public static final String CHANNEL_NAME_READY = "EAG|1.8-Ready";
public static final String CHANNEL_NAME_MODERN = "eagler:1-8-rpc";
public static final String CHANNEL_NAME_READY_MODERN = "eagler:1-8-ready";
public static final int CLIENT_TO_SERVER = 0; public static final int CLIENT_TO_SERVER = 0;
public static final int SERVER_TO_CLIENT = 1; public static final int SERVER_TO_CLIENT = 1;