the bois
This commit is contained in:
commit
ae4da96810
BIN
lib/travertine-1.16-168.jar
Normal file
BIN
lib/travertine-1.16-168.jar
Normal file
Binary file not shown.
BIN
lib/velocity-3.1.1-98.jar
Normal file
BIN
lib/velocity-3.1.1-98.jar
Normal file
Binary file not shown.
99
pom.xml
Normal file
99
pom.xml
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>gg.spoofmc.spoofer</groupId>
|
||||
<artifactId>spoofer</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>rip.teams.spigot</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.8.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>rip.teams.spigot</groupId>
|
||||
<artifactId>spigot-server</artifactId>
|
||||
<version>1.8.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>travertine</groupId>
|
||||
<artifactId>travertine</artifactId>
|
||||
<version>1.16</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${basedir}/lib/travertine-1.16-168.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>1.16</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${basedir}/lib/velocity-3.1.1-98.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.11.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>4.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.20</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
94
src/main/java/gg/spoof/bungee/Spoof.java
Normal file
94
src/main/java/gg/spoof/bungee/Spoof.java
Normal file
@ -0,0 +1,94 @@
|
||||
package gg.spoof.bungee;
|
||||
|
||||
import gg.spoof.bungee.controller.PluginMessageController;
|
||||
import gg.spoof.bungee.controller.ProxyController;
|
||||
import gg.spoof.bungee.controller.RedisController;
|
||||
import gg.spoof.bungee.listener.BungeePingListener;
|
||||
import gg.spoof.bungee.util.ServerData;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
|
||||
public class Spoof extends Plugin {
|
||||
|
||||
@Getter
|
||||
private static Spoof instance;
|
||||
private final Map<String, ServerData> servers = new ConcurrentHashMap<>();
|
||||
private boolean debug;
|
||||
private ProxyController controller;
|
||||
|
||||
public Map<String, ServerData> getServers() {
|
||||
return this.servers;
|
||||
}
|
||||
|
||||
public void debug(String message) {
|
||||
if (this.debug)
|
||||
this.getLogger().info(message);
|
||||
}
|
||||
|
||||
public void debug(String message, Throwable throwable) {
|
||||
if (this.debug)
|
||||
this.getLogger().log(Level.INFO, message, throwable);
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
try {
|
||||
instance = this;
|
||||
final Path configFile = this.getDataFolder().toPath().resolve("config.yml");
|
||||
// ResourceLoader.loadDefaultResource(this.getClass().getClassLoader(), "bungee-config.yml", configFile);
|
||||
final Configuration config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile.toFile());
|
||||
|
||||
this.debug = config.getBoolean("settings.debug");
|
||||
this.registerController(config);
|
||||
this.setupServersCleanup();
|
||||
this.getProxy().getPluginManager().registerListener(this, new BungeePingListener(this));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
if (this.controller != null)
|
||||
this.controller.close();
|
||||
}
|
||||
|
||||
private void registerController(Configuration config) {
|
||||
String controllerType;
|
||||
switch (controllerType = config.getString("settings.controller.selected").toLowerCase()) {
|
||||
case "redis": {
|
||||
final String[] address = config.getString("settings.controller.redis.address").split(":", 2);
|
||||
final String password = config.getString("settings.controller.redis.password");
|
||||
this.controller = new RedisController(this, address[0], Integer.parseInt(address[1]), password);
|
||||
break;
|
||||
}
|
||||
case "messaging": {
|
||||
this.controller = new PluginMessageController(this);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RuntimeException("The controller type '" + controllerType + "' isn't valid!");
|
||||
}
|
||||
}
|
||||
this.getLogger().info("Using " + controllerType + " for the receiver.");
|
||||
}
|
||||
|
||||
private void setupServersCleanup() {
|
||||
this.getProxy().getScheduler().schedule(this, () -> {
|
||||
final long currentTIme = System.currentTimeMillis();
|
||||
for (Map.Entry<String, ServerData> serverSet : this.servers.entrySet()) {
|
||||
ServerData server = serverSet.getValue();
|
||||
if (currentTIme - server.getLastPing() <= TimeUnit.MINUTES.toMillis(1L)) continue;
|
||||
this.servers.remove(serverSet.getKey());
|
||||
}
|
||||
}, 10L, 10L, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
13
src/main/java/gg/spoof/bungee/SpoofAPI.java
Normal file
13
src/main/java/gg/spoof/bungee/SpoofAPI.java
Normal file
@ -0,0 +1,13 @@
|
||||
package gg.spoof.bungee;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SpoofAPI {
|
||||
|
||||
public static int getProxyCount() {
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
Spoof.getInstance().getServers().forEach((key, value) -> count.addAndGet(value.getOnline()));
|
||||
return count.get();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package gg.spoof.bungee.controller;
|
||||
|
||||
import gg.spoof.bungee.Spoof;
|
||||
import gg.spoof.common.proxy.ProxyChannelFormat;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
public class PluginMessageController extends ProxyController implements Listener {
|
||||
|
||||
public PluginMessageController(Spoof plugin) {
|
||||
super(plugin);
|
||||
plugin.getProxy().registerChannel(ProxyChannelFormat.TAG_SERVER_PLAYERS);
|
||||
plugin.getProxy().getPluginManager().registerListener(plugin, this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginMessage(PluginMessageEvent event) {
|
||||
if (!(event.getSender() instanceof Server))
|
||||
return;
|
||||
|
||||
if (!event.getTag().equals(ProxyChannelFormat.TAG_SERVER_PLAYERS))
|
||||
return;
|
||||
|
||||
try {
|
||||
final ProxyChannelFormat.ServerPlayers serverPlayers = ProxyChannelFormat.decodeServerPlayers(event.getData());
|
||||
this.updateServerPlayerCount(serverPlayers.getServerId(), serverPlayers.getCount());
|
||||
} catch (Exception ex) {
|
||||
this.plugin.debug("Error receiving server players", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int proxyPlayerCount = this.getProxyPlayerCount();
|
||||
byte[] proxyPlayerCountData = ProxyChannelFormat.encodeProxyPlayerCount(proxyPlayerCount);
|
||||
this.plugin.getProxy().getServers().values().forEach(serverInfo -> serverInfo.sendData(ProxyChannelFormat.TAG_PROXY_PLAYER_COUNT, proxyPlayerCountData, false));
|
||||
this.plugin.debug("Sent proxy player count " + proxyPlayerCount);
|
||||
} catch (Exception ex) {
|
||||
this.plugin.debug("Error sending proxy player count", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package gg.spoof.bungee.controller;
|
||||
|
||||
import gg.spoof.bungee.Spoof;
|
||||
import gg.spoof.bungee.util.ServerData;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ProxyController {
|
||||
|
||||
protected final Spoof plugin;
|
||||
|
||||
public abstract void close();
|
||||
|
||||
protected int getProxyPlayerCount() {
|
||||
return this.plugin.getServers().values().stream().mapToInt(ServerData::getOnline).sum();
|
||||
}
|
||||
|
||||
protected void updateServerPlayerCount(String server, int online) {
|
||||
this.plugin.getServers().computeIfAbsent(server, k -> new ServerData()).setOnline(online);
|
||||
this.plugin.debug("Updated server " + server + " player count to " + online);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package gg.spoof.bungee.controller;
|
||||
|
||||
import gg.spoof.bungee.Spoof;
|
||||
import gg.spoof.common.proxy.ProxyChannelFormat;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
|
||||
public class RedisController extends ProxyController {
|
||||
|
||||
private Jedis jedisRX;
|
||||
private Jedis jedisTX;
|
||||
|
||||
public RedisController(final Spoof plugin, String host, int port, String password) {
|
||||
super(plugin);
|
||||
this.jedisRX = this.create(host, port, password);
|
||||
this.jedisTX = this.create(host, port, password);
|
||||
|
||||
plugin.getProxy().getScheduler().runAsync(plugin, () -> {
|
||||
final JedisPubSub jedisPubSub = new JedisPubSub() {
|
||||
|
||||
@Override
|
||||
public void onMessage(String channel, String message) {
|
||||
try {
|
||||
final ProxyChannelFormat.ServerPlayers players = ProxyChannelFormat.decodeB64ServerPlayers(message);
|
||||
updateServerPlayerCount(players.getServerId(), players.getCount());
|
||||
} catch (Exception ex) {
|
||||
plugin.debug("Error receiving server players", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int proxyPlayerCount = RedisController.this.getProxyPlayerCount();
|
||||
jedisTX.publish("spoof:pr_pl_cnt", ProxyChannelFormat.encodeB64ProxyPlayerCount(proxyPlayerCount));
|
||||
plugin.debug("Sent total player count " + proxyPlayerCount);
|
||||
} catch (Exception ex) {
|
||||
plugin.debug("Error sending proxy player count", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(String channel, int subscribedChannels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnsubscribe(String channel, int subscribedChannels) {
|
||||
}
|
||||
};
|
||||
this.jedisRX.subscribe(jedisPubSub, ProxyChannelFormat.TAG_SERVER_PLAYERS);
|
||||
});
|
||||
}
|
||||
|
||||
private Jedis create(String host, int port, String password) {
|
||||
final Jedis jedis = new Jedis(host, port);
|
||||
jedis.connect();
|
||||
|
||||
if (!password.isEmpty())
|
||||
jedis.auth(password);
|
||||
|
||||
if (!jedis.isConnected())
|
||||
throw new IllegalStateException("Failed to connect to redis");
|
||||
|
||||
return jedis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.jedisRX != null) {
|
||||
this.jedisRX.close();
|
||||
this.jedisRX = null;
|
||||
}
|
||||
if (this.jedisTX != null) {
|
||||
this.jedisTX.close();
|
||||
this.jedisTX = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package gg.spoof.bungee.listener;
|
||||
|
||||
import gg.spoof.bungee.Spoof;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BungeePingListener implements Listener {
|
||||
|
||||
protected final Spoof plugin;
|
||||
|
||||
@EventHandler
|
||||
public void onProxyPing(ProxyPingEvent event) {
|
||||
final ServerPing ping = event.getResponse();
|
||||
final ServerPing.Players players = ping.getPlayers();
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
|
||||
this.plugin.getServers().forEach((key, value) -> count.addAndGet(value.getOnline()));
|
||||
this.plugin.debug("Setting proxy count to " + count + ".");
|
||||
|
||||
ping.setPlayers(new ServerPing.Players(players.getMax(), count.get(), players.getSample()));
|
||||
event.setResponse(ping);
|
||||
}
|
||||
|
||||
}
|
16
src/main/java/gg/spoof/bungee/util/ServerData.java
Normal file
16
src/main/java/gg/spoof/bungee/util/ServerData.java
Normal file
@ -0,0 +1,16 @@
|
||||
package gg.spoof.bungee.util;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ServerData {
|
||||
|
||||
private volatile int online;
|
||||
private volatile long lastPing;
|
||||
|
||||
public void setOnline(int online) {
|
||||
this.online = online;
|
||||
this.lastPing = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
72
src/main/java/gg/spoof/common/proxy/ProxyChannelFormat.java
Normal file
72
src/main/java/gg/spoof/common/proxy/ProxyChannelFormat.java
Normal file
@ -0,0 +1,72 @@
|
||||
package gg.spoof.common.proxy;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Base64;
|
||||
|
||||
public class ProxyChannelFormat {
|
||||
|
||||
public static final String TAG_SERVER_PLAYERS = "spoof:srv_pl";
|
||||
public static final String TAG_PROXY_PLAYER_COUNT = "spoof:pr_pl_cnt";
|
||||
|
||||
public static ServerPlayers decodeServerPlayers(byte[] message) throws IOException {
|
||||
try (final DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(message))) {
|
||||
final String serverId = dataInputStream.readUTF();
|
||||
final int count = dataInputStream.readInt();
|
||||
|
||||
return new ServerPlayers(serverId, count);
|
||||
}
|
||||
}
|
||||
|
||||
public static ServerPlayers decodeB64ServerPlayers(String message) throws IOException {
|
||||
return decodeServerPlayers(Base64.getDecoder().decode(message));
|
||||
}
|
||||
|
||||
public static byte[] encodeServerPlayers(ServerPlayers serverPlayers) throws IOException {
|
||||
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try (final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream)) {
|
||||
dataOutputStream.writeUTF(serverPlayers.getServerId());
|
||||
dataOutputStream.writeInt(serverPlayers.getCount());
|
||||
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static String encodeB64ServerPlayers(ServerPlayers serverPlayers) throws IOException {
|
||||
return Base64.getEncoder().encodeToString(encodeServerPlayers(serverPlayers));
|
||||
}
|
||||
|
||||
public static int decodeProxyPlayerCount(byte[] data) throws IOException {
|
||||
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
|
||||
try (final DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream)) {
|
||||
return dataInputStream.readInt();
|
||||
}
|
||||
}
|
||||
|
||||
public static int decodeB64ProxyPlayerCount(String message) throws IOException {
|
||||
return decodeProxyPlayerCount(Base64.getDecoder().decode(message));
|
||||
}
|
||||
|
||||
public static byte[] encodeProxyPlayerCount(int var0) throws IOException {
|
||||
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try (final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream)) {
|
||||
dataOutputStream.writeInt(var0);
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static String encodeB64ProxyPlayerCount(int var0) throws IOException {
|
||||
return Base64.getEncoder().encodeToString(encodeProxyPlayerCount(var0));
|
||||
}
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public static class ServerPlayers {
|
||||
|
||||
protected final String serverId;
|
||||
protected final int count;
|
||||
|
||||
}
|
||||
}
|
26
src/main/java/gg/spoof/common/utils/ResourceLoader.java
Normal file
26
src/main/java/gg/spoof/common/utils/ResourceLoader.java
Normal file
@ -0,0 +1,26 @@
|
||||
package gg.spoof.common.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ResourceLoader {
|
||||
|
||||
public static void loadDefaultResource(ClassLoader classLoader, String var1, Path path) throws IOException {
|
||||
if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) {
|
||||
final Path parent = path.getParent();
|
||||
Files.createDirectories(parent);
|
||||
|
||||
final InputStream resourceAsStream = classLoader.getResourceAsStream(var1);
|
||||
Files.copy(Objects.requireNonNull(resourceAsStream), parent, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
163
src/main/java/gg/spoof/spigot/Spoof.java
Normal file
163
src/main/java/gg/spoof/spigot/Spoof.java
Normal file
@ -0,0 +1,163 @@
|
||||
package gg.spoof.spigot;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import gg.spoof.spigot.api.ProxyController;
|
||||
import gg.spoof.spigot.api.SpoofConfig;
|
||||
import gg.spoof.spigot.api.manager.ModuleManager;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.commands.CmdCommand;
|
||||
import gg.spoof.spigot.controller.NoopController;
|
||||
import gg.spoof.spigot.controller.RedisController;
|
||||
import gg.spoof.spigot.listener.DeathHandler;
|
||||
import gg.spoof.spigot.listener.MiscHandler;
|
||||
import gg.spoof.spigot.listener.SpawnHandler;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import gg.spoof.spigot.module.*;
|
||||
import gg.spoof.spigot.module.fluctuation.AccountsRegistry;
|
||||
import gg.spoof.spigot.module.fluctuation.FluctuationModule;
|
||||
import gg.spoof.spigot.nms.NMSWrapper;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@Getter
|
||||
public class Spoof extends JavaPlugin {
|
||||
|
||||
@Getter
|
||||
private static Spoof plugin;
|
||||
public static Executor POOL;
|
||||
private final SpoofConfig spoofConfig = new SpoofConfig(this);
|
||||
private ProxyController proxyController = new NoopController();
|
||||
private NMSWrapper platform;
|
||||
private AccountsRegistry accounts;
|
||||
|
||||
public Spoof() {
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
POOL = Executors.newFixedThreadPool(5, new ThreadFactoryBuilder().setDaemon(true).setNameFormat("%d - Stellar Ghost").build());
|
||||
|
||||
this.saveDefaultConfig();
|
||||
this.loadConfiguration();
|
||||
this.setupCompatibility();
|
||||
|
||||
this.accounts = AccountsRegistry.create(this);
|
||||
|
||||
final PluginManager pluginManager = getServer().getPluginManager();
|
||||
Arrays.asList(
|
||||
new MiscHandler(this),
|
||||
new SpawnHandler(this),
|
||||
new DeathHandler(this),
|
||||
new CmdCommand(this, true)
|
||||
).forEach(it -> pluginManager.registerEvents(it, this));
|
||||
|
||||
this.setupProxyController();
|
||||
|
||||
Arrays.asList(
|
||||
// new PickupModule(this),
|
||||
// new PingModule(this),
|
||||
new FluctuationModule(this, true),
|
||||
// new ActionModule(this),
|
||||
new WelcomeModule(this)
|
||||
// new RankModule(this),
|
||||
// new VoteModule(this)
|
||||
).forEach(ModuleManager::registerModule);
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
PlayerManager.getPlayerMap().values().forEach(spoofPlayer -> this.getPlatform().removeSpoofPlayer(spoofPlayer));
|
||||
}
|
||||
|
||||
private void setupCompatibility() {
|
||||
try {
|
||||
final String packageName = Bukkit.getServer().getClass().getPackage().getName();
|
||||
final String version = packageName.substring(packageName.lastIndexOf(".") + 1);
|
||||
|
||||
final Class<?> aClass = Class.forName("gg.spoof.spigot.nms." + version + ".NMSWrapper");
|
||||
this.platform = (NMSWrapper) aClass.getDeclaredConstructor(Spoof.class).newInstance(this);
|
||||
} catch (Exception e) {
|
||||
this.debug("Error initializing platform support");
|
||||
this.getPluginLoader().disablePlugin(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadConfiguration() {
|
||||
this.reloadConfig();
|
||||
final FileConfiguration config = this.getConfig();
|
||||
for (TL message : TL.values()) {
|
||||
if (config.getString("messages." + message.getPath()) == null) continue;
|
||||
message.setMessage(config.getString("messages." + message.getPath()));
|
||||
}
|
||||
this.spoofConfig.load();
|
||||
}
|
||||
|
||||
public void setupProxyController() {
|
||||
this.proxyController.close();
|
||||
this.proxyController = new NoopController();
|
||||
|
||||
try {
|
||||
String controllerType;
|
||||
if (!this.getConfig().getBoolean("settings.proxy-mode", false)) {
|
||||
return;
|
||||
}
|
||||
switch (controllerType = this.getConfig().getString("settings.controller.selected", "redis").toLowerCase(Locale.ENGLISH)) {
|
||||
case "redis": {
|
||||
String[] address = this.getConfig().getString("settings.controller.redis.address").split(":", 2);
|
||||
String password = this.getConfig().getString("settings.controller.redis.password");
|
||||
this.proxyController = new RedisController(this, address[0], Integer.parseInt(address[1]), password);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("The controller type '" + controllerType + "' isn't valid! Please use the follow (REDIS, MESSAGING)");
|
||||
}
|
||||
}
|
||||
this.getServer().getScheduler().runTaskTimerAsynchronously(this, () -> this.proxyController.sendServerPlayerCount(), 100L, 100L);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
this.getLogger().log(Level.SEVERE, "Failed to init proxy controller", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWhitelisted(CommandSender commandSender) {
|
||||
if (!(commandSender instanceof Player))
|
||||
return true;
|
||||
|
||||
final Player player = (Player) commandSender;
|
||||
return this.spoofConfig.getWhitelistedUsers().contains(player.getUniqueId().toString())
|
||||
|| this.spoofConfig.getWhitelistedUsers().contains(player.getName());
|
||||
}
|
||||
|
||||
public void print(String message) {
|
||||
this.getLogger().info(message);
|
||||
}
|
||||
|
||||
public void print(String message, Throwable t) {
|
||||
this.getLogger().log(Level.INFO, message, t);
|
||||
}
|
||||
|
||||
public void debug(String message) {
|
||||
if (!this.spoofConfig.isDebug())
|
||||
return;
|
||||
|
||||
this.print(message);
|
||||
}
|
||||
|
||||
public void debug(String message, Throwable t) {
|
||||
if (!this.spoofConfig.isDebug())
|
||||
return;
|
||||
|
||||
this.print(message, t);
|
||||
}
|
||||
|
||||
}
|
9
src/main/java/gg/spoof/spigot/SpoofAPI.java
Normal file
9
src/main/java/gg/spoof/spigot/SpoofAPI.java
Normal file
@ -0,0 +1,9 @@
|
||||
package gg.spoof.spigot;
|
||||
|
||||
public class SpoofAPI {
|
||||
|
||||
public static int getTotalCount() {
|
||||
return Spoof.getPlugin().getProxyController().getTotalPlayerCount();
|
||||
}
|
||||
|
||||
}
|
10
src/main/java/gg/spoof/spigot/actions/Action.java
Normal file
10
src/main/java/gg/spoof/spigot/actions/Action.java
Normal file
@ -0,0 +1,10 @@
|
||||
package gg.spoof.spigot.actions;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Action {
|
||||
|
||||
void run(Player var1, String var2);
|
||||
|
||||
}
|
68
src/main/java/gg/spoof/spigot/actions/ActionRegistry.java
Normal file
68
src/main/java/gg/spoof/spigot/actions/ActionRegistry.java
Normal file
@ -0,0 +1,68 @@
|
||||
package gg.spoof.spigot.actions;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.util.StringUtil;
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Getter
|
||||
public class ActionRegistry {
|
||||
|
||||
private final Spoof plugin;
|
||||
private final Map<String, Action> actions = new ConcurrentHashMap<>();
|
||||
|
||||
public ActionRegistry(Spoof plugin) {
|
||||
this.plugin = plugin;
|
||||
this.addAction("console", (player, data) -> plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), data));
|
||||
this.addAction("player", Player::performCommand);
|
||||
this.addAction("broadcast", (player, data) -> plugin.getServer().broadcastMessage(data));
|
||||
this.addAction("message", CommandSender::sendMessage);
|
||||
this.addAction("chat", Player::chat);
|
||||
this.addAction("close", (player, data) -> player.closeInventory());
|
||||
this.addAction("json", (player, data) -> player.spigot().sendMessage(ComponentSerializer.parse(data)));
|
||||
}
|
||||
|
||||
public void addAction(String id, Action action) {
|
||||
this.actions.put(id.toUpperCase(), action);
|
||||
}
|
||||
|
||||
public void runActions(final Player player, List<String> items) {
|
||||
items.forEach(item -> {
|
||||
final String actionData = !item.contains(" ") ? "" : StringUtil.translate(item.split(" ", 2)[1]).replace("%player%", player.getName());
|
||||
final Action action = this.getAction(item);
|
||||
final Server server = player.getServer();
|
||||
|
||||
server.getScheduler().runTask(this.plugin, () -> {
|
||||
if (action != null) {
|
||||
action.run(player, actionData);
|
||||
} else {
|
||||
plugin.getServer().dispatchCommand(server.getConsoleSender(), item);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void runActions(Player player, String... items) {
|
||||
this.runActions(player, Arrays.asList(items));
|
||||
}
|
||||
|
||||
public Action getAction(String item) {
|
||||
boolean singleAction = !item.contains(" ");
|
||||
String actionPrefix = singleAction ? item : item.split(" ", 2)[0].toUpperCase();
|
||||
String rawAction = StringUtils.substringBetween(actionPrefix, "[", "]");
|
||||
if (rawAction != null) {
|
||||
return this.actions.get(rawAction);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
98
src/main/java/gg/spoof/spigot/api/Module.java
Normal file
98
src/main/java/gg/spoof/spigot/api/Module.java
Normal file
@ -0,0 +1,98 @@
|
||||
package gg.spoof.spigot.api;
|
||||
|
||||
import gg.spoof.spigot.api.manager.ModuleManager;
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public abstract class Module<T extends Plugin> {
|
||||
|
||||
protected final JavaPlugin plugin;
|
||||
|
||||
protected Module(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
protected Module() {
|
||||
this.plugin = JavaPlugin.getProvidingPlugin(this.getClass());
|
||||
}
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public String getIdentifier() {
|
||||
return this.getName().toLowerCase();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.getBoolean("enabled", false);
|
||||
}
|
||||
|
||||
public abstract String getAuthor();
|
||||
|
||||
public abstract String getVersion();
|
||||
|
||||
public String getRequiredPlugin() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void onEnable();
|
||||
|
||||
public abstract void onDisable();
|
||||
|
||||
public boolean isRegistered() {
|
||||
Validate.notNull(this.getIdentifier(), "Module identifier can not be null!");
|
||||
return ModuleManager.isRegistered(this.getIdentifier());
|
||||
}
|
||||
|
||||
public boolean canRegister() {
|
||||
return this.getRequiredPlugin() == null || Bukkit.getPluginManager().getPlugin(this.getRequiredPlugin()) != null;
|
||||
}
|
||||
|
||||
public boolean register() {
|
||||
Validate.notNull(this.getIdentifier(), "Module identifier can not be null!");
|
||||
return ModuleManager.registerModule(this);
|
||||
}
|
||||
|
||||
public String getString(String path, String def) {
|
||||
return this.plugin.getConfig().getString("modules." + this.getIdentifier().toLowerCase() + "." + path, def);
|
||||
}
|
||||
|
||||
public int getInt(String path, int def) {
|
||||
return this.plugin.getConfig().getInt("modules." + this.getIdentifier().toLowerCase() + "." + path, def);
|
||||
}
|
||||
|
||||
public long getLong(String path, long def) {
|
||||
return this.plugin.getConfig().getLong("modules." + this.getIdentifier().toLowerCase() + "." + path, def);
|
||||
}
|
||||
|
||||
public double getDouble(String path, double def) {
|
||||
return this.plugin.getConfig().getDouble("modules." + this.getIdentifier().toLowerCase() + "." + path, def);
|
||||
}
|
||||
|
||||
public boolean getBoolean(String path, boolean def) {
|
||||
return this.plugin.getConfig().getBoolean("modules." + this.getIdentifier().toLowerCase() + "." + path, def);
|
||||
}
|
||||
|
||||
public List<String> getStringList(String path) {
|
||||
return this.plugin.getConfig().getStringList("modules." + this.getIdentifier().toLowerCase() + "." + path);
|
||||
}
|
||||
|
||||
public Object get(String path, Object def) {
|
||||
return this.plugin.getConfig().get("modules." + this.getIdentifier().toLowerCase() + "." + path, def);
|
||||
}
|
||||
|
||||
public ConfigurationSection getConfigSection(String path) {
|
||||
return this.plugin.getConfig().getConfigurationSection("modules." + this.getIdentifier().toLowerCase() + "." + path);
|
||||
}
|
||||
|
||||
public ConfigurationSection getConfigSection() {
|
||||
return this.plugin.getConfig().getConfigurationSection("modules." + this.getIdentifier().toLowerCase());
|
||||
}
|
||||
|
||||
public boolean configurationContains(String path) {
|
||||
return this.plugin.getConfig().contains("modules." + this.getIdentifier().toLowerCase() + "." + path);
|
||||
}
|
||||
}
|
11
src/main/java/gg/spoof/spigot/api/ProxyController.java
Normal file
11
src/main/java/gg/spoof/spigot/api/ProxyController.java
Normal file
@ -0,0 +1,11 @@
|
||||
package gg.spoof.spigot.api;
|
||||
|
||||
public interface ProxyController {
|
||||
|
||||
int getTotalPlayerCount();
|
||||
|
||||
void sendServerPlayerCount();
|
||||
|
||||
void close();
|
||||
|
||||
}
|
53
src/main/java/gg/spoof/spigot/api/SpoofConfig.java
Normal file
53
src/main/java/gg/spoof/spigot/api/SpoofConfig.java
Normal file
@ -0,0 +1,53 @@
|
||||
package gg.spoof.spigot.api;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class SpoofConfig {
|
||||
|
||||
private final Spoof plugin;
|
||||
private boolean visible = true;
|
||||
private boolean debug = false;
|
||||
private boolean enableJoinLeave = true;
|
||||
private int joinCommandsDelay = 0;
|
||||
private List<String> joinCommands = Collections.emptyList();
|
||||
private String serverId = "none-specified";
|
||||
private List<String> whitelistedUsers = Collections.emptyList();
|
||||
private String spawnWorld;
|
||||
private double spawnX;
|
||||
private double spawnY;
|
||||
private double spawnZ;
|
||||
|
||||
public void load() {
|
||||
final FileConfiguration config = this.plugin.getConfig();
|
||||
this.visible = config.getBoolean("settings.show-bot-entity", true);
|
||||
this.debug = config.getBoolean("settings.debug", true);
|
||||
this.enableJoinLeave = config.getBoolean("settings.enable-join-leave", true);
|
||||
this.joinCommands = config.getStringList("settings.join-commands");
|
||||
this.joinCommandsDelay = config.getInt("settings.join-commands-delay", this.joinCommandsDelay);
|
||||
this.serverId = config.getString("settings.server-id", "none-specified");
|
||||
this.whitelistedUsers = config.getStringList("settings.whitelisted");
|
||||
this.spawnWorld = config.getString("settings.spawn-locations.world");
|
||||
this.spawnX = config.getInt("settings.spawn-locations.x");
|
||||
this.spawnY = config.getInt("settings.spawn-locations.y");
|
||||
this.spawnZ = config.getInt("settings.spawn-locations.z");
|
||||
}
|
||||
|
||||
public Location getSpawnLocation() {
|
||||
try {
|
||||
return new Location(this.plugin.getServer().getWorld(this.spawnWorld), this.spawnX, this.spawnY, this.spawnZ);
|
||||
} catch (Exception e) {
|
||||
this.plugin.debug("Couldn't find spawn location! Using default location");
|
||||
return this.plugin.getServer().getWorlds().get(0).getSpawnLocation();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
35
src/main/java/gg/spoof/spigot/api/SpoofPlayer.java
Normal file
35
src/main/java/gg/spoof/spigot/api/SpoofPlayer.java
Normal file
@ -0,0 +1,35 @@
|
||||
package gg.spoof.spigot.api;
|
||||
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@Getter
|
||||
public class SpoofPlayer {
|
||||
|
||||
private final UUID id;
|
||||
private final String name;
|
||||
private final PlayerManager.PlayerManagementType managementType;
|
||||
private Player player;
|
||||
|
||||
public SpoofPlayer(UUID id, String name, PlayerManager.PlayerManagementType managementType) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.managementType = managementType;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.player != null ? this.player : Bukkit.getPlayer(this.id);
|
||||
}
|
||||
|
||||
public void setPlayer(Player player) {
|
||||
if (!this.id.equals(player.getUniqueId()))
|
||||
throw new IllegalArgumentException("Id missmatch");
|
||||
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
}
|
107
src/main/java/gg/spoof/spigot/api/manager/ModuleManager.java
Normal file
107
src/main/java/gg/spoof/spigot/api/manager/ModuleManager.java
Normal file
@ -0,0 +1,107 @@
|
||||
package gg.spoof.spigot.api.manager;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.Module;
|
||||
import gg.spoof.spigot.module.InternalModule;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
public class ModuleManager {
|
||||
|
||||
private static final Map<String, Map.Entry<Module<?>, Boolean>> modules = new HashMap<>();
|
||||
|
||||
public static boolean isRegistered(String identifier) {
|
||||
return ModuleManager.getRegisteredIdentifiers().stream().filter(id -> id.equalsIgnoreCase(identifier)).findFirst().orElse(null) != null;
|
||||
}
|
||||
|
||||
public static void unregisterModule(String identifier) {
|
||||
Validate.notNull(identifier, "Identifier can not be null");
|
||||
Map.Entry<Module<?>, Boolean> moduleEntry = modules.remove(identifier.toLowerCase());
|
||||
if (moduleEntry != null && moduleEntry.getValue()) {
|
||||
ModuleManager.setModuleDisabled(moduleEntry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getRegisteredIdentifiers() {
|
||||
return ImmutableSet.copyOf(modules.keySet());
|
||||
}
|
||||
|
||||
public static Map<String, Module<?>> getModules() {
|
||||
return modules.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> (entry.getValue()).getKey()));
|
||||
}
|
||||
|
||||
protected static void unregisterAll() {
|
||||
ModuleManager.unregisterAllProvidedModules();
|
||||
modules.clear();
|
||||
}
|
||||
|
||||
public static void unregisterAllProvidedModules() {
|
||||
if (modules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ModuleManager.getModules().values().forEach(module -> {
|
||||
if (module instanceof InternalModule) {
|
||||
ModuleManager.unregisterModule(module.getIdentifier());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean registerModule(Module<?> module) {
|
||||
Validate.notNull(module, "Module can not be null");
|
||||
Validate.notNull(module.getIdentifier(), "Identifier can not be null");
|
||||
|
||||
if (!module.canRegister() || ModuleManager.isRegistered(module.getIdentifier()))
|
||||
return false;
|
||||
|
||||
boolean enabled = module.isEnabled();
|
||||
|
||||
if (enabled)
|
||||
enabled = ModuleManager.setModuleEnabled(module);
|
||||
|
||||
modules.put(module.getIdentifier().toLowerCase(), new AbstractMap.SimpleEntry<>(module, enabled));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void reloadModules() {
|
||||
modules.values().forEach(moduleEntry -> {
|
||||
boolean enabled;
|
||||
final Module module = moduleEntry.getKey();
|
||||
|
||||
if (moduleEntry.getValue())
|
||||
ModuleManager.setModuleDisabled(module);
|
||||
|
||||
|
||||
if (enabled = module.isEnabled())
|
||||
enabled = ModuleManager.setModuleEnabled(module);
|
||||
|
||||
moduleEntry.setValue(enabled);
|
||||
});
|
||||
}
|
||||
|
||||
protected static boolean setModuleEnabled(Module<?> module) {
|
||||
try {
|
||||
module.onEnable();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
Spoof.getPlugin().print("Failed to enable module " + module.getName(), t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean setModuleDisabled(Module<?> module) {
|
||||
try {
|
||||
module.onDisable();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
Spoof.getPlugin().print("Failed to disable module " + module.getName(), t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
89
src/main/java/gg/spoof/spigot/api/manager/PlayerManager.java
Normal file
89
src/main/java/gg/spoof/spigot/api/manager/PlayerManager.java
Normal file
@ -0,0 +1,89 @@
|
||||
package gg.spoof.spigot.api.manager;
|
||||
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerManager {
|
||||
|
||||
private static final ConcurrentHashMap<UUID, SpoofPlayer> PLAYER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
public static Map<UUID, SpoofPlayer> getPlayerMap() {
|
||||
return PLAYER_MAP;
|
||||
}
|
||||
|
||||
public static int getLoadedAmount() {
|
||||
return PLAYER_MAP.size();
|
||||
}
|
||||
|
||||
public static int getLoadedAmount(PlayerManagementType mtype) {
|
||||
int counter = 0;
|
||||
for (SpoofPlayer spoofPlayer : PLAYER_MAP.values()) {
|
||||
if (spoofPlayer.getManagementType() != mtype) continue;
|
||||
++counter;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
public static boolean exists(Player player) {
|
||||
return PLAYER_MAP.containsKey(player.getUniqueId());
|
||||
}
|
||||
|
||||
public static SpoofPlayer getPlayer(Player player) {
|
||||
return PLAYER_MAP.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public static SpoofPlayer getPlayer(String player) {
|
||||
return PLAYER_MAP.values().stream().filter(spoofPlayer -> spoofPlayer.getName().equalsIgnoreCase(player)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static SpoofPlayer getPlayer(UUID ID) {
|
||||
return PLAYER_MAP.get(ID);
|
||||
}
|
||||
|
||||
public static SpoofPlayer[] getRandomPlayers(int count) {
|
||||
SpoofPlayer[] players = PLAYER_MAP.values().toArray(new SpoofPlayer[0]);
|
||||
Collections.shuffle(Arrays.asList(players));
|
||||
return players.length < count ? players : Arrays.copyOfRange(players, 0, count);
|
||||
}
|
||||
|
||||
public static SpoofPlayer getRandomPlayer() {
|
||||
if (PLAYER_MAP.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
SpoofPlayer[] players = PLAYER_MAP.values().toArray(new SpoofPlayer[0]);
|
||||
return players[ThreadLocalRandom.current().nextInt(players.length)];
|
||||
}
|
||||
|
||||
public static SpoofPlayer getRandomPlayer(PlayerManagementType mtype) {
|
||||
if (PLAYER_MAP.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
SpoofPlayer[] players = PLAYER_MAP.values().stream().filter(player -> player.getManagementType() == mtype).toArray(SpoofPlayer[]::new);
|
||||
return players[ThreadLocalRandom.current().nextInt(players.length)];
|
||||
}
|
||||
|
||||
public static SpoofPlayer addPlayer(UUID id, String name, PlayerManagementType mtype) {
|
||||
if (PLAYER_MAP.containsKey(id)) {
|
||||
throw new IllegalArgumentException("Player with id " + id + " already exists");
|
||||
}
|
||||
SpoofPlayer player = new SpoofPlayer(id, name, mtype);
|
||||
PLAYER_MAP.put(id, player);
|
||||
return player;
|
||||
}
|
||||
|
||||
public static void removePlayer(UUID id) {
|
||||
PLAYER_MAP.remove(id);
|
||||
}
|
||||
|
||||
public enum PlayerManagementType {
|
||||
AUTO,
|
||||
MANUAL
|
||||
}
|
||||
|
||||
}
|
103
src/main/java/gg/spoof/spigot/commands/CmdCommand.java
Normal file
103
src/main/java/gg/spoof/spigot/commands/CmdCommand.java
Normal file
@ -0,0 +1,103 @@
|
||||
package gg.spoof.spigot.commands;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
import gg.spoof.spigot.commands.subs.*;
|
||||
import gg.spoof.spigot.util.ReflectionUtil;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class CmdCommand implements Listener {
|
||||
|
||||
protected final Spoof plugin;
|
||||
protected final Map<Class<?>, AbstractCommand> subcommands = new HashMap<>();
|
||||
|
||||
protected void addCommand(AbstractCommand abstractCommand) {
|
||||
this.subcommands.put(abstractCommand.getClass(), abstractCommand);
|
||||
}
|
||||
|
||||
public CmdCommand(Spoof plugin, boolean premium) {
|
||||
this.plugin = plugin;
|
||||
this.addCommand(new CmdHelp(plugin));
|
||||
this.addCommand(new CmdReload(plugin));
|
||||
if (premium) {
|
||||
this.addCommand(new CmdAdd(plugin));
|
||||
this.addCommand(new CmdAddNm(plugin));
|
||||
this.addCommand(new CmdModules(plugin));
|
||||
this.addCommand(new CmdRemove(plugin));
|
||||
this.addCommand(new CmdSummon(plugin));
|
||||
// this.addCommand(new CmdAuction(plugin));
|
||||
// this.addCommand(new CmdDonation(plugin));
|
||||
}
|
||||
ReflectionUtil.validateInitBySpoof();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
protected void onPlayerCommandUse(PlayerCommandPreprocessEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
if (this.plugin.isWhitelisted(player)) {
|
||||
final String message = event.getMessage();
|
||||
final List<String> args = new ArrayList<>(Arrays.asList(message.split(" ")));
|
||||
|
||||
String enteredCommand = (!args.isEmpty() ? args.remove(0) : message).replace("/", "");
|
||||
|
||||
if (enteredCommand.equalsIgnoreCase("spoof")) {
|
||||
event.setCancelled(true);
|
||||
this.handleCommand(player, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
protected void onConsoleCommandUse(ServerCommandEvent event) {
|
||||
final String command = event.getCommand();
|
||||
final List<String> args = Arrays.asList(command.split(" "));
|
||||
final String remove = args.remove(0);
|
||||
|
||||
if (remove.equalsIgnoreCase("spoof")) {
|
||||
event.setCancelled(true);
|
||||
this.handleCommand(event.getSender(), args);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleCommand(CommandSender sender, List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
this.subcommands.get(CmdHelp.class).execute(sender, args);
|
||||
return;
|
||||
}
|
||||
|
||||
final String commandLabel = args.get(0);
|
||||
|
||||
this.getCommands().forEach(abstractCommand -> {
|
||||
final String label = abstractCommand.getLabel();
|
||||
final List<String> alias = abstractCommand.getAlias();
|
||||
|
||||
if (alias.contains(commandLabel) || label.equalsIgnoreCase(commandLabel)) {
|
||||
this.execute(sender, args, abstractCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void execute(final CommandSender sender, final List<String> args, final AbstractCommand abstractCommand) {
|
||||
final String permission = abstractCommand.getPermission();
|
||||
|
||||
if (sender.hasPermission(permission)) {
|
||||
abstractCommand.execute(sender, args);
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou don't have the permission to do that."));
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<AbstractCommand> getCommands() {
|
||||
return this.subcommands.values();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package gg.spoof.spigot.commands.extend;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.commands.extend.Executable;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public abstract class AbstractCommand implements Executable {
|
||||
|
||||
private final Spoof plugin;
|
||||
private final String label;
|
||||
private final List<String> alias = new ArrayList<>();
|
||||
|
||||
protected AbstractCommand(Spoof plugin, String label, String ... alias) {
|
||||
this.plugin = plugin;
|
||||
this.label = label;
|
||||
this.alias.addAll(Arrays.asList(alias));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package gg.spoof.spigot.commands.extend;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public interface Executable {
|
||||
|
||||
boolean execute(CommandSender sender, List<String> args);
|
||||
|
||||
String getDescription();
|
||||
|
||||
String getPermission();
|
||||
|
||||
boolean isPlayerRequired();
|
||||
|
||||
List<String> getAutoCompletes();
|
||||
|
||||
}
|
60
src/main/java/gg/spoof/spigot/commands/subs/CmdAdd.java
Normal file
60
src/main/java/gg/spoof/spigot/commands/subs/CmdAdd.java
Normal file
@ -0,0 +1,60 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import gg.spoof.spigot.nms.NMSWrapper;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CmdAdd extends AbstractCommand {
|
||||
|
||||
public CmdAdd(Spoof plugin) {
|
||||
super(plugin, "add");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
if (args.size() <= 1) {
|
||||
TL.INVALID_COMMAND_USAGE.send(sender, new Placeholder("<command>", "/spoof add <player>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
final String name = args.get(1);
|
||||
final Spoof plugin = Spoof.getPlugin();
|
||||
plugin.getPlatform().addSpoofPlayer(name, PlayerManager.PlayerManagementType.MANUAL);
|
||||
|
||||
TL.PLAYER_ADDED.send(sender, new Placeholder("<player>", name));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Add more players";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.add";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
68
src/main/java/gg/spoof/spigot/commands/subs/CmdAddNm.java
Normal file
68
src/main/java/gg/spoof/spigot/commands/subs/CmdAddNm.java
Normal file
@ -0,0 +1,68 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import gg.spoof.spigot.module.fluctuation.AccountsRegistry;
|
||||
import gg.spoof.spigot.module.fluctuation.NameMCAccountsRegistry;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CmdAddNm extends AbstractCommand {
|
||||
|
||||
public CmdAddNm(Spoof plugin) {
|
||||
super(plugin, "addnm");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
if (args.size() <= 1) {
|
||||
TL.INVALID_COMMAND_USAGE.send(sender, new Placeholder("<command>", "/spoof add <nm>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
final String amount = args.get(1);
|
||||
final Spoof plugin = Spoof.getPlugin();
|
||||
|
||||
try {
|
||||
final int amtI = Integer.parseInt(amount);
|
||||
for (int i = 0; i < amtI; i++) {
|
||||
final AccountsRegistry accounts = plugin.getAccounts();
|
||||
final UUID randomAccount = accounts.getRandomAccount();
|
||||
accounts.takeAccount(randomAccount);
|
||||
plugin.getPlatform().addSpoofPlayer(randomAccount.toString(), PlayerManager.PlayerManagementType.MANUAL);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
sender.sendMessage("Done");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Add more players";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.add";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/gg/spoof/spigot/commands/subs/CmdAuction.java
Normal file
74
src/main/java/gg/spoof/spigot/commands/subs/CmdAuction.java
Normal file
@ -0,0 +1,74 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class CmdAuction extends AbstractCommand {
|
||||
|
||||
public CmdAuction(Spoof plugin) {
|
||||
super(plugin, "auction");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
final String playerName = args.get(0);
|
||||
final SpoofPlayer spoofPlayer = PlayerManager.getPlayer(playerName);
|
||||
|
||||
final String s = args.get(1);
|
||||
final int price = Integer.parseInt(s);
|
||||
|
||||
if (spoofPlayer == null) {
|
||||
TL.NULL_PLAYER.send(sender, new Placeholder("<player>", playerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
final Player player = spoofPlayer.getPlayer();
|
||||
final ItemStack itemInHand = player.getItemInHand();
|
||||
final Material type = itemInHand.getType();
|
||||
|
||||
if (type == Material.AIR) {
|
||||
TL.MISSING_AUCTION_ITEM.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
// start auction
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Have the spoof player auction something";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.auction";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
72
src/main/java/gg/spoof/spigot/commands/subs/CmdDonation.java
Normal file
72
src/main/java/gg/spoof/spigot/commands/subs/CmdDonation.java
Normal file
@ -0,0 +1,72 @@
|
||||
//package gg.spoof.spigot.commands.subs;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.api.SpoofPlayer;
|
||||
//import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
//
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import net.buycraft.plugin.bukkit.events.BuycraftPurchaseEvent;
|
||||
//import org.bukkit.command.CommandSender;
|
||||
//import org.bukkit.configuration.file.FileConfiguration;
|
||||
//import org.bukkit.event.EventHandler;
|
||||
//import org.bukkit.event.Listener;
|
||||
//
|
||||
//public class CmdDonation extends AbstractCommand implements Listener {
|
||||
//
|
||||
// private final boolean enabled;
|
||||
// private final int minDelay;
|
||||
// private final int maxDelay;
|
||||
// private final int minResponders;
|
||||
// private final int maxResponders;
|
||||
// private final List<String> responses;
|
||||
// private final Map<String, List<String>> packages;
|
||||
//
|
||||
// public CmdDonation(Spoof plugin) {
|
||||
// super(plugin, "donation", new String[0]);
|
||||
// FileConfiguration config = plugin.getConfig();
|
||||
// this.enabled = config.getBoolean("modules.donations.enabled");
|
||||
// this.responses = config.getStringList("modules.donations.responses");
|
||||
// this.minDelay = config.getInt("modules.donations.settings.delay.min");
|
||||
// this.maxDelay = config.getInt("modules.donations.settings.delay.max");
|
||||
// this.minResponders = config.getInt("modules.donations.settings.responders.min");
|
||||
// this.maxResponders = config.getInt("modules.donations.settings.responders.min");
|
||||
// this.packages = new HashMap<>();
|
||||
// for (String dKey : config.getConfigurationSection("modules.donations.packages").getKeys(false)) {
|
||||
// this.packages.put(dKey, config.getStringList("modules.donations.packages." + dKey + ".message"));
|
||||
// }
|
||||
// this.getPlugin().getServer().getPluginManager().registerEvents(this, this.getPlugin());
|
||||
// }
|
||||
//
|
||||
// public String getRandomResponse(); was ntv
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onBuycraftPurchaseEvent(BuycraftPurchaseEvent var1); was ntv
|
||||
//
|
||||
// @Override
|
||||
// public boolean execute(CommandSender sender, List<String> args); was ntv
|
||||
//
|
||||
// @Override
|
||||
// public String getDescription(); was ntv
|
||||
//
|
||||
// @Override
|
||||
// public String getPermission(); was ntv
|
||||
//
|
||||
// @Override
|
||||
// public boolean isPlayerRequired(); was ntv
|
||||
//
|
||||
// @Override
|
||||
// public List<String> getAutoCompletes(); was ntv
|
||||
//
|
||||
// private static void lambda$execute$1(SpoofPlayer var0, String var1); was ntv
|
||||
//
|
||||
// private static void lambda$onBuycraftPurchaseEvent$0(SpoofPlayer var0, String var1); was ntv
|
||||
//
|
||||
//}
|
53
src/main/java/gg/spoof/spigot/commands/subs/CmdHelp.java
Normal file
53
src/main/java/gg/spoof/spigot/commands/subs/CmdHelp.java
Normal file
@ -0,0 +1,53 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class CmdHelp extends AbstractCommand {
|
||||
|
||||
public CmdHelp(Spoof plugin) {
|
||||
super(plugin, "help", "h");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
final Spoof plugin = Spoof.getPlugin();
|
||||
final FileConfiguration config = plugin.getConfig();
|
||||
|
||||
TL.message(sender, config.getStringList("messages.help"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "A help command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.help";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
62
src/main/java/gg/spoof/spigot/commands/subs/CmdModules.java
Normal file
62
src/main/java/gg/spoof/spigot/commands/subs/CmdModules.java
Normal file
@ -0,0 +1,62 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.manager.ModuleManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import gg.spoof.spigot.message.C;
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class CmdModules extends AbstractCommand {
|
||||
|
||||
public CmdModules(Spoof plugin) {
|
||||
super(plugin, "modules");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
final Spoof plugin = this.getPlugin();
|
||||
final FileConfiguration config = plugin.getConfig();
|
||||
final String configKey = "messages.modules-information";
|
||||
|
||||
config.getStringList(configKey).forEach(s -> {
|
||||
C.color(s,
|
||||
new Placeholder("<module-size>", ModuleManager.getModules().size()),
|
||||
new Placeholder("<module-loaded>", "<module-loaded>")
|
||||
);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "View modules";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.modules";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
55
src/main/java/gg/spoof/spigot/commands/subs/CmdReload.java
Normal file
55
src/main/java/gg/spoof/spigot/commands/subs/CmdReload.java
Normal file
@ -0,0 +1,55 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.manager.ModuleManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CmdReload extends AbstractCommand {
|
||||
|
||||
public CmdReload(Spoof plugin) {
|
||||
super(plugin, "reload", "r");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
final Spoof plugin = this.getPlugin();
|
||||
plugin.loadConfiguration();
|
||||
plugin.setupProxyController();
|
||||
ModuleManager.reloadModules();
|
||||
|
||||
TL.RELOADED.send(sender, new Placeholder("<version>", plugin.getDescription().getVersion()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Reload the config and messages!";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.reload";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
77
src/main/java/gg/spoof/spigot/commands/subs/CmdRemove.java
Normal file
77
src/main/java/gg/spoof/spigot/commands/subs/CmdRemove.java
Normal file
@ -0,0 +1,77 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import gg.spoof.spigot.nms.NMSWrapper;
|
||||
import gg.spoof.spigot.util.StringUtil;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CmdRemove extends AbstractCommand {
|
||||
|
||||
public CmdRemove(Spoof plugin) {
|
||||
super(plugin, "remove");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, List<String> args) {
|
||||
if (args.size() <= 1) {
|
||||
TL.INVALID_COMMAND_USAGE.send(sender, new Placeholder("<command>", "/spoof remove <player>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
final String playerName = args.get(1);
|
||||
final SpoofPlayer player;
|
||||
|
||||
if (StringUtil.isUUID(playerName)) {
|
||||
player = PlayerManager.getPlayer(UUID.fromString(playerName));
|
||||
} else {
|
||||
player = PlayerManager.getPlayer(playerName);
|
||||
}
|
||||
|
||||
if (player == null) {
|
||||
TL.INVALID_USER.send(sender, new Placeholder("<player>", playerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
final NMSWrapper platform = this.getPlugin().getPlatform();
|
||||
platform.removeSpoofPlayer(player);
|
||||
|
||||
TL.PLAYER_REMOVED.send(sender, new Placeholder("<player>", playerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Remove players";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.remove";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
67
src/main/java/gg/spoof/spigot/commands/subs/CmdSummon.java
Normal file
67
src/main/java/gg/spoof/spigot/commands/subs/CmdSummon.java
Normal file
@ -0,0 +1,67 @@
|
||||
package gg.spoof.spigot.commands.subs;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.commands.extend.AbstractCommand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import gg.spoof.spigot.message.TL;
|
||||
import net.minecraft.server.v1_8_R3.PlayerConnection;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CmdSummon extends AbstractCommand {
|
||||
|
||||
public CmdSummon(Spoof plugin) {
|
||||
super(plugin, "summon");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender commandSender, List<String> args) {
|
||||
if (args.size() <= 1) {
|
||||
TL.INVALID_COMMAND_USAGE.send(commandSender, new Placeholder("<command>", "/spoof summon <player>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
final String name = args.get(1);
|
||||
final Player sender = (Player) commandSender;
|
||||
final Player player = this.getPlugin().getServer().getPlayer(name);
|
||||
|
||||
if (player != null && PlayerManager.exists(player)) {
|
||||
player.teleport(sender.getLocation());
|
||||
TL.PLAYER_SUMMONED.send(commandSender, new Placeholder("<player>", player.getName()));
|
||||
} else TL.NULL_PLAYER.send(commandSender, new Placeholder("<player>", name));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Summon a spoofed player";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "spoof.summon";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAutoCompletes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
25
src/main/java/gg/spoof/spigot/controller/NoopController.java
Normal file
25
src/main/java/gg/spoof/spigot/controller/NoopController.java
Normal file
@ -0,0 +1,25 @@
|
||||
package gg.spoof.spigot.controller;
|
||||
|
||||
import gg.spoof.spigot.api.ProxyController;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class NoopController implements ProxyController {
|
||||
|
||||
public static NoopController INSTANCE;
|
||||
|
||||
public NoopController() {
|
||||
INSTANCE = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPlayerCount() {
|
||||
return Bukkit.getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendServerPlayerCount() {}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package gg.spoof.spigot.controller;
|
||||
|
||||
import gg.spoof.common.proxy.ProxyChannelFormat;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.ProxyController;
|
||||
import gg.spoof.spigot.controller.redis.RedisControllerPubSub;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
@Data
|
||||
public class RedisController implements ProxyController {
|
||||
|
||||
private final Spoof plugin;
|
||||
private Jedis jedisRX;
|
||||
private Jedis jedisTX;
|
||||
private int playerTotalCount = 0;
|
||||
|
||||
private final RedisControllerPubSub controllerPubSub;
|
||||
|
||||
public RedisController(Spoof plugin, String host, int port, String password) {
|
||||
this.plugin = plugin;
|
||||
this.jedisRX = this.create(host, port, password);
|
||||
this.jedisTX = this.create(host, port, password);
|
||||
|
||||
this.controllerPubSub = new RedisControllerPubSub(this.plugin, this);
|
||||
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, this::lambda$new$0);
|
||||
}
|
||||
|
||||
private Jedis create(String host, int port, String password) {
|
||||
final Jedis jedis = new Jedis(host, port);
|
||||
jedis.connect();
|
||||
|
||||
if (!password.isEmpty())
|
||||
jedis.auth(password);
|
||||
|
||||
if (!jedis.isConnected())
|
||||
throw new IllegalStateException("Failed to connect to redis");
|
||||
|
||||
return jedis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPlayerCount() {
|
||||
return this.playerTotalCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendServerPlayerCount() {
|
||||
try {
|
||||
final String channel = "spoof:srv_pl";
|
||||
final String serverId = this.plugin.getSpoofConfig().getServerId();
|
||||
final int size = Bukkit.getOnlinePlayers().size();
|
||||
|
||||
final ProxyChannelFormat.ServerPlayers serverPlayers = new ProxyChannelFormat.ServerPlayers(serverId, size);
|
||||
final String encoded = ProxyChannelFormat.encodeB64ServerPlayers(serverPlayers);
|
||||
|
||||
this.jedisTX.publish(channel, encoded);
|
||||
this.plugin.debug("Sent server player count " + size);
|
||||
} catch (Exception exception) {
|
||||
this.plugin.debug("Error sending server count");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.jedisRX.close();
|
||||
this.jedisTX.close();
|
||||
}
|
||||
|
||||
private void lambda$new$0() {
|
||||
this.jedisRX.subscribe(this.controllerPubSub, "spoof:pr_pl_cnt");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package gg.spoof.spigot.controller.redis;
|
||||
|
||||
import gg.spoof.common.proxy.ProxyChannelFormat;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.controller.RedisController;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class RedisControllerPubSub extends JedisPubSub {
|
||||
|
||||
public final Spoof plugin;
|
||||
private final RedisController redisController;
|
||||
|
||||
@Override
|
||||
public void onMessage(String channel, String message) {
|
||||
try {
|
||||
final int i = ProxyChannelFormat.decodeB64ProxyPlayerCount(message);
|
||||
this.redisController.setPlayerTotalCount(i);
|
||||
|
||||
String stringBuilder = "Updated total player count to " + this.redisController.getTotalPlayerCount();
|
||||
this.plugin.debug(stringBuilder);
|
||||
} catch (Exception exception) {
|
||||
this.plugin.debug("Error receiving proxy player count");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
41
src/main/java/gg/spoof/spigot/listener/DeathHandler.java
Normal file
41
src/main/java/gg/spoof/spigot/listener/DeathHandler.java
Normal file
@ -0,0 +1,41 @@
|
||||
package gg.spoof.spigot.listener;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.util.MathUtility;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class DeathHandler extends BukkitRunnable implements Listener {
|
||||
|
||||
protected final Spoof plugin;
|
||||
private Player player;
|
||||
|
||||
@EventHandler
|
||||
protected void onDeath(PlayerDeathEvent event) {
|
||||
final Player entity = event.getEntity();
|
||||
if (!PlayerManager.exists(entity))
|
||||
return;
|
||||
|
||||
this.player = entity;
|
||||
this.runTaskLater(this.plugin, MathUtility.getRandomNumber(10, 50));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.player.spigot().respawn();
|
||||
}
|
||||
|
||||
}
|
61
src/main/java/gg/spoof/spigot/listener/MiscHandler.java
Normal file
61
src/main/java/gg/spoof/spigot/listener/MiscHandler.java
Normal file
@ -0,0 +1,61 @@
|
||||
package gg.spoof.spigot.listener;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
|
||||
import gg.spoof.spigot.api.SpoofConfig;
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class MiscHandler implements Listener {
|
||||
|
||||
private final Spoof plugin;
|
||||
|
||||
@EventHandler
|
||||
protected void onJoin(PlayerJoinEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
if (PlayerManager.exists(player))
|
||||
this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> this.lambdaJoin(player), this.plugin.getSpoofConfig().getJoinCommandsDelay());
|
||||
|
||||
this.plugin.getProxyController().sendServerPlayerCount();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
protected void onQuit(PlayerQuitEvent event) {
|
||||
this.plugin.getProxyController().sendServerPlayerCount();
|
||||
final UUID uniqueId = event.getPlayer().getUniqueId();
|
||||
|
||||
if (PlayerManager.exists(event.getPlayer())) {
|
||||
final SpoofPlayer player = PlayerManager.getPlayer(uniqueId);
|
||||
PlayerManager.removePlayer(player.getId());
|
||||
|
||||
final String unexpectedQuit = "Unexpected quit of spoof player " + player.getName();
|
||||
final String debugTrace = "Debug trace";
|
||||
|
||||
this.plugin.debug(unexpectedQuit, new Throwable(debugTrace));
|
||||
}
|
||||
}
|
||||
|
||||
private void lambdaJoin(Player player) {
|
||||
final ConsoleCommandSender consoleSender = this.plugin.getServer().getConsoleSender();
|
||||
final SpoofConfig spoofConfig = this.plugin.getSpoofConfig();
|
||||
final String name = player.getName();
|
||||
|
||||
spoofConfig.getJoinCommands().forEach(s -> this.plugin.getServer().dispatchCommand(consoleSender, s.replace("%player%", name)));
|
||||
}
|
||||
|
||||
static Spoof access$000(MiscHandler miscHandler) {
|
||||
return miscHandler.plugin;
|
||||
}
|
||||
|
||||
}
|
37
src/main/java/gg/spoof/spigot/listener/SpawnHandler.java
Normal file
37
src/main/java/gg/spoof/spigot/listener/SpawnHandler.java
Normal file
@ -0,0 +1,37 @@
|
||||
package gg.spoof.spigot.listener;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.spigotmc.event.player.PlayerSpawnLocationEvent;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SpawnHandler implements Listener {
|
||||
|
||||
protected final Spoof plugin;
|
||||
|
||||
@EventHandler
|
||||
protected void onInitialSpawn(PlayerSpawnLocationEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
if (!PlayerManager.exists(player))
|
||||
return;
|
||||
|
||||
if (player.hasPlayedBefore())
|
||||
return;
|
||||
|
||||
final Location spawnLocation = this.plugin.getSpoofConfig().getSpawnLocation();
|
||||
event.setSpawnLocation(spawnLocation);
|
||||
}
|
||||
|
||||
}
|
66
src/main/java/gg/spoof/spigot/message/C.java
Normal file
66
src/main/java/gg/spoof/spigot/message/C.java
Normal file
@ -0,0 +1,66 @@
|
||||
package gg.spoof.spigot.message;
|
||||
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public final class C {
|
||||
public static String color(String s) {
|
||||
return ChatColor.translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
public static String color(String s, Placeholder ... placeHolders) {
|
||||
String message = s;
|
||||
for (Placeholder placeHolder : placeHolders) {
|
||||
message = C.color(message.replace(placeHolder.getPlaceHolder(), placeHolder.getReplace()));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public static List<String> color(List<String> s) {
|
||||
ArrayList<String> toReturn = new ArrayList<String>();
|
||||
for (String str : s) {
|
||||
toReturn.add(C.color(str));
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static List<String> color(List<String> messages, Placeholder ... placeholders) {
|
||||
ArrayList<String> colored = new ArrayList<String>();
|
||||
Iterator<String> iterator = messages.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
String line;
|
||||
String coloredLine = line = iterator.next();
|
||||
for (Placeholder placeholder : placeholders) {
|
||||
coloredLine = C.color(coloredLine.replace(placeholder.getPlaceHolder(), placeholder.getReplace()));
|
||||
}
|
||||
colored.add(coloredLine);
|
||||
}
|
||||
return colored;
|
||||
}
|
||||
|
||||
public static String strip(String s) {
|
||||
return ChatColor.stripColor(s);
|
||||
}
|
||||
|
||||
public static String strip(String string, Placeholder ... placeHolders) {
|
||||
String message = string;
|
||||
for (Placeholder placeHolder : placeHolders) {
|
||||
message = message.replace(placeHolder.getPlaceHolder(), placeHolder.getReplace());
|
||||
}
|
||||
return ChatColor.stripColor(message);
|
||||
}
|
||||
|
||||
public static String capitalizeFirstLetter(String original) {
|
||||
if (original == null || original.length() == 0) {
|
||||
return original;
|
||||
}
|
||||
return original.substring(0, 1).toUpperCase() + original.substring(1);
|
||||
}
|
||||
|
||||
private C() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
}
|
46
src/main/java/gg/spoof/spigot/message/Placeholder.java
Normal file
46
src/main/java/gg/spoof/spigot/message/Placeholder.java
Normal file
@ -0,0 +1,46 @@
|
||||
package gg.spoof.spigot.message;
|
||||
|
||||
public class Placeholder {
|
||||
|
||||
private final String placeHolder;
|
||||
private final String replace;
|
||||
|
||||
public Placeholder(String placeHolder, String replace) {
|
||||
this.placeHolder = placeHolder;
|
||||
this.replace = replace;
|
||||
}
|
||||
|
||||
public Placeholder(String placeHolder, boolean bool) {
|
||||
this.replace = String.valueOf(bool);
|
||||
this.placeHolder = placeHolder;
|
||||
}
|
||||
|
||||
public Placeholder(String placeHolder, int i) {
|
||||
this.replace = String.valueOf(i);
|
||||
this.placeHolder = placeHolder;
|
||||
}
|
||||
|
||||
public Placeholder(String placeHolder, double i) {
|
||||
this.replace = String.valueOf(i);
|
||||
this.placeHolder = placeHolder;
|
||||
}
|
||||
|
||||
public Placeholder(String placeHolder, long i) {
|
||||
this.replace = String.valueOf(i);
|
||||
this.placeHolder = placeHolder;
|
||||
}
|
||||
|
||||
public Placeholder(String placeHolder, float i) {
|
||||
this.replace = String.valueOf(i);
|
||||
this.placeHolder = placeHolder;
|
||||
}
|
||||
|
||||
public String getPlaceHolder() {
|
||||
return this.placeHolder;
|
||||
}
|
||||
|
||||
public String getReplace() {
|
||||
return this.replace;
|
||||
}
|
||||
|
||||
}
|
88
src/main/java/gg/spoof/spigot/message/TL.java
Normal file
88
src/main/java/gg/spoof/spigot/message/TL.java
Normal file
@ -0,0 +1,88 @@
|
||||
package gg.spoof.spigot.message;
|
||||
|
||||
import gg.spoof.spigot.message.C;
|
||||
import gg.spoof.spigot.message.Placeholder;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public enum TL {
|
||||
NO_PERMISSION("no_permission", "&cYou don't have the permission to do that."),
|
||||
INVALID_ARGUMENT_NUMBER("invalid-number", "&c'<argument>' has to be a number"),
|
||||
INVALID_COMMAND_USAGE("invalid-command-usage", "&eIncorrect Usage: &a<command>"),
|
||||
PLAYER_ONLY("player-only", "&cThis command is for players only!"),
|
||||
RELOADED("reload", "&8[&b&l\u26a1&8] &bSpoof v<version> &8- &fThe Ultimate Spoofing Solution&7."),
|
||||
PLAYER_NOT_ONLINE("player-not-online", "&cPlayer seems to be not online!"),
|
||||
INVALID_USER("invalid-user", "&b[&lSpoof&b] &7The username (&b<player>&7) specified is invalid!"),
|
||||
ALREADY_ONLINE("already-online", "&b[&lSpoof&b] &7That player (&b<player>&7) is already online!"),
|
||||
PLAYER_ADDED("player-added", "&b[&lSpoof&b] &7You added &b<player> &7to the server!"),
|
||||
PLAYER_REMOVED("player-removed", "&b[&lSpoof&b] &7You removed &b<player> &7from the server!"),
|
||||
NULL_PLAYER("player-not-found", "&b[&lSpoof&b] &7This spoof player (&b<player>&7) does not exist!"),
|
||||
MISSING_AUCTION_ITEM("missing-auction-item", "&b[&lSpoof&b] &7You must have something in your hand to auction!"),
|
||||
ITEM_AUCTIONED("item-auctioned", "&b[&lSpoof&b] &7You have auction an item under the spoofed player <player>!"),
|
||||
INVALID_DONATION_PACKAGE("invalid-donation-package", "&b[&lSpoof&b] &7This package ID you have provided does not exist!"),
|
||||
PLAYER_SUMMONED("player-teleported", "&aYou have summoned <player> to you!");
|
||||
|
||||
private String path;
|
||||
private String message;
|
||||
|
||||
private TL(String path, String message) {
|
||||
this.path = path;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void send(CommandSender sender) {
|
||||
if (sender instanceof Player) {
|
||||
sender.sendMessage(C.color(this.getMessage()));
|
||||
} else {
|
||||
sender.sendMessage(C.strip(this.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void send(CommandSender sender, Placeholder ... placeHolders) {
|
||||
if (sender instanceof Player) {
|
||||
sender.sendMessage(C.color(this.getMessage(), placeHolders));
|
||||
} else {
|
||||
sender.sendMessage(C.strip(this.getMessage(), placeHolders));
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcast(Placeholder ... placeholders) {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
player.sendMessage(C.color(this.getMessage(), placeholders));
|
||||
}
|
||||
}
|
||||
|
||||
public static void message(CommandSender sender, String message) {
|
||||
sender.sendMessage(C.color(message));
|
||||
}
|
||||
|
||||
public static void message(CommandSender sender, String message, Placeholder ... placeHolders) {
|
||||
sender.sendMessage(C.color(message, placeHolders));
|
||||
}
|
||||
|
||||
public static void message(CommandSender sender, List<String> message) {
|
||||
message.forEach(m -> sender.sendMessage(C.color(m)));
|
||||
}
|
||||
|
||||
public static void message(CommandSender sender, List<String> message, Placeholder ... placeHolders) {
|
||||
message.forEach(m -> sender.sendMessage(C.color(m, placeHolders)));
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
24
src/main/java/gg/spoof/spigot/module/ActionModule$1.java
Normal file
24
src/main/java/gg/spoof/spigot/module/ActionModule$1.java
Normal file
@ -0,0 +1,24 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import java.util.List;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.scheduler.BukkitRunnable;
|
||||
//
|
||||
//class ActionModule$1 extends BukkitRunnable {
|
||||
//
|
||||
// ActionModule$1() {
|
||||
// }
|
||||
//
|
||||
// public native void run();
|
||||
//
|
||||
// private native void performActions();
|
||||
//
|
||||
// private native void lambda$performActions$3(Player var1, List var2);
|
||||
//
|
||||
// private static native boolean lambda$performActions$2(List var0);
|
||||
//
|
||||
// private native List lambda$performActions$1(String var1);
|
||||
//
|
||||
// private native boolean lambda$performActions$0(int var1, String var2);
|
||||
//
|
||||
//}
|
54
src/main/java/gg/spoof/spigot/module/ActionModule.java
Normal file
54
src/main/java/gg/spoof/spigot/module/ActionModule.java
Normal file
@ -0,0 +1,54 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.actions.ActionRegistry;
|
||||
//import gg.spoof.spigot.module.InternalModule;
|
||||
//import gg.spoof.spigot.util.ReflectionUtil;
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.List;
|
||||
//import org.bukkit.scheduler.BukkitTask;
|
||||
//
|
||||
//public class ActionModule extends InternalModule {
|
||||
//
|
||||
// private int minDelay;
|
||||
// private int maxDelay;
|
||||
// private List<String> actions;
|
||||
// private ActionRegistry actionRegistry;
|
||||
// private BukkitTask task;
|
||||
//
|
||||
// public ActionModule(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// ReflectionUtil.validateInitBySpoof();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public String getAuthor() {
|
||||
// return plugin.getDescription().getAuthors().get(0);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getVersion() {
|
||||
// return plugin.getDescription().getVersion();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native void onEnable();
|
||||
//
|
||||
// @Override
|
||||
// public native void onDisable();
|
||||
//
|
||||
// private native void sched();
|
||||
//
|
||||
//// static native void access$000(ActionModule var0);
|
||||
////
|
||||
//// static native List access$100(ActionModule var0);
|
||||
////
|
||||
//// static native ActionRegistry access$200(ActionModule var0);
|
||||
//}
|
12
src/main/java/gg/spoof/spigot/module/InternalModule.java
Normal file
12
src/main/java/gg/spoof/spigot/module/InternalModule.java
Normal file
@ -0,0 +1,12 @@
|
||||
package gg.spoof.spigot.module;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.Module;
|
||||
|
||||
public abstract class InternalModule extends Module<Spoof> {
|
||||
|
||||
protected InternalModule(Spoof plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
}
|
13
src/main/java/gg/spoof/spigot/module/PickupModule$1.java
Normal file
13
src/main/java/gg/spoof/spigot/module/PickupModule$1.java
Normal file
@ -0,0 +1,13 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import org.bukkit.scheduler.BukkitRunnable;
|
||||
//
|
||||
//class PickupModule$1 extends BukkitRunnable {
|
||||
// PickupModule$1() {
|
||||
// }
|
||||
//
|
||||
// public native void run();
|
||||
//
|
||||
// private native void pickup();
|
||||
//
|
||||
//}
|
43
src/main/java/gg/spoof/spigot/module/PickupModule.java
Normal file
43
src/main/java/gg/spoof/spigot/module/PickupModule.java
Normal file
@ -0,0 +1,43 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.InternalModule;
|
||||
//import org.bukkit.plugin.Plugin;
|
||||
//import org.bukkit.scheduler.BukkitTask;
|
||||
//
|
||||
//public class PickupModule extends InternalModule {
|
||||
//
|
||||
// private int minDelay;
|
||||
// private int maxDelay;
|
||||
// private BukkitTask task;
|
||||
//
|
||||
// public PickupModule(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public String getAuthor() {
|
||||
// return plugin.getDescription().getAuthors().get(0);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getVersion() {
|
||||
// return plugin.getDescription().getVersion();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native void onEnable();
|
||||
//
|
||||
// @Override
|
||||
// public native void onDisable();
|
||||
//
|
||||
// private native void sched();
|
||||
//
|
||||
//// static native void access$000(PickupModule var0);
|
||||
////
|
||||
//// static native Plugin access$100(PickupModule var0);
|
||||
//
|
||||
//}
|
14
src/main/java/gg/spoof/spigot/module/PingModule$1.java
Normal file
14
src/main/java/gg/spoof/spigot/module/PingModule$1.java
Normal file
@ -0,0 +1,14 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import org.bukkit.scheduler.BukkitRunnable;
|
||||
//
|
||||
//class PingModule$1 extends BukkitRunnable {
|
||||
//
|
||||
// PingModule$1() {
|
||||
// }
|
||||
//
|
||||
// public native void run();
|
||||
//
|
||||
// private native void updatePing();
|
||||
//
|
||||
//}
|
47
src/main/java/gg/spoof/spigot/module/PingModule.java
Normal file
47
src/main/java/gg/spoof/spigot/module/PingModule.java
Normal file
@ -0,0 +1,47 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.InternalModule;
|
||||
//import org.bukkit.plugin.Plugin;
|
||||
//import org.bukkit.scheduler.BukkitTask;
|
||||
//
|
||||
//public class PingModule extends InternalModule {
|
||||
//
|
||||
// private int minDelay;
|
||||
// private int maxDelay;
|
||||
// private int minPing;
|
||||
// private int maxPing;
|
||||
// private BukkitTask task;
|
||||
//
|
||||
// public PingModule(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public String getAuthor() {
|
||||
// return plugin.getDescription().getAuthors().get(0);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getVersion() {
|
||||
// return plugin.getDescription().getVersion();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native void onEnable();
|
||||
//
|
||||
// @Override
|
||||
// public native void onDisable();
|
||||
//
|
||||
// private native void sched();
|
||||
//
|
||||
//// static native void access$000(PingModule var0);
|
||||
////
|
||||
//// static native int access$100(PingModule var0);
|
||||
////
|
||||
//// static native int access$200(PingModule var0);
|
||||
//
|
||||
//}
|
13
src/main/java/gg/spoof/spigot/module/VoteModule$1.java
Normal file
13
src/main/java/gg/spoof/spigot/module/VoteModule$1.java
Normal file
@ -0,0 +1,13 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import org.bukkit.scheduler.BukkitRunnable;
|
||||
//
|
||||
//class VoteModule$1 extends BukkitRunnable {
|
||||
// VoteModule$1() {
|
||||
// }
|
||||
//
|
||||
// public native void run();
|
||||
//
|
||||
// private native void vote();
|
||||
//
|
||||
//}
|
80
src/main/java/gg/spoof/spigot/module/VoteModule.java
Normal file
80
src/main/java/gg/spoof/spigot/module/VoteModule.java
Normal file
@ -0,0 +1,80 @@
|
||||
//package gg.spoof.spigot.module;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.InternalModule;
|
||||
//import gg.spoof.spigot.util.ReflectionUtil;
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//import java.util.UUID;
|
||||
//import org.bukkit.plugin.Plugin;
|
||||
//import org.bukkit.scheduler.BukkitTask;
|
||||
//
|
||||
//public class VoteModule extends InternalModule {
|
||||
//
|
||||
// private long expiration;
|
||||
// private int minDelay;
|
||||
// private int maxDelay;
|
||||
// private List<String> services;
|
||||
// private Map<UUID, Long> voted;
|
||||
// private BukkitTask task;
|
||||
//
|
||||
// public VoteModule(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// ReflectionUtil.validateInitBySpoof();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public String getAuthor() {
|
||||
// return plugin.getDescription().getAuthors().get(0);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getVersion() {
|
||||
// return plugin.getDescription().getVersion();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native void onEnable();
|
||||
//
|
||||
// @Override
|
||||
// public native void onDisable();
|
||||
//
|
||||
// private native void sched();
|
||||
//
|
||||
// static native void access$000(VoteModule var0);
|
||||
//
|
||||
// static native Map access$100(VoteModule var0);
|
||||
//
|
||||
// static native long access$200(VoteModule var0);
|
||||
//
|
||||
// static native Plugin access$300(VoteModule var0);
|
||||
//
|
||||
// static native Plugin access$400(VoteModule var0);
|
||||
//
|
||||
// static native List access$500(VoteModule var0);
|
||||
//
|
||||
// static native Plugin access$600(VoteModule var0);
|
||||
//
|
||||
// protected static class VoteSubmitRunnable implements Runnable {
|
||||
// protected final Spoof plugin;
|
||||
// protected final String name;
|
||||
// protected final List<String> services;
|
||||
//
|
||||
// public VoteSubmitRunnable(Spoof plugin, String name, List<String> services) {
|
||||
// this.plugin = plugin;
|
||||
// this.name = name;
|
||||
// this.services = services;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native void run();
|
||||
// }
|
||||
//}
|
95
src/main/java/gg/spoof/spigot/module/WelcomeModule.java
Normal file
95
src/main/java/gg/spoof/spigot/module/WelcomeModule.java
Normal file
@ -0,0 +1,95 @@
|
||||
package gg.spoof.spigot.module;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.util.MathUtility;
|
||||
import gg.spoof.spigot.util.ReflectionUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
public class WelcomeModule extends InternalModule implements Listener {
|
||||
|
||||
private int minDelay;
|
||||
private int maxDelay;
|
||||
private int minResponders;
|
||||
private int maxResponders;
|
||||
private List<String> joinResponses;
|
||||
private List<String> rejoinResponses;
|
||||
|
||||
public WelcomeModule(Spoof plugin) {
|
||||
super(plugin);
|
||||
ReflectionUtil.validateInitBySpoof();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Welcome";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return plugin.getDescription().getAuthors().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
minDelay = getInt("settings.delay.min", 10);
|
||||
maxDelay = getInt("settings.delay.max", 30);
|
||||
minResponders = getInt("settings.responders.min", 10);
|
||||
maxResponders = getInt("settings.responders.max", 20);
|
||||
joinResponses = getStringList("responses.join");
|
||||
rejoinResponses = getStringList("responses.rejoin");
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
final int randomNumber = MathUtility.getRandomNumber(this.minResponders, this.maxResponders);
|
||||
final SpoofPlayer[] randomPlayers = PlayerManager.getRandomPlayers(randomNumber);
|
||||
|
||||
for (SpoofPlayer spoof : randomPlayers) {
|
||||
if (spoof.getId().equals(player.getUniqueId()))
|
||||
return;
|
||||
|
||||
plugin.getServer().getScheduler().runTaskLater(plugin, () -> {
|
||||
if (player.isOnline() && !player.hasMetadata("vanished")) {
|
||||
final Player spoofPlayer = spoof.getPlayer();
|
||||
if (spoofPlayer != null && spoofPlayer.canSee(player)) {
|
||||
player.chat((spoofPlayer.hasPlayedBefore() ? this.getRejoinResponse() : this.getJoinResponse()).replace("%player%", spoofPlayer.getName()));
|
||||
}
|
||||
}
|
||||
}, MathUtility.getRandomNumber(minDelay, maxDelay));
|
||||
}
|
||||
}
|
||||
|
||||
public String getJoinResponse() {
|
||||
return this.joinResponses.get(ThreadLocalRandom.current().nextInt(this.joinResponses.size()));
|
||||
}
|
||||
|
||||
public String getRejoinResponse() {
|
||||
return this.rejoinResponses.get(ThreadLocalRandom.current().nextInt(this.joinResponses.size()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package gg.spoof.spigot.module.fluctuation;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.Module;
|
||||
import gg.spoof.spigot.util.StringUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class AccountsRegistry {
|
||||
|
||||
protected final Spoof plugin;
|
||||
protected final Set<UUID> accounts = new HashSet<>();
|
||||
|
||||
public static AccountsRegistry create(Spoof spoof) {
|
||||
final AccountsRegistry accountsRegistry = new NameMCAccountsRegistry(spoof);
|
||||
|
||||
accountsRegistry.loadAccounts();
|
||||
return accountsRegistry;
|
||||
}
|
||||
|
||||
protected void loadAccounts() {
|
||||
}
|
||||
|
||||
public void returnAccount(UUID uuid) {
|
||||
this.accounts.add(uuid);
|
||||
}
|
||||
|
||||
public void takeAccount(UUID uuid) {
|
||||
this.accounts.remove(uuid);
|
||||
}
|
||||
|
||||
public UUID getRandomAccount() {
|
||||
final ThreadLocalRandom current = ThreadLocalRandom.current();
|
||||
final int i = current.nextInt(this.accounts.size());
|
||||
|
||||
return (UUID) this.accounts.toArray()[i];
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package gg.spoof.spigot.module.fluctuation;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.module.InternalModule;
|
||||
import gg.spoof.spigot.util.Common;
|
||||
import gg.spoof.spigot.util.MathUtility;
|
||||
import gg.spoof.spigot.util.ReflectionUtil;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class FluctuationModule extends InternalModule {
|
||||
|
||||
private final boolean premium;
|
||||
private int minCheckDelay;
|
||||
private int maxCheckDelay;
|
||||
private double minPercent;
|
||||
private double maxPercent;
|
||||
private boolean async;
|
||||
private BukkitTask task;
|
||||
|
||||
private final AccountsRegistry accounts;
|
||||
|
||||
public FluctuationModule(Spoof plugin, boolean premium) {
|
||||
super(plugin);
|
||||
this.premium = premium;
|
||||
ReflectionUtil.validateInitBySpoof();
|
||||
|
||||
this.accounts = plugin.getAccounts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Fluctuation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return plugin.getDescription().getAuthors().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.minCheckDelay = getInt("settings.delay.min", 10);
|
||||
this.maxCheckDelay = getInt("settings.delay.max", 20);
|
||||
this.minPercent = getDouble("settings.percent.min", 2.0);
|
||||
this.maxPercent = getDouble("settings.percent.max", 2.5);
|
||||
this.async = getBoolean("async", false);
|
||||
|
||||
this.minPercent = Math.max(1.15, this.minPercent);
|
||||
this.maxPercent = Math.max(1.15, this.maxPercent);
|
||||
|
||||
if (this.premium) {
|
||||
((Spoof) this.plugin).print("Name generator generated " + accounts.getAccounts().size() + " minecraft accounts");
|
||||
}
|
||||
|
||||
this.sched();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
private void sched() {
|
||||
final int targetDelay = MathUtility.getRandomNumber(this.minCheckDelay, this.maxCheckDelay);
|
||||
final double targetPercent = Common.formatDouble(ThreadLocalRandom.current().nextDouble(this.minPercent, this.maxPercent));
|
||||
|
||||
if (this.async) {
|
||||
this.task = this.plugin.getServer().getScheduler().runTaskLaterAsynchronously(this.plugin, () -> {
|
||||
this.fluctuate(targetPercent);
|
||||
this.sched();
|
||||
}, 20L * targetDelay);
|
||||
} else {
|
||||
this.task = this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> {
|
||||
this.fluctuate(targetPercent);
|
||||
this.sched();
|
||||
}, 20L * targetDelay);
|
||||
}
|
||||
}
|
||||
|
||||
private void fluctuate(double multiplier) {
|
||||
final int real = Bukkit.getOnlinePlayers().size() - PlayerManager.getLoadedAmount();
|
||||
final double floor = Math.floor(real * multiplier);
|
||||
|
||||
final int autoLoadedAmount = PlayerManager.getLoadedAmount(PlayerManager.PlayerManagementType.AUTO);
|
||||
final Spoof plugin = Spoof.getPlugin();
|
||||
final double needed = floor - real - autoLoadedAmount;
|
||||
|
||||
if (needed <= 0) {
|
||||
plugin.debug("Skipping, the target count has been reached");
|
||||
return;
|
||||
}
|
||||
|
||||
final String bar = "---------------------------------";
|
||||
plugin.debug(bar);
|
||||
plugin.debug("Real: " + real + " | Target: " + floor + " | Multiplier: " + multiplier + " | Needed: " + needed);
|
||||
plugin.debug(bar);
|
||||
|
||||
final SpoofPlayer randomPlayer = PlayerManager.getRandomPlayer(PlayerManager.PlayerManagementType.AUTO);
|
||||
|
||||
if (randomPlayer != null) {
|
||||
plugin.debug("Removing a %player% from the the server".replace("%player%", Objects.requireNonNull(randomPlayer).getName()));
|
||||
|
||||
plugin.getPlatform().removeSpoofPlayer(randomPlayer);
|
||||
this.accounts.returnAccount(randomPlayer.getId());
|
||||
}
|
||||
|
||||
if (this.accounts.getAccounts().isEmpty()) {
|
||||
plugin.debug("Failed to add player, all players from database are online!");
|
||||
return;
|
||||
}
|
||||
|
||||
final UUID randomAccount = this.accounts.getRandomAccount();
|
||||
final Player player = plugin.getServer().getPlayer(randomAccount);
|
||||
|
||||
plugin.debug("Adding a player to the server.");
|
||||
|
||||
if (player != null) {
|
||||
plugin.debug("Player already exists on the server");
|
||||
return;
|
||||
}
|
||||
|
||||
this.accounts.takeAccount(randomAccount);
|
||||
assert randomPlayer != null;
|
||||
plugin.getPlatform().addSpoofPlayer(randomAccount.toString(), PlayerManager.PlayerManagementType.AUTO);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package gg.spoof.spigot.module.fluctuation;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonParser;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.Module;
|
||||
import gg.spoof.spigot.module.fluctuation.AccountsRegistry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NameMCAccountsRegistry extends AccountsRegistry {
|
||||
|
||||
public NameMCAccountsRegistry(Spoof plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAccounts() {
|
||||
try {
|
||||
final URL url = new URL("https://api.namemc.com/server/mc.hypixel.net/likes");
|
||||
final InputStreamReader inputStreamReader = new InputStreamReader(url.openStream());
|
||||
final JsonParser jsonParser = new JsonParser();
|
||||
final JsonArray asJsonArray = jsonParser.parse(inputStreamReader).getAsJsonArray();
|
||||
|
||||
asJsonArray.forEach(jsonElement -> this.accounts.add(UUID.fromString(jsonElement.getAsString())));
|
||||
inputStreamReader.close();
|
||||
} catch (IOException e) {
|
||||
this.plugin.print("Unable to load accounts from NameMC");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
//package gg.spoof.spigot.module.rank;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.rank.PermissionHook;
|
||||
//
|
||||
//import java.util.Map;
|
||||
//import java.util.UUID;
|
||||
//import java.util.concurrent.ConcurrentHashMap;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.permissions.PermissionAttachment;
|
||||
//
|
||||
//public class BukkitPermsHook extends PermissionHook {
|
||||
//
|
||||
// private final Map<UUID, PermissionAttachment> attachments = new ConcurrentHashMap<>();
|
||||
//
|
||||
// public BukkitPermsHook(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public native void addRank(Player player, String rankName);
|
||||
//
|
||||
// @Override
|
||||
// public native void cleanup(Player player);
|
||||
//
|
||||
// private native PermissionAttachment lambda$addRank$0(Player player, UUID uuid);
|
||||
//
|
||||
//}
|
50
src/main/java/gg/spoof/spigot/module/rank/LuckPermsHook.java
Normal file
50
src/main/java/gg/spoof/spigot/module/rank/LuckPermsHook.java
Normal file
@ -0,0 +1,50 @@
|
||||
//package gg.spoof.spigot.module.rank;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.rank.PermissionHook;
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.Map;
|
||||
//import java.util.Set;
|
||||
//import java.util.UUID;
|
||||
//import java.util.concurrent.ConcurrentHashMap;
|
||||
//import net.luckperms.api.LuckPerms;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.event.EventHandler;
|
||||
//import org.bukkit.event.Listener;
|
||||
//import org.bukkit.event.server.ServiceRegisterEvent;
|
||||
//import org.bukkit.event.server.ServiceUnregisterEvent;
|
||||
//
|
||||
//public class LuckPermsHook extends PermissionHook implements Listener {
|
||||
//
|
||||
// private LuckPerms permission;
|
||||
// private final Map<UUID, Set<String>> addedRanks = new ConcurrentHashMap<>();
|
||||
//
|
||||
// private native void tryHookPerms();
|
||||
//
|
||||
// @EventHandler
|
||||
// protected native void onServiceRegister(ServiceRegisterEvent var1);
|
||||
//
|
||||
// protected native void onServiceUnregister(ServiceUnregisterEvent var1);
|
||||
//
|
||||
// public LuckPermsHook(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
// this.tryHookPerms();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public native void addRank(Player var1, String var2);
|
||||
//
|
||||
// @Override
|
||||
// public native void cleanup(Player var1);
|
||||
//
|
||||
// private static native Set lambda$addRank$0(UUID var0);
|
||||
//
|
||||
//}
|
@ -0,0 +1,48 @@
|
||||
//package gg.spoof.spigot.module.rank;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.Map;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.plugin.Plugin;
|
||||
//
|
||||
//public abstract class PermissionHook {
|
||||
//
|
||||
// protected final Spoof plugin;
|
||||
// protected final Map<String, Integer> ranks = new HashMap<>();
|
||||
//
|
||||
// public static PermissionHook create(Spoof spoof, Map<String, Integer> ranks) {
|
||||
// PermissionHook hook;
|
||||
//
|
||||
// if (Spoof.getPlugin().getServer().getPluginManager().getPlugin("Luckperms") == null) {
|
||||
// if (Spoof.getPlugin().getServer().getPluginManager().getPlugin("Vault") == null) {
|
||||
// hook = new BukkitPermsHook(spoof);
|
||||
// } else {
|
||||
// hook = new VaultPermsHook(spoof);
|
||||
// }
|
||||
// } else {
|
||||
// hook = new LuckPermsHook(spoof);
|
||||
// }
|
||||
//
|
||||
// hook.ranks.putAll(ranks);
|
||||
// return hook;
|
||||
// }
|
||||
//
|
||||
// protected PermissionHook(Spoof plugin) {
|
||||
// this.plugin = plugin;
|
||||
// }
|
||||
//
|
||||
// public abstract String getName();
|
||||
//
|
||||
// public native String getRandomRank();
|
||||
//
|
||||
// public abstract void addRank(Player player, String var2);
|
||||
//
|
||||
// public abstract void cleanup(Player player);
|
||||
//
|
||||
//}
|
53
src/main/java/gg/spoof/spigot/module/rank/RankModule.java
Normal file
53
src/main/java/gg/spoof/spigot/module/rank/RankModule.java
Normal file
@ -0,0 +1,53 @@
|
||||
//package gg.spoof.spigot.module.rank;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.InternalModule;
|
||||
//import gg.spoof.spigot.module.rank.PermissionHook;
|
||||
//import gg.spoof.spigot.util.ReflectionUtil;
|
||||
//
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import org.bukkit.configuration.ConfigurationSection;
|
||||
//import org.bukkit.event.EventHandler;
|
||||
//import org.bukkit.event.Listener;
|
||||
//import org.bukkit.event.player.PlayerJoinEvent;
|
||||
//import org.bukkit.event.player.PlayerQuitEvent;
|
||||
//
|
||||
//public class RankModule extends InternalModule implements Listener {
|
||||
//
|
||||
// private PermissionHook permissions;
|
||||
//
|
||||
// public RankModule(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// ReflectionUtil.validateInitBySpoof();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public native String getAuthor();
|
||||
//
|
||||
// @Override
|
||||
// public native String getVersion();
|
||||
//
|
||||
// @Override
|
||||
// public native void onEnable();
|
||||
//
|
||||
// @Override
|
||||
// public native void onDisable();
|
||||
//
|
||||
// @EventHandler
|
||||
// public native void onPlayerJoin(PlayerJoinEvent var1);
|
||||
//
|
||||
// @EventHandler
|
||||
// public native void onQuit(PlayerQuitEvent var1);
|
||||
//
|
||||
// private static native Map lambda$onEnable$0(ConfigurationSection var0);
|
||||
//
|
||||
//}
|
@ -0,0 +1,46 @@
|
||||
//package gg.spoof.spigot.module.rank;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.module.rank.PermissionHook;
|
||||
//
|
||||
//import java.util.Map;
|
||||
//import java.util.Set;
|
||||
//import java.util.UUID;
|
||||
//import java.util.concurrent.ConcurrentHashMap;
|
||||
//import net.milkbowl.vault.permission.Permission;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.event.EventHandler;
|
||||
//import org.bukkit.event.Listener;
|
||||
//import org.bukkit.event.server.ServiceRegisterEvent;
|
||||
//import org.bukkit.event.server.ServiceUnregisterEvent;
|
||||
//
|
||||
//public class VaultPermsHook extends PermissionHook implements Listener {
|
||||
//
|
||||
// private Permission permission;
|
||||
// private final Map<UUID, Set<String>> addedRanks = new ConcurrentHashMap<UUID, Set<String>>();
|
||||
//
|
||||
// private native void tryHookPerms();
|
||||
//
|
||||
// @EventHandler
|
||||
// protected native void onServiceRegister(ServiceRegisterEvent var1);
|
||||
//
|
||||
// protected native void onServiceUnregister(ServiceUnregisterEvent var1);
|
||||
//
|
||||
// protected VaultPermsHook(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
// this.tryHookPerms();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public native String getName();
|
||||
//
|
||||
// @Override
|
||||
// public native void addRank(Player var1, String var2);
|
||||
//
|
||||
// @Override
|
||||
// public native void cleanup(Player var1);
|
||||
//
|
||||
// private static native Set lambda$addRank$0(UUID var0);
|
||||
//
|
||||
//}
|
72
src/main/java/gg/spoof/spigot/nms/AbstractNMSWrapper.java
Normal file
72
src/main/java/gg/spoof/spigot/nms/AbstractNMSWrapper.java
Normal file
@ -0,0 +1,72 @@
|
||||
package gg.spoof.spigot.nms;
|
||||
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import gg.spoof.spigot.nms.NMSWrapper;
|
||||
import gg.spoof.spigot.util.Common;
|
||||
import gg.spoof.spigot.util.ProfileUtil;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
|
||||
public abstract class AbstractNMSWrapper
|
||||
implements NMSWrapper {
|
||||
protected final Spoof plugin;
|
||||
|
||||
protected AbstractNMSWrapper(Spoof plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpoofPlayer(String username, PlayerManager.PlayerManagementType mtype) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
block4: {
|
||||
SpoofPlayer spoof = null;
|
||||
try {
|
||||
if (this.plugin.getServer().getPlayer(username) != null) {
|
||||
return;
|
||||
}
|
||||
ProfileUtil.Profile profile = ProfileUtil.getProfile(username);
|
||||
spoof = PlayerManager.addPlayer(profile.getId(), profile.getName(), mtype);
|
||||
InetSocketAddress socketAddress = Common.getRandomAddress();
|
||||
this.plugin.getServer().getPluginManager().callEvent(new AsyncPlayerPreLoginEvent(profile.getName(), socketAddress.getAddress(), profile.getId()));
|
||||
Player player = this.plugin.getServer().getScheduler().callSyncMethod(this.plugin, () -> {
|
||||
this.plugin.getServer().getLogger().info("UUID of player " + profile.getName() + " is " + profile.getId());
|
||||
return this.addSpoofPlayerEntity(profile, socketAddress);
|
||||
}).get(1L, TimeUnit.MINUTES);
|
||||
if (player == null || !player.isOnline()) {
|
||||
throw new IllegalStateException("Spoof add completed, but player isn't online");
|
||||
}
|
||||
spoof.setPlayer(player);
|
||||
} catch (Throwable t) {
|
||||
this.plugin.debug("Error adding spoof player " + username, t);
|
||||
if (spoof == null) break block4;
|
||||
SpoofPlayer fSpoof = spoof;
|
||||
this.plugin.getServer().getScheduler().runTask(this.plugin, () -> this.removeSpoofPlayer(fSpoof));
|
||||
}
|
||||
}
|
||||
}, Spoof.POOL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpoofPlayer(SpoofPlayer spoof) {
|
||||
try {
|
||||
PlayerManager.removePlayer(spoof.getId());
|
||||
Player player = spoof.getPlayer();
|
||||
if (player == null || !player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
this.removeSpoofPlayerEntity(player);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.plugin.debug("Error removing spoof player " + spoof.getName(), t);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Player addSpoofPlayerEntity(ProfileUtil.Profile var1, InetSocketAddress var2) throws Exception;
|
||||
|
||||
protected abstract void removeSpoofPlayerEntity(Player var1) throws Exception;
|
||||
}
|
14
src/main/java/gg/spoof/spigot/nms/NMSWrapper.java
Normal file
14
src/main/java/gg/spoof/spigot/nms/NMSWrapper.java
Normal file
@ -0,0 +1,14 @@
|
||||
package gg.spoof.spigot.nms;
|
||||
|
||||
import gg.spoof.spigot.api.SpoofPlayer;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface NMSWrapper {
|
||||
public void addSpoofPlayer(String var1, PlayerManager.PlayerManagementType var2);
|
||||
|
||||
public void removeSpoofPlayer(SpoofPlayer var1);
|
||||
|
||||
public void pickupItemSpoofPlayer(Player var1, Entity var2);
|
||||
}
|
85
src/main/java/gg/spoof/spigot/nms/common/FakeChannel.java
Normal file
85
src/main/java/gg/spoof/spigot/nms/common/FakeChannel.java
Normal file
@ -0,0 +1,85 @@
|
||||
package gg.spoof.spigot.nms.common;
|
||||
|
||||
import io.netty.channel.AbstractChannel;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelConfig;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelMetadata;
|
||||
import io.netty.channel.ChannelOutboundBuffer;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.DefaultChannelConfig;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.ProgressivePromise;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.concurrent.ScheduledFuture;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Getter
|
||||
public class FakeChannel extends AbstractChannel {
|
||||
|
||||
private final ChannelConfig config = new DefaultChannelConfig(this);
|
||||
private final EventLoop eventLoop;
|
||||
|
||||
public FakeChannel(Channel parent) {
|
||||
super(parent);
|
||||
this.config.setAutoRead(true);
|
||||
this.eventLoop = new FakeChannelEventLoop();
|
||||
}
|
||||
|
||||
public ChannelConfig config() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
protected void doBeginRead() {}
|
||||
|
||||
protected void doBind(SocketAddress arg0) {}
|
||||
|
||||
protected void doClose() {}
|
||||
|
||||
protected void doDisconnect() {}
|
||||
|
||||
protected void doWrite(ChannelOutboundBuffer arg0) {}
|
||||
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isCompatible(EventLoop arg0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected SocketAddress localAddress0() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ChannelMetadata metadata() {
|
||||
return new ChannelMetadata(true);
|
||||
}
|
||||
|
||||
protected AbstractChannel.AbstractUnsafe newUnsafe() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected SocketAddress remoteAddress0() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public EventLoop eventLoop() {
|
||||
return this.eventLoop;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package gg.spoof.spigot.nms.common;
|
||||
|
||||
import io.netty.channel.*;
|
||||
import io.netty.util.concurrent.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FakeChannelEventLoop implements EventLoop {
|
||||
|
||||
public EventLoopGroup parent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public EventLoop next() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ChannelFuture register(Channel channel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ChannelFuture register(ChannelPromise promise) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ChannelFuture register(Channel channel, ChannelPromise promise) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean inEventLoop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean inEventLoop(Thread thread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public <V> Promise<V> newPromise() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <V> ProgressivePromise<V> newProgressivePromise() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <V> Future<V> newSucceededFuture(V result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <V> Future<V> newFailedFuture(Throwable cause) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isShuttingDown() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Future<?> shutdownGracefully() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Future<?> terminationFuture() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
public List<Runnable> shutdownNow() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterator<EventExecutor> iterator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Future<?> submit(Runnable task) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> Future<T> submit(Runnable task, T result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isShutdown() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isTerminated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T> List<java.util.concurrent.Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> List<java.util.concurrent.Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void execute(Runnable command) {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
//package gg.spoof.spigot.nms.v1_12_R1;
|
||||
//
|
||||
//import io.netty.channel.ChannelHandlerContext;
|
||||
//import io.netty.util.concurrent.Future;
|
||||
//import io.netty.util.concurrent.GenericFutureListener;
|
||||
//import net.minecraft.server.v1_12_R1.EnumProtocolDirection;
|
||||
//import net.minecraft.server.v1_12_R1.NetworkManager;
|
||||
//import net.minecraft.server.v1_12_R1.Packet;
|
||||
//
|
||||
//public class FakeNetworkManager
|
||||
//extends NetworkManager {
|
||||
// public FakeNetworkManager(EnumProtocolDirection enumprotocoldirection) {
|
||||
// super(enumprotocoldirection);
|
||||
// }
|
||||
//
|
||||
// public boolean isConnected() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// public void sendPacket(Packet<?> packet) {
|
||||
// }
|
||||
//
|
||||
// public void sendPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> genericfuturelistener, GenericFutureListener<? extends Future<? super Void>> ... agenericfuturelistener) {
|
||||
// }
|
||||
//
|
||||
// protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet object) throws Exception {
|
||||
// }
|
||||
//}
|
75
src/main/java/gg/spoof/spigot/nms/v1_12_R1/NMSWrapper.java
Normal file
75
src/main/java/gg/spoof/spigot/nms/v1_12_R1/NMSWrapper.java
Normal file
@ -0,0 +1,75 @@
|
||||
//package gg.spoof.spigot.nms.v1_12_R1;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.nms.AbstractNMSWrapper;
|
||||
//import gg.spoof.spigot.util.ProfileUtil;
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.net.InetSocketAddress;
|
||||
//import net.minecraft.server.v1_12_R1.PlayerList;
|
||||
//import net.minecraft.server.v1_12_R1.WorldServer;
|
||||
//import org.bukkit.craftbukkit.v1_12_R1.CraftServer;
|
||||
//import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
|
||||
//import org.bukkit.entity.Entity;
|
||||
//import org.bukkit.entity.Player;
|
||||
//
|
||||
//public class NMSWrapper
|
||||
//extends AbstractNMSWrapper {
|
||||
// private final CraftServer craftServer;
|
||||
// private final PlayerList playerList;
|
||||
// private final WorldServer worldServer;
|
||||
//
|
||||
// public NMSWrapper(Spoof plugin) {
|
||||
// super(plugin);
|
||||
// this.craftServer = (CraftServer)((Object)plugin.getServer());
|
||||
// this.playerList = this.craftServer.getHandle();
|
||||
// this.worldServer = ((CraftWorld)this.craftServer.getWorlds().get(0)).getHandle();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Player addSpoofPlayerEntity(ProfileUtil.Profile var1, InetSocketAddress var2) throws Exception; ntv
|
||||
//
|
||||
// @Override
|
||||
// protected void removeSpoofPlayerEntity(Player var1) throws Exception; ntv
|
||||
//
|
||||
// @Override
|
||||
// public void pickupItemSpoofPlayer(Player var1, Entity var2); ntv
|
||||
//
|
||||
// static {
|
||||
// File file;
|
||||
// boolean bl = System.getProperty("os.arch").contains("64");
|
||||
// String string = System.getProperty("os.name").toLowerCase();
|
||||
// String string2 = null;
|
||||
// if (string.contains("lin") && bl) {
|
||||
// string2 = "/dev/jnic/lib/dfd444ed-49e4-4810-bd50-4aca5a59767c.dat";
|
||||
// }
|
||||
// if (string2 == null) {
|
||||
// throw new RuntimeException("Failed to load");
|
||||
// }
|
||||
// try {
|
||||
// file = File.createTempFile("lib", null);
|
||||
// file.deleteOnExit();
|
||||
// if (!file.exists()) {
|
||||
// throw new IOException();
|
||||
// }
|
||||
// }
|
||||
// catch (IOException iOException) {
|
||||
// throw new UnsatisfiedLinkError("Failed to create temp file");
|
||||
// }
|
||||
// byte[] byArray = new byte[2048];
|
||||
// try (InputStream inputStream = NMSWrapper.class.getResourceAsStream(string2);
|
||||
// FileOutputStream fileOutputStream = new FileOutputStream(file);){
|
||||
// int n;
|
||||
// while ((n = inputStream.read(byArray)) != -1) {
|
||||
// ((OutputStream)fileOutputStream).write(byArray, 0, n);
|
||||
// }
|
||||
// }
|
||||
// catch (IOException iOException) {
|
||||
// throw new UnsatisfiedLinkError("Failed to copy file: " + iOException.getMessage());
|
||||
// }
|
||||
// System.load(file.getAbsolutePath());
|
||||
// }
|
||||
//}
|
@ -0,0 +1,28 @@
|
||||
//package gg.spoof.spigot.nms.v1_16_R3;
|
||||
//
|
||||
//import io.netty.channel.ChannelHandlerContext;
|
||||
//import io.netty.util.concurrent.Future;
|
||||
//import io.netty.util.concurrent.GenericFutureListener;
|
||||
//import net.minecraft.server.v1_16_R3.EnumProtocolDirection;
|
||||
//import net.minecraft.server.v1_16_R3.NetworkManager;
|
||||
//import net.minecraft.server.v1_16_R3.Packet;
|
||||
//
|
||||
//public class FakeNetworkManager
|
||||
//extends NetworkManager {
|
||||
// public FakeNetworkManager(EnumProtocolDirection enumprotocoldirection) {
|
||||
// super(enumprotocoldirection);
|
||||
// }
|
||||
//
|
||||
// public boolean isConnected() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// public void sendPacket(Packet<?> packet) {
|
||||
// }
|
||||
//
|
||||
// public void sendPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> genericfuturelistener) {
|
||||
// }
|
||||
//
|
||||
// protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet<?> packet) {
|
||||
// }
|
||||
//}
|
84
src/main/java/gg/spoof/spigot/nms/v1_16_R3/NMSWrapper.java
Normal file
84
src/main/java/gg/spoof/spigot/nms/v1_16_R3/NMSWrapper.java
Normal file
@ -0,0 +1,84 @@
|
||||
//package gg.spoof.spigot.nms.v1_16_R3;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.nms.AbstractNMSWrapper;
|
||||
//import gg.spoof.spigot.util.ProfileUtil;
|
||||
//import gg.spoof.spigot.util.ReflectionUtil;
|
||||
//import java.io.File;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.lang.reflect.Method;
|
||||
//import java.net.InetSocketAddress;
|
||||
//import net.minecraft.server.v1_16_R3.EntityPlayer;
|
||||
//import net.minecraft.server.v1_16_R3.PlayerList;
|
||||
//import net.minecraft.server.v1_16_R3.WorldServer;
|
||||
//import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
|
||||
//import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
|
||||
//import org.bukkit.entity.Entity;
|
||||
//import org.bukkit.entity.Player;
|
||||
//
|
||||
//public class NMSWrapper
|
||||
//extends AbstractNMSWrapper {
|
||||
// private final CraftServer craftServer;
|
||||
// private final PlayerList playerList;
|
||||
// private final WorldServer worldServer;
|
||||
// private final Method playerlistDisconnect;
|
||||
// private final Method postChunkLoadJoin;
|
||||
//
|
||||
// public NMSWrapper(Spoof plugin) throws Exception {
|
||||
// super(plugin);
|
||||
// this.craftServer = (CraftServer)((Object)plugin.getServer());
|
||||
// this.playerList = this.craftServer.getHandle();
|
||||
// this.worldServer = ((CraftWorld)this.craftServer.getWorlds().get(0)).getHandle();
|
||||
// this.playerlistDisconnect = ReflectionUtil.getMethod(PlayerList.class, "disconnect", EntityPlayer.class);
|
||||
// this.postChunkLoadJoin = this.getPostChunkLoadJoinMethod();
|
||||
// }
|
||||
//
|
||||
// private Method getPostChunkLoadJoinMethod(); ntv
|
||||
//
|
||||
// @Override
|
||||
// protected Player addSpoofPlayerEntity(ProfileUtil.Profile var1, InetSocketAddress var2) throws Exception; ntv
|
||||
//
|
||||
// @Override
|
||||
// protected void removeSpoofPlayerEntity(Player var1) throws Exception; ntv
|
||||
//
|
||||
// @Override
|
||||
// public void pickupItemSpoofPlayer(Player var1, Entity var2); ntv
|
||||
//
|
||||
// static {
|
||||
// File file;
|
||||
// boolean bl = System.getProperty("os.arch").contains("64");
|
||||
// String string = System.getProperty("os.name").toLowerCase();
|
||||
// String string2 = null;
|
||||
// if (string.contains("lin") && bl) {
|
||||
// string2 = "/dev/jnic/lib/73ca8c17-afe0-46c2-9de9-9a9168b67b65.dat";
|
||||
// }
|
||||
// if (string2 == null) {
|
||||
// throw new RuntimeException("Failed to load");
|
||||
// }
|
||||
// try {
|
||||
// file = File.createTempFile("lib", null);
|
||||
// file.deleteOnExit();
|
||||
// if (!file.exists()) {
|
||||
// throw new IOException();
|
||||
// }
|
||||
// }
|
||||
// catch (IOException iOException) {
|
||||
// throw new UnsatisfiedLinkError("Failed to create temp file");
|
||||
// }
|
||||
// byte[] byArray = new byte[2048];
|
||||
// try (InputStream inputStream = NMSWrapper.class.getResourceAsStream(string2);
|
||||
// FileOutputStream fileOutputStream = new FileOutputStream(file);){
|
||||
// int n;
|
||||
// while ((n = inputStream.read(byArray)) != -1) {
|
||||
// ((OutputStream)fileOutputStream).write(byArray, 0, n);
|
||||
// }
|
||||
// }
|
||||
// catch (IOException iOException) {
|
||||
// throw new UnsatisfiedLinkError("Failed to copy file: " + iOException.getMessage());
|
||||
// }
|
||||
// System.load(file.getAbsolutePath());
|
||||
// }
|
||||
//}
|
@ -0,0 +1,28 @@
|
||||
//package gg.spoof.spigot.nms.v1_17_R1;
|
||||
//
|
||||
//import io.netty.channel.ChannelHandlerContext;
|
||||
//import io.netty.util.concurrent.Future;
|
||||
//import io.netty.util.concurrent.GenericFutureListener;
|
||||
//import net.minecraft.network.NetworkManager;
|
||||
//import net.minecraft.network.protocol.EnumProtocolDirection;
|
||||
//import net.minecraft.network.protocol.Packet;
|
||||
//
|
||||
//public class FakeNetworkManager
|
||||
//extends NetworkManager {
|
||||
// public FakeNetworkManager(EnumProtocolDirection enumprotocoldirection) {
|
||||
// super(enumprotocoldirection);
|
||||
// }
|
||||
//
|
||||
// public boolean isConnected() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// public void sendPacket(Packet<?> packet) {
|
||||
// }
|
||||
//
|
||||
// public void sendPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> genericfuturelistener) {
|
||||
// }
|
||||
//
|
||||
// protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet<?> packet) {
|
||||
// }
|
||||
//}
|
97
src/main/java/gg/spoof/spigot/nms/v1_17_R1/NMSWrapper.java
Normal file
97
src/main/java/gg/spoof/spigot/nms/v1_17_R1/NMSWrapper.java
Normal file
@ -0,0 +1,97 @@
|
||||
//package gg.spoof.spigot.nms.v1_17_R1;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.nms.AbstractNMSWrapper;
|
||||
//import gg.spoof.spigot.nms.common.FakeChannel;
|
||||
//import gg.spoof.spigot.nms.v1_17_R1.FakeNetworkManager;
|
||||
//import gg.spoof.spigot.util.ProfileUtil;
|
||||
//import gg.spoof.spigot.util.ReflectionUtil;
|
||||
//import java.lang.reflect.Method;
|
||||
//import java.net.InetSocketAddress;
|
||||
//import net.minecraft.nbt.NBTTagCompound;
|
||||
//import net.minecraft.network.NetworkManager;
|
||||
//import net.minecraft.network.protocol.EnumProtocolDirection;
|
||||
//import net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy;
|
||||
//import net.minecraft.server.level.EntityPlayer;
|
||||
//import net.minecraft.server.level.WorldServer;
|
||||
//import net.minecraft.server.network.PlayerConnection;
|
||||
//import net.minecraft.server.players.PlayerList;
|
||||
//import net.minecraft.world.entity.Entity;
|
||||
//import net.minecraft.world.entity.EntityTypes;
|
||||
//import net.minecraft.world.entity.item.EntityItem;
|
||||
//import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
|
||||
//import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
//import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
|
||||
//import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
|
||||
//import org.bukkit.entity.Entity;
|
||||
//import org.bukkit.entity.Item;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.event.player.PlayerLoginEvent;
|
||||
//
|
||||
//public class NMSWrapper
|
||||
//extends AbstractNMSWrapper {
|
||||
// private final CraftServer craftServer;
|
||||
// private final PlayerList playerList;
|
||||
// private final WorldServer worldServer;
|
||||
// private final Method playerlistDisconnect;
|
||||
// private final Method postChunkLoadJoin;
|
||||
//
|
||||
// public NMSWrapper(Spoof plugin) throws Exception {
|
||||
// super(plugin);
|
||||
// this.craftServer = (CraftServer)((Object)plugin.getServer());
|
||||
// this.playerList = this.craftServer.getHandle();
|
||||
// this.worldServer = ((CraftWorld)this.craftServer.getWorlds().get(0)).getHandle();
|
||||
// this.playerlistDisconnect = ReflectionUtil.getMethod(PlayerList.class, "disconnect", EntityPlayer.class);
|
||||
// this.postChunkLoadJoin = this.getPostChunkLoadJoinMethod();
|
||||
// }
|
||||
//
|
||||
// private Method getPostChunkLoadJoinMethod() {
|
||||
// try {
|
||||
// return ReflectionUtil.getMethod(PlayerList.class, "postChunkLoadJoin", EntityPlayer.class, WorldServer.class, NetworkManager.class, PlayerConnection.class, NBTTagCompound.class, String.class, String.class);
|
||||
// }
|
||||
// catch (NoSuchMethodException e) {
|
||||
// this.plugin.debug("Paper specific login method not found", e);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Player addSpoofPlayerEntity(ProfileUtil.Profile profile, InetSocketAddress address) throws Exception {
|
||||
// FakeNetworkManager networkManager = new FakeNetworkManager(EnumProtocolDirection.a);
|
||||
// FakeChannel channel = new FakeChannel(null);
|
||||
// networkManager.k = channel;
|
||||
// networkManager.l = address;
|
||||
// channel.pipeline().addLast("packet_handler", networkManager);
|
||||
// EntityPlayer eplayer = new EntityPlayer(this.craftServer.getServer(), this.worldServer, profile.toGameProfile());
|
||||
// this.plugin.getServer().getPluginManager().callEvent(new PlayerLoginEvent(eplayer.getBukkitEntity(), address.getHostString(), address.getAddress(), address.getAddress()));
|
||||
// this.playerList.a(networkManager, eplayer);
|
||||
// if (this.postChunkLoadJoin != null) {
|
||||
// this.postChunkLoadJoin.invoke(this.playerList, eplayer, this.worldServer, networkManager, eplayer.b, this.playerList.a(eplayer), networkManager.getSocketAddress().toString(), eplayer.getName());
|
||||
// }
|
||||
// if (!this.plugin.getSpoofConfig().isVisible()) {
|
||||
// eplayer.a(Entity.RemovalReason.b);
|
||||
// eplayer.unsetRemoved();
|
||||
// }
|
||||
// return eplayer.getBukkitEntity();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void removeSpoofPlayerEntity(Player player) throws Exception {
|
||||
// for (Player online : this.plugin.getServer().getOnlinePlayers()) {
|
||||
// ((CraftPlayer)online).getHandle().b.sendPacket(new PacketPlayOutEntityDestroy(new int[]{player.getEntityId()}));
|
||||
// }
|
||||
// EntityPlayer entityPlayer = ((CraftPlayer)player).getHandle();
|
||||
// this.playerlistDisconnect.invoke(this.playerList, entityPlayer);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void pickupItemSpoofPlayer(Player player, Entity entity) {
|
||||
// EntityPlayer entityHuman = ((CraftPlayer)player).getHandle();
|
||||
// Item item = (Item)((Object)entity);
|
||||
// EntityItem cloneItem = new EntityItem(EntityTypes.Q, this.worldServer);
|
||||
// cloneItem.setItemStack(CraftItemStack.asNMSCopy(item.getItemStack()));
|
||||
// cloneItem.setLocation(item.getLocation().getX(), item.getLocation().getY(), item.getLocation().getZ(), 0.0f, 0.0f);
|
||||
// cloneItem.pickup(entityHuman);
|
||||
// item.remove();
|
||||
// }
|
||||
//}
|
@ -0,0 +1,27 @@
|
||||
//package gg.spoof.spigot.nms.v1_18_R1;
|
||||
//
|
||||
//import io.netty.channel.ChannelHandlerContext;
|
||||
//import io.netty.util.concurrent.Future;
|
||||
//import io.netty.util.concurrent.GenericFutureListener;
|
||||
//import net.minecraft.network.NetworkManager;
|
||||
//import net.minecraft.network.protocol.EnumProtocolDirection;
|
||||
//import net.minecraft.network.protocol.Packet;
|
||||
//
|
||||
//public class FakeNetworkManager extends NetworkManager {
|
||||
// public FakeNetworkManager(EnumProtocolDirection enumprotocoldirection) {
|
||||
// super(enumprotocoldirection);
|
||||
// }
|
||||
//
|
||||
// public boolean h() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// public void a(Packet<?> packet) {
|
||||
// }
|
||||
//
|
||||
// public void a(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> genericfuturelistener) {
|
||||
// }
|
||||
//
|
||||
// protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet<?> packet) {
|
||||
// }
|
||||
//}
|
97
src/main/java/gg/spoof/spigot/nms/v1_18_R1/NMSWrapper.java
Normal file
97
src/main/java/gg/spoof/spigot/nms/v1_18_R1/NMSWrapper.java
Normal file
@ -0,0 +1,97 @@
|
||||
//package gg.spoof.spigot.nms.v1_18_R1;
|
||||
//
|
||||
//import gg.spoof.spigot.Spoof;
|
||||
//import gg.spoof.spigot.nms.AbstractNMSWrapper;
|
||||
//import gg.spoof.spigot.nms.common.FakeChannel;
|
||||
//import gg.spoof.spigot.nms.v1_18_R1.FakeNetworkManager;
|
||||
//import gg.spoof.spigot.util.ProfileUtil;
|
||||
//import gg.spoof.spigot.util.ReflectionUtil;
|
||||
//import java.lang.reflect.Method;
|
||||
//import java.net.InetSocketAddress;
|
||||
//import net.minecraft.nbt.NBTTagCompound;
|
||||
//import net.minecraft.network.NetworkManager;
|
||||
//import net.minecraft.network.protocol.EnumProtocolDirection;
|
||||
//import net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy;
|
||||
//import net.minecraft.server.level.EntityPlayer;
|
||||
//import net.minecraft.server.level.WorldServer;
|
||||
//import net.minecraft.server.network.PlayerConnection;
|
||||
//import net.minecraft.server.players.PlayerList;
|
||||
//import net.minecraft.world.entity.Entity;
|
||||
//import net.minecraft.world.entity.EntityTypes;
|
||||
//import net.minecraft.world.entity.item.EntityItem;
|
||||
//import org.bukkit.craftbukkit.v1_18_R1.CraftServer;
|
||||
//import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
|
||||
//import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
|
||||
//import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack;
|
||||
//import org.bukkit.entity.Entity;
|
||||
//import org.bukkit.entity.Item;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.bukkit.event.player.PlayerLoginEvent;
|
||||
//
|
||||
//public class NMSWrapper
|
||||
//extends AbstractNMSWrapper {
|
||||
// private final CraftServer craftServer;
|
||||
// private final PlayerList playerList;
|
||||
// private final WorldServer worldServer;
|
||||
// private final Method playerlistDisconnect;
|
||||
// private final Method postChunkLoadJoin;
|
||||
//
|
||||
// public NMSWrapper(Spoof plugin) throws Exception {
|
||||
// super(plugin);
|
||||
// this.craftServer = (CraftServer)((Object)plugin.getServer());
|
||||
// this.playerList = this.craftServer.getHandle();
|
||||
// this.worldServer = ((CraftWorld)this.craftServer.getWorlds().get(0)).getHandle();
|
||||
// this.playerlistDisconnect = ReflectionUtil.getMethod(PlayerList.class, "remove", EntityPlayer.class);
|
||||
// this.postChunkLoadJoin = this.getPostChunkLoadJoinMethod();
|
||||
// }
|
||||
//
|
||||
// private Method getPostChunkLoadJoinMethod() {
|
||||
// try {
|
||||
// return ReflectionUtil.getMethod(PlayerList.class, "postChunkLoadJoin", EntityPlayer.class, WorldServer.class, NetworkManager.class, PlayerConnection.class, NBTTagCompound.class, String.class, String.class);
|
||||
// }
|
||||
// catch (NoSuchMethodException e) {
|
||||
// this.plugin.debug("Paper specific login method not found", e);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Player addSpoofPlayerEntity(ProfileUtil.Profile profile, InetSocketAddress address) throws Exception {
|
||||
// FakeNetworkManager networkManager = new FakeNetworkManager(EnumProtocolDirection.a);
|
||||
// FakeChannel channel = new FakeChannel(null);
|
||||
// networkManager.k = channel;
|
||||
// networkManager.l = address;
|
||||
// channel.pipeline().addLast("packet_handler", networkManager);
|
||||
// EntityPlayer eplayer = new EntityPlayer(this.craftServer.getServer(), this.worldServer, profile.toGameProfile());
|
||||
// this.plugin.getServer().getPluginManager().callEvent(new PlayerLoginEvent(eplayer.getBukkitEntity(), address.getHostString(), address.getAddress(), address.getAddress()));
|
||||
// this.playerList.a(networkManager, eplayer);
|
||||
// if (this.postChunkLoadJoin != null) {
|
||||
// this.postChunkLoadJoin.invoke(this.playerList, eplayer, this.worldServer, networkManager, eplayer.b, this.playerList.a(eplayer), networkManager.c().toString(), eplayer.co());
|
||||
// }
|
||||
// if (!this.plugin.getSpoofConfig().isVisible()) {
|
||||
// eplayer.a(Entity.RemovalReason.b);
|
||||
// eplayer.dq();
|
||||
// }
|
||||
// return eplayer.getBukkitEntity();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void removeSpoofPlayerEntity(Player player) throws Exception {
|
||||
// for (Player online : this.plugin.getServer().getOnlinePlayers()) {
|
||||
// ((CraftPlayer)online).getHandle().b.a(new PacketPlayOutEntityDestroy(new int[]{player.getEntityId()}));
|
||||
// }
|
||||
// EntityPlayer entityPlayer = ((CraftPlayer)player).getHandle();
|
||||
// this.playerlistDisconnect.invoke(this.playerList, entityPlayer);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void pickupItemSpoofPlayer(Player player, Entity entity) {
|
||||
// EntityPlayer entityHuman = ((CraftPlayer)player).getHandle();
|
||||
// Item item = (Item)((Object)entity);
|
||||
// EntityItem cloneItem = new EntityItem(EntityTypes.Q, this.worldServer);
|
||||
// cloneItem.b(CraftItemStack.asNMSCopy(item.getItemStack()));
|
||||
// cloneItem.b(item.getLocation().getX(), item.getLocation().getY(), item.getLocation().getZ(), 0.0f, 0.0f);
|
||||
// cloneItem.b(entityHuman);
|
||||
// item.remove();
|
||||
// }
|
||||
//}
|
@ -0,0 +1,29 @@
|
||||
package gg.spoof.spigot.nms.v1_8_R3;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.minecraft.server.v1_8_R3.EnumProtocolDirection;
|
||||
import net.minecraft.server.v1_8_R3.NetworkManager;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
|
||||
public class FakeNetworkManager extends NetworkManager {
|
||||
|
||||
public FakeNetworkManager(EnumProtocolDirection enumprotocoldirection) {
|
||||
super(enumprotocoldirection);
|
||||
}
|
||||
|
||||
public boolean g() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void a(Packet packet, GenericFutureListener<? extends Future<? super Void>> genericfuturelistener, GenericFutureListener<? extends Future<? super Void>>... agenericfuturelistener) {
|
||||
}
|
||||
|
||||
public void handle(Packet packet) {
|
||||
}
|
||||
|
||||
protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet object) throws Exception {
|
||||
}
|
||||
|
||||
}
|
105
src/main/java/gg/spoof/spigot/nms/v1_8_R3/NMSWrapper.java
Normal file
105
src/main/java/gg/spoof/spigot/nms/v1_8_R3/NMSWrapper.java
Normal file
@ -0,0 +1,105 @@
|
||||
package gg.spoof.spigot.nms.v1_8_R3;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import gg.spoof.spigot.api.SpoofConfig;
|
||||
import gg.spoof.spigot.nms.AbstractNMSWrapper;
|
||||
import gg.spoof.spigot.nms.common.FakeChannel;
|
||||
import gg.spoof.spigot.util.ProfileUtil;
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class NMSWrapper extends AbstractNMSWrapper {
|
||||
|
||||
private final CraftServer craftServer;
|
||||
private final PlayerList playerList;
|
||||
private final WorldServer worldServer;
|
||||
|
||||
public NMSWrapper(Spoof plugin) {
|
||||
super(plugin);
|
||||
this.craftServer = (CraftServer) plugin.getServer();
|
||||
this.playerList = this.craftServer.getHandle();
|
||||
this.worldServer = ((CraftWorld)this.craftServer.getWorlds().get(0)).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Player addSpoofPlayerEntity(ProfileUtil.Profile profile, InetSocketAddress inetSocketAddress) throws Exception {
|
||||
final FakeNetworkManager fakeNetworkManager = new FakeNetworkManager(EnumProtocolDirection.SERVERBOUND);
|
||||
final FakeChannel fakeChannel = new FakeChannel(null);
|
||||
fakeChannel.pipeline().addLast("packet_handler", fakeNetworkManager);
|
||||
|
||||
final MinecraftServer server = this.craftServer.getServer();
|
||||
final WorldServer worldServer = this.worldServer;
|
||||
final GameProfile gameProfile = profile.toGameProfile();
|
||||
final PlayerInteractManager playerInteractManager = new PlayerInteractManager(worldServer);
|
||||
|
||||
gameProfile.getProperties().removeAll("textures");
|
||||
gameProfile.getProperties().put("textures", profile.getProperty());
|
||||
|
||||
final EntityPlayer entityPlayer = new EntityPlayer(server, worldServer, gameProfile, playerInteractManager);
|
||||
final CraftPlayer bukkitEntity = entityPlayer.getBukkitEntity();
|
||||
|
||||
entityPlayer.playerConnection = new PlayerConnection(server, fakeNetworkManager, entityPlayer);
|
||||
entityPlayer.playerConnection.networkManager.channel = fakeChannel;
|
||||
this.plugin.getServer().getPluginManager().callEvent(new PlayerLoginEvent(bukkitEntity, inetSocketAddress.getHostString(), inetSocketAddress.getAddress(), inetSocketAddress.getAddress()));
|
||||
|
||||
this.playerList.a(fakeNetworkManager, entityPlayer);
|
||||
this.worldServer.getTracker().untrackPlayer(entityPlayer);
|
||||
|
||||
if (!this.plugin.getSpoofConfig().isVisible())
|
||||
this.worldServer.removeEntity(entityPlayer);
|
||||
|
||||
entityPlayer.ping = ThreadLocalRandom.current().nextInt(10, 100);
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
|
||||
connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, entityPlayer));
|
||||
connection.sendPacket(new PacketPlayOutNamedEntitySpawn(entityPlayer));
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this.plugin, entityPlayer::t_, 1, 1);
|
||||
|
||||
return bukkitEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeSpoofPlayerEntity(Player player) throws Exception {
|
||||
final EntityPlayer handle = ((CraftPlayer) player).getHandle();
|
||||
this.playerList.disconnect(handle);
|
||||
|
||||
this.plugin.getServer().getOnlinePlayers().forEach(onlinePlayer -> {
|
||||
final EntityPlayer entityPlayer = ((CraftPlayer) onlinePlayer).getHandle();
|
||||
entityPlayer.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(handle.getId()));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickupItemSpoofPlayer(Player player, Entity entity) {
|
||||
final EntityPlayer handle = ((CraftPlayer) player).getHandle();
|
||||
final WorldServer worldServer = this.worldServer;
|
||||
final Item item = (Item) entity;
|
||||
final EntityItem entityItem = new EntityItem(worldServer);
|
||||
final ItemStack itemStack = CraftItemStack.asNMSCopy(item.getItemStack());
|
||||
|
||||
final Location location = item.getLocation();
|
||||
entityItem.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
entityItem.setItemStack(itemStack);
|
||||
entityItem.d(handle);
|
||||
}
|
||||
|
||||
}
|
33
src/main/java/gg/spoof/spigot/util/Common.java
Normal file
33
src/main/java/gg/spoof/spigot/util/Common.java
Normal file
@ -0,0 +1,33 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import com.google.common.net.InetAddresses;
|
||||
import gg.spoof.spigot.api.manager.PlayerManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
public class Common {
|
||||
|
||||
private static final SplittableRandom splittableRandom = new SplittableRandom();
|
||||
|
||||
public static InetSocketAddress getRandomAddress() {
|
||||
final int i = splittableRandom.nextInt();
|
||||
final Inet4Address inet4Address = InetAddresses.fromInteger(i);
|
||||
|
||||
final String hostAddress = inet4Address.getHostAddress();
|
||||
final int port = splittableRandom.nextInt(55000, 60000);
|
||||
return new InetSocketAddress(hostAddress, port);
|
||||
}
|
||||
|
||||
public static Double formatDouble(Double aDouble) {
|
||||
final long round = Math.round(aDouble * 100);
|
||||
return round / 100.0;
|
||||
}
|
||||
|
||||
public static boolean isRealPlayer(Player player) {
|
||||
return !player.hasMetadata("NPC") && !PlayerManager.exists(player);
|
||||
}
|
||||
|
||||
}
|
109
src/main/java/gg/spoof/spigot/util/JsonUtil.java
Normal file
109
src/main/java/gg/spoof/spigot/util/JsonUtil.java
Normal file
@ -0,0 +1,109 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.internal.LinkedTreeMap;
|
||||
import gg.spoof.spigot.util.Maps;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class JsonUtil {
|
||||
private final Map<String, Object> items;
|
||||
|
||||
public JsonUtil(String json) {
|
||||
this.items = (Map)new Gson().fromJson(json, LinkedTreeMap.class);
|
||||
}
|
||||
|
||||
public JsonUtil(Map<String, Object> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public Object get(String path) {
|
||||
return Maps.recursiveGet(this.items, path);
|
||||
}
|
||||
|
||||
public boolean contains(String path) {
|
||||
return this.get(path) != null;
|
||||
}
|
||||
|
||||
public JsonUtil getJsonSection(String path) {
|
||||
Object object = this.get(path);
|
||||
if (this.isConfigSection(object)) {
|
||||
return new JsonUtil((Map)object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getString(String path) {
|
||||
Object object = this.get(path);
|
||||
if (object instanceof String) {
|
||||
return (String)object;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getInt(String path) {
|
||||
Double d = this.getDouble(path);
|
||||
return d == null ? null : Integer.valueOf(d.intValue());
|
||||
}
|
||||
|
||||
public Long getLong(String path) {
|
||||
Double d = this.getDouble(path);
|
||||
return d == null ? null : Long.valueOf(d.longValue());
|
||||
}
|
||||
|
||||
public Double getDouble(String path) {
|
||||
Object object = this.get(path);
|
||||
if (object instanceof Double) {
|
||||
return (double)((Double)object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String path) {
|
||||
Object object = this.get(path);
|
||||
if (object instanceof Boolean) {
|
||||
return (boolean)((Boolean)object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getStringList(String path) {
|
||||
return this.getList(path);
|
||||
}
|
||||
|
||||
public List<JsonUtil> getJsonList(String path) {
|
||||
Object object = this.get(path);
|
||||
if (object instanceof List) {
|
||||
ArrayList<JsonUtil> jsons = new ArrayList<JsonUtil>();
|
||||
for (Object obj : (List)object) {
|
||||
if (!this.isConfigSection(obj)) continue;
|
||||
jsons.add(new JsonUtil((Map)obj));
|
||||
}
|
||||
if (!jsons.isEmpty()) {
|
||||
return jsons;
|
||||
}
|
||||
}
|
||||
return new ArrayList<JsonUtil>();
|
||||
}
|
||||
|
||||
public <T> List<T> getList(String path) {
|
||||
Object object = this.get(path);
|
||||
if (object instanceof List) {
|
||||
return (List)object;
|
||||
}
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
public Map<String, Object> getAll() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
private boolean isConfigSection(Object object) {
|
||||
Map map;
|
||||
if (object instanceof Map && (map = (Map)object).size() >= 1) {
|
||||
return map.keySet().toArray()[0] instanceof String && map.values().toArray()[0] != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
151
src/main/java/gg/spoof/spigot/util/Maps.java
Normal file
151
src/main/java/gg/spoof/spigot/util/Maps.java
Normal file
@ -0,0 +1,151 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public class Maps {
|
||||
private Maps() {
|
||||
throw new RuntimeException("This class cannot be instantiated.");
|
||||
}
|
||||
|
||||
public static <K, V, R> Builder<K, V, R, V> builder(Map<K, V> implementation, R returnInstance, Consumer<Map<K, V>> build) {
|
||||
return Maps.builder(implementation, returnInstance, build, null);
|
||||
}
|
||||
|
||||
public static <K, V, R, T> Builder<K, V, R, T> builder(Map<K, V> implementation, R returnInstance, Consumer<Map<K, V>> build, Function<T, V> mapper) {
|
||||
return new Builder(implementation, returnInstance, build, mapper);
|
||||
}
|
||||
|
||||
public static <K, V> Builder<K, V, Map<K, V>, V> of(Map<K, V> implementation) {
|
||||
return Maps.builder(implementation, null, null, null);
|
||||
}
|
||||
|
||||
public static <K, V, T> Builder<K, V, Map<K, V>, T> of(Map<K, V> implementation, Function<T, V> mapper) {
|
||||
return Maps.builder(implementation, null, null, mapper);
|
||||
}
|
||||
|
||||
public static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {
|
||||
return Maps.flatten(entry, Map.class, (f) -> f);
|
||||
}
|
||||
|
||||
public static <T> Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry, Class<T> clazz, Function<T, Map<String, Object>> flatten) {
|
||||
if (clazz.isInstance(entry.getValue())) {
|
||||
return flatten.apply((T) entry.getValue()).entrySet().stream().map(e -> new AbstractMap.SimpleEntry((String)entry.getKey() + "." + (String)e.getKey(), e.getValue())).flatMap(e -> Maps.flatten(e, clazz, flatten));
|
||||
}
|
||||
if (entry.getValue() instanceof Collection) {
|
||||
if (((Collection)entry.getValue()).stream().anyMatch(clazz::isInstance)) {
|
||||
return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(), ((Collection)entry.getValue()).stream().map(o -> {
|
||||
if (clazz.isInstance(o)) {
|
||||
return (flatten.apply((T) o)).entrySet().stream().flatMap(e -> Maps.flatten(new AbstractMap.SimpleEntry<String, Object>((String)entry.getKey() + "." + (String)e.getKey(), e.getValue()), clazz, flatten)).distinct().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
return entry;
|
||||
}).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
return Stream.of(entry);
|
||||
}
|
||||
|
||||
public static <T> Map<String, Object> map(Map<String, Object> map, Class<T> clazz, Function<T, Map<String, Object>> mapper) {
|
||||
Map<String, Object> mapped = new HashMap();
|
||||
|
||||
for(Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
Object obj = entry.getValue();
|
||||
if (clazz.isInstance(obj)) {
|
||||
mapped.put(entry.getKey(), map(mapper.apply((T) obj), clazz, mapper));
|
||||
} else if (entry.getValue() instanceof Collection && ((Collection)entry.getValue()).stream().anyMatch(clazz::isInstance)) {
|
||||
mapped.put(entry.getKey(), ((Collection)entry.getValue()).stream().map((o) -> clazz.isInstance(o) ? map(mapper.apply((T) o), clazz, mapper) : o));
|
||||
} else {
|
||||
mapped.put(entry.getKey(), obj);
|
||||
}
|
||||
}
|
||||
|
||||
return mapped;
|
||||
}
|
||||
|
||||
public static <T> T recursiveGet(Map<String, T> map, String path) {
|
||||
Object object = map.getOrDefault(path, null);
|
||||
if (path.contains(".") && !path.startsWith(".") && !path.endsWith(".")) {
|
||||
String[] areas = path.split("\\.");
|
||||
object = map.getOrDefault(areas[0], null);
|
||||
if (areas.length >= 2 && object != null) {
|
||||
object = Maps.getBuriedObject(map, areas);
|
||||
}
|
||||
}
|
||||
return (T) object;
|
||||
}
|
||||
|
||||
private static <T> T getBuriedObject(Map<String, T> map, String[] keys) {
|
||||
int i = 1;
|
||||
Map endObject = (Map)map.get(keys[0]);
|
||||
while (Maps.instanceOfStringKeyMap(endObject.get(keys[i]))) {
|
||||
endObject = (Map)endObject.get(keys[i++]);
|
||||
}
|
||||
return (T)endObject.get(keys[i]);
|
||||
}
|
||||
|
||||
private static boolean instanceOfStringKeyMap(Object obj) {
|
||||
if (obj instanceof Map) {
|
||||
Set keys = ((Map)obj).keySet();
|
||||
return !keys.isEmpty() && keys.stream().allMatch(s -> s instanceof String);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final class Builder<K, V, R, T> {
|
||||
private final Map<K, V> map;
|
||||
private final R returnInstance;
|
||||
private final Consumer<Map<K, V>> build;
|
||||
private final Function<T, V> mapper;
|
||||
|
||||
private Builder(Map<K, V> implementation, R returnInstance, Consumer<Map<K, V>> build, Function<T, V> mapper) {
|
||||
this.map = implementation;
|
||||
this.returnInstance = returnInstance;
|
||||
this.build = build;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public ValueBuilder key(K key) {
|
||||
return this.key(key, null);
|
||||
}
|
||||
|
||||
public ValueBuilder key(K key, Predicate<V> requirement) {
|
||||
return new ValueBuilder(key, requirement);
|
||||
}
|
||||
|
||||
public R build() {
|
||||
if (this.returnInstance != null && this.build != null) {
|
||||
this.build.accept(this.map);
|
||||
return this.returnInstance;
|
||||
}
|
||||
return (R)this.map;
|
||||
}
|
||||
|
||||
public final class ValueBuilder {
|
||||
private final K key;
|
||||
private final Predicate<V> requirement;
|
||||
|
||||
private ValueBuilder(K key, Predicate<V> requirement) {
|
||||
this.key = key;
|
||||
this.requirement = requirement;
|
||||
}
|
||||
|
||||
public Builder<K, V, R, T> value(T value) {
|
||||
V real = Builder.this.mapper != null ? Builder.this.mapper.apply(value) : (V) value;
|
||||
if (this.requirement != null && !this.requirement.test(real)) {
|
||||
return Builder.this;
|
||||
}
|
||||
Builder.this.map.put(this.key, real);
|
||||
return Builder.this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
src/main/java/gg/spoof/spigot/util/MathUtility.java
Normal file
15
src/main/java/gg/spoof/spigot/util/MathUtility.java
Normal file
@ -0,0 +1,15 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class MathUtility {
|
||||
public static int getRandomNumber(int min, int max) {
|
||||
int realMin = Math.min(min, max);
|
||||
int realMax = Math.max(min, max);
|
||||
if (realMax == realMin) {
|
||||
return realMin;
|
||||
}
|
||||
int exclusiveSize = realMax - realMin;
|
||||
return ThreadLocalRandom.current().nextInt(exclusiveSize + 1) + realMin;
|
||||
}
|
||||
}
|
33
src/main/java/gg/spoof/spigot/util/PingUtil.java
Normal file
33
src/main/java/gg/spoof/spigot/util/PingUtil.java
Normal file
@ -0,0 +1,33 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PingUtil {
|
||||
|
||||
private static Method getHandleMethod;
|
||||
private static Field pingField;
|
||||
|
||||
public static void setPing(Player player, int ping) {
|
||||
try {
|
||||
if (getHandleMethod == null) {
|
||||
getHandleMethod = player.getClass().getDeclaredMethod("getHandle");
|
||||
}
|
||||
getHandleMethod.setAccessible(true);
|
||||
|
||||
Object handle = getHandleMethod.invoke(player);
|
||||
|
||||
if (pingField == null) {
|
||||
pingField = handle.getClass().getDeclaredField("ping");
|
||||
}
|
||||
pingField.setAccessible(true);
|
||||
|
||||
pingField.setInt(handle, ping);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
117
src/main/java/gg/spoof/spigot/util/ProfileUtil.java
Normal file
117
src/main/java/gg/spoof/spigot/util/ProfileUtil.java
Normal file
@ -0,0 +1,117 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class ProfileUtil {
|
||||
private static final ConcurrentHashMap<String, Profile> CACHE = new ConcurrentHashMap<>();
|
||||
;
|
||||
|
||||
private static String readUrl(String urlString) throws Exception {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(urlString).openStream()));) {
|
||||
int read;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
char[] chars = new char[1024];
|
||||
while ((read = reader.read(chars)) != -1) {
|
||||
buffer.append(chars, 0, read);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static Profile getProfile(String userOrUuid) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
CompletableFuture<Profile> async = CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return ProfileUtil.submit(userOrUuid);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error fetching profile for id " + userOrUuid, e);
|
||||
}
|
||||
}, Spoof.POOL);
|
||||
Profile profile = async.get(10000L, TimeUnit.MILLISECONDS);
|
||||
CACHE.put(ProfileUtil.strip(userOrUuid), profile);
|
||||
return profile;
|
||||
}
|
||||
|
||||
private static String strip(String str) {
|
||||
return str.replace("-", "");
|
||||
}
|
||||
|
||||
private static Profile submit(String str) throws Exception {
|
||||
String stripped = strip(str);
|
||||
|
||||
if (CACHE.containsKey(stripped))
|
||||
return CACHE.get(stripped);
|
||||
|
||||
if (!StringUtil.isUUID(stripped))
|
||||
stripped = str;
|
||||
|
||||
final String url = "https://api.ashcon.app/mojang/v2/user/" + stripped;
|
||||
final JsonUtil jsonUtil = new JsonUtil(readUrl(url));
|
||||
|
||||
if (jsonUtil.contains("code") && jsonUtil.getInt("code") == 404)
|
||||
throw new IllegalArgumentException("Error whilst getting player: does not exist");
|
||||
|
||||
final String username = jsonUtil.getString("username");
|
||||
final UUID uuid = UUID.fromString(Objects.requireNonNull(jsonUtil.getString("uuid")));
|
||||
final Property property = new Property(
|
||||
"textures",
|
||||
jsonUtil.getString("textures.raw.value"),
|
||||
jsonUtil.getString("textures.raw.signature")
|
||||
);
|
||||
|
||||
return new Profile(username, uuid, property);
|
||||
}
|
||||
|
||||
public static class Profile {
|
||||
private final UUID uuid;
|
||||
private final String username;
|
||||
private final Property property;
|
||||
|
||||
public Profile(String username, UUID uuid, Property property) {
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public Property getProperty() {
|
||||
return this.property;
|
||||
}
|
||||
|
||||
public void setSkin(GameProfile gameProfile) {
|
||||
gameProfile.getProperties().put("textures", this.property);
|
||||
}
|
||||
|
||||
public GameProfile toGameProfile() {
|
||||
GameProfile profile = new GameProfile(this.uuid, this.username);
|
||||
this.setSkin(profile);
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
}
|
103
src/main/java/gg/spoof/spigot/util/ReflectionUtil.java
Normal file
103
src/main/java/gg/spoof/spigot/util/ReflectionUtil.java
Normal file
@ -0,0 +1,103 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import gg.spoof.spigot.Spoof;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReflectionUtil {
|
||||
private static final Map<String, ClassData> CACHE = Maps.newHashMap();
|
||||
|
||||
public static void validateInitBySpoof() {
|
||||
String spoofClassName = Spoof.class.getName();
|
||||
for (StackTraceElement element : new Exception("trace").getStackTrace()) {
|
||||
if (!element.getClassName().equals(spoofClassName) || !element.getMethodName().equals("onEnable")) continue;
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("This module can only be initalized by plugin itself in onEnable");
|
||||
}
|
||||
|
||||
public static Field getField(Class<?> klass, String name) throws NoSuchFieldException, SecurityException {
|
||||
Field field = klass.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
|
||||
public static Field getField(Object obj, String name) throws NoSuchFieldException, SecurityException {
|
||||
Field field = obj.getClass().getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
|
||||
public static Method getMethod(Class<?> klass, String name, Class<?> ... parameterTypes) throws NoSuchMethodException, SecurityException {
|
||||
Method method = klass.getDeclaredMethod(name, parameterTypes);
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
}
|
||||
|
||||
public static void set(Field field, Object toUse, Object toReplace) {
|
||||
try {
|
||||
field.set(toUse, toReplace);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getValue(Object obj, String name) {
|
||||
try {
|
||||
Field field = obj.getClass().getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field.get(obj);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setValue(Object obj, String fieldName, Object value) {
|
||||
try {
|
||||
Field field;
|
||||
String className = obj.getClass().getName();
|
||||
ClassData data = CACHE.get(className + fieldName);
|
||||
if (data != null) {
|
||||
field = data.field;
|
||||
} else {
|
||||
field = obj.getClass().getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
data = new ClassData(obj.getClass(), fieldName, field);
|
||||
CACHE.put(className + fieldName, data);
|
||||
}
|
||||
field.set(obj, value);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClassData {
|
||||
Class<? extends Object> className;
|
||||
String fieldId;
|
||||
Field field;
|
||||
|
||||
public ClassData(Class<? extends Object> className, String fieldId, Field field) {
|
||||
this.className = className;
|
||||
this.fieldId = fieldId;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.className.hashCode() * 31 + this.fieldId.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ClassData)) {
|
||||
return false;
|
||||
}
|
||||
ClassData otherClassData = (ClassData)other;
|
||||
return otherClassData.field.equals(this.field) && otherClassData.fieldId.equals(this.fieldId) && otherClassData.className.equals(this.className);
|
||||
}
|
||||
}
|
||||
}
|
24
src/main/java/gg/spoof/spigot/util/StringUtil.java
Normal file
24
src/main/java/gg/spoof/spigot/util/StringUtil.java
Normal file
@ -0,0 +1,24 @@
|
||||
package gg.spoof.spigot.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class StringUtil {
|
||||
public static boolean isUUID(String str) {
|
||||
return str.matches("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");
|
||||
}
|
||||
|
||||
public static String translate(String message) {
|
||||
return ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
|
||||
public static List<String> translate(String ... message) {
|
||||
return Arrays.stream(message).map(StringUtil::translate).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<String> translate(List<String> message) {
|
||||
return message.stream().map(StringUtil::translate).collect(Collectors.toList());
|
||||
}
|
||||
}
|
102
src/main/java/gg/spoof/velocity/Spoof.java
Normal file
102
src/main/java/gg/spoof/velocity/Spoof.java
Normal file
@ -0,0 +1,102 @@
|
||||
package gg.spoof.velocity;
|
||||
|
||||
import com.typesafe.config.Config;
|
||||
import com.typesafe.config.ConfigFactory;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import gg.spoof.common.utils.ResourceLoader;
|
||||
import gg.spoof.velocity.controller.PluginMessageController;
|
||||
import gg.spoof.velocity.controller.ProxyController;
|
||||
import gg.spoof.velocity.controller.RedisController;
|
||||
import gg.spoof.velocity.listener.VelocityPingListener;
|
||||
import gg.spoof.velocity.util.ServerData;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Getter
|
||||
public class Spoof {
|
||||
|
||||
private final ProxyServer proxy;
|
||||
private final Logger logger;
|
||||
private final Path pluginDataDir;
|
||||
private final Map<String, ServerData> servers = new ConcurrentHashMap<>();
|
||||
private boolean debug;
|
||||
private ProxyController controller;
|
||||
|
||||
@Inject
|
||||
public Spoof(ProxyServer proxy, Logger logger, @DataDirectory Path pluginDir) {
|
||||
this.proxy = proxy;
|
||||
this.logger = logger;
|
||||
this.pluginDataDir = pluginDir;
|
||||
}
|
||||
|
||||
public void debug(String message) {
|
||||
if (this.debug)
|
||||
this.getLogger().info(message);
|
||||
}
|
||||
|
||||
public void debug(String message, Throwable t) {
|
||||
if (this.debug)
|
||||
this.getLogger().log(Level.INFO, message, t);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onEnable(ProxyInitializeEvent event) throws IOException {
|
||||
final Path configFile = this.pluginDataDir.resolve("config.conf");
|
||||
ResourceLoader.loadDefaultResource(this.getClass().getClassLoader(), "velocity-config.conf", configFile);
|
||||
final Config config = ConfigFactory.parseFile(configFile.toFile());
|
||||
|
||||
this.debug = config.getBoolean("settings.debug");
|
||||
this.registerController(config);
|
||||
this.setupServersCleanup();
|
||||
this.getProxy().getEventManager().register(this, new VelocityPingListener(this));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onDisable(ProxyShutdownEvent event) {
|
||||
if (this.controller != null)
|
||||
this.controller.close();
|
||||
}
|
||||
|
||||
private void registerController(Config config) {
|
||||
String controllerType;
|
||||
switch (controllerType = config.getString("settings.controller.selected").toLowerCase()) {
|
||||
case "redis": {
|
||||
final String[] address = config.getString("settings.controller.redis.address").split(":", 2);
|
||||
final String password = config.getString("settings.controller.redis.password");
|
||||
this.controller = new RedisController(this, address[0], Integer.parseInt(address[1]), password);
|
||||
break;
|
||||
}
|
||||
case "messaging": {
|
||||
this.controller = new PluginMessageController(this);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RuntimeException("The controller type '" + controllerType + "' isn't valid!");
|
||||
}
|
||||
}
|
||||
this.getLogger().info("Using " + controllerType + " for the receiver.");
|
||||
}
|
||||
|
||||
private void setupServersCleanup() {
|
||||
this.getProxy().getScheduler().buildTask(this, () -> {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
for (Map.Entry<String, ServerData> serverSet : this.servers.entrySet()) {
|
||||
ServerData server = serverSet.getValue();
|
||||
if (currentTime - server.getLastPing() <= TimeUnit.MINUTES.toMillis(1L)) continue;
|
||||
this.servers.remove(serverSet.getKey());
|
||||
}
|
||||
}).delay(10L, TimeUnit.SECONDS).repeat(10L, TimeUnit.SECONDS).schedule();
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package gg.spoof.velocity.controller;
|
||||
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.PluginMessageEvent;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import gg.spoof.common.proxy.ProxyChannelFormat;
|
||||
import gg.spoof.velocity.Spoof;
|
||||
|
||||
public class PluginMessageController extends ProxyController {
|
||||
|
||||
protected final ChannelIdentifier proxyboundServerPlayers = MinecraftChannelIdentifier.from("spoof:srv_pl");
|
||||
protected final ChannelIdentifier serverboundProxyPlayerCount = MinecraftChannelIdentifier.from("spoof:pr_pl_cnt");
|
||||
|
||||
public PluginMessageController(Spoof plugin) {
|
||||
super(plugin);
|
||||
plugin.getProxy().getChannelRegistrar().register(this.proxyboundServerPlayers);
|
||||
plugin.getProxy().getEventManager().register(plugin, this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPluginMessage(PluginMessageEvent event) {
|
||||
if (!(event.getSource() instanceof ServerConnection))
|
||||
return;
|
||||
|
||||
if (!event.getIdentifier().equals(this.proxyboundServerPlayers))
|
||||
return;
|
||||
|
||||
try {
|
||||
final ProxyChannelFormat.ServerPlayers serverPlayers = ProxyChannelFormat.decodeServerPlayers(event.getData());
|
||||
this.updateServerPlayerCount(serverPlayers.getServerId(), serverPlayers.getCount());
|
||||
} catch (Exception ex) {
|
||||
this.plugin.debug("Error receiving server players", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int proxyPlayerCount = this.getProxyPlayerCount();
|
||||
byte[] proxyPlayerCountData = ProxyChannelFormat.encodeProxyPlayerCount(proxyPlayerCount);
|
||||
for (RegisteredServer server : this.plugin.getProxy().getAllServers()) {
|
||||
server.sendPluginMessage(this.serverboundProxyPlayerCount, proxyPlayerCountData);
|
||||
}
|
||||
this.plugin.debug("Sent proxy player count " + proxyPlayerCount);
|
||||
} catch (Exception ex) {
|
||||
this.plugin.debug("Error sending proxy player count", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package gg.spoof.velocity.controller;
|
||||
|
||||
import gg.spoof.velocity.Spoof;
|
||||
import gg.spoof.velocity.util.ServerData;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ProxyController {
|
||||
|
||||
protected final Spoof plugin;
|
||||
|
||||
public abstract void close();
|
||||
|
||||
public int getProxyPlayerCount() {
|
||||
return this.plugin.getServers().values().stream().mapToInt(ServerData::getOnline).sum();
|
||||
}
|
||||
|
||||
public void updateServerPlayerCount(String server, int online) {
|
||||
this.plugin.getServers().computeIfAbsent(server, k -> new ServerData()).setOnline(online);
|
||||
this.plugin.debug("Updated server " + server + " player count to " + online);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package gg.spoof.velocity.controller;
|
||||
|
||||
import gg.spoof.velocity.Spoof;
|
||||
import gg.spoof.velocity.controller.redis.RedisPubSub;
|
||||
import lombok.Getter;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
@Getter
|
||||
public class RedisController extends ProxyController {
|
||||
|
||||
private Jedis jedisRX;
|
||||
private Jedis jedisTX;
|
||||
private final RedisPubSub redisPubSub;
|
||||
|
||||
public RedisController(final Spoof plugin, String host, int port, String password) {
|
||||
super(plugin);
|
||||
this.jedisRX = this.create(host, port, password);
|
||||
this.jedisTX = this.create(host, port, password);
|
||||
this.redisPubSub = new RedisPubSub(plugin, this);
|
||||
|
||||
plugin.getProxy().getScheduler().buildTask(plugin, () -> this.jedisRX.subscribe(this.redisPubSub, "spoof:srv_pl")).schedule();
|
||||
}
|
||||
|
||||
private Jedis create(String host, int port, String password) {
|
||||
final Jedis jedis = new Jedis(host, port);
|
||||
jedis.connect();
|
||||
|
||||
if (!password.isEmpty())
|
||||
jedis.auth(password);
|
||||
|
||||
if (!jedis.isConnected())
|
||||
throw new IllegalStateException("Failed to connect to redis");
|
||||
|
||||
return jedis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.jedisRX != null) {
|
||||
this.jedisRX.close();
|
||||
this.jedisRX = null;
|
||||
}
|
||||
if (this.jedisTX != null) {
|
||||
this.jedisTX.close();
|
||||
this.jedisTX = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package gg.spoof.velocity.controller.redis;
|
||||
|
||||
import gg.spoof.common.proxy.ProxyChannelFormat;
|
||||
import gg.spoof.velocity.Spoof;
|
||||
import gg.spoof.velocity.controller.RedisController;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class RedisPubSub extends JedisPubSub {
|
||||
|
||||
private final Spoof plugin;
|
||||
private final RedisController redisController;
|
||||
|
||||
@Override
|
||||
public void onMessage(String channel, String message) {
|
||||
try {
|
||||
final ProxyChannelFormat.ServerPlayers players = ProxyChannelFormat.decodeB64ServerPlayers(message);
|
||||
this.redisController.updateServerPlayerCount(players.getServerId(), players.getCount());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.plugin.debug("Error receiving server players", ex);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int proxyPlayerCount = this.redisController.getProxyPlayerCount();
|
||||
this.redisController.getJedisTX().publish("spoof:pr_pl_cnt", ProxyChannelFormat.encodeB64ProxyPlayerCount(proxyPlayerCount));
|
||||
this.plugin.debug("Sent total player count " + proxyPlayerCount);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.plugin.debug("Error sending proxy player count", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(String channel, int subscribedChannels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnsubscribe(String channel, int subscribedChannels) {
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package gg.spoof.velocity.listener;
|
||||
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||
import gg.spoof.velocity.Spoof;
|
||||
import gg.spoof.velocity.util.ServerData;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class VelocityPingListener {
|
||||
|
||||
protected final Spoof plugin;
|
||||
|
||||
@Subscribe
|
||||
public void onProxyPing(ProxyPingEvent event) {
|
||||
int count = this.plugin.getServers().values().stream().mapToInt(ServerData::getOnline).sum();
|
||||
this.plugin.debug("Setting proxy count to " + count + ".");
|
||||
event.setPing(event.getPing().asBuilder().onlinePlayers(count).build());
|
||||
}
|
||||
|
||||
}
|
16
src/main/java/gg/spoof/velocity/util/ServerData.java
Normal file
16
src/main/java/gg/spoof/velocity/util/ServerData.java
Normal file
@ -0,0 +1,16 @@
|
||||
package gg.spoof.velocity.util;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ServerData {
|
||||
|
||||
private volatile int online;
|
||||
private volatile long lastPing;
|
||||
|
||||
public void setOnline(int online) {
|
||||
this.online = online;
|
||||
this.lastPing = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
16
src/main/resources/bungee-config.yml
Normal file
16
src/main/resources/bungee-config.yml
Normal file
@ -0,0 +1,16 @@
|
||||
settings:
|
||||
# This is a developer mode, useful for logging
|
||||
# various aspects of the plugin to console.
|
||||
debug: true
|
||||
|
||||
controller:
|
||||
# This is the controller type you wish to handle.
|
||||
selected: "redis"
|
||||
|
||||
# Specify your redis credentials here if your server
|
||||
# includes a proxy.
|
||||
redis:
|
||||
# Specify your address:port
|
||||
address: '127.0.0.1:6379'
|
||||
# If you use credentials, specify here
|
||||
password: ''
|
4
src/main/resources/bungee.yml
Normal file
4
src/main/resources/bungee.yml
Normal file
@ -0,0 +1,4 @@
|
||||
name: Spoof
|
||||
version: 2.5.2
|
||||
main: gg.spoof.bungee.Spoof
|
||||
author: "Stellar Dev"
|
184
src/main/resources/config.yml
Normal file
184
src/main/resources/config.yml
Normal file
@ -0,0 +1,184 @@
|
||||
settings:
|
||||
debug: true
|
||||
|
||||
# Whether the player entity should be shown
|
||||
# in-game, useful for Hub servers.
|
||||
show-bot-entity: true
|
||||
|
||||
# Add your username or uuid here to gain access to the in-game
|
||||
# commands. This is to ensure others with full perms cannot
|
||||
# see the plugin exists.
|
||||
whitelisted:
|
||||
- 'SpoofPlayer'
|
||||
|
||||
# If you wish to run within a proxy,
|
||||
# enable this and specify redis settings below.
|
||||
proxy-mode: false
|
||||
|
||||
# This is your unique server identifier, this MUST be
|
||||
# set if using a proxy - e.g. BungeeCord.
|
||||
server-id: "server"
|
||||
|
||||
# You can optionally run commands from console when a
|
||||
# spoofed player joins. Use %player% for the players
|
||||
# username, no slash is needed.
|
||||
join-commands: []
|
||||
join-commands-delay: 0
|
||||
|
||||
controller:
|
||||
# This is the controller type you wish to use.
|
||||
selected: "redis"
|
||||
|
||||
# Specify your redis credentials here if your server
|
||||
# includes a proxy.
|
||||
redis:
|
||||
# Specify your address:port
|
||||
address: '127.0.0.1:6379'
|
||||
# If you use credentials, specify here
|
||||
password: ''
|
||||
|
||||
# This is the location that the bots spawn in when loaded
|
||||
spawn-locations:
|
||||
x: 0
|
||||
y: 0
|
||||
z: 0
|
||||
world: "world"
|
||||
|
||||
# These are your list of modules, a developer may ask
|
||||
# you to add their own module name below.
|
||||
modules:
|
||||
# This module connects to Buycraft with fake donations
|
||||
# and reacting to donations events with our forked buycraft
|
||||
donations:
|
||||
enabled: true
|
||||
settings:
|
||||
delay:
|
||||
min: 10
|
||||
max: 20
|
||||
responders:
|
||||
min: 1
|
||||
max: 3
|
||||
responses:
|
||||
- "gg"
|
||||
packages:
|
||||
1: # The package ID for fake donations
|
||||
message:
|
||||
- "&7[&6Buycraft&7] &c&l<player> &7has bought &a1x &6Legendary &7key!"
|
||||
|
||||
# This module has the bots respond to people joining/rejoining
|
||||
# with random responses and random selected players
|
||||
welcome:
|
||||
enabled: false
|
||||
settings:
|
||||
delay:
|
||||
min: 10
|
||||
max: 20
|
||||
responders:
|
||||
min: 1
|
||||
max: 3
|
||||
responses:
|
||||
join:
|
||||
- "Welcome to Stellar Dev %player%"
|
||||
- "Aye looks whos here"
|
||||
rejoin:
|
||||
- "Wb"
|
||||
- "Welcome back retard"
|
||||
# This module gives random ranks to the bots
|
||||
# useful to make bots look more realistic
|
||||
ranks:
|
||||
enabled: false
|
||||
settings:
|
||||
# RANK:CHANCE
|
||||
rank-chances:
|
||||
gem: 10
|
||||
interstellar: 20
|
||||
stellar: 30
|
||||
elapsed: 40
|
||||
beer: 50
|
||||
|
||||
# This module automatically fluctuates a random
|
||||
# bots ping, useful for looking realistic.
|
||||
ping:
|
||||
enabled: true
|
||||
settings:
|
||||
delay:
|
||||
min: 1
|
||||
max: 10
|
||||
ping:
|
||||
min: 100
|
||||
max: 150
|
||||
|
||||
# This module lets bots pickup items dropped nearby.
|
||||
# Not recommended, but delay can be tweaked for performance.
|
||||
pickup:
|
||||
enabled: true
|
||||
settings:
|
||||
delay:
|
||||
min: 5
|
||||
max: 5
|
||||
|
||||
# This module lets you run a random command on a bot.
|
||||
# This is useful for having bots automatically teleport etc.
|
||||
action:
|
||||
enabled: false
|
||||
settings:
|
||||
delay:
|
||||
min: 1
|
||||
max: 10
|
||||
actions:
|
||||
# You can add and remove these, e.g. a 70% and a 30% chance action.
|
||||
test:
|
||||
chance: 100
|
||||
list:
|
||||
- '[PLAYER] me woah, cool server!'
|
||||
|
||||
# This module makes a random bot vote (server-sided!).
|
||||
# Enabling this usually motivates real players to want to vote.
|
||||
vote:
|
||||
enabled: false
|
||||
settings:
|
||||
expiration: 3600000
|
||||
delay:
|
||||
min: 1
|
||||
max: 10
|
||||
services:
|
||||
- 'PMC'
|
||||
- 'MinecraftMP'
|
||||
|
||||
# This module makes bots automatically join and leave, depending
|
||||
# on how many real players are currently online.
|
||||
#
|
||||
# I'd recommend 1.2 (20%) to 1.25 (25%) on a production server.
|
||||
fluctuation:
|
||||
enabled: true
|
||||
debug: true
|
||||
settings:
|
||||
# Legit uuids generator
|
||||
accounts:
|
||||
# NameMC, List
|
||||
generator: "NameMC"
|
||||
# List generator users
|
||||
users:
|
||||
- 'dbba4003-2ef3-4857-ab28-610501f34d51'
|
||||
- '157e8dba-c2e6-4fe7-8d01-438b8e4cc898'
|
||||
- '995d6b61-6588-44f6-a919-28f908d06862'
|
||||
delay:
|
||||
min: 1
|
||||
max: 10
|
||||
percent:
|
||||
min: 2.0
|
||||
max: 2.5
|
||||
|
||||
messages:
|
||||
help:
|
||||
- '&8[&b&l⚡&8] &bSpoof &8- &fThe Ultimate Spoofing Solution&7.'
|
||||
- '&8[&b&l⚡ &b/spoof add&8] &7Add a spoofed player to the server'
|
||||
- '&8[&b&l⚡ &b/spoof remove&8] &7Remove a spoofed player from the server'
|
||||
- '&8[&b&l⚡ &b/spoof reload&8] &7Reload the modules and configs'
|
||||
- '&8[&b&l⚡ &b/spoof modules&8] &7View the modules information'
|
||||
- '&8[&b&l⚡ &b/spoof auction&8] &7Auction an item under a spoofed player'
|
||||
- '&8[&b&l⚡ &b/spoof summon&8] &7Summon a spoofed player to your location'
|
||||
- '&8[&b&l⚡ &b/spoof donation&8] &7Create a fake donation reaction with spoof players'
|
||||
modules-information:
|
||||
- '&8[&b&l⚡&8] &bSpoof &8- &fThe Ultimate Spoofing Solution&7.'
|
||||
- '&8[&b&l⚡&8] &7Modules (&a<modules-size>&7): &b<module-loaded>'
|
5
src/main/resources/plugin.yml
Normal file
5
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,5 @@
|
||||
name: Spoof
|
||||
version: 2.5.2
|
||||
main: gg.spoof.spigot.Spoof
|
||||
author: "Stellar Dev"
|
||||
softdepend: ["Votifier", "Vault", "LuckPerms"]
|
21
src/main/resources/velocity-config.conf
Normal file
21
src/main/resources/velocity-config.conf
Normal file
@ -0,0 +1,21 @@
|
||||
license: licensekey
|
||||
|
||||
settings: {
|
||||
# This is a developer mode, useful for logging
|
||||
# various aspects of the plugin to console.
|
||||
debug: true
|
||||
|
||||
controller: {
|
||||
# This is the controller type you wish to handle.
|
||||
selected: "redis"
|
||||
|
||||
# Specify your redis credentials here if your server
|
||||
# includes a proxy.
|
||||
redis: {
|
||||
# Specify your address:port
|
||||
address: "127.0.0.1:6379"
|
||||
# If you use credentials, specify here
|
||||
password: ""
|
||||
}
|
||||
}
|
||||
}
|
10
src/main/resources/velocity-plugin.json
Normal file
10
src/main/resources/velocity-plugin.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "spoof",
|
||||
"id": "spoof",
|
||||
"main": "gg.spoof.velocity.Spoof",
|
||||
"version": "2.5.2",
|
||||
"dependencies": [],
|
||||
"authors": [
|
||||
"Stellar Dev"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user