Implemented more ways to get Ping on bukkit
Affects issues: - Close #1962
This commit is contained in:
parent
170add8989
commit
db0d3ff6ac
|
@ -31,7 +31,6 @@ import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
|||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.PingStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
||||
import net.playeranalytics.plugin.scheduling.TimeAmount;
|
||||
import net.playeranalytics.plugin.server.Listeners;
|
||||
|
@ -44,10 +43,6 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
@ -69,9 +64,6 @@ public class BukkitPingCounter extends TaskSystem.Task implements Listener {
|
|||
|
||||
private static boolean pingMethodAvailable;
|
||||
|
||||
private static MethodHandle pingField;
|
||||
private static MethodHandle getHandleMethod;
|
||||
|
||||
private final Map<UUID, List<DateObj<Integer>>> playerHistory;
|
||||
|
||||
private final Listeners listeners;
|
||||
|
@ -80,6 +72,8 @@ public class BukkitPingCounter extends TaskSystem.Task implements Listener {
|
|||
private final ServerInfo serverInfo;
|
||||
private final RunnableFactory runnableFactory;
|
||||
|
||||
private PingMethod pingMethod;
|
||||
|
||||
@Inject
|
||||
public BukkitPingCounter(
|
||||
Listeners listeners,
|
||||
|
@ -89,57 +83,46 @@ public class BukkitPingCounter extends TaskSystem.Task implements Listener {
|
|||
RunnableFactory runnableFactory
|
||||
) {
|
||||
this.listeners = listeners;
|
||||
BukkitPingCounter.loadPingMethodDetails();
|
||||
this.config = config;
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
this.runnableFactory = runnableFactory;
|
||||
playerHistory = new HashMap<>();
|
||||
|
||||
Optional<PingMethod> pingMethod = loadPingMethod();
|
||||
if (pingMethod.isPresent()) {
|
||||
this.pingMethod = pingMethod.get();
|
||||
pingMethodAvailable = true;
|
||||
} else {
|
||||
pingMethodAvailable = false;
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<PingMethod> loadPingMethod() {
|
||||
PingMethod[] methods = new PingMethod[]{
|
||||
new PaperPingMethod(),
|
||||
new ReflectiveLatencyFieldMethod(),
|
||||
new ReflectivePingFieldMethod(),
|
||||
new ReflectiveLevelEntityPlayerLatencyFieldMethod(),
|
||||
new ReflectiveUnmappedLatencyFieldMethod()
|
||||
};
|
||||
StringBuilder reasonsForUnavailability = new StringBuilder();
|
||||
|
||||
private static void loadPingMethodDetails() {
|
||||
pingMethodAvailable = isPingMethodAvailable();
|
||||
|
||||
MethodHandle localHandle = null;
|
||||
MethodHandle localPing = null;
|
||||
if (!pingMethodAvailable) {
|
||||
try {
|
||||
Class<?> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
|
||||
Class<?> entityPlayer = Reflection.getMinecraftClass("EntityPlayer");
|
||||
|
||||
Lookup lookup = MethodHandles.publicLookup();
|
||||
|
||||
Method getHandleMethod = craftPlayerClass.getDeclaredMethod("getHandle");
|
||||
localHandle = lookup.unreflect(getHandleMethod);
|
||||
|
||||
localPing = lookup.findGetter(entityPlayer, "ping", Integer.TYPE);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | NoSuchFieldException reflectiveEx) {
|
||||
Logger.getGlobal().log(
|
||||
Level.WARNING,
|
||||
"Plan: Could not register Ping counter due to " + reflectiveEx
|
||||
);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Logger.getGlobal().log(
|
||||
Level.WARNING,
|
||||
"Plan: No Ping method handle found - Ping will not be recorded."
|
||||
);
|
||||
for (PingMethod potentialMethod : methods) {
|
||||
if (potentialMethod.isAvailable()) {
|
||||
return Optional.of(potentialMethod);
|
||||
} else {
|
||||
reasonsForUnavailability.append("\n ").append(potentialMethod.getReasonForUnavailability());
|
||||
}
|
||||
}
|
||||
Logger.getGlobal().log(
|
||||
Level.WARNING,
|
||||
"Plan: No Ping method found - Ping will not be recorded:" + reasonsForUnavailability.toString()
|
||||
);
|
||||
|
||||
getHandleMethod = localHandle;
|
||||
pingField = localPing;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static boolean isPingMethodAvailable() {
|
||||
try {
|
||||
//Only available in Paper
|
||||
Class.forName("org.bukkit.entity.Player$Spigot").getDeclaredMethod("getPing");
|
||||
return true;
|
||||
} catch (ClassNotFoundException | NoSuchMethodException noSuchMethodEx) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(RunnableFactory runnableFactory) {
|
||||
|
@ -164,7 +147,7 @@ public class BukkitPingCounter extends TaskSystem.Task implements Listener {
|
|||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
int ping = getPing(player);
|
||||
if (ping < -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
if (ping <= -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
// Don't accept bad values
|
||||
continue;
|
||||
}
|
||||
|
@ -191,22 +174,9 @@ public class BukkitPingCounter extends TaskSystem.Task implements Listener {
|
|||
|
||||
private int getPing(Player player) {
|
||||
if (pingMethodAvailable) {
|
||||
// This method is from Paper
|
||||
return player.spigot().getPing();
|
||||
}
|
||||
|
||||
return getReflectionPing(player);
|
||||
}
|
||||
|
||||
private int getReflectionPing(Player player) {
|
||||
try {
|
||||
Object entityPlayer = getHandleMethod.invoke(player);
|
||||
return (int) pingField.invoke(entityPlayer);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
} catch (Throwable throwable) {
|
||||
throw (Error) throwable;
|
||||
return pingMethod.getPing(player);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PaperPingMethod implements PingMethod {
|
||||
|
||||
private String reasonForUnavailability;
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
try {
|
||||
//Only available in Paper
|
||||
Class.forName("org.bukkit.entity.Player$Spigot").getDeclaredMethod("getPing");
|
||||
return true;
|
||||
} catch (ClassNotFoundException | NoSuchMethodException noSuchMethodEx) {
|
||||
reasonForUnavailability = noSuchMethodEx.toString();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
return player.spigot().getPing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReasonForUnavailability() {
|
||||
return reasonForUnavailability;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface PingMethod {
|
||||
|
||||
boolean isAvailable();
|
||||
|
||||
int getPing(Player player);
|
||||
|
||||
String getReasonForUnavailability();
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectiveLatencyFieldMethod implements PingMethod {
|
||||
|
||||
private static MethodHandle pingField;
|
||||
private static MethodHandle getHandleMethod;
|
||||
|
||||
private String reasonForUnavailability;
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
MethodHandle localHandle = null;
|
||||
MethodHandle localPing = null;
|
||||
try {
|
||||
Class<?> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
|
||||
Class<?> entityPlayer = Reflection.getMinecraftClass("EntityPlayer");
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||
|
||||
Method getHandleMethod = craftPlayerClass.getDeclaredMethod("getHandle");
|
||||
localHandle = lookup.unreflect(getHandleMethod);
|
||||
|
||||
localPing = lookup.findGetter(entityPlayer, "ping", Integer.TYPE);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | NoSuchFieldException | IllegalArgumentException reflectiveEx) {
|
||||
reasonForUnavailability = reflectiveEx.toString();
|
||||
return false;
|
||||
}
|
||||
getHandleMethod = localHandle;
|
||||
pingField = localPing;
|
||||
return pingField != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
try {
|
||||
Object entityPlayer = getHandleMethod.invoke(player);
|
||||
return (int) pingField.invoke(entityPlayer);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
} catch (Throwable throwable) {
|
||||
throw (Error) throwable;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReasonForUnavailability() {
|
||||
return reasonForUnavailability;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectiveLevelEntityPlayerLatencyFieldMethod implements PingMethod {
|
||||
|
||||
private static MethodHandle pingField;
|
||||
private static MethodHandle getHandleMethod;
|
||||
|
||||
private String reasonForUnavailability;
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
MethodHandle localHandle = null;
|
||||
MethodHandle localPing = null;
|
||||
try {
|
||||
Class<?> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
|
||||
Class<?> entityPlayer = Class.forName("net.minecraft.server.level.EntityPlayer");
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||
|
||||
Method getHandleMethod = craftPlayerClass.getDeclaredMethod("getHandle");
|
||||
localHandle = lookup.unreflect(getHandleMethod);
|
||||
|
||||
localPing = lookup.findGetter(entityPlayer, "latency", Integer.TYPE);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | NoSuchFieldException | ClassNotFoundException | IllegalArgumentException reflectiveEx) {
|
||||
reasonForUnavailability = reflectiveEx.toString();
|
||||
return false;
|
||||
}
|
||||
getHandleMethod = localHandle;
|
||||
pingField = localPing;
|
||||
return pingField != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
try {
|
||||
Object entityPlayer = getHandleMethod.invoke(player);
|
||||
return (int) pingField.invoke(entityPlayer);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
} catch (Throwable throwable) {
|
||||
throw (Error) throwable;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReasonForUnavailability() {
|
||||
return reasonForUnavailability;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectivePingFieldMethod implements PingMethod {
|
||||
|
||||
private static MethodHandle pingField;
|
||||
private static MethodHandle getHandleMethod;
|
||||
|
||||
private String reasonForUnavailability;
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
MethodHandle localHandle = null;
|
||||
MethodHandle localPing = null;
|
||||
try {
|
||||
Class<?> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
|
||||
Class<?> entityPlayer = Reflection.getMinecraftClass("EntityPlayer");
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||
|
||||
Method getHandleMethod = craftPlayerClass.getDeclaredMethod("getHandle");
|
||||
localHandle = lookup.unreflect(getHandleMethod);
|
||||
|
||||
localPing = lookup.findGetter(entityPlayer, "ping", Integer.TYPE);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | NoSuchFieldException | IllegalArgumentException reflectiveEx) {
|
||||
reasonForUnavailability = reflectiveEx.toString();
|
||||
return false;
|
||||
}
|
||||
getHandleMethod = localHandle;
|
||||
pingField = localPing;
|
||||
return pingField != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
try {
|
||||
Object entityPlayer = getHandleMethod.invoke(player);
|
||||
return (int) pingField.invoke(entityPlayer);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
} catch (Throwable throwable) {
|
||||
throw (Error) throwable;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReasonForUnavailability() {
|
||||
return reasonForUnavailability;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectiveUnmappedLatencyFieldMethod implements PingMethod {
|
||||
|
||||
private static MethodHandle pingField;
|
||||
private static MethodHandle getHandleMethod;
|
||||
|
||||
private String reasonForUnavailability;
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
MethodHandle localHandle = null;
|
||||
MethodHandle localPing = null;
|
||||
try {
|
||||
Class<?> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
|
||||
Class<?> entityPlayer = Class.forName("net.minecraft.server.level.EntityPlayer");
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||
|
||||
Method getHandleMethod = craftPlayerClass.getDeclaredMethod("getHandle");
|
||||
localHandle = lookup.unreflect(getHandleMethod);
|
||||
|
||||
// e is latency in unmapped jar
|
||||
localPing = lookup.findGetter(entityPlayer, "e", Integer.TYPE);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | NoSuchFieldException | ClassNotFoundException | IllegalArgumentException reflectiveEx) {
|
||||
reasonForUnavailability = reflectiveEx.toString();
|
||||
return false;
|
||||
}
|
||||
getHandleMethod = localHandle;
|
||||
pingField = localPing;
|
||||
return pingField != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
try {
|
||||
Object entityPlayer = getHandleMethod.invoke(player);
|
||||
return (int) pingField.invoke(entityPlayer);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
} catch (Throwable throwable) {
|
||||
throw (Error) throwable;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReasonForUnavailability() {
|
||||
return reasonForUnavailability;
|
||||
}
|
||||
}
|
|
@ -90,7 +90,7 @@ public class BungeePingCounter extends TaskSystem.Task implements Listener {
|
|||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
|
||||
if (player != null) {
|
||||
int ping = getPing(player);
|
||||
if (ping < -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
if (ping <= -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
// Don't accept bad values
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public class NukkitPingCounter extends TaskSystem.Task implements Listener {
|
|||
Optional<Player> player = Server.getInstance().getPlayer(uuid);
|
||||
if (player.isPresent()) {
|
||||
int ping = player.get().getPing();
|
||||
if (ping < -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
if (ping <= -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
// Don't accept bad values
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class SpongePingCounter extends TaskSystem.Task {
|
|||
Optional<Player> player = Sponge.getServer().getPlayer(uuid);
|
||||
if (player.isPresent()) {
|
||||
int ping = getPing(player.get());
|
||||
if (ping < -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
if (ping <= -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
// Don't accept bad values
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public class VelocityPingCounter extends TaskSystem.Task {
|
|||
Player player = plugin.getProxy().getPlayer(uuid).orElse(null);
|
||||
if (player != null) {
|
||||
int ping = getPing(player);
|
||||
if (ping < -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
if (ping <= -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
// Don't accept bad values
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue