This commit is contained in:
Brandon 2023-05-21 19:56:35 +01:00
commit ae4da96810
96 changed files with 5234 additions and 0 deletions

BIN
lib/travertine-1.16-168.jar Normal file

Binary file not shown.

BIN
lib/velocity-3.1.1-98.jar Normal file

Binary file not shown.

99
pom.xml Normal file
View 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>

View 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);
}
}

View 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();
}
}

View File

@ -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() {
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View 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();
}
}

View 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;
}
}

View 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);
}
}
}

View 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);
}
}

View File

@ -0,0 +1,9 @@
package gg.spoof.spigot;
public class SpoofAPI {
public static int getTotalCount() {
return Spoof.getPlugin().getProxyController().getTotalPlayerCount();
}
}

View 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);
}

View 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;
}
}

View 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);
}
}

View File

@ -0,0 +1,11 @@
package gg.spoof.spigot.api;
public interface ProxyController {
int getTotalPlayerCount();
void sendServerPlayerCount();
void close();
}

View 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();
}
}
}

View 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;
}
}

View 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;
}
}
}

View 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
}
}

View 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();
}
}

View File

@ -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));
}
}

View File

@ -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();
}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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
//
//}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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() {}
}

View File

@ -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");
}
}

View File

@ -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");
}
}
}

View 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();
}
}

View 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;
}
}

View 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);
}
}

View 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");
}
}

View 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;
}
}

View 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;
}
}

View 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);
//
//}

View 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);
//}

View 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);
}
}

View 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();
//
//}

View 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);
//
//}

View 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();
//
//}

View 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);
//
//}

View 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();
//
//}

View 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();
// }
//}

View 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()));
}
}

View File

@ -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];
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}
}

View File

@ -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);
//
//}

View 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);
//
//}

View File

@ -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);
//
//}

View 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);
//
//}

View File

@ -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);
//
//}

View 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;
}

View 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);
}

View 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;
}
}

View File

@ -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) {
}
}

View File

@ -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 {
// }
//}

View 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());
// }
//}

View File

@ -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) {
// }
//}

View 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());
// }
//}

View File

@ -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) {
// }
//}

View 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();
// }
//}

View File

@ -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) {
// }
//}

View 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();
// }
//}

View File

@ -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 {
}
}

View 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);
}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}
}
}

View 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;
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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());
}
}

View 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();
}
}

View File

@ -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() {
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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) {
}
}

View File

@ -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());
}
}

View 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();
}
}

View 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: ''

View File

@ -0,0 +1,4 @@
name: Spoof
version: 2.5.2
main: gg.spoof.bungee.Spoof
author: "Stellar Dev"

View 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>'

View File

@ -0,0 +1,5 @@
name: Spoof
version: 2.5.2
main: gg.spoof.spigot.Spoof
author: "Stellar Dev"
softdepend: ["Votifier", "Vault", "LuckPerms"]

View 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: ""
}
}
}

View File

@ -0,0 +1,10 @@
{
"name": "spoof",
"id": "spoof",
"main": "gg.spoof.velocity.Spoof",
"version": "2.5.2",
"dependencies": [],
"authors": [
"Stellar Dev"
]
}