commit 37f08be28b0f1254785b5c3fc24f8eefa9e06f97 Author: Brandon <46827438+disclearing@users.noreply.github.com> Date: Wed May 3 15:21:03 2023 +0100 ggg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..744289d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Project exclude paths +/target/ \ No newline at end of file diff --git a/Bridge.iml b/Bridge.iml new file mode 100644 index 0000000..8924c7a --- /dev/null +++ b/Bridge.iml @@ -0,0 +1,104 @@ + + + + + + + BUNGEECORD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..7e73f6a --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,18 @@ +node { + stage('Clone') { + checkout scm + } + + stage('Build') { + sh "mvn clean install -U" + } + + stage('Archive') { + archiveArtifacts artifacts: 'target/*.jar', fingerprint: true + } + + stage('Uploading to Nexus') { + pom = readMavenPom file: 'pom.xml' + nexusPublisher nexusInstanceId: 'prnex', nexusRepositoryId: 'bridge', packages: [[$class: 'MavenPackage', mavenAssetList: [[classifier: '', extension: 'jar', filePath: "target/${pom.name}.jar"]], mavenCoordinate: [artifactId: pom.artifactId, groupId: 'rip.bridge', packaging: 'jar', version: pom.version]]] + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..8e26ec4 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +"# Bridge" diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..15ac3d4 --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,160 @@ + + + 4.0.0 + rip.bridge + Bridge + Bridge + 1.0 + + + + true + src/main/resources + + plugin.yml + + + + src/main/resources + + plugin.yml + + + + ${project.name} + + + net.md-5 + scriptus + 0.2 + + + initialize + + describe + + + %s + bridge.desc + + + + + + maven-compiler-plugin + 3.5.1 + + + default-compile + none + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + 1.8 + 1.8 + + + org.projectlombok + lombok + 1.16.16 + + + + + + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + vault-repo + http://nexus.hc.to/content/repositories/pub_releases + + + lunarclient-public + https://maven.moonsworth.com/repository/lunarclient-public/ + + + zeroturnaround-repo + https://repos.zeroturnaround.com/nexus/content/repositories/zt-public-releases/ + + + depends + redacted + + + bridge + redacted + + + + + rip.bridge + mspigot-server + 1.7.10-R0.1-SNAPSHOT + provided + + + rip.bridge + qLib + 1.0 + provided + + + org.projectlombok + lombok + 1.16.16 + provided + + + net.md_5.bungee + bungee + 1.7.10-R0.1-SNAPSHOT + system + ${project.basedir}/lib/BungeeCord.jar + + + com.comphenix.protocol + ProtocolLib-v1_7_R4 + 3.7.0-BETA + system + ${project.basedir}/lib/ProtocolLib-v1_7_R4-3.7.0-BETA.jar + + + + UTF-8 + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9350b93 --- /dev/null +++ b/pom.xml @@ -0,0 +1,257 @@ + + 4.0.0 + rip.bridge + Bridge + Bridge + ${git.commit.id.abbrev} + + + UTF-8 + + + + ${project.name} + src/main/java + + + pl.project13.maven + git-commit-id-plugin + 4.0.0 + + + get-the-git-infos + + revision + + initialize + + + + true + ${project.build.outputDirectory}/git.properties + + + ^git.build.(time|version)$ + ^git.commit.id.(abbrev|full)$ + + full + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + + + default-compile + none + + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + 1.8 + 1.8 + + + org.projectlombok + lombok + 1.16.16 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.6 + + + make-assembly + package + + single + + + false + + jar-with-dependencies + + + + + + + + + src/main/resources + true + + + + + + sonatype-snapshots + Sonatype Snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + vault-repo + http://nexus.hc.to/content/repositories/pub_releases + + + lunarclient-public + https://maven.moonsworth.com/repository/lunarclient-public/ + + + zeroturnaround-repo + https://repos.zeroturnaround.com/nexus/content/repositories/zt-public-releases/ + + + depends + redacted + default + + + + bridge + redacted + default + + + + + + + com.google.code.gson + gson + 2.8.6 + compile + + + + com.google.auth + google-auth-library-oauth2-http + 0.25.3 + + + + + net.md_5.bungee + bungee + 1.7.10-R0.1-SNAPSHOT + system + ${project.basedir}/lib/BungeeCord.jar + + + + + rip.bridge + mspigot-server + 1.7.10-R0.1-SNAPSHOT + provided + + + + + + rip.bridge + qLib + LATEST + provided + + + + javax.mail + mail + 1.4 + + + + commons-validator + commons-validator + 1.7 + + + + org.apache.commons + commons-lang3 + 3.8.1 + compile + + + + redis.clients + jedis + 2.10.2 + compile + + + + org.mongodb + mongo-java-driver + 3.10.2 + compile + + + + org.projectlombok + lombok + 1.16.16 + provided + + + + commons-configuration + commons-configuration + 1.10 + + + + com.comphenix.protocol + ProtocolLib-v1_7_R4 + 3.7.0-BETA + system + ${project.basedir}/lib/ProtocolLib-v1_7_R4-3.7.0-BETA.jar + + + jakarta.validation + jakarta.validation-api + 2.0.1 + compile + + + com.warrenstrange + googleauth + 1.4.0 + + + + diff --git a/src/main/java/rip/bridge/bridge/BridgeGlobal.java b/src/main/java/rip/bridge/bridge/BridgeGlobal.java new file mode 100644 index 0000000..0f2dcf5 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/BridgeGlobal.java @@ -0,0 +1,327 @@ +package rip.bridge.bridge; + +import com.google.common.collect.Lists; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.listener.GeneralListener; +import rip.bridge.bridge.bungee.BridgeBungee; +import rip.bridge.bridge.bungee.listener.GeneralBungeeListener; +import rip.bridge.bridge.global.disguise.DisguiseManager; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.handlers.PrefixHandler; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.bridge.global.status.ServerHandler; +import rip.bridge.bridge.global.status.threads.StatusUpdateThread; +import rip.bridge.bridge.global.updater.UpdaterManager; +import rip.bridge.bridge.global.util.SystemType; +import lombok.Getter; +import lombok.Setter; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; +import rip.bridge.bridge.global.handlers.*; + +import java.util.*; + +public class BridgeGlobal { + + @Getter @Setter public static SystemType systemType = SystemType.UNKNOWN; + + @Getter private static boolean mongoAuth, redisAuth, allowBannedJoins; + + @Getter private static int mongoPort, redisPort, redisDB; + @Getter private static String mongoHost, mongoUsername, mongoPassword, mongoDatabase, redisHost, redisPassword, redisChannel, screenName, screenPath, serverName, serverDisplayName, serverWebsite, pluginUpdateDir ="%user_home%/Bridge/updater", groupName = "N/A"; + private static List updaterGroups; + private static String serverDeploymentDir; + private static String serverTemplateDir; + private static boolean handleServerDeployment; + @Getter private static long startTime = -1L; + @Getter private static MongoHandler mongoHandler; + @Getter private static RankHandler rankHandler; + @Getter private static PacketLogHandler packetLogHandler; + @Getter private static PrefixHandler prefixHandler; + @Getter private static ProfileHandler profileHandler; + @Getter private static UpdaterManager updaterManager; + @Getter private static FilterHandler filterHandler; + @Getter private static ServerHandler serverHandler; + @Getter private static JedisPool jedisPool; + @Getter private static JsonParser parser = new JsonParser(); + @Getter private static DisguiseManager disguiseManager; + + @Getter @Setter private static boolean shutdown; + + public BridgeGlobal() { + this("", "", "", "", 27017, false, "", "", "", 0, 6379, false, true); + } + + public BridgeGlobal(String mongoHost, String mongoUsername, String mongoPassword, String mongoDatabase, int mongoPort, boolean mongoAuth, String redisHost, String redisPassword, String redisChannelKek, int redisDB, int redisPort, boolean redisAuth, boolean getFromConfig) { + this(mongoHost, mongoUsername, mongoPassword, mongoDatabase, mongoPort, mongoAuth, redisHost, redisPassword, redisChannelKek, redisDB, redisPort, redisAuth, getFromConfig, null); + } + + public BridgeGlobal(String mongoHost, String mongoUsername, String mongoPassword, String mongoDatabase, int mongoPort, boolean mongoAuth, String redisHost, String redisPassword, String redisChannelKek, int redisDB, int redisPort, boolean redisAuth, boolean getFromConfig, String customServerName) { + setSystemType(currentSystemType()); + sendLog("We have detected that Bridge is running on System Type: " + getSystemType().name()); + + if (customServerName != null) + serverName = customServerName; + + if(getFromConfig) { + setupConfigValues(); + }else { + BridgeGlobal.mongoAuth = mongoAuth; + BridgeGlobal.mongoPort = mongoPort; + BridgeGlobal.mongoHost = mongoHost; + BridgeGlobal.mongoUsername = mongoUsername; + BridgeGlobal.mongoPassword = mongoPassword; + BridgeGlobal.mongoDatabase = mongoDatabase; + BridgeGlobal.redisAuth = redisAuth; + BridgeGlobal.redisHost = redisHost; + BridgeGlobal.redisPort = redisPort; + BridgeGlobal.redisPassword = redisPassword; + BridgeGlobal.redisChannel = redisChannelKek; + BridgeGlobal.redisDB = redisDB; + } + sendLog("Loading Mongo backend..."); + mongoHandler = new MongoHandler(); + + sendLog("Loading Ranks"); + rankHandler = new RankHandler(); + rankHandler.init(); + + profileHandler = new ProfileHandler(); + profileHandler.init(); + sendLog("Successfully loaded the Profile Handler"); + + prefixHandler = new PrefixHandler(); + prefixHandler.init(); + sendLog("Successfully loaded the Prefix Handler"); + + packetLogHandler = new PacketLogHandler(); + sendLog("Successfully loaded the PacketLog Handler"); + + filterHandler = new FilterHandler(); + filterHandler.init(); + sendLog("Successfully loaded the Filter Handler"); + + jedisPool = new JedisPool(new JedisPoolConfig(), BridgeGlobal.getRedisHost(), BridgeGlobal.getRedisPort(), 0, (BridgeGlobal.isRedisAuth() ? BridgeGlobal.getRedisPassword() : null), BridgeGlobal.getRedisDB()); + PacketHandler.init(jedisPool, redisChannel); + +// sendLog("Setting up status handler"); +// StatusHandler.init(); + + serverHandler = new ServerHandler(); + serverHandler.init(); + sendLog("Successfully setup the Server Handler"); + + + if(pluginUpdateDir != null && !pluginUpdateDir.isEmpty()) { + sendLog("Setting up the update handler"); + updaterManager = new UpdaterManager(); + } + startTime = System.currentTimeMillis(); + sendLog("Completed Bridge Backend - loaded " + getSystemType() + " system type."); + } + + public static void loadDisguise(boolean bungee) { + disguiseManager = new DisguiseManager(bungee); + sendLog("Successfully loaded the Disguise Handler"); + } + + private void setupConfigValues() { + mongoAuth = Boolean.parseBoolean(getFromConfig("mongo.auth.enabled")); + mongoPort = Integer.parseInt(getFromConfig("mongo.port")); + mongoHost = getFromConfig("mongo.host"); + mongoUsername = getFromConfig("mongo.auth.username"); + mongoPassword = getFromConfig("mongo.auth.password"); + mongoDatabase = getFromConfig("mongo.database"); + + redisAuth = !getFromConfig("redis.password").equals(""); + redisHost = getFromConfig("redis.host"); + redisPort = Integer.parseInt(getFromConfig("redis.port")); + redisPassword = getFromConfig("redis.password"); + redisChannel = getFromConfig("redis.channel"); + redisDB = Integer.parseInt(getFromConfig("redis.db")); + screenName = getFromConfig("screenName"); + screenPath = getFromConfig("screenPath"); + serverName = getFromConfig("serverName"); + allowBannedJoins = Boolean.parseBoolean(getFromConfig("AllowBannedJoins")); + serverDisplayName = getFromConfig("serverDisplayName"); + serverWebsite = getFromConfig("serverWebsite"); + pluginUpdateDir = getFromConfig("pluginUpdateDirectory"); + groupName = getFromConfig("serverGroup"); + handleServerDeployment = Boolean.parseBoolean(BridgeGlobal.getFromConfig("handleServerDeployment")); + serverDeploymentDir = BridgeGlobal.getFromConfig("serverDeploymentDirectory"); + serverTemplateDir = BridgeGlobal.getFromConfig("serverTemplateDirectory"); + if(getSystemType() == SystemType.BUKKIT) updaterGroups = Bridge.getInstance().getConfig().getStringList("updaterGroups"); + } + + public static void shutdown() { + shutdown = true; + StatusUpdateThread.saveShutdown(); + getProfileHandler().saveDisable(); + getRankHandler().saveDisable(); + getMongoHandler().getMongoClient().close(); + getJedisPool().close(); + } + + private static SystemType currentSystemType() { + try { + Class.forName("net.md_5.bungee.BungeeCord"); + return SystemType.BUNGEE; + } catch (ClassNotFoundException ignored) {} + try { + Class.forName("org.bukkit.Bukkit"); + return SystemType.BUKKIT; + } catch (ClassNotFoundException ignored) {} + return SystemType.UNKNOWN; + } + + public static String getSystemName() { + switch (getSystemType()) { + case BUNGEE: + case BUKKIT: { + return serverName; + } + default: { + if (serverName != null && !serverName.isEmpty()) + return serverName; + + return "Custom Java Applet"; + } + } + } + + public static void sendLog(String msg, boolean packetIncoming) { + String logMessage = "%prefix% §r" + msg; + switch (systemType) { + case BUNGEE: + GeneralBungeeListener.logMessages(msg.replace("%prefix%", "[Bridge]")); + return; + case BUKKIT: + GeneralListener.logMessages(msg.replace("%prefix%", "[Bridge]"), packetIncoming); + return; + default: + System.out.println(logMessage.replace("%prefix%", "[Bridge]").replace("§", "")); + } + } + + public static void sendLog(String msg) { + sendLog(msg, false); + } + + + public static String getFromConfig(String path) { + switch(systemType) { + case BUNGEE: { + return BridgeBungee.getConfig().getString(path); + } + case UNKNOWN: { + return null; + } + case BUKKIT: { + return Bridge.getInstance().getConfig().getString(path); + } + } + return null; + } + + public static List getUpdaterGroups() { + if(getSystemType() != SystemType.BUKKIT) return null; + List list = new ArrayList<>(Collections.singletonList(getGroupName())); + if(!updaterGroups.isEmpty()) list.addAll(updaterGroups); + return list; + } + + public static boolean isHandleServerDeployment() { + return handleServerDeployment; + } + + public static void setHandleServerDeployment(boolean handleServerDeployment) { + BridgeGlobal.handleServerDeployment = handleServerDeployment; + } + + public static String getServerDeploymentDir() { + return serverDeploymentDir.replace("%user_home%", System.getProperty("user.home")); + } + + public static void setServerDeploymentDir(String serverDeploymentDir) { + BridgeGlobal.serverDeploymentDir = serverDeploymentDir; + } + + public static String getServerTemplateDir() { + return serverTemplateDir.replace("%user_home%", System.getProperty("user.home")); + } + + public static void setServerTemplateDir(String serverTemplateDir) { + BridgeGlobal.serverTemplateDir = serverTemplateDir; + } + + public static void addUpdaterGroup(String group) { + updaterGroups.add(group); + } + + public static void removeUpdaterGroup(String group) { + updaterGroups.remove(group); + } + + public static void savePlayerData(String key, UUID uuid, JsonObject data) { + try (Jedis jedis = jedisPool.getResource()) { + jedis.hset(key, uuid.toString(), data.toString()); + } + } + + public static void deletePlayerData(String key, UUID uuid) { + try (Jedis jedis = jedisPool.getResource()) { + jedis.hdel(key, uuid.toString()); + } + } + + public static JsonObject getPlayerData(UUID uuid, String key) { + try (Jedis jedis = jedisPool.getResource()) { + String data = jedis.hget(key, uuid.toString()); + + if(data == null) { + return null; + } + + try { + JsonObject object = parser.parse(data).getAsJsonObject(); + + if(object.has("data")) { + return object.get("data").getAsJsonObject(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + return null; + } + + public static List getUsedDisguisedNames() { + try (Jedis jedis = jedisPool.getResource()) { + Map data = jedis.hgetAll("disguise"); + + if(data == null) { + return null; + } + + List names = Lists.newArrayList(); + + for(String dataStructure : data.values()) { + JsonObject object = parser.parse(dataStructure).getAsJsonObject(); + + if(object.has("data")) { + JsonObject values = object.get("data").getAsJsonObject(); + + if(values.has("disguiseName")) { + names.add(values.get("disguiseName").getAsString()); + } + } + } + + return names; + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/Bridge.java b/src/main/java/rip/bridge/bridge/bukkit/Bridge.java new file mode 100644 index 0000000..94a1e59 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/Bridge.java @@ -0,0 +1,65 @@ +package rip.bridge.bridge.bukkit; + +import lombok.Setter; +import net.minecraft.server.v1_7_R4.Packet; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.listener.BridgeListener; +import rip.bridge.bridge.bukkit.listener.FreezeListener; +import rip.bridge.bridge.bukkit.parameters.*; +import rip.bridge.bridge.bukkit.parameters.param.filter.FilterActionParameter; +import rip.bridge.bridge.bukkit.parameters.param.filter.FilterParameter; +import rip.bridge.bridge.bukkit.parameters.param.filter.FilterTypeParameter; +import rip.bridge.bridge.bukkit.util.BukkitUtils; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.bridge.global.filter.FilterAction; +import rip.bridge.bridge.global.filter.FilterType; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import rip.bridge.qlib.command.FrozenCommandHandler; +import rip.bridge.qlib.nametag.FrozenNametagHandler; + +import java.util.ArrayList; + +public class Bridge extends JavaPlugin { + + @Getter private static Bridge instance; + @Getter private boolean isBooted = false; + @Getter private ArrayList blockedPackets = new ArrayList<>(); + @Getter @Setter public boolean togglePacketLogger = false; + + @Override + public void onLoad() { + (instance = this).saveDefaultConfig(); + new BridgeGlobal(); + BridgeGlobal.getServerHandler().registerProvider(new BukkitStatusImplementer()); + } + + @Override + public void onEnable() { + FrozenCommandHandler.registerAll(this); + FrozenCommandHandler.registerParameterType(Rank.class, new RankParamater()); + FrozenCommandHandler.registerParameterType(DisguiseProfile.class, new DisguiseParameter()); + FrozenCommandHandler.registerParameterType(Profile.class, new ProfileParamater()); + FrozenCommandHandler.registerParameterType(Plugin.class, new PluginParameter()); + FrozenCommandHandler.registerParameterType(FilterAction.class, new FilterActionParameter()); + FrozenCommandHandler.registerParameterType(FilterType.class, new FilterTypeParameter()); + FrozenCommandHandler.registerParameterType(Filter.class, new FilterParameter()); + FrozenNametagHandler.registerProvider(new BridgeNameTagProvider()); + + BukkitUtils.registerListeners(BridgeListener.class); + BukkitUtils.registerListeners(FreezeListener.class); + Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> isBooted = true); + BridgeGlobal.loadDisguise(false); + } + + @Override + public void onDisable() { + BridgeGlobal.shutdown(); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java b/src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java new file mode 100644 index 0000000..eafcbe2 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java @@ -0,0 +1,488 @@ +package rip.bridge.bridge.bukkit; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.MojangUtils; +import net.minecraft.server.v1_7_R4.Packet; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.Warning; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class BukkitAPI { + + private static Pattern uuidPattern = Pattern.compile("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}"); + public static String LINE = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + "---------------------------------------------"; + public static String RED_LINE = ChatColor.RED.toString() + ChatColor.STRIKETHROUGH + "---------------------------------------------"; + public static String BLUE_LINE = ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + "---------------------------------------------"; + private static final UUID ZERO_UUID = new UUID(0, 0); + + public static boolean isUUID(String string) { + return uuidPattern.matcher(string).find(); + } + + public static Player getPlayer(String string) { + + if (string == null) { + return null; + } else { + return isUUID(string) ? Bukkit.getPlayer(UUID.fromString(string)) : Bukkit.getPlayer(string); + } + } + + public static Rank getRank(String name) { + return BridgeGlobal.getRankHandler().getRankByName(name); + } + + public static Rank getRank(UUID uuid) { + return BridgeGlobal.getRankHandler().getRankByID(uuid); + } + + public static Rank createRank(String name) { + if(BridgeGlobal.getRankHandler().getRankByName(name) != null) { + return null; + } + Rank r = new Rank(UUID.randomUUID(), name, false); + r.saveRank(); + BridgeGlobal.getRankHandler().addRank(r); + return r; + } + + public static Profile getProfile(UUID uuid) { + if(uuid == null) return Profile.getConsoleProfile(); + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid); + } + + public static Profile getProfile(CommandSender sender) { + return (sender instanceof Player ? BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(((Player)sender).getUniqueId()) : Profile.getConsoleProfile()); + } + + public static Profile getProfile(Player player) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()); + } + + public static Profile getProfile(OfflinePlayer offlinePlayer) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()); + } + + public static Profile getProfile(String name) { + Profile disguisedProfile = BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile -> profile.getDisguise() != null && profile.getDisguise().getDisguiseName().equalsIgnoreCase(name)).findAny().orElse(null); + if(disguisedProfile != null) return disguisedProfile; + return BridgeGlobal.getProfileHandler().getProfileByUsernameOrCreate(name); + } + + public static Profile getProfileNotCreate(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUID(uuid); + } + + public static Profile getProfileNotCreate(Player player) { + return getProfileNotCreate(player.getUniqueId()); + } + + public static Profile getProfileNotCreate(OfflinePlayer player) { + return getProfileNotCreate(player.getUniqueId()); + } + + + @Warning(reason = "This requires to be ran on a seperate thread, otherwise there will be lag on the main server thread.") + public static Profile getProfileOrCreateNew(UUID uuid) { + String name; + try { + name = MojangUtils.fetchName(uuid); + }catch(Exception e) { + return null; + } + return BridgeGlobal.getProfileHandler().getNewProfileOrCreate(name, uuid); + } + + public static Profile getProfileOrCreateNew(String username, UUID uuid) { + return BridgeGlobal.getProfileHandler().getNewProfileOrCreate(username, uuid); + } + + public static List getOnlineProfiles() { + return Bukkit.getOnlinePlayers().stream().filter(player -> getProfile(player) != null).map(BukkitAPI::getProfile).collect(Collectors.toList()); + } + + public static Rank getDefaultRank() { + return BridgeGlobal.getRankHandler().getDefaultRank(); + } + + public static Rank getPlayerRank(CommandSender player, boolean ignoreDisguise) { + if(!(player instanceof Player)) { + return getRank("Owner"); + } + if(getProfile(player) == null) { + return getDefaultRank(); + } + + if(ignoreDisguise) { + return getPlayerRank(((Player)player), true); + }else { + if(getProfile(player).getDisguisedRank() != null) { + return getProfile(player).getDisguisedRank(); + } + } + + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(((Player)player).getUniqueId()).getCurrentGrant().getRank(); + } + + public static Rank getPlayerRank(CommandSender player) { + return getPlayerRank(player, false); + } + + public static Rank getPlayerRank(Player player) { + if(getProfile(player) == null) { + return getDefaultRank(); + } + if(getProfile(player).getDisguisedRank() != null) { + return getProfile(player).getDisguisedRank(); + } + + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getCurrentGrant().getRank(); + } + + public static Rank getPlayerRank(UUID uuid) { + if(getProfile(uuid) == null) { + return getDefaultRank(); + } + if(getProfile(uuid).getDisguisedRank() != null) { + return getProfile(uuid).getDisguisedRank(); + } + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getCurrentGrant().getRank(); + } + + public static Rank getPlayerRank(OfflinePlayer offlinePlayer) { + if(getProfile(offlinePlayer) == null) { + return getDefaultRank(); + } + if(getProfile(offlinePlayer).getDisguisedRank() != null) { + return getProfile(offlinePlayer).getDisguisedRank(); + } + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getCurrentGrant().getRank(); + } + + public static Rank getPlayerRank(Profile profile) { + if(profile == null) { + return getDefaultRank(); + } + if(profile.getUuid().toString().equals(Profile.getConsoleProfile().getUuid().toString())) { + return getRank("Default"); + } + if(profile.getDisguisedRank() != null) { + return profile.getDisguisedRank(); + } + return profile.getCurrentGrant().getRank(); + } + + public boolean canPunish(CommandSender sender, Profile target) { + if(!(sender instanceof Player)) return true; + return (getPlayerRank(sender).isStaff() && getPlayerRank(target).isStaff()) && getPlayerRank(sender).getPriority() > getPlayerRank(target).getPriority(); + } + + @Deprecated + public static boolean canOverride(CommandSender sender, Profile on) { + return canOverride(getProfile(sender), on); + } + + public static boolean canOverride(Profile sender, Profile on) { + if (compareUUID(sender.getUuid(), ZERO_UUID)) // Always allow to override console + return true; + + if (compareUUID(sender.getUuid(), on.getUuid())) // Always allow to override own punishments + return true; + + return getRankPriority(sender) >= getRankPriority(on); + } + + public static boolean compareUUID(UUID first, UUID second) { + return first.getLeastSignificantBits() == second.getLeastSignificantBits() && first.getMostSignificantBits() == second.getMostSignificantBits(); + } + + public static int getRankPriority(Profile profile) { + if (profile == null) + return 0; + + Rank rank = getPlayerRank(profile, true); + + if (rank == null) + return 0; + + return rank.getPriority(); + } + + public static Rank getPlayerRank(Player player, boolean ignoreDisguise) { + if(getProfile(player) == null) { + return getDefaultRank(); + } + if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getCurrentGrant().getRank(); + + else if(getProfile(player).getDisguisedRank() != null) { + return getProfile(player).getDisguisedRank(); + } + return null; + + } + + public static Rank getPlayerRank(UUID uuid, boolean ignoreDisguise) { + if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getCurrentGrant().getRank(); + + else if(getProfile(uuid).getDisguisedRank() != null) { + return getProfile(uuid).getDisguisedRank(); + } + return null; + } + + public static Rank getPlayerRank(OfflinePlayer offlinePlayer, boolean ignoreDisguise) { + if(getProfile(offlinePlayer) == null) { + return getDefaultRank(); + } + if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getCurrentGrant().getRank(); + + else if(getProfile(offlinePlayer).getDisguisedRank() != null) { + return getProfile(offlinePlayer).getDisguisedRank(); + } + return null; + } + + public static Rank getPlayerRank(Profile profile, boolean ignoreDisguise) { + if(profile == null) { + return getDefaultRank(); + } + + if (profile.getUuid().getLeastSignificantBits() == 0 && profile.getUuid().getMostSignificantBits() == 0) + return null; + + if(ignoreDisguise) return profile.getCurrentGrant().getRank(); + + else if(profile.getDisguisedRank() != null) { + return profile.getDisguisedRank(); + } + return null; + } + + public static String getColor(CommandSender sender) { + if(getProfile(sender) == null) { + return getDefaultRank().getColor(); + } + if(!getProfile(sender).getColor().equals("")) { + return getProfile(sender).getColor(); + }else { + return getPlayerRank(sender).getColor(); + } + } + + public static String getColor(Player player) { + if(getProfile(player) == null) { + return getDefaultRank().getColor(); + } + if(!getProfile(player).getColor().equals("")) { + return getProfile(player).getColor(); + }else { + return getPlayerRank(player).getColor(); + } + } + + public static String getColor(OfflinePlayer player) { + if(getProfile(player) == null) { + return getDefaultRank().getColor(); + } + if(!getProfile(player).getColor().equals("")) { + return getProfile(player).getColor(); + }else { + return getPlayerRank(player).getColor(); + } + } + + public static String getColor(UUID player) { + if(!getProfile(player).getColor().equals("")) { + return getProfile(player).getColor(); + }else { + return getPlayerRank(player).getColor(); + } + } + + public static String getColor(Profile profile) { + if(!profile.getColor().equals("")) { + return profile.getColor(); + }else { + return getPlayerRank(profile).getColor(); + } + } + + public static String getPrefix(Player player) { + if(getProfile(player) == null) { + return getDefaultRank().getPrefix(); + } + if(!getProfile(player).getPrefix().equals("")) { + return getProfile(player).getPrefix(); + }else { + return getPlayerRank(player).getPrefix(); + } + } + + public static String getPrefix(OfflinePlayer player) { + if(getProfile(player) == null) { + return getDefaultRank().getPrefix(); + } + if(!getProfile(player).getPrefix().equals("")) { + return getProfile(player).getPrefix(); + }else { + return getPlayerRank(player).getPrefix(); + } + } + public static String getPrefix(UUID player) { + if(getProfile(player) == null) { + return getDefaultRank().getPrefix(); + } + if(!getProfile(player).getPrefix().equals("")) { + return getProfile(player).getPrefix(); + }else { + return getPlayerRank(player).getPrefix(); + } + } + + public static String getPrefix(Profile profile) { + if(profile == null) { + return getDefaultRank().getPrefix(); + } + if(!profile.getPrefix().equals("")) { + return profile.getPrefix(); + }else { + return getPlayerRank(profile).getPrefix(); + } + } + + public static String getSuffix(Player player) { + if(getProfile(player) == null) { + return getDefaultRank().getSuffix(); + } + if(!getProfile(player).getSuffix().equals("")) { + return getProfile(player).getSuffix(); + }else { + return getPlayerRank(player).getSuffix(); + } + } + + public static String getSuffix(OfflinePlayer player) { + if(getProfile(player) == null) { + return getDefaultRank().getSuffix(); + } + if(!getProfile(player).getSuffix().equals("")) { + return getProfile(player).getSuffix(); + }else { + return getPlayerRank(player).getSuffix(); + } + } + + public static String getSuffix(UUID player) { + if(getProfile(player) == null) { + return getDefaultRank().getSuffix(); + } + if(!getProfile(player).getSuffix().equals("")) { + return getProfile(player).getSuffix(); + }else { + return getPlayerRank(player).getSuffix(); + } + } + + public static String getSuffix(Profile profile) { + if(profile == null) { + return getDefaultRank().getSuffix(); + } + if(!profile.getSuffix().equals("")) { + return profile.getSuffix(); + }else { + return getPlayerRank(profile).getSuffix(); + } + } + + + public static String getName(Profile profile, boolean ignoreDisguise) { + return (ignoreDisguise || profile.getDisguise() == null) ? profile.getUsername() : profile.getDisguise().getDisguiseName(); + } + + public static String getRealName(Profile profile) { + return profile.getDisguise() == null ? profile.getUsername() : profile.getDisguise().getName(); + } + + public static String getRealName(UUID uuid) { + return getRealName(getProfile(uuid)); + } + + public static String getRealName(Player player) { + return getRealName(getProfile(player)); + } + + + public static void sendPacket(Player player, Packet packet){ + CraftPlayer cp = (CraftPlayer) player; + cp.getHandle().playerConnection.sendPacket(packet); + } + + public static List getActiveGrants(Player player) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getActiveGrants(); + } + + public static List getActiveGrants(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getActiveGrants(); + } + + public static List getActiveGrants(OfflinePlayer offlinePlayer) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getActiveGrants(); + } + + public static List getActiveGrants(Profile profile) { + return profile.getActiveGrants(); + } + + public static List getCurrentScopeRanks(Player player) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList()); + } + + public static List getCurrentScopeRanks(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList()); + } + + public static List getCurrentScopeRanks(OfflinePlayer offlinePlayer) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList()); + } + + public static List getAllGrants(Player player) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getGrants(); + } + + public static List getAllGrants(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getGrants(); + } + + public static List getAllGrants(OfflinePlayer offlinePlayer) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getGrants(); + } + + public static void sendToStaff(String message) { + BridgeGlobal.sendLog(message); + Bukkit.getOnlinePlayers().stream().filter(p -> getPlayerRank(p, true).isStaff()).forEach(p -> { + ((Player) p).sendMessage(ChatColor.translateAlternateColorCodes('&', message)); + }); + } + + public static void sendToStaff(List message) { + message.forEach(BridgeGlobal::sendLog); + Bukkit.getOnlinePlayers().stream().filter(p -> getPlayerRank(p, true).isStaff()).forEach(p -> { + message.forEach(string -> { + ((Player) p).sendMessage(ChatColor.translateAlternateColorCodes('&', string)); + }); + }); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java new file mode 100644 index 0000000..360179f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.auth; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.map.MapView; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; + +import java.awt.image.BufferedImage; + +public class TotpMapCreator { + + public ItemStack createMap(Player player, BufferedImage bufferedImage) { + MapView mapView = Bridge.getInstance().getServer().createMap(player.getWorld()); + mapView.getRenderers().forEach(mapView::removeRenderer); + mapView.addRenderer(new TotpMapRenderer(player.getUniqueId(), bufferedImage)); + player.sendMap(mapView); + return new ItemStack(Material.MAP, 0, mapView.getId()); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java new file mode 100644 index 0000000..a0a46da --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java @@ -0,0 +1,29 @@ +package rip.bridge.bridge.bukkit.auth; + +import org.bukkit.entity.Player; +import org.bukkit.map.MapCanvas; +import org.bukkit.map.MapRenderer; +import org.bukkit.map.MapView; + +import java.awt.image.BufferedImage; +import java.util.Map; +import java.util.UUID; + +public class TotpMapRenderer extends MapRenderer { + + private final UUID targetPlayer; + private BufferedImage image; + + public TotpMapRenderer(UUID targetPlayer, BufferedImage image) { + this.targetPlayer = targetPlayer; + this.image = image; + } + + public void render(MapView mapView, MapCanvas mapCanvas, Player player) { + if(player.getUniqueId().equals(this.targetPlayer)) { + mapCanvas.drawImage(0, 0, this.image); + this.image = null; + } + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java new file mode 100644 index 0000000..dc16400 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java @@ -0,0 +1,26 @@ +package rip.bridge.bridge.bukkit.auth.prompt; + +import org.bukkit.ChatColor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; + +public class InitialDisclaimerPrompt extends StringPrompt { + + public String getPromptText(ConversationContext context) { + return ChatColor.RED.toString() + ChatColor.BOLD + "Take a minute to read over this, it's important. " + + ChatColor.RED + "2FA can be enabled to protect against hackers getting into your Minecraft account. " + + "If you enable 2FA, you'll be required to enter a code every time you log in. If you lose your 2FA device, you wont be able to log into the Bridge Network." + + ChatColor.GRAY + " If you have read the above and would like to proceed, type \"yes\" in the chat. Otherwise, type anything else."; + } + + public Prompt acceptInput(ConversationContext context, String s) { + if(s.equalsIgnoreCase("yes")) { + return new ScanMapPrompt(); + } else { + context.getForWhom().sendRawMessage(ChatColor.GREEN + "Aborted 2FA setup."); + return Prompt.END_OF_CONVERSATION; + } + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java new file mode 100644 index 0000000..2918d98 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java @@ -0,0 +1,124 @@ +package rip.bridge.bridge.bukkit.auth.prompt; + +import com.google.common.escape.Escaper; +import com.google.common.net.UrlEscapers; +import com.warrenstrange.googleauth.GoogleAuthenticator; +import net.minecraft.util.org.apache.commons.codec.binary.Base32; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.auth.TotpMapCreator; +import rip.bridge.bridge.global.profile.Profile; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import java.net.URLEncoder; +import java.security.GeneralSecurityException; +import java.security.SecureRandom; + +public class ScanMapPrompt extends StringPrompt { + + private static final String totptImageUrlFormat = "https://www.google.com/chart?chs=130x130&chld=M%%7C0&cht=qr&chl=%s"; + private static final TotpMapCreator totpMapCreator = new TotpMapCreator(); + private static final Base32 base32Encoder = new Base32(); + private static SecureRandom secureRandom; + int failures = 0; + + public String getPromptText(ConversationContext context) { + Player player = (Player) context.getForWhom(); + if(this.failures == 0) { + Bukkit.getScheduler().runTaskAsynchronously(Bridge.getInstance(), () -> { + String totpSecret = generateTotpSecret(); + BufferedImage totpImage = createTotpImage(player, totpSecret); + Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> { + ItemStack map = totpMapCreator.createMap(player, totpImage); + context.setSessionData("totpSecret", totpSecret); + context.setSessionData("totpMap", map); + player.getInventory().addItem(map); + }); + }); + } + + return ChatColor.RED + "On your 2FA device, scan the map given to you. Once you've scanned the map, type the code displayed on your device in chat."; + } + + public Prompt acceptInput(ConversationContext context, String s) { + Player player = (Player) context.getForWhom(); + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + ItemStack totpMap = (ItemStack) context.getSessionData("totpMap"); + player.getInventory().remove(totpMap); + String totpSecret = (String) context.getSessionData("totpSecret"); + + if(this.failures >= 3) { + context.getForWhom().sendRawMessage(ChatColor.RED + "Cancelling 2FA setup due to too many incorrect codes."); + context.getForWhom().sendRawMessage(ChatColor.RED + "Contact the Bridge Network staff team for any questions you may have about 2FA."); + return Prompt.END_OF_CONVERSATION; + } + + int totpCode; + try { + totpCode = Integer.parseInt(s.replaceAll(" ", "")); + } catch(NumberFormatException ex) { + context.getForWhom().sendRawMessage(" "); + context.getForWhom().sendRawMessage(ChatColor.RED + s + " isn't a valid totp code. Let's try that again"); + return this; + } + + Bukkit.getScheduler().runTaskAsynchronously(Bridge.getInstance(), () -> { + + GoogleAuthenticator gAuth = new GoogleAuthenticator(); + boolean isValid = gAuth.authorize(totpSecret, totpCode); + + if(isValid) { + profile.setSecretKey(totpSecret); + profile.saveProfile(); + + player.removeMetadata("Locked", Bridge.getInstance()); + + player.sendMessage(ChatColor.GREEN + "2FA setup completed successfully."); + } else { + context.getForWhom().sendRawMessage(ChatColor.RED + s + " isn't a valid totp code. Let's try that again"); + failures++; + } + + }); + return Prompt.END_OF_CONVERSATION; + } + + private static String generateTotpSecret() { + byte[] secretKey = new byte[10]; + secureRandom.nextBytes(secretKey); + return base32Encoder.encodeToString(secretKey); + } + + private static BufferedImage createTotpImage(Player player, String secret) { + Escaper urlEscaper = UrlEscapers.urlFragmentEscaper(); + String totpUrl = "otpauth://totp/" + urlEscaper.escape(player.getName()) + "?secret=" + secret + "&issuer=" + urlEscaper.escape("Bridge Network"); + String totpImageUrl = String.format(totptImageUrlFormat, URLEncoder.encode(totpUrl)); + + try { + return ImageIO.read(new URL(totpImageUrl)); + } catch (IOException ex) { + ex.printStackTrace(); + return null; + } + } + + static { + try { + secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN"); + } catch (GeneralSecurityException ex) { + ex.printStackTrace(); + } + + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java new file mode 100644 index 0000000..5107591 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java @@ -0,0 +1,20 @@ +package rip.bridge.bridge.bukkit.commands; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.bukkit.parameters.AlertPacket; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.xpacket.FrozenXPacketHandler; + +public class AlertCommand { + + @Command(names = "alert", permission = "bridge.alert", description = "Alert a message to the network", async = true) + public static void alert(CommandSender sender, @Param(name = "message", wildcard = true) String msg) { + FrozenXPacketHandler.sendToAll(new AlertPacket(msg, false)); + } + + @Command(names = "rawalert", permission = "bridge.alert", description = "Alert a raw message to the network", async = true) + public static void rawalert(CommandSender sender, @Param(name = "message", wildcard = true) String msg) { + FrozenXPacketHandler.sendToAll(new AlertPacket(msg, true)); + } + } \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java new file mode 100644 index 0000000..e8772cd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands; + +import net.minecraft.server.v1_7_R4.PacketPlayOutGameStateChange; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class DemoCommand { + + @Command(names = "demo", permission = "op", hidden = true) + public static void demo(Player player, @Param(name = "target") Player target) { + PacketPlayOutGameStateChange packet = new PacketPlayOutGameStateChange(5, 0); + ((CraftPlayer)target).getHandle().playerConnection.sendPacket(packet); + player.sendMessage(ChatColor.YELLOW + "Demo screened " + target.getDisplayName() + ChatColor.YELLOW + "!"); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java new file mode 100644 index 0000000..8e2ec8d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands; + +import net.minecraft.server.v1_7_R4.PacketPlayOutGameStateChange; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class EndScreenCommand { + + @Command(names = "endscreen", permission = "op", hidden = true) + public static void endscreen(Player player, @Param(name = "target") Player target) { + PacketPlayOutGameStateChange packet = new PacketPlayOutGameStateChange(4, 0.0F); + ((CraftPlayer)target).getHandle().playerConnection.sendPacket(packet); + player.sendMessage(ChatColor.YELLOW + "End screened " + target.getDisplayName() + ChatColor.YELLOW + "!"); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java b/src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java new file mode 100644 index 0000000..1f15428 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java @@ -0,0 +1,72 @@ +package rip.bridge.bridge.bukkit.commands; + +import org.bukkit.ChatColor; +import org.bukkit.conversations.*; +import org.bukkit.entity.Player; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.ServerCommandPacket; +import rip.bridge.bridge.global.packet.types.ServerGroupCommandPacket; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class ExecuteCommands { + + @Command(names = {"execcmd server", "executecommands server"}, permission = "bridge.execute", hidden = true, async = true) + public static void server(Player sender, @Param(name = "server") String server, @Param(name = "command", wildcard = true) String command) { + promptExecute(sender, server, command); + } + + @Command(names = {"execcmd global", "executecommands global"}, permission = "bridge.execute", hidden = true, async = true) + public static void global(Player sender, @Param(name = "command", wildcard = true) String command) { + promptExecute(sender, "globally", command); + } + + @Command(names = {"execcmd group", "executecommands group"}, permission = "bridge.execute", hidden = true, async = true) + public static void group(Player sender, @Param(name = "group") String serverGroup, @Param(name = "command", wildcard = true) String command) { + promptExecute2(sender, serverGroup, command); + } + + private static void promptExecute(Player player, String server, String command) { + ConversationFactory factory = (new ConversationFactory(Bridge.getInstance())).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return ChatColor.translateAlternateColorCodes('&', "&eYou are about to execute the command &c\"" + command + "\" &c" + server + " &eare you sure you want to do this? If so type &ayes&c."); + } + + public Prompt acceptInput(ConversationContext context, String input) { + if (input.equalsIgnoreCase("yes")) { + context.getForWhom().sendRawMessage(ChatColor.GREEN + "Sending cross-bungee command..."); + PacketHandler.sendToAll(new ServerCommandPacket(server, command)); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.execute.view", "&8[&eServer Monitor&8] " + player.getDisplayName() + " &fexecuted command &d" + command + (server.equals("globally") ? " &f" : " &fon ") + server)); + } else { + context.getForWhom().sendRawMessage(ChatColor.RED + "Executing canclled."); + } + return Prompt.END_OF_CONVERSATION; + } + }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } + + private static void promptExecute2(Player player, String serverGroup, String command) { + ConversationFactory factory = (new ConversationFactory(Bridge.getInstance())).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return ChatColor.translateAlternateColorCodes('&', "&eYou are about to execute the command &c\"" + command + "\" to the server group &c" + serverGroup + " &eare you sure you want to do this? If so type &ayes&c."); + } + + public Prompt acceptInput(ConversationContext context, String input) { + if (input.equalsIgnoreCase("yes")) { + context.getForWhom().sendRawMessage(ChatColor.GREEN + "Sending cross-bungee command..."); + PacketHandler.sendToAll(new ServerGroupCommandPacket(serverGroup, command)); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.execute.view", "&8[&eServer Monitor&8] " + player.getDisplayName() + " &fexecuted command &d" + command + " &fon the server group " + serverGroup)); + } else { + context.getForWhom().sendRawMessage(ChatColor.RED + "Executing canclled."); + } + return Prompt.END_OF_CONVERSATION; + } + }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java new file mode 100644 index 0000000..03b7257 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java @@ -0,0 +1,29 @@ +package rip.bridge.bridge.bukkit.commands; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class FindCommand { + + @Command(names = { "find" }, permission = "bridge.find", description = "See the server a player is currently playing on", async = true) + public static void find(CommandSender sender, @Param(name = "player", extraData = "get") Profile profile) { + findresponse(sender, profile); + } + + public static void findresponse(CommandSender sender, Profile profile) { + BridgeServer server = BridgeGlobal.getServerHandler().findPlayerServer(profile.getUuid()); + BridgeServer proxy = BridgeGlobal.getServerHandler().findPlayerProxy(profile.getUuid()); + if (server == null) { + sender.sendMessage(ChatColor.RED + (profile.getDisguise() != null ? profile.getDisguise().getDisguiseName() : profile.getUsername()) + " is currently not on the network."); + return; + } + + sender.sendMessage(ChatColor.YELLOW + (profile.getDisguise() != null ? profile.getDisguise().getDisguiseName() : profile.getUsername()) + " is on " + ChatColor.GREEN + server.getName() + (proxy != null ? ChatColor.YELLOW + " (" + ChatColor.GREEN + proxy.getName() + " Proxy" + ChatColor.YELLOW + ")" : "")); + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java new file mode 100644 index 0000000..324c451 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java @@ -0,0 +1,70 @@ +package rip.bridge.bridge.bukkit.commands; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.visibility.FrozenVisibilityHandler; + +import java.util.*; +import java.util.stream.Collectors; + +public class ListCommand { + + @Command(names = { "list", "who", "players" }, permission = "", description = "See a list of online players", async = true) + public static void list(CommandSender sender) { + Map> sorted = new TreeMap<>(Comparator.comparingInt(Rank::getPriority).reversed()); + int online = 0; + for (Player player : Bukkit.getOnlinePlayers()) { + + if(!sender.hasPermission("basic.staff") && !canSee(sender, player)) continue; + ++online; + Profile profile = BukkitAPI.getProfile(player.getUniqueId()); + Rank rank = BukkitAPI.getPlayerRank(profile); + + String displayName = player.getDisplayName() + ChatColor.WHITE; + if (player.hasMetadata("invisible")) { + displayName = ChatColor.GRAY + "*" + displayName + ChatColor.WHITE; + } + sorted.putIfAbsent(rank, new LinkedList<>()); + sorted.get(rank).add(displayName); + } + List merged = new LinkedList<>(); + for (List part : sorted.values()) { + part.sort(String.CASE_INSENSITIVE_ORDER); + merged.addAll(part); + } + sender.sendMessage(getHeader(sender)); + sender.sendMessage("(" + online + "/" + Bukkit.getMaxPlayers() + ") " + merged); + } + + private static String getHeader(CommandSender sender) { + StringBuilder builder = new StringBuilder(); + List ranks = BridgeGlobal.getRankHandler().getRanks().parallelStream().sorted(Comparator.comparingInt(Rank::getPriority).reversed()).collect(Collectors.toList()); + for (Rank rank : ranks) { + boolean displayed = rank.getPriority() >= 0; + if (displayed) { + if(rank.isHidden() && sender.hasPermission("bridge.hiddenranks")) { + builder.append(ChatColor.GRAY + "*").append(rank.getColor()).append(rank.getDisplayName()).append(ChatColor.RESET).append(", "); + }else if(!rank.isHidden()){ + builder.append(rank.getColor()).append(rank.getDisplayName()).append(ChatColor.RESET).append(", "); + } + } + } + if (builder.length() > 2) { + builder.setLength(builder.length() - 2); + } + return builder.toString(); + } + + private static boolean canSee(CommandSender sender, CommandSender target) { + if(!(sender instanceof Player)) return true; + return FrozenVisibilityHandler.treatAsOnline((Player)target, (Player)sender); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java b/src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java new file mode 100644 index 0000000..d1278c6 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java @@ -0,0 +1,62 @@ +package rip.bridge.bridge.bukkit.commands; + +import com.google.common.collect.Maps; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packetlogger.PacketLog; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +import java.util.Map; + +public class PacketLoggerCommands { + + @Command(names = {"packetlogger info"}, permission = "op", hidden = true, async = true) + public static void packetloggerinfo(CommandSender sender, @Param(name = "target", defaultValue = "self") Player target) { + + sender.sendMessage(ChatColor.GREEN + "Getting Packet Log for " + target.getDisplayName() + ChatColor.GREEN + "..."); + sender.sendMessage(BukkitAPI.LINE); + + Map packetInfo = Maps.newHashMap(); + Map canceled = Maps.newHashMap(); + for (PacketLog packetLog : BridgeGlobal.getPacketLogHandler().getLog(target.getUniqueId())) { + + int amount = 1; + if (packetInfo.containsKey(packetLog.getPacket().getClass().getSimpleName())) { + amount = packetInfo.get(packetLog.getPacket().getClass().getSimpleName()); + amount++; + } + int amountFlagged = 1; + if (canceled.containsKey(packetLog.getPacket().getClass().getSimpleName())) { + amountFlagged = canceled.get(packetLog.getPacket().getClass().getSimpleName()); + amountFlagged++; + } + canceled.put(packetLog.getPacket().getClass().getSimpleName(), amount); + } + if (packetInfo.size() == 0) { + sender.sendMessage(ChatColor.RED + target.getName() + " has no packet logs."); + } else { + for (Map.Entry entry : packetInfo.entrySet()) { + sender.sendMessage(BukkitAPI.LINE); + sender.sendMessage(ChatColor.YELLOW + entry.getKey() + ChatColor.GRAY + " (" + ChatColor.RED + entry.getValue() + ChatColor.GRAY + ") " + + ChatColor.YELLOW + "Times Flagged: " + canceled.get(entry.getKey())); + } + sender.sendMessage(BukkitAPI.LINE); + + + } + } + + @Command(names = {"packetlogger toggle "}, permission = "op", hidden = true, async = true) + public static void packetloggertoggle(CommandSender sender) { + boolean toogled = Bridge.getInstance().togglePacketLogger; + Bridge.getInstance().setTogglePacketLogger(!Bridge.getInstance().togglePacketLogger); + sender.sendMessage(ChatColor.YELLOW + "PacketLogger: " + (!toogled ? ChatColor.RED + "Disabled" : ChatColor.GREEN + "Enabled") + ChatColor.YELLOW + "."); + + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java new file mode 100644 index 0000000..0017700 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java @@ -0,0 +1,45 @@ +package rip.bridge.bridge.bukkit.commands; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.util.PaginatedResult; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Optional; + +public class PermsCommand { + + @Command(names = { "perms" }, permission = "bridge.viewperms", description = "View an player's permissions", async = true) + public static void perms(CommandSender sender, @Param(name = "player", defaultValue = "self") Player player, @Param(name = "page", defaultValue = "1") int page) { + Optional optionalProfile = Optional.ofNullable(BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId())); + if (!optionalProfile.isPresent()) { + sender.sendMessage(ChatColor.RED + player.getName() + "'s profile isn't loaded."); + return; + } + Rank rank = optionalProfile.get().getCurrentGrant().getRank(); + List toSend = Lists.newArrayList(); + for (String permission : rank.getPermissions().keySet()) { + toSend.add((player.hasPermission(permission) ? (ChatColor.GREEN + " + ") : (ChatColor.RED + " - ")) + ChatColor.WHITE + permission + " (" + rank.getPermissions().get(permission) + ")"); + } + new PaginatedResult() { + @Override + public String getHeader(int page, int maxPages) { + return ChatColor.translateAlternateColorCodes('&', "&c" + StringUtils.repeat('-', 3) + " &r" + player.getDisplayName() + "&7(&r" + rank.getColor() + rank.getDisplayName() + "&7)'s Permissions (&e" + page + "&7/&e" + maxPages + "&7) &c" + StringUtils.repeat('-', 3)); + } + + @Override + public String format(String entry, int index) { + return entry; + } + }.display(sender, toSend, page); + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java new file mode 100644 index 0000000..8db553e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java @@ -0,0 +1,34 @@ +package rip.bridge.bridge.bukkit.commands; + +import mkremins.fanciful.FancyMessage; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.util.TimeUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.Date; + +public class SeenCommand { + + @Command(names = {"lastseen", "seen"}, permission = "bridge.seen", description = "See when a player was last on", async = true) + public static void lastseen(CommandSender sender, @Param(name = "player", extraData = "get") Profile profile) { + + if (profile.isOnline()) { + sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36)); + sender.sendMessage((ChatColor.RED + profile.getUsername() + ChatColor.YELLOW + " is currently on " + ChatColor.RED + profile.getConnectedServer() + ChatColor.YELLOW + ".")); + sender.sendMessage(ChatColor.GOLD + "Check out their info on the website: bridge.rip/u/" + profile.getUsername()); + sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36)); + } else { + sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36)); + sender.sendMessage((ChatColor.RED + profile.getUsername() + ChatColor.YELLOW + " is currently " + ChatColor.RED + "offline" + ChatColor.YELLOW + ".")); + sender.sendMessage(ChatColor.YELLOW + "Last seen at " + ChatColor.RED + TimeUtils.formatIntoCalendarString(new Date(profile.getLastJoined())) + ChatColor.YELLOW + " on " + ChatColor.RED + profile.getConnectedServer() + ChatColor.YELLOW + "."); + sender.sendMessage(ChatColor.GOLD + "Check out their info on the website: bridge.rip/u/" + profile.getUsername()); + sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36)); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java b/src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java new file mode 100644 index 0000000..50827f7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java @@ -0,0 +1,66 @@ +package rip.bridge.bridge.bukkit.commands; + +import com.google.common.collect.Maps; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; +import rip.bridge.qlib.command.Command; + +import java.util.HashMap; +import java.util.Set; + +import static org.spigotmc.TicksPerSecondCommand.format; + + +public class ThreadProfilerCommands { + + @Command(names = {"threadprofiler list"}, permission = "op", hidden = true, async = true) + public static void threadprofilerlist(CommandSender sender) { + Set threads = Thread.getAllStackTraces().keySet(); + for (Thread thread : threads) { + sender.sendMessage(ChatColor.translateAlternateColorCodes + ('&', " &6* &e" + + thread.getName() + " &d(State: " + + (thread.getState()) + ", Priority: " + + thread.getPriority() + ")")); + } + + } + + @Command(names = {"threadprofiler gc"}, permission = "op", hidden = true, async = true) + public static void threadprofilergc(CommandSender sender) { + Runtime runtime = Runtime.getRuntime(); + sender.sendMessage(ChatColor.YELLOW + "Trying to run Java garbage collector to free up memory."); + long before = System.currentTimeMillis(); + runtime.gc(); + long after = System.currentTimeMillis(); + sender.sendMessage(ChatColor.GOLD + + "* " + + ChatColor.YELLOW + "Finished! Took " + + ChatColor.LIGHT_PURPLE + + (after - before) + + "ms"); + + } + + @Command(names = {"threadprofiler threads"}, permission = "op", hidden = true, async = true) + public static void threadprofilerthreads(CommandSender sender) { + Set threads = Thread.getAllStackTraces().keySet(); + Runtime runtime = Runtime.getRuntime(); + HashMap pending = Maps.newHashMap(); + for (BukkitTask worker : Bukkit.getScheduler().getPendingTasks()) { + pending.put(worker.getOwner(), pending.getOrDefault(worker.getOwner(), 0) + 1); + } + sender.sendMessage(ChatColor.GOLD + "Alive Threads: " + ChatColor.LIGHT_PURPLE + Thread.getAllStackTraces().keySet().parallelStream().filter(Thread::isAlive).count()); + sender.sendMessage(ChatColor.GOLD + "Daemon Threads: " + ChatColor.LIGHT_PURPLE + Thread.getAllStackTraces().keySet().parallelStream().filter(Thread::isDaemon).count()); + sender.sendMessage(ChatColor.GOLD + "Interrupted Threads: " + ChatColor.LIGHT_PURPLE + Thread.getAllStackTraces().keySet().parallelStream().filter(Thread::isInterrupted).count()); + sender.sendMessage(ChatColor.GOLD + "Active Workers: " + ChatColor.LIGHT_PURPLE + Bukkit.getScheduler().getActiveWorkers().size()); + sender.sendMessage(ChatColor.GOLD + "Pending Tasks: " + ChatColor.LIGHT_PURPLE + Bukkit.getScheduler().getPendingTasks().size()); + sender.sendMessage(ChatColor.GOLD + "Threads: " + ChatColor.YELLOW + "(" + threads.size() + " Active) (Ram " + ChatColor.LIGHT_PURPLE + format(runtime.freeMemory()) + " free out of " + ChatColor.LIGHT_PURPLE + format(runtime.maxMemory()) + " " + ChatColor.LIGHT_PURPLE + format(runtime.maxMemory() - runtime.freeMemory()) + " used" + ChatColor.GOLD + ")"); + sender.sendMessage(""); + pending.keySet().stream().sorted((o1, o2) -> pending.get(o2) - pending.get(o1)).forEachOrdered(plugin -> sender.sendMessage(ChatColor.RED + "* " + ChatColor.YELLOW + plugin.getName() + ": " + ChatColor.WHITE + pending.get(plugin))); + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java new file mode 100644 index 0000000..9586f32 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java @@ -0,0 +1,98 @@ +package rip.bridge.bridge.bukkit.commands; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.util.TimeUtil; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class TimelineCommand { + + public static String blockColors = "▋"; + + @Command(names = {"timeline"}, permission = "basic.staff", description = "Check for how long you've been staff!", async = true) + public static void timeline(Player sender, @Param(name = "target", defaultValue = "self") Profile target) { + + if (!target.getCurrentGrant().getRank().isStaff() && target.getRemovedStaffOn() == 0) { + sender.sendMessage(ChatColor.RED + "That player has never been apart of the staff team."); + } else { + sender.sendMessage(BukkitAPI.RED_LINE); + + List grants = new ArrayList<>(target.getGrants()); + List blockLines = new ArrayList<>(); + + grants.sort(new SortByDate()); + + boolean isFirst = false; + for(Grant grant : grants) { + if(!grant.getRank().isStaff()) continue; + +// Random randie = new Random(); +// +// int random = randie.nextInt(15); + + blockLines.add(grant.getRank().getColor().replace("§o", "") + ChatColor.STRIKETHROUGH + blockColors + "" + ChatColor.RESET); + for (int i = 0; i < Math.abs(TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - grant.getInitialTime()) / 7); ++i) { + blockLines.add(ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH.toString() + blockColors + ChatColor.RESET); + } + + if(!isFirst) { + sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " joined the team on " + ChatColor.LIGHT_PURPLE + grant.getDate() + + ChatColor.YELLOW + " and was given " + grant.getRank().getColor() + grant.getRank().getDisplayName() + + ChatColor.YELLOW + " by " + ChatColor.LIGHT_PURPLE + grant.getGrantedByColorless()); + isFirst = true; + continue; + } + + if(grant.getRank().getPriority() > 70) { + sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " was" + ChatColor.GREEN + " promoted " + ChatColor.YELLOW + "to " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.YELLOW + + " on " + ChatColor.LIGHT_PURPLE + grant.getDate() + + ChatColor.YELLOW + " by " + ChatColor.LIGHT_PURPLE + grant.getGrantedByColorless()); + } else { + sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " was granted " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.YELLOW + + " on " + ChatColor.LIGHT_PURPLE + grant.getDate() + + ChatColor.YELLOW + " by " + ChatColor.LIGHT_PURPLE + grant.getGrantedByColorless()); + + } + } + + sender.sendMessage(" "); + sender.sendMessage(ChatColor.AQUA + "Timeline:"); + + String result = StringUtils.join(blockLines, ""); + + sender.sendMessage(result + ChatColor.GOLD + ChatColor.STRIKETHROUGH + "▋"); + + sender.sendMessage(" "); + if(target.getRemovedStaffOn() != 0) { + Date timeAdded = new Date(target.getBecameStaffOn()); + Date timeRemoved = new Date(target.getRemovedStaffOn()); + long diffInM = Math.abs(timeRemoved.getTime() - timeAdded.getTime()); + long diff = TimeUnit.DAYS.convert(diffInM, TimeUnit.MILLISECONDS); + + sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " parted ways with the staff team on " + ChatColor.LIGHT_PURPLE + TimeUtils.formatIntoCalendarStringNoTime(new Date(target.getRemovedStaffOn())) + ChatColor.YELLOW + "."); + sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.GREEN + " helped the staff team for " + ChatColor.LIGHT_PURPLE + TimeUtil.millisToRoundedTime(timeRemoved.getTime() - timeAdded.getTime()) + ChatColor.YELLOW + "."); + } else { + sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " has been helping the staff team for " + ChatColor.LIGHT_PURPLE + TimeUtil.millisToRoundedTime(System.currentTimeMillis() - target.getBecameStaffOn()) + ChatColor.YELLOW + "."); + } + + sender.sendMessage(BukkitAPI.RED_LINE); + + } + } + + static class SortByDate implements Comparator { + @Override + public int compare(Grant a, Grant b) { + return a.getDate().compareTo(b.getDate()); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java new file mode 100644 index 0000000..0e906df --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java @@ -0,0 +1,49 @@ +package rip.bridge.bridge.bukkit.commands.auth; + +import com.warrenstrange.googleauth.GoogleAuthenticator; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class AuthCommand { + + @Command(names = {"auth", "authenticate", "2fa", "otp"}, permission = "basic.staff", description = "Authenticate with the API, verifying your identity", hidden = true) + public static void auth(Player sender, @Param(name = "code", wildcard = true) String input) { + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(sender.getUniqueId()); + if(!sender.hasMetadata("Locked")) { + sender.sendMessage(ChatColor.RED + "You don't need to authenticate at the moment."); + } else { + input = input.replace(" ", ""); + int code = Integer.parseInt(input); + Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> { + if (profile == null) { + sender.sendMessage(ChatColor.DARK_RED.toString() + ChatColor.BOLD + "Your profile hasn't yet been loaded."); + } else { + + if(profile.getSecretKey().isEmpty()) { + sender.sendMessage(ChatColor.RED + "You need to setup your 2FA first using: /2fasetup."); + return; + } + + GoogleAuthenticator gAuth = new GoogleAuthenticator(); + boolean isValid = gAuth.authorize(profile.getSecretKey(), code); + + if(isValid) { + sender.removeMetadata("Locked", Bridge.getInstance()); + + sender.sendMessage(ChatColor.DARK_GREEN + "✓ " + ChatColor.GREEN + "Authenticated"); + } else { + sender.sendMessage(ChatColor.RED + "Invalid auth code."); + } + + } + }); + } + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java new file mode 100644 index 0000000..3925bd3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java @@ -0,0 +1,20 @@ +package rip.bridge.bridge.bukkit.commands.auth; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class ForceAuthCommand { + + @Command(names = {"forceauth"}, permission = "op", description = "Forcefully authenticate a player", hidden = true) + public static void forceAuth(CommandSender sender, @Param(name = "player") Player player) { + player.removeMetadata("Locked", Bridge.getInstance()); + player.setMetadata("ForceAuth", new FixedMetadataValue(Bridge.getInstance(), true)); + sender.sendMessage(ChatColor.YELLOW + player.getName() + " has been forcefully authenticated."); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java new file mode 100644 index 0000000..2481853 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java @@ -0,0 +1,24 @@ +package rip.bridge.bridge.bukkit.commands.auth; + +import org.bukkit.ChatColor; +import org.bukkit.conversations.Conversation; +import org.bukkit.conversations.ConversationFactory; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.auth.prompt.InitialDisclaimerPrompt; +import rip.bridge.qlib.command.Command; + +public class Setup2faCommand { + + @Command(names = {"setup2fa", "2fasetup"}, permission = "basic.staff", description = "Sign up to use 2FA to verify your identity", hidden = true) + public static void setup2fa(Player sender) { + if (!BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(sender.getUniqueId()).getSecretKey().isEmpty()) { + sender.sendMessage(ChatColor.RED + "You already have 2FA setup!"); + } else { + ConversationFactory factory = (new ConversationFactory(Bridge.getInstance())).withFirstPrompt(new InitialDisclaimerPrompt()).withLocalEcho(false).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(sender); + sender.beginConversation(con); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java new file mode 100644 index 0000000..bdd7be5 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java @@ -0,0 +1,52 @@ +package rip.bridge.bridge.bukkit.commands.disguise; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.disguise.menu.DisguiseRankMenu; +import rip.bridge.bridge.global.util.mojang.GameProfileUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; + +import java.util.Objects; +import java.util.regex.Pattern; + +public class DisguiseCommand { + + @Command(names = {"disguise", "dis", "d", "nick"}, permission = "bridge.disguise", description = "Disguise as another player", hidden = true) + public static void disguise(Player player, @Flag(value = {"cc"}, description = "Disable case-correction of the name") boolean caseCorrection, @Param(name = "name") String name) { + if (!Pattern.compile("^\\w{1,16}$").matcher(name).matches()) { + player.sendMessage(ChatColor.RED + "Invalid username: " + name); + return; + } + + String finalName = name; + if (Bukkit.getPlayerExact(name) != null || Objects.requireNonNull(BridgeGlobal.getUsedDisguisedNames()).stream().anyMatch(n -> n.equalsIgnoreCase(finalName))) { + player.sendMessage(ChatColor.RED + "The name \"" + name + "\" is unavailable."); + return; + } // try this + + if (BukkitAPI.getProfile(name) != null && BukkitAPI.getPlayerRank(BukkitAPI.getProfile(name)).isStaff()) { + player.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name."); + return; + } + + if (BukkitAPI.getProfile(name) != null) { + player.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name."); + return; + } + + String realName = GameProfileUtil.getRealName(name); + + + if (!caseCorrection && realName != null && !name.equals(realName)) { + + name = realName; + } + + new DisguiseRankMenu(name, realName != null).openMenu(player); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java new file mode 100644 index 0000000..fc2fd6a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java @@ -0,0 +1,52 @@ +package rip.bridge.bridge.bukkit.commands.disguise; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RealNameCommand { + + @Command(names = {"realname", "realnick", "checkdisguise"}, permission = "basic.staff", description = "Check who the person is!", hidden = true) + public static void check(Player sender, @Param(name = "name") String name) { + Player player = Bukkit.getPlayer(name); + + if (player == null) { + for (DisguisePlayer disguisePlayer : BridgeGlobal.getDisguiseManager().getDisguisePlayers().values()) { + if (name.equalsIgnoreCase(disguisePlayer.getName())) { + Player dPlayer = Bukkit.getPlayer(disguisePlayer.getDisguiseName()); + + if (dPlayer != null) { + player = dPlayer; + break; + } + } + } + } + + if (player == null) { + sender.sendMessage("§cNo player with the name" + " \"" + name + "\" found."); + return; + } + + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId()); + Profile data = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + DisguiseProfile profile = disguisePlayer != null ? BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values() + .stream() + .filter(dp -> disguisePlayer.getDisguiseSkin() != null && dp.getSkinName().equalsIgnoreCase(disguisePlayer.getDisguiseSkin())) + .findFirst() + .orElse(null) : null; + + sender.sendMessage(data.getCurrentGrant().getRank().getColor() + data.getUsername() + ChatColor.GOLD + (disguisePlayer != null ? " is disguised" : ChatColor.RED + " is NOT disguised") + '.'); + if (disguisePlayer != null) { + sender.sendMessage(ChatColor.GRAY.toString() + ' ' + "*" + ' ' + ChatColor.GOLD + "Disguise Name: " + ChatColor.RESET + disguisePlayer.getDisguiseName()); + sender.sendMessage(ChatColor.GRAY.toString() + ' ' + "*" + ' ' + ChatColor.GOLD + "Disguise Skin: " + ChatColor.WHITE + ChatColor.stripColor((profile != null ? profile.getDisplayName() : disguisePlayer.getDisguiseSkin()))); + sender.sendMessage(ChatColor.GRAY.toString() + ' ' + "*" + ' ' + ChatColor.GOLD + "Disguise Rank: " + disguisePlayer.getDisguiseRank().getColor() + disguisePlayer.getDisguiseRank().getName()); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java new file mode 100644 index 0000000..77e978a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java @@ -0,0 +1,119 @@ +package rip.bridge.bridge.bukkit.commands.disguise; + +import net.minecraft.util.com.mojang.authlib.GameProfile; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.commands.disguise.menu.DisguiseSkinMenu; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.disguise.DisguisePlayerSkin; +import rip.bridge.bridge.global.disguise.runnable.DisguiseRunnable; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.Tasks; +import rip.bridge.bridge.global.util.mojang.GameProfileUtil; +import rip.bridge.bridge.global.util.mojang.UUIDFetcher; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.nametag.FrozenNametagHandler; + +import java.util.*; + +public class SkinCommand { + + @Command(names = {"skin"}, permission = "bridge.disguise", async = true, hidden = true) + public static void skin(Player player, @Param(name = "skin", defaultValue = "N/A") String skin) { + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId()); + Profile playerProfile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + Rank current = playerProfile.getCurrentGrant().getRank(); + + if (skin.equals("N/A")) { + skin = disguisePlayer != null ? disguisePlayer.getDisguiseName() : player.getName(); + new DisguiseSkinMenu(skin, disguisePlayer != null ? disguisePlayer.getDisguiseRank() : current != null ? current : BridgeGlobal.getRankHandler().getDefaultRank(), true, true).openMenu(player); + return; + } + + if (disguisePlayer != null) { + disguisePlayer.setDisguiseSkin(skin); + + GameProfile profile = GameProfileUtil.getSkinCache().get(skin.toLowerCase()); + + if (profile == null) { + Map fetched = null; + + try { + fetched = new UUIDFetcher(Collections.singletonList(skin)).call(); + } catch (Exception e) { + e.printStackTrace(); + } + + Optional fetchedUuid = Objects.requireNonNull(fetched).values().stream().findFirst(); + if (!fetchedUuid.isPresent()) { + player.sendMessage(ChatColor.RED + "Skin by that name doesn't exist."); + return; + } + + profile = GameProfileUtil.loadGameProfile(fetchedUuid.get(), skin); + } + + DisguisePlayerSkin fakeSkin = BridgeGlobal.getDisguiseManager().setupDisguiseSkin(profile); + + if (fakeSkin == null) { + player.sendMessage(ChatColor.RED + "Failed to setup skin."); + return; + } + + disguisePlayer.setFakeSkin(fakeSkin); + + Tasks.run(new DisguiseRunnable(player, profile, disguisePlayer.getDisguiseName())); + + Tasks.run(() -> { + FrozenNametagHandler.reloadPlayer(player); + FrozenNametagHandler.reloadOthersFor(player); + }); + Rank rank = disguisePlayer.getDisguiseRank(); + String nickName = disguisePlayer.getDisguiseName(); + player.sendMessage(ChatColor.GREEN + "Success! You now look like " + rank.getPrefix() + rank.getColor() + nickName + ChatColor.GREEN + (!nickName.equals(skin) && !nickName.equals(ChatColor.stripColor(skin)) ? " (in the skin of " + ChatColor.YELLOW + ChatColor.stripColor(skin) + ChatColor.GREEN + ")" : "") + "!"); + + String realName = GameProfileUtil.getRealName(nickName); + if (realName != null) { + player.sendMessage(ChatColor.RED + nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked."); + } + + String realSkin = GameProfileUtil.getRealName(skin); + String finalSkin = skin; + if (realSkin == null && BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values().stream().noneMatch(p -> p.getSkinName().equalsIgnoreCase(finalSkin)) || skin.equals("Steve") || skin.equals("Alex")) { + player.sendMessage(ChatColor.YELLOW + "Note: You will look like " + (skin.equals("Alex") ? "Alex" : "Steve") + " since the account \"" + skin + "\" does not exist."); + } + } else { + try { + disguisePlayer = new DisguisePlayer(player.getName()); + + disguisePlayer.setDisguiseRank(current != null ? current : BridgeGlobal.getRankHandler().getDefaultRank()); + disguisePlayer.setDisguiseName(player.getName()); + disguisePlayer.setDisguiseSkin(skin); + + Rank rank = disguisePlayer.getDisguiseRank(); + String nickName = disguisePlayer.getDisguiseName(); + + if (BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, null, false, true, false)) { + player.sendMessage(ChatColor.GREEN + "Success! You now look like " + rank.getPrefix() + rank.getColor() + nickName + ChatColor.GREEN + (!nickName.equals(skin) && !nickName.equals(ChatColor.stripColor(skin)) ? " (in the skin of " + ChatColor.YELLOW + ChatColor.stripColor(skin) + ChatColor.GREEN + ")" : "") + "!"); + + String realName = GameProfileUtil.getRealName(nickName); + if (realName != null) { + player.sendMessage(ChatColor.RED + nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked."); + } + + String realSkin = GameProfileUtil.getRealName(skin); + String finalSkin = skin; + if (realSkin == null && BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values().stream().noneMatch(p -> p.getSkinName().equalsIgnoreCase(finalSkin)) || skin.equals("Steve") || skin.equals("Alex")) { + player.sendMessage(ChatColor.YELLOW + "Note: You will look like " + (skin.equals("Alex") ? "Alex" : "Steve") + " since the account \"" + skin + "\" does not exist."); + } + } + } catch (Exception e) { + e.printStackTrace(); + player.sendMessage(ChatColor.RED + "Something went wrong while disguising you! Please contact a staff member or any online developer."); + } + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java new file mode 100644 index 0000000..0222fe1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java @@ -0,0 +1,67 @@ +package rip.bridge.bridge.bukkit.commands.disguise; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.nametag.FrozenNametagHandler; + +public class TagCommand { + + @Command(names = {"tag"}, permission = "bridge.disguise", async = true, hidden = true) + public static void tag(Player player, @Param(name = "rank") String rank) { + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + + Rank current = profile.getCurrentGrant().getRank(); + Rank select = BridgeGlobal.getRankHandler().getRankByName(rank); + + if (rank.equalsIgnoreCase("clear")) { + select = current; + BridgeGlobal.getDisguiseManager().undisguise(player, false, false); + } + + if (select == null) { + select = BridgeGlobal.getRankHandler().getDefaultRank(); + } + + if (select.getPriority() > current.getPriority()) { + player.sendMessage(ChatColor.RED + "You are not allowed to set your tag to " + select.getColor() + select.getDisplayName() + ChatColor.RED + "."); + return; + } + + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId()); + + if (disguisePlayer != null) { + disguisePlayer.setDisguiseRank(select); + + player.setPlayerListName(select.getColor() + disguisePlayer.getDisguiseName()); + player.setDisplayName(select.getColor() + disguisePlayer.getDisguiseName()); + player.setCustomName(select.getColor() + disguisePlayer.getDisguiseName()); + profile.updateColor(); + profile.saveProfile(); + + BridgeGlobal.getDisguiseManager().save(player.getUniqueId(), false); + } else { + try { + disguisePlayer = new DisguisePlayer(player.getName()); + disguisePlayer.setDisguiseRank(select); + disguisePlayer.setDisguiseName(player.getName()); + disguisePlayer.setDisguiseSkin(player.getName()); + + BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, null,false, false, false); + } catch (Exception e) { + e.printStackTrace(); + player.sendMessage(ChatColor.RED + "Something went wrong while disguising you! Please contact a staff member or any online developer."); + } + } + + FrozenNametagHandler.reloadPlayer(player); + FrozenNametagHandler.reloadOthersFor(player); + + player.sendMessage(ChatColor.GREEN + "Setting your tag to " + select.getColor() + select.getDisplayName() + ChatColor.GREEN + "..."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java new file mode 100644 index 0000000..2506a92 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.disguise; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.qlib.command.Command; + +public class UnDisguiseCommand { + + @Command(names = {"undisguise", "undis", "ud", "unnick", "und"}, permission = "bridge.disguise", description = "Reveal yourself once again!", hidden = true) + public static void undisguise(Player player) { + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId()); + + if (disguisePlayer == null) { + player.sendMessage(ChatColor.RED + "You're not disguised!"); + return; + } + + player.sendMessage(ChatColor.GREEN + "Removing the disguise..."); + BridgeGlobal.getDisguiseManager().undisguise(player, true, false); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java new file mode 100644 index 0000000..45682cf --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.disguise; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.qlib.command.Command; + +public class UnTagCommand { + + @Command(names = {"untag"}, permission = "bridge.disguise", hidden = true) + public static void untag(Player player) { + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId()); + + if (disguisePlayer == null) { + player.sendMessage(ChatColor.RED + "You're not tagged!"); + return; + } + + player.sendMessage(ChatColor.GREEN + "Removing the tag..."); + BridgeGlobal.getDisguiseManager().undisguise(player, true, false); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java new file mode 100644 index 0000000..23ac2a4 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java @@ -0,0 +1,38 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +import java.util.regex.Pattern; + +public class DisguiseProfileCreateCommand { + + @Command(names = {"disguiseprofile create"}, permission = "bridge.disguise.admin", description = "Create a disguise profile", hidden = true) + public static void disguise(Player player, @Param(name = "name") String name, @Param(name = "skin") String skin) { + if (!Pattern.compile("^\\w{1,16}$").matcher(name).matches()) { + player.sendMessage(ChatColor.RED + "That is not a valid username."); + return; + } + + if (!Pattern.compile("^\\w{1,16}$").matcher(skin).matches()) { + player.sendMessage(ChatColor.RED + "That is not a valid skin."); + return; + } + + boolean added = BridgeGlobal.getDisguiseManager().addProfile(name, skin); + + if (!added) { + player.sendMessage(ChatColor.RED + "Failed to add disguise profile with name " + name + " and skin " + skin + '.'); + return; + } + + DisguiseProfile profile = BridgeGlobal.getDisguiseManager().getProfile(name); + + profile.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + player.sendMessage(ChatColor.GREEN + "You have created a disguise profile with name " + ChatColor.RESET + name + ChatColor.GREEN + " and skin " + ChatColor.RESET + skin + ChatColor.GREEN + '.'); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java new file mode 100644 index 0000000..0e1e9e3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class DisguiseProfileDeleteCommand { + + @Command(names = {"disguiseprofile delete", "disguiseprofile remove"}, permission = "bridge.disguise.admin", description = "Remove disguise profiles", hidden = true) + public static void disguise(Player player, @Param(name = "name") String name) { + boolean removed = BridgeGlobal.getDisguiseManager().removeProfile(name); + + if (!removed) { + player.sendMessage(ChatColor.RED + "Failed to remove disguise profile with name " + name + '.'); + return; + } + + player.sendMessage(ChatColor.GREEN + "You have deleted a disguise profile with name " + ChatColor.RESET + name + ChatColor.GREEN + '.'); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java new file mode 100644 index 0000000..02a3bd4 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java @@ -0,0 +1,89 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +import java.util.Objects; +import java.util.regex.Pattern; + +public class DisguiseProfileDisguiseCommand { + + @Command(names = {"disguiseprofile disguise"}, permission = "bridge.disguise.admin", description = "Disguise other players", hidden = true) + public static void odisguise(Player sender, @Param(name = "player") String playerName, @Param(name = "rank") String rank, @Param(name = "name") String name, @Param(name = "skin") String skin) { + Player player = Bukkit.getPlayer(playerName); + + if (player == null) { + for (DisguisePlayer disguisePlayer : BridgeGlobal.getDisguiseManager().getDisguisePlayers().values()) { + if (playerName.equalsIgnoreCase(disguisePlayer.getName())) { + Player dPlayer = Bukkit.getPlayer(disguisePlayer.getDisguiseName()); + + if (dPlayer != null) { + sender.sendMessage(ChatColor.RED + "That player is already disguised."); + return; + } + } + } + } + + if (player == null) { + sender.sendMessage("§cNo player with the name" + " \"" + name + "\" found."); + return; + } + + if (!Pattern.compile("^\\w{1,16}$").matcher(name).matches()) { + player.sendMessage(ChatColor.RED + "Invalid username: " + name); + return; + } + + if (Bukkit.getPlayerExact(name) != null || Objects.requireNonNull(BridgeGlobal.getUsedDisguisedNames()).stream().anyMatch(n -> n.equalsIgnoreCase(name))) { + player.sendMessage(ChatColor.RED + "The name \"" + name + "\" is unavailable."); + return; + } + + if (BukkitAPI.getProfile(name) != null && BukkitAPI.getPlayerRank(BukkitAPI.getProfile(name)).isStaff()) { + sender.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name."); + return; + } + + if (BukkitAPI.getProfile(name) != null) { + sender.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name."); + return; + } + + if (!Pattern.compile("^\\w{1,16}$").matcher(skin).matches()) { + sender.sendMessage(ChatColor.RED + "That is not a valid username."); + return; + } + + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(sender.getUniqueId()); + Rank current = profile.getCurrentGrant().getRank(); + Rank select = BridgeGlobal.getRankHandler().getRankByName(rank); + + if (select.getPriority() > current.getPriority()) { + sender.sendMessage(ChatColor.RED + "You are not allowed to set " + playerName + "'s tag to " + select.getColor() + select.getDisplayName() + ChatColor.RED + "."); + return; + } + + DisguisePlayer disguisePlayer = new DisguisePlayer(player.getName()); + disguisePlayer.setDisguiseRank(select); + disguisePlayer.setDisguiseName(name); + disguisePlayer.setDisguiseSkin(skin); + + try { + if (BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, null,false, true, false)) { + player.sendMessage(ChatColor.GREEN + "You have been manually disguised by a staff member."); + player.sendMessage(ChatColor.GREEN + "Success! You now look like " + select.getPrefix() + select.getColor() + name + ChatColor.GREEN + " (in the skin of " + ChatColor.YELLOW + skin + ChatColor.GREEN + ")!"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java new file mode 100644 index 0000000..2a54211 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class DisguiseProfileInfoCommand { + + @Command(names = {"disguiseprofile info"}, permission = "bridge.disguise.admin", description = "Get information about a disguise profile", hidden = true) + public static void disguiseprofileinfo(CommandSender s, @Param(name = "name") DisguiseProfile disguiseProfile) { + s.sendMessage(BukkitAPI.LINE); + s.sendMessage(disguiseProfile.getDisplayName() + " Disguise Profile §7❘ §fInformation"); + s.sendMessage(BukkitAPI.LINE); + s.sendMessage("§6Name: §f" + disguiseProfile.getName() + " §7(" + net.md_5.bungee.api.ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Display Name: §f" + disguiseProfile.getDisplayName() + " §7(" + net.md_5.bungee.api.ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Skin: §f" + disguiseProfile.getSkinName()); + s.sendMessage(""); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java new file mode 100644 index 0000000..0e55643 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java @@ -0,0 +1,52 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.qlib.command.Command; + +import java.util.ArrayList; + +public class DisguiseProfileListCommand { + + @Command(names = {"disguiseprofile list"}, permission = "bridge.disguise.admin", description = "List all created disguise profiles", hidden = true) + public static void disguiseprofilelist(CommandSender s) { + s.sendMessage(BukkitAPI.LINE); + s.sendMessage("§6§lDisguise Profiles §f(" + BridgeGlobal.getDisguiseManager().getDisguiseProfiles().size() + ")"); + s.sendMessage(BukkitAPI.LINE); + if (BridgeGlobal.getDisguiseManager().getDisguiseProfiles().isEmpty()) { + s.sendMessage(ChatColor.RESET + "No disguise profiles were created yet"); + } else { + ArrayList disguiseProfiles = new ArrayList<>(BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values()); + + disguiseProfiles.forEach(disguiseProfile -> { + if (s instanceof Player) { + + ComponentBuilder cp = new ComponentBuilder(disguiseProfile.getDisplayName() + " §7❘ §f" + disguiseProfile.getName()).event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText( + "§6Name: §f" + disguiseProfile.getName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")" + "\n" + + "§6Display Name: §f" + disguiseProfile.getDisplayName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")" + "\n" + + "§6Skin: §f" + disguiseProfile.getSkinName() + "\n\n" + + "§7§oClick for more information" + ))).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/disguiseprofile info " + disguiseProfile.getName())); + ((Player) s).spigot().sendMessage(cp.create()); + } else { + s.sendMessage(disguiseProfile.getDisplayName() + " §7❘ §f" + disguiseProfile.getName()); + s.sendMessage("§6Name: §f" + disguiseProfile.getName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Display Name: §f" + disguiseProfile.getDisplayName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Skin: §f" + disguiseProfile.getSkinName()); + s.sendMessage(""); + } + }); + s.sendMessage(""); + s.sendMessage(s instanceof Player ? "§7§oHover over the disguise profiles for more information." : "§7§oType /disguise profileinfo for more information."); + s.sendMessage(BukkitAPI.LINE); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java new file mode 100644 index 0000000..dbf217d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class DisguiseProfileSetDisplayNameCommand { + + @Command(names = {"disguiseprofile setdisplayname"}, permission = "bridge.disguise.admin", description = "Set a disguise profile display name", hidden = true) + public static void disguised(Player player, @Param(name = "name") String name, @Param(name = "displayName", wildcard = true) String displayName) { + DisguiseProfile profile = BridgeGlobal.getDisguiseManager().getProfile(name); + + profile.setDisplayName(ChatColor.translateAlternateColorCodes('&', displayName)); + BridgeGlobal.getDisguiseManager().saveProfiles(true); + player.sendMessage(ChatColor.GREEN + "You've changed display name of " + ChatColor.RESET + profile.getName() + ChatColor.GREEN + " to " + displayName + ChatColor.GREEN + '.'); + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java new file mode 100644 index 0000000..522c784 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java @@ -0,0 +1,28 @@ +package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class DisguiseProfileUnDisguiseCommand { + + @Command(names = {"disguiseprofile undisguise"}, permission = "bridge.undisguise.admin", description = "UnDisguise other players", hidden = true) + public static void undisguiseprofile(Player player, @Param(name = "player") Player target) { + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(target.getUniqueId()); + Profile target2 = BridgeGlobal.getProfileHandler().getProfileByUUID(target.getUniqueId()); + + if (disguisePlayer == null) { + player.sendMessage(ChatColor.RED + target2.getUsername() + " is not disguised!"); + return; + } + + player.sendMessage(ChatColor.GREEN + "You have removed the disguise of " + target2.getColor() + target2.getUsername() + ChatColor.GREEN + "."); + target.sendMessage(ChatColor.RED + "You have been manually undisguised by a staff member."); + target.sendMessage(ChatColor.GREEN + "Removing the disguise..."); + BridgeGlobal.getDisguiseManager().undisguise(target, true, false); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java new file mode 100644 index 0000000..01b0255 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java @@ -0,0 +1,99 @@ +package rip.bridge.bridge.bukkit.commands.disguise.menu; + +import com.google.common.collect.Maps; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.grant.menu.grant.RankButton; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class DisguiseRankMenu extends Menu { + + private String nickName; + private boolean real; + + public DisguiseRankMenu(String nickName, boolean real) { + super(ChatColor.DARK_GRAY + "Pick a rank"); + + this.nickName = nickName; + this.real = real; + this.setPlaceholder(true); + } + + @Override + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + + List ranks = BridgeGlobal.getRankHandler().getRanks().stream() + .filter(rank -> { + Profile profile = BukkitAPI.getProfile(player); + if(rank.isHidden() || !rank.isGrantable()) return false; + if(profile.hasPermission("bridge.disguise.all")) return true; + if(profile.hasPermission("bridge.disguise." + rank.getName().toLowerCase())) return true; + return Objects.requireNonNull(BukkitAPI.getPlayerRank(profile, true)).getPriority() >= rank.getPriority(); + }) + .sorted(Comparator.comparingInt(Rank::getPriority)) + .collect(Collectors.toList()); + + int slot = 1; + for(Rank rank : ranks) { + buttons.put(slot, new Button() { + + @Override + public String getName(Player player) { + return rank.getColor() + rank.getDisplayName(); + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return Material.LEATHER_CHESTPLATE; + } + + @Override + public byte getDamageValue(Player player) { + return 0; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack item = super.getButtonItem(player); + LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta(); + meta.setColor(RankButton.getColor(rank.getColor().charAt(1)).getColor()); + item.setItemMeta(meta); + return item; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + new DisguiseSkinMenu(nickName, rank, false, real).openMenu(player); + } + }); + + slot += slot == 7 || slot == 16 || slot == 25 || slot == 34 + || slot == 43 || slot == 52 || slot == 61 || slot == 70 ? 3 : 2; + } + + return buttons; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java new file mode 100644 index 0000000..20346bd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java @@ -0,0 +1,464 @@ +package rip.bridge.bridge.bukkit.commands.disguise.menu; + +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import net.minecraft.server.v1_7_R4.GameProfileSerializer; +import net.minecraft.server.v1_7_R4.NBTTagCompound; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.properties.Property; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.conversations.*; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.mojang.GameProfileUtil; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; +import rip.bridge.qlib.util.ItemBuilder; + +import java.util.*; +import java.util.regex.Pattern; + +@RequiredArgsConstructor +public class DisguiseSkinMenu extends PaginatedMenu { + + private final String nickName; + private final Rank rank; + private final boolean skinCmd; + private final boolean real; + + private static final GameProfile QUESTION_MARK_SKIN, STEVE_SKIN, ALEX_SKIN, DSKIN; + + static { + QUESTION_MARK_SKIN = new GameProfile(UUID.randomUUID(), "__Q_MARK__"); + QUESTION_MARK_SKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYzMjM1NTQwMTk5MSwKICAicHJvZmlsZUlkIiA6ICJkNTI0NjJmOTZlZjA0OThmODhhYzg4ZDI3ZjMyOGEzMCIsCiAgInByb2ZpbGVOYW1lIiA6ICJuaWd3YWciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ViYjQ3YTY1NDcyYjI4MjRmNDNjNDY0Yzc0NmI2Y2I3NGNmYmU5NWJkODk1MTM2Yjg3MWQ3ZTk3ZGM1NDY4MyIKICAgIH0sCiAgICAiQ0FQRSIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjM0MGMwZTAzZGQyNGExMWIxNWE4YjMzYzJhN2U5ZTMyYWJiMjA1MWIyNDgxZDBiYTdkZWZkNjM1Y2E3YTkzMyIKICAgIH0KICB9Cn0=", "jCNxGyWZtXrpgp9iA9z9/cpAkPcbXUz3QyQbBL9y58QaAvwpCC5t/0UReOBppIwS3Kye5JNf4W/sgk37+dSwej9ioiXAGQNQo56jCqaioaq4kKlaFls+dgbw2AJticzWsJicT70omH9O/NHV2kLP1RxPSQBQwkgnmmYBUtMYENf5S/zzUddZtbr3g0G5elpgwGuDaIJiNNdNTGwatUNfUlNLV/a9Z1nAniwfOUWul2U0tGTLnmrSyMLQe6auLyF/ddMneU1ecVTqjqUQZ8USOjva8N9tryRVGgkHujmMgd8zkOlU/FPxdLZeJoii4KQoSHznHx5IJplGvwEwUDR2cgNnzAzl7utMMRTC715TiLtcayqG3VJj1qRERt3uzDCBAidDcghwB+7GWkzZQ5Fq3P+pOGQdaOLyfiOoJojcKskPjAeGyLMq1rZd9VQ1RT/CuCCTgNhuIH8Ro4uyXXi18r63AMuHEhbzsD5wP+Okm6Z3SGzPJPOWQwQxHnmnO+6l11FZaMyJx68w90QCbmbiWXBDC89MVVLkl3rvUXmXKTr2N0HdjRY2uo4myqKugfR4ltT5jNMHLBy2yAg/dt/RminWB3SFbqFaK9iNam2XpOBW+q9Ihrmd81dfLhl663ORN+ikkiZzO2AZozvWCNx36snAPpMeBhs4f4Aehux+DH4=")); + + GameProfileUtil.getSkinCache().put(QUESTION_MARK_SKIN.getName().toLowerCase(), QUESTION_MARK_SKIN); + + DSKIN = new GameProfile(UUID.randomUUID(), "__D_SKIN__"); + DSKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYwNTgwNjE3MDgyNSwKICAicHJvZmlsZUlkIiA6ICIzY2FjYjhkY2YyMzk0ZDgwOTZiMWIyMmUzNjQ2MDlmYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJjcmVlcGVyX2dvZDIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE2ZTRjNTY1NDhiZmM0NjRmZGQ1NmJkMGViMmE2NGEzZWNiMTY4MWVhMDk5MWM0ZWY3NzFmNmQxMThiNGMzYyIKICAgIH0KICB9Cn0=", "FpKriqMG97l8aCmUfsa0Dq8ArVPCFiw6Mt2HwIwxHKUXKfhEK074MyeZwV5MQKaK/kEkqgYrCVK1Upm4y+SIp1znmoz9Qdb9lfdctXwznjwNW6x60qP9u5Wadg9T2CBw3KkogSTlFJpeiKnOb9bT4IezQgu8fL1Or5yX5LGkxrcZpDpCGJgENmLPdwoSaZxfZbOEnEGKRNrhqnPm29ScuUAf3JtQGccElXlJ4wBH02ZbuoFA75mnbCMixNmgiBpBIhqzAq7at+YrFqU1Nn6MYokFP91EbQvfxHP9vNN5ANJVDuhUPHNAvwK3M4XYthJ01Vm0oCRO/WqKDZCepV5j3pAZHKGA9ubeKAA2zTWwILxjgx1BaKBYO9idTdhI5RgsK78hg2ICD6ySZ7S+WFLYx7gTHSgp+TFaMsqeHHy5XGUHFUj7FOAktTu/lMs9KjK8n1FM5V3JDvAU5c7xuuErQ3HoYc5wO+Wm2gj9i5LBucU9qWlVSO51W1guwTSD9U8kzuw8Z4xoikF6of0/ZtmMjUneOGnzDqV2wNKnDbV/V5ASSVDjERvQCyK44YS1w9oO/p3ROjdhuN+JWP4zPCmfFdDxhgLcEhrTBcm7kBNx+b6agudfz4i6i7dAPN2W5AZ2RKbc60kkJncxtgfvfLk3Gw1j8TLAT1EjyDnhcMRitXY=")); + + STEVE_SKIN = new GameProfile(UUID.randomUUID(), "Steve"); + STEVE_SKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYwNTYxMTkyMjAyNywKICAicHJvZmlsZUlkIiA6ICJiOTgzZmU5YWJjMWI0MTkwYjIxZTUxZmU0Yjg3OTcxNCIsCiAgInByb2ZpbGVOYW1lIiA6ICI5Z3lhciIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82ZDNiMDZjMzg1MDRmZmMwMjI5Yjk0OTIxNDdjNjlmY2Y1OWZkMmVkNzg4NWY3ODUwMjE1MmY3N2I0ZDUwZGUxIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=", "nquy5XsHlcsQn0QTFW0vOVnodhCizG3VlfPtqgkqmTliNsuWd+GxdUV6u00eOhmYrkHOtD52eWF0tYG+j/BYUBwE2SvZHt3V7OjAO3OzMy8sNzuyymEfzoqFXB2+IBAAbWi54TZHI4l03wtDFuUNBhPZ/q0h9KmasFv8zTfCht+TEThmp7gjCkmAs6Tkr1jqAQyQfCQCQwBN0a8Rx0NzsGJAOvQFmfdksxuLzckR8abt9Qb39QXulFAKqkNoVYajvRxG21WTELgJEM+nuVInt0QT91t6Al1E7xExCbrOJITomk2CLAHSJzTx0QBYmKMbPeuXcR1jT50FA4qzqY5LsmmVWb1PkaucFQ2+tHHKncNg44XMju2PaNNLFek39AhOp4FnyLHBK5RuCJEcv0ybcNyCxFmKBSb5Ryv+XxsQQjzcT0fSc5png0NvBVknk4KnWkuimMJp84nBSzJ9htS38mOZWdFcj61ulqk99+7wJfqO8OgtOlfn4Hpk6rbVcFtARnW8TQIPcNzX6/B385fARO5VwFmts7UVxRGenQOJwzbezGPKBTfQyODpPxX2DYTR4v8fGfVpaO3ZReq0vDLvl/x5CpyFISJhorfZSIiAXJeRRKj8qHr6eM1lqzkzwu6tUV8nITzg/QxVuOddik01HJritR/iTgfrCQNI2fjhJY8=")); + + GameProfileUtil.getSkinCache().put(STEVE_SKIN.getName().toLowerCase(), STEVE_SKIN); + + ALEX_SKIN = new GameProfile(UUID.randomUUID(), "Alex"); + ALEX_SKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYwNTYxMTgxNjQ1NiwKICAicHJvZmlsZUlkIiA6ICIwNDQ4NzNiYTMzZDI0Y2Q4YTQ1M2M4ODkwYTFjODM4MCIsCiAgInByb2ZpbGVOYW1lIiA6ICJMQVNEIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzNiNjBhMWY2ZDU2MmY1MmFhZWJiZjE0MzRmMWRlMTQ3OTMzYTNhZmZlMGU3NjRmYTQ5ZWEwNTc1MzY2MjNjZDMiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "u0w6ba9InsC1Nj1xRxO5Jl6XsiuKEP0oMDQEBGoEEZJ8+thETE2Ics2lRY0jTKkboJV+7FwJunkYCJyoR6sRKYsXW6z5FOxsvCu9biAwIEcmRXljBUnIMzhefCqovZJ07AjA0rM8aKSH9V47BbpfGzBgSaLukdem0VpvV4LfZFIGTvqEZD6QnlYDQUJNEDaIac1X4xOJlPXzXV0d7EwSZSa6zKv6nswgbsp3aWleJoUoXhjqB3Em5wbdJbbvDdr0v7PPPYVzgS2sqD+RpUap21jG8teb4Wan4qjZQLTbmRxJE68IMaaylygwJFinxViZw3ubV7uTz26BSAhvOQ2wLpcNtTqqr+8atIA1+C5ijhBmQLEH6U2aYb7K+qF83YhxTzFeeoHcdoDNHC+7LDgEFEnM0hpIuHPTho2uTJtvAHx2iuLd/Kzau+EFyZDlKHowN7UW6LwNXRldTPr5DHBEuAMTiSGBivYZi778Hx8b3fpb6I7rUN5o4l3RdktCPlrElPnmEYXBGH+4ZLkeNxajCMxvm0WJFEouQcpnxKmON4z9Q6bduFdSqgm+huGACPhMG41J2f6fsnTOFKQDluyekF1ur3KoNCdqEYMDqXHmSobRaaKhvoclQuO1oxjFkFAiKox5cOAOf+pmhwbgq9a26n6MzvYvLb+tVXkbN9V6ewQ=")); + + GameProfileUtil.getSkinCache().put(ALEX_SKIN.getName().toLowerCase(), ALEX_SKIN); + } + + @Override + public String getPrePaginatedTitle(Player player) { + return ChatColor.DARK_GRAY + "Pick a skin"; + } + + @Override + public int getMaxItemsPerPage(Player player) { + return 36; + } + + @Override + public Map getAllPagesButtons(Player player) { + HashMap buttons = Maps.newHashMap(); + + int slot = 0; + for(DisguiseProfile profile : BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values()) { + buttons.put(slot++, new Button() { + + @Override + public String getName(Player player) { + return null; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return null; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM) + .data((short) 3) + .name(profile.getDisplayName() != null ? ChatColor.translateAlternateColorCodes('&', profile.getDisplayName()) : ChatColor.BLUE + profile.getName()) + .setLore(Collections.singletonList("")).build(); + + net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack); + + GameProfile gameProfile = GameProfileUtil.getSkinCache().get(profile.getName().toLowerCase()); + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + + if (gameProfile == null) { + gameProfile = new GameProfile(profile.getSkin().getProfileUuid(), profile.getName()); + gameProfile.getProperties().put("textures", profile.getSkin().getProperty()); + GameProfileUtil.getSkinCache().put(profile.getName().toLowerCase(), gameProfile); + } + + GameProfileSerializer.serialize(nbtTagCompound, gameProfile); + NBTTagCompound itemNbtTag = item.getTag(); + itemNbtTag.set("SkullOwner", nbtTagCompound); + stack = CraftItemStack.asCraftMirror(item); + + return stack; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + disguise(player, rank, profile.getSkinName(), nickName, profile.getDisplayName() != null ? ChatColor.translateAlternateColorCodes('&', profile.getDisplayName()) : profile.getSkinName(), profile.getName()); + } + }); + } + + return buttons; + } + + @Override + public Map getGlobalButtons(Player player) { + HashMap buttons = Maps.newHashMap(); + + buttons.put(1, new Button() { + + @Override + public String getName(Player player) { + return null; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return null; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM) + .data((short) 3) + .name(ChatColor.BLUE + "Your Own") + .setLore(Collections.singletonList("")).build(); + + net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack); + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + + + GameProfileSerializer.serialize(nbtTagCompound, ((CraftPlayer) player).getProfile()); + + NBTTagCompound itemNbtTag = item.getTag(); + itemNbtTag.set("SkullOwner", nbtTagCompound); + stack = CraftItemStack.asCraftMirror(item); + + return stack; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId()); + disguise(player, rank, player.getName(), nickName, disguisePlayer != null ? disguisePlayer.getName() : player.getName()); + } + }); + + buttons.put(2, new Button() { + + @Override + public String getName(Player player) { + return null; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return null; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM) + .data((short) 3) + .name(ChatColor.BLUE + "Random") + .setLore(Collections.singletonList("")).build(); + + net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack); + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + GameProfileSerializer.serialize(nbtTagCompound, QUESTION_MARK_SKIN); + NBTTagCompound itemNbtTag = item.getTag(); + itemNbtTag.set("SkullOwner", nbtTagCompound); + stack = CraftItemStack.asCraftMirror(item); + + return stack; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + + DisguiseProfile profile = BridgeGlobal.getDisguiseManager().getRandomDisguiseProfile(); + + if(profile == null) { + player.sendMessage(ChatColor.RED + "Failed to find random disguise profile."); + return; + } + + disguise(player, rank, profile.getSkinName(), nickName, profile.getDisplayName() != null ? ChatColor.translateAlternateColorCodes('&', profile.getDisplayName()) : profile.getSkinName()); + } + }); + + buttons.put(3, new Button() { + + @Override + public String getName(Player player) { + return ChatColor.BLUE + "Pick a Name"; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return Material.SIGN; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()) + .withModality(true) + .withPrefix(new NullConversationPrefix()) + .withFirstPrompt(new StringPrompt() { + + @Override + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Enter a name of a player using your desired skin:"; + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + if(!Pattern.compile("^\\w{1,16}$").matcher(input).matches()) { + player.sendMessage(ChatColor.RED + "Invalid username: " + input); + + String realName = GameProfileUtil.getRealName(input); + + new DisguiseSkinMenu(nickName, rank, skinCmd, realName != null).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + disguise(player, rank, input, nickName, input); + return Prompt.END_OF_CONVERSATION; + } + }) + + .withLocalEcho(false) + .withEscapeSequence("/no") + .withTimeout(10) + .thatExcludesNonPlayersWithMessage("Go away evil console!"); + + player.beginConversation(factory.buildConversation(player)); + } + }); + + buttons.put(4, Button.placeholder(Material.STAINED_GLASS_PANE, (byte) 7, " ")); + + buttons.put(5, new Button() { + + @Override + public String getName(Player player) { + return null; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return null; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM) + .data((short) 3) + .name(ChatColor.BLUE + nickName) + .setLore(Collections.singletonList("")).build(); + + net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack); + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + GameProfileSerializer.serialize(nbtTagCompound, DSKIN); + NBTTagCompound itemNbtTag = item.getTag(); + itemNbtTag.set("SkullOwner", nbtTagCompound); + stack = CraftItemStack.asCraftMirror(item); + + return stack; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + + int version = ((CraftPlayer) player).getHandle().playerConnection.networkManager.getVersion(); + + disguise(player, rank, real ? nickName : version == 47 ? ALEX_SKIN.getName() : STEVE_SKIN.getName(), nickName, nickName); + } + }); + + buttons.put(6, new Button() { + + @Override + public String getName(Player player) { + return null; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return null; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM) + .data((short) 3) + .name(ChatColor.BLUE + "Steve") + .setLore(Collections.singletonList("")).build(); + + net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack); + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + GameProfileSerializer.serialize(nbtTagCompound, STEVE_SKIN); + NBTTagCompound itemNbtTag = item.getTag(); + itemNbtTag.set("SkullOwner", nbtTagCompound); + stack = CraftItemStack.asCraftMirror(item); + + return stack; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + disguise(player, rank, STEVE_SKIN.getName(), nickName, "Steve"); + } + }); + + buttons.put(7, new Button() { + + @Override + public String getName(Player player) { + return null; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return null; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM) + .data((short) 3) + .name(ChatColor.BLUE + "Alex") + .setLore(Collections.singletonList("")).build(); + + net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack); + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + GameProfileSerializer.serialize(nbtTagCompound, ALEX_SKIN); + NBTTagCompound itemNbtTag = item.getTag(); + itemNbtTag.set("SkullOwner", nbtTagCompound); + stack = CraftItemStack.asCraftMirror(item); + + return stack; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + Button.playSuccess(player); + disguise(player, rank, ALEX_SKIN.getName(), nickName, "Alex"); + } + }); + + return buttons; + } + + private void disguise(Player player, Rank rank, String skin, String name, String skinName) { + this.disguise(player, rank, skin, name, skinName, null); + } + + private void disguise(Player player, Rank rank, String skin, String name, String skinName, String profileName) { + try { + // disguise(player, rank, player.getName(), nickName, disguisePlayer != null ? disguisePlayer.getName() : player.getName()); + DisguisePlayer disguisePlayer = new DisguisePlayer(player.getName()); + disguisePlayer.setDisguiseRank(rank); + disguisePlayer.setDisguiseName(name); + disguisePlayer.setDisguiseSkin(skin); + + if(BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, profileName,false, true, !this.skinCmd)) { + player.sendMessage(ChatColor.GREEN + "Success! You now look like " + this.rank.getPrefix() + this.rank.getColor() + this.nickName + ChatColor.GREEN + (!name.equals(skin) && !name.equals(ChatColor.stripColor(skinName)) ? " (in the skin of " + ChatColor.YELLOW + ChatColor.stripColor(skinName) + ChatColor.GREEN + ")" : "") + "!"); + + String realName = GameProfileUtil.getRealName(this.nickName); + if (realName != null) { + player.sendMessage(ChatColor.RED + this.nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked."); + } + + String realSkin = GameProfileUtil.getRealName(skin); + if (realSkin == null && BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values().stream().noneMatch(p -> p.getSkinName().equalsIgnoreCase(skin)) || skin.equals(STEVE_SKIN.getName()) || skin.equals(ALEX_SKIN.getName())) { + player.sendMessage(ChatColor.YELLOW + "Note: You will look like " + (skin.equals("Alex") ? "Alex" : "Steve") + " since the account \"" + skin + "\" does not exist."); + } + + /* + String realName = GameProfileUtil.getRealName(this.nickName); + if (realName != null) { + player.sendMessage(ChatColor.RED + this.nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked."); + } else { + String realSkin = GameProfileUtil.getRealName(skin); + if (realSkin != null) { + player.sendMessage(ChatColor.YELLOW + "Note: You will look like Steve since the account \"" + skin + "\" does not exist."); + } + } + */ + } + } catch (Exception e) { + e.printStackTrace(); + player.sendMessage(ChatColor.RED + "Something went wrong while disguising you! Please contact a staff member or any online developer."); + } + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java new file mode 100644 index 0000000..2617091 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java @@ -0,0 +1,27 @@ +package rip.bridge.bridge.bukkit.commands.filter; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterCreatePacket; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.bridge.global.filter.FilterType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.xpacket.FrozenXPacketHandler; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class FilterCreateCommand { + @Command(names = "filter create", permission = "bridge.filter", description = "Create a filter", hidden = true) + public static void create(CommandSender sender, @Param(name = "filterType") FilterType filterType, @Param(name = "pattern", wildcard = true) String pattern) { + Filter filter = BridgeGlobal.getFilterHandler().getFilter(pattern); + if (filter != null) { + sender.sendMessage(ChatColor.RED + "This filter already exists"); + return; + } + (filter = new Filter(filterType, pattern)).save(); + BridgeGlobal.getFilterHandler().addFilter(filter); + FrozenXPacketHandler.sendToAll(new FilterCreatePacket(filter, Bukkit.getServerName())); + sender.sendMessage(ChatColor.GREEN + "Successfully created the filter."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java new file mode 100644 index 0000000..0d5b3c4 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java @@ -0,0 +1,30 @@ +package rip.bridge.bridge.bukkit.commands.filter; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterCreatePacket; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.bridge.global.filter.FilterType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.xpacket.FrozenXPacketHandler; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class FilterCreateMuteCommand { + + @Command(names = "filter create mute", permission = "bridge.filter", description = "Create a mute filter", hidden = true) + public static void create(CommandSender sender, @Param(name = "filterType") FilterType filterType, @Param(name = "duration") Long duration, @Param(name = "pattern", wildcard = true) String pattern) { + Filter filter = BridgeGlobal.getFilterHandler().getFilter(pattern); + if (filter != null) { + sender.sendMessage(ChatColor.RED + "This filter already exists"); + return; + } + + (filter = new Filter(filterType, pattern, duration)).save(); + BridgeGlobal.getFilterHandler().addFilter(filter); + FrozenXPacketHandler.sendToAll(new FilterCreatePacket(filter, Bukkit.getServerName())); + sender.sendMessage(ChatColor.GREEN + "Successfully created the filter."); + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java new file mode 100644 index 0000000..fb142de --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java @@ -0,0 +1,20 @@ +package rip.bridge.bridge.bukkit.commands.filter; + +import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterDeletePacket; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.xpacket.FrozenXPacketHandler; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class FilterDeleteCommand { + + @Command(names = "filter delete", permission = "bridge.filter", description = "Delete a filter", hidden = true) + public static void delete(CommandSender sender, @Param(name = "filter", wildcard = true) Filter filter) { + filter.delete(); + FrozenXPacketHandler.sendToAll(new FilterDeletePacket(filter, Bukkit.getServerName())); + sender.sendMessage(ChatColor.GREEN + "Successfully deleted the filter."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java new file mode 100644 index 0000000..662daf2 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java @@ -0,0 +1,40 @@ +package rip.bridge.bridge.bukkit.commands.filter; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.filter.FilterAction; +import rip.bridge.bridge.global.util.TimeUtil; +import rip.bridge.qlib.command.Command; +import mkremins.fanciful.FancyMessage; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.List; + +public class FilterListCommand { + + @Command(names = "filter list", permission = "bridge.filter", description = "List all created filters", hidden = true) + public static void filter(CommandSender sender) { + sender.sendMessage(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34)); + BridgeGlobal.getFilterHandler().getFilters().forEach(filter -> { + FancyMessage fancyMessage = new FancyMessage(ChatColor.RED + (isLong(filter.getPattern()) ? filter.getPattern().substring(0, 20) + "..." : filter.getPattern())); + if (isLong(filter.getPattern())) { + List lore = new ArrayList<>(); + int index = 0; + while (index < filter.getPattern().length()) { + lore.add(filter.getPattern().substring(index, Math.min(index + 40, filter.getPattern().length()))); + index += 40; + } + fancyMessage.tooltip(lore); + } + fancyMessage.then(ChatColor.GRAY + " - " + "[" + filter.getFilterType().name() + "]" + (filter.getFilterAction() == FilterAction.MUTE ? " - Mute: " + TimeUtil.millisToTimer(filter.getMuteTime()) : "")); + fancyMessage.send(sender); + }); + sender.sendMessage(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34)); + } + + private static boolean isLong(String filter) { + return filter.length() > 20; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java new file mode 100644 index 0000000..7df1f76 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java @@ -0,0 +1,25 @@ +package rip.bridge.bridge.bukkit.commands.filter; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.bridge.global.filter.FilterAction; +import rip.bridge.bridge.global.util.TimeUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class FilterTestCommand { + + @Command(names = "filter test", permission = "bridge.filter", description = "Test a filter", hidden = true) + public static void test(CommandSender sender, @Param(name = "message", wildcard = true) String message) { + Filter filter = BridgeGlobal.getFilterHandler().isViolatingFilter(message); + if(filter == null) { + sender.sendMessage(ChatColor.GREEN + "This message is not filtered."); + return; + } + + sender.sendMessage(ChatColor.RED + "Your message currently flags for the filter: " + filter.getPattern()); + if(filter.getFilterAction() == FilterAction.MUTE) sender.sendMessage(ChatColor.RED + "This message would of caused you to be muted for " + TimeUtil.millisToTimer(filter.getMuteTime())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java new file mode 100644 index 0000000..cf3374a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java @@ -0,0 +1,37 @@ +package rip.bridge.bridge.bukkit.commands.filter; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.qlib.command.Command; + +import java.util.*; + +public class ToggleFilterCommand { + + @Getter + private final static Map filter = new HashMap<>(); + + @Command(names = "togglefilter", permission = "basic.staff", description = "Toggle filter alerts", hidden = true) + public static void toggle(Player player) { + String value = filter.getOrDefault(player.getUniqueId(), "global"); + switch (value) { + case "global": { + filter.put(player.getUniqueId(), "server"); + player.sendMessage(ChatColor.YELLOW + "You have now limited your filter messages to " + ChatColor.LIGHT_PURPLE + "local server" + ChatColor.YELLOW + "."); + return; + } + + case "server": { + filter.put(player.getUniqueId(), "off"); + player.sendMessage(ChatColor.RED + "You have disabled your filter messages."); + return; + } + + case "off": { + filter.put(player.getUniqueId(), "global"); + player.sendMessage(ChatColor.YELLOW + "You have now limited your filter messages to " + ChatColor.LIGHT_PURPLE + "global network" + ChatColor.YELLOW + "."); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java new file mode 100644 index 0000000..276f7bb --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java @@ -0,0 +1,27 @@ +package rip.bridge.bridge.bukkit.commands.grant; + +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.bukkit.commands.punishment.menu.MainPunishmentMenu; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; + +public class ClearGrantsCommand { + + @Command(names = {"cleargrants"}, permission = "bridge.cleargrants", description = "Clear player's grants from the entire network", async = true) + public static void clearGrants(CommandSender s, @Param(name = "target") Profile target) { + + if (target.getGrants().isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " does not have any grants."); + return; + } + s.sendMessage(ChatColor.GREEN + "Successfully cleared " + target.getCurrentGrant().getRank().getColor() + target.getUsername() + ChatColor.GREEN + "'s grants."); + target.getGrants().clear(); + target.saveProfile(); + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java new file mode 100644 index 0000000..908efbe --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java @@ -0,0 +1,15 @@ +package rip.bridge.bridge.bukkit.commands.grant; + +import rip.bridge.bridge.bukkit.commands.grant.menu.grant.RanksMenu; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.entity.Player; + +public class GrantCommand { + + @Command(names = "grant", permission = "bridge.grant", description = "Add a grant to an player's account", async = true) + public static void grantCmd(Player p, @Param(name = "player") Profile target) { + new RanksMenu(target.getUsername(), target.getUuid()).openMenu(p); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java new file mode 100644 index 0000000..a37b57a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java @@ -0,0 +1,43 @@ +package rip.bridge.bridge.bukkit.commands.grant; + +import mkremins.fanciful.FancyMessage; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.grant.menu.grants.GrantsMenu; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.stream.Collectors; + +public class GrantsCommand { + + @Command(names = "grants", permission = "bridge.grants", description = "Check a player's grants", async = true) + public static void grantsCmd(Player sender, @Flag(value = {"w", "website"}, description = "Check a player's active grants through the website") boolean website, @Param(name = "player", extraData = "get") Profile profile) { + + if (BukkitAPI.getPlayerRank(profile, true).getPriority() > BukkitAPI.getPlayerRank(sender, true).getPriority()) { + + sender.sendMessage(ChatColor.RED + "You cannot view the grants of \"" + (profile.getDisguise() != null ? profile.getDisguise().getDisguiseName() : profile.getUsername()) + "\"."); + return; + } + + if (website) { + FancyMessage message = new FancyMessage(org.bukkit.ChatColor.GREEN + "[Click Here]" + org.bukkit.ChatColor.YELLOW + " to view all of " + profile.getUsername() + "'s grants"); + message.tooltip(org.bukkit.ChatColor.GRAY + "Click here: https://www.bridge.rip/u/" + profile.getUsername() + "/grants").link("https://www.bridge.rip/u/" + profile.getUsername() + "/grants"); + message.send(sender); + } else { + List allGrants = profile.getGrants().stream().filter(grant -> !grant.getRank().isDefaultRank()).sorted((first, second) -> { + if (first.getInitialTime() > second.getInitialTime()) { + return -1; + } else { + return 1; + } + }).collect(Collectors.toList()); + new GrantsMenu(profile, allGrants).openMenu(sender); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java new file mode 100644 index 0000000..3d930e9 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java @@ -0,0 +1,30 @@ +package rip.bridge.bridge.bukkit.commands.grant; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.TimeUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.apache.commons.lang.StringUtils; +import org.bukkit.command.CommandSender; + +import java.util.Arrays; +import java.util.List; + +public class OGrantCommand { + + @Command(names = {"ogrant"}, permission = "bridge.ogrant", description = "Add a grant to an player's account", async = true) + public static void consolegrantCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "rank") Rank r, @Param(name = "duration") String l, @Param(name = "scopes") String scope, @Param(name = "reason", wildcard = true) String reason) { + if (!r.isGrantable()) { + s.sendMessage("§cThis rank is not grantable."); + return; + } + List scopes = Arrays.asList(scope.split(",")); + long length = (l.equalsIgnoreCase("Permanent") ? Long.MAX_VALUE : TimeUtil.parseTime(l)); + pf.applyGrant(new Grant(r, length, scopes, reason, Profile.getConsoleProfile().getUuid().toString(), BridgeGlobal.getSystemName()), null); + pf.saveProfile(); + s.sendMessage("§aSuccessfully granted " + pf.getUsername() + " the rank " + r.getDisplayName() + " on the scopes: " + StringUtils.join(scopes, ", ")); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java new file mode 100644 index 0000000..972afa3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java @@ -0,0 +1,17 @@ +package rip.bridge.bridge.bukkit.commands.grant.events; + +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.bukkit.util.BaseEvent; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; + +@AllArgsConstructor +@Getter +public class GrantCreateEvent extends BaseEvent { + + private UUID uuid; + private Grant grant; + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java new file mode 100644 index 0000000..87dbe40 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java @@ -0,0 +1,17 @@ +package rip.bridge.bridge.bukkit.commands.grant.events; + +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.bukkit.util.BaseEvent; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; + +@AllArgsConstructor +@Getter +public class GrantRemoveEvent extends BaseEvent { + + private UUID uuid; + private Grant grant; + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java new file mode 100644 index 0000000..884b82c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java @@ -0,0 +1,17 @@ +package rip.bridge.bridge.bukkit.commands.grant.events; + +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.bukkit.util.BaseEvent; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; + +@AllArgsConstructor +@Getter +public class GrantUpdateEvent extends BaseEvent { + + private UUID uuid; + private Grant grant; + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java new file mode 100644 index 0000000..3400140 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java @@ -0,0 +1,43 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grant; + +import com.google.common.collect.ImmutableList; +import rip.bridge.qlib.menu.Button; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.List; + +public class GlobalButton extends Button { + + private ScopesMenu parent; + + public String getName(Player player) { + return ChatColor.BLUE + "Global"; + } + + public List getDescription(Player player) { + return ImmutableList.of(); + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + return this.parent.isGlobal() ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + for (String key : this.parent.getStatus().keySet()) { + this.parent.getStatus().put(key, false); + } + this.parent.setGlobal(!this.parent.isGlobal()); + } + + public GlobalButton(ScopesMenu parent) { + this.parent = parent; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java new file mode 100644 index 0000000..5569ac0 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java @@ -0,0 +1,84 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grant; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.grant.events.GrantCreateEvent; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.GrantCreatePacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.util.TimeUtils; +import lombok.AllArgsConstructor; +import net.md_5.bungee.api.ChatColor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class GrantButton extends Button { + private Rank rank; + private String targetName; + private UUID targetUUID; + private String reason; + private ScopesMenu parent; + private List scopes; + private long duration; + + public String getName(Player player) { + return ChatColor.GREEN + "Confirm and Grant"; + } + + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + description.add(ChatColor.BLUE + "Click to add the " + ChatColor.WHITE + this.rank.getColor() + this.rank.getDisplayName() + ChatColor.BLUE + " to " + ChatColor.WHITE + this.targetName + ChatColor.BLUE + "."); + if (this.parent.isGlobal()) { + description.add(ChatColor.BLUE + "This grant will be " + ChatColor.WHITE + "Global" + ChatColor.BLUE + "."); + } + else { + List scopes = new ArrayList<>(this.scopes); + description.add(ChatColor.BLUE + "This grant will apply on: " + ChatColor.WHITE + scopes.toString()); + } + description.add(ChatColor.BLUE + "Reasoning: " + ChatColor.WHITE + this.reason); + description.add(ChatColor.BLUE + "Duration: " + ChatColor.WHITE + ((this.duration < Long.MAX_VALUE) ? TimeUtils.formatIntoDetailedString((int) (this.duration / 1000)) : "Permanent")); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.DIAMOND_SWORD; + } + + public byte getDamageValue(Player player) { + return 0; + } + + public void clicked(Player player, int i, ClickType clickType) { + this.grant(this.targetUUID, this.targetName, this.reason, this.scopes, this.rank, this.duration, player); + player.closeInventory(); + } + + private void grant(UUID user, String targetName, String reason, List scopes, Rank rank, long duration, Player sender) { + List finalScopes = (this.parent.isGlobal() || scopes.isEmpty() ? new ArrayList< >(Collections.singleton("Global")) : scopes.stream().map(s -> "GR-" + s).collect(Collectors.toList())); + Grant grant; + Profile pr = BukkitAPI.getProfile(user); + pr.applyGrant((grant=new Grant(rank, duration, finalScopes, reason, sender.getUniqueId().toString(), BridgeGlobal.getSystemName())), sender.getUniqueId()); + pr.saveProfile(); + PacketHandler.sendToAll(new GrantCreatePacket(grant, user, sender.getDisplayName(), BridgeGlobal.getSystemName())); + new GrantCreateEvent(pr.getUuid(), grant).call(); + sender.sendMessage(ChatColor.GREEN + "Successfully granted " + ChatColor.WHITE + targetName + ChatColor.GREEN + " the " + ChatColor.WHITE + rank.getColor() + rank.getDisplayName() + ChatColor.GREEN + " rank."); + this.parent.setComplete(true); + + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java new file mode 100644 index 0000000..8844a45 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java @@ -0,0 +1,146 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grant; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.TimeUtil; +import rip.bridge.qlib.menu.Button; +import lombok.AllArgsConstructor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.conversations.*; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.List; +import java.util.UUID; + +@AllArgsConstructor +public class RankButton extends Button +{ + private String targetName; + private UUID targetUUID; + private Rank rank; + + public String getName(Player player) { + return this.rank.getColor() + this.rank.getDisplayName(); + } + + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + description.add(ChatColor.BLUE + "Click to grant " + ChatColor.WHITE + this.targetName + ChatColor.BLUE + " the " + ChatColor.WHITE + this.rank.getColor() + this.rank.getDisplayName() + ChatColor.BLUE + " rank."); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + return getColor(this.rank.getColor().charAt(1)).getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + player.closeInventory(); + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Please type a reason for this grant to be added, or type " + ChatColor.RED + "cancel" + ChatColor.YELLOW + " to cancel."; + } + + public Prompt acceptInput(ConversationContext context, String input) { + if (input.equalsIgnoreCase("cancel")) { + context.getForWhom().sendRawMessage(ChatColor.RED + "Granting cancelled."); + return Prompt.END_OF_CONVERSATION; + } + new BukkitRunnable() { + public void run() { + RankButton.this.promptTime(player, input); + } + }.runTask(Bridge.getInstance()); + return Prompt.END_OF_CONVERSATION; + } + }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } + + private void promptTime(Player player, String reason) { + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Please type a duration for this grant, (\"perm\" for permanent) or type " + ChatColor.RED + "cancel" + ChatColor.YELLOW + " to cancel."; + } + + public Prompt acceptInput(ConversationContext context, String input) { + if (input.equalsIgnoreCase("cancel")) { + context.getForWhom().sendRawMessage(ChatColor.RED + "Granting cancelled."); + return Prompt.END_OF_CONVERSATION; + } + long duration = TimeUtil.parseTime(input); + if (duration != -1L) { + new BukkitRunnable() { + public void run() { + new ScopesMenu(false, false, RankButton.this.rank, RankButton.this.targetName, RankButton.this.targetUUID, reason, duration).openMenu(player); + } + }.runTask(Bridge.getInstance()); + return Prompt.END_OF_CONVERSATION; + } + context.getForWhom().sendRawMessage(ChatColor.RED + "Invalid duration."); + return Prompt.END_OF_CONVERSATION; + } + }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } + + public static DyeColor getColor(char str) { + ChatColor color = ChatColor.getByChar(str); + switch (color) { + case DARK_BLUE: + case BLUE: { + return DyeColor.BLUE; + } + case DARK_GREEN: { + return DyeColor.GREEN; + } + case DARK_AQUA: + case AQUA: { + return DyeColor.CYAN; + } + case DARK_RED: + case RED: { + return DyeColor.RED; + } + case DARK_PURPLE: { + return DyeColor.PURPLE; + } + case GOLD: { + return DyeColor.ORANGE; + } + case GRAY: + case DARK_GRAY: { + return DyeColor.GRAY; + } + case GREEN: { + return DyeColor.LIME; + } + case LIGHT_PURPLE: { + return DyeColor.PINK; + } + case YELLOW: { + return DyeColor.YELLOW; + } + case WHITE: { + return DyeColor.WHITE; + } + default: { + return DyeColor.BLACK; + } + } + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java new file mode 100644 index 0000000..dee6e22 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java @@ -0,0 +1,65 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grant; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; +import lombok.AllArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@AllArgsConstructor +public class RanksMenu extends Menu { + + private String targetName; + private UUID targetUUID; + + public String getTitle(Player player) { + return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Choose a Rank"; + } + + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + List ranks = this.getAllowedRanks(player); + for (int i = 0; i < ranks.size(); ++i) { + buttons.put(i, new RankButton(this.targetName, this.targetUUID, ranks.get(i))); + } + return buttons; + } + + private List getAllowedRanks(Player player) { + List allRanks = new ArrayList<>(BridgeGlobal.getRankHandler().getRanks()); + List ranks = Lists.newArrayList(); + for (int i = 0; i < allRanks.size(); ++i) { + //if (i != 0) { + if(allRanks.get(i).isDefaultRank()) continue; + if (this.isAllowed(allRanks.get(i), player)) ranks.add(allRanks.get(i)); + //} + } + ranks.sort((o1, o2) -> o2.getPriority() - o1.getPriority()); + return ranks; + } + + private boolean isAllowed(Rank rank, Player player) { + return BukkitAPI.getProfile(player).hasPermission("bridge.grant.create.*") || BukkitAPI.getProfile(player).hasPermission("bridge.grant.create." + rank.getName()); + } + + public void onClose(Player player) { + new BukkitRunnable() { + public void run() { + if (!Menu.currentlyOpenedMenus.containsKey(player.getName())) player.sendMessage(ChatColor.RED + "Granting cancelled."); + } + }.runTaskLater(Bridge.getInstance(), 1L); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java new file mode 100644 index 0000000..2d2713b --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java @@ -0,0 +1,53 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grant; + +import com.google.common.collect.Lists; +import rip.bridge.qlib.menu.Button; +import lombok.AllArgsConstructor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.List; + +@AllArgsConstructor +public class ScopeButton extends Button { + private ScopesMenu parent; + private String scope; + + public String getName(Player player) { + boolean status = this.parent.getStatus().get(this.scope); + return (status ? ChatColor.GREEN : ChatColor.RED) + this.scope; + } + + public List getDescription(Player player) { + boolean status = this.parent.getStatus().get(this.scope); + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + if (status) { + description.add(ChatColor.BLUE + "Click to " + ChatColor.RED + "remove " + ChatColor.YELLOW + this.scope + ChatColor.BLUE + " from this grant's scopes."); + } + else { + description.add(ChatColor.BLUE + "Click to " + ChatColor.GREEN + "add " + ChatColor.YELLOW + this.scope + ChatColor.BLUE + " to this grant's scopes."); + } + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + boolean status = this.parent.getStatus().get(this.scope); + return status ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + this.parent.getStatus().put(this.scope, !this.parent.getStatus().getOrDefault(this.scope, false)); + this.parent.setGlobal(false); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java new file mode 100644 index 0000000..f62fd1f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java @@ -0,0 +1,78 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grant; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +@Getter @Setter +public class ScopesMenu extends Menu { + + private Map status; + private boolean global; + private boolean complete; + private Rank rank; + private String targetName; + private UUID targetUUID; + private String reason; + private long duration; + + public String getTitle(Player player) { + return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Select the Scopes"; + } + + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + List groups = Lists.newArrayList(); + groups.addAll(BridgeGlobal.getServerHandler().getGroups()); + + int i = 0; + for (String scope : groups) { + if(scope == null) continue; + this.status.putIfAbsent(scope, false); + buttons.put(i, new ScopeButton(this, scope)); + ++i; + } + List scopes = Lists.newArrayList(); + scopes.addAll(this.status.keySet().stream().filter(this.status::get).collect(Collectors.toList())); + buttons.put(22, new GlobalButton(this)); + buttons.put(31, new GrantButton(this.rank, this.targetName, this.targetUUID, this.reason, this, scopes, this.duration)); + return buttons; + } + + public void onClose(Player player) { + new BukkitRunnable() { + public void run() { + if (!Menu.currentlyOpenedMenus.containsKey(player.getName()) && !ScopesMenu.this.complete) { + player.sendMessage(ChatColor.RED + "Granting cancelled."); + } + } + }.runTaskLater(Bridge.getInstance(), 1L); + } + + public ScopesMenu(boolean global, boolean complete, Rank rank, String targetName, UUID targetUUID, String reason, long duration) { + this.status = Maps.newHashMap(); + this.global = false; + this.global = global; + this.complete = complete; + this.rank = rank; + this.targetName = targetName; + this.targetUUID = targetUUID; + this.reason = reason; + this.duration = duration; + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java new file mode 100644 index 0000000..e869f05 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java @@ -0,0 +1,129 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grants; + + +import com.google.common.collect.Lists; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.util.TimeUtils; +import lombok.AllArgsConstructor; +import net.md_5.bungee.api.ChatColor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.conversations.*; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.Date; +import java.util.List; + +@AllArgsConstructor +public class GrantsButton extends Button { + + private Profile profile; + private Grant grant; + + public String getName(Player player) { + return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.grant.getInitialTime())); + } + + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + String by = this.grant.getGrantedBy(); + description.add(ChatColor.YELLOW + "By: " + ChatColor.RED + by); + description.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + this.grant.getReason()); + description.add(ChatColor.YELLOW + "Scopes: " + ChatColor.RED + (this.grant.getScope().isEmpty() ? "Global" : this.grant.getScope())); + description.add(ChatColor.YELLOW + "Rank: " + ChatColor.RED + this.grant.getRank().getDisplayName()); + if (this.grant.isStillActive()) { + if (this.grant.getActiveUntil() != Long.MAX_VALUE) { + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + description.add(ChatColor.YELLOW + "Time remaining: " + ChatColor.RED + TimeUtils.formatIntoDetailedString((int) ((this.grant.getActiveUntil() - System.currentTimeMillis()) / 1000))); + } + else { + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + description.add(ChatColor.YELLOW + "This is a permanent grant."); + } + if (player.hasPermission("bridge.grant.remove." + this.grant.getRank())) { + description.add(""); + description.add(ChatColor.RED.toString() + ChatColor.BOLD + "Click to remove"); + description.add(ChatColor.RED.toString() + ChatColor.BOLD + "this grant"); + } + } + else if (this.grant.isRemoved()) { + String removedBy = this.grant.getRemovedBy(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + description.add(ChatColor.RED + "Removed:"); + description.add(ChatColor.YELLOW + removedBy + ": " + ChatColor.RED + this.grant.getRemovedReason()); + description.add(ChatColor.RED + "at " + ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.grant.getRemovedAt()))); + if (this.grant.getActiveUntil() != Long.MAX_VALUE) { + description.add(""); + description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int) (this.grant.getLength() / 1000))); + } + } + else if (!this.grant.isStillActive() && this.grant.getActiveUntil() <= Long.MAX_VALUE) { + description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.grant.getLength()) / 1000L))); + description.add(ChatColor.GREEN + "Expired"); + } + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + return description; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + return this.grant.isStillActive() ? DyeColor.LIME.getWoolData() : DyeColor.RED.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + if (!player.hasPermission("bridge.grant.remove." + this.grant.getRank()) || !this.grant.isStillActive()) { + return; + } + player.closeInventory(); + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return "§aType a reason to be used when removing this grant. Type §cno§a to quit."; + } + + public Prompt acceptInput(ConversationContext cc, String s) { + if (s.equalsIgnoreCase("no")) { + cc.getForWhom().sendRawMessage(ChatColor.GREEN + "Grant removal aborted."); + } + else { + grant.setRemoved(true); + grant.setRemovedAt(System.currentTimeMillis()); + grant.setRemovedBy(player.getUniqueId().toString()); + grant.setRemovedOn(BridgeGlobal.getSystemName()); + grant.setRemovedReason(s); + + boolean isThereStaff = false; + for(Grant g : profile.getGrants()) { + if(g.getRank().isStaff() && !g.isRemoved()) { + isThereStaff = true; + break; + } + } + + if(!isThereStaff) { + if(profile.getBecameStaffOn() != 0) { + profile.setRemovedStaffOn(System.currentTimeMillis()); + } + } + + profile.saveProfile(); + + + cc.getForWhom().sendRawMessage(ChatColor.GREEN + "You have removed the grant."); + } + return Prompt.END_OF_CONVERSATION; + } + }).withLocalEcho(false).withEscapeSequence("/no").withTimeout(60).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java new file mode 100644 index 0000000..fcf998f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java @@ -0,0 +1,68 @@ +package rip.bridge.bridge.bukkit.commands.grant.menu.grants; + +import com.google.common.collect.Maps; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.List; +import java.util.Map; + +public class GrantsMenu extends PaginatedMenu { + + private Profile profile; + private List grants; + + public GrantsMenu(Profile profile, List grants) { + this.profile = profile; + this.grants = grants; + setAutoUpdate(true); + } + + public String getPrePaginatedTitle(final Player player) { + return ChatColor.RED + "Grants"; + } + + public Map getGlobalButtons(final Player player) { + final Map buttons = Maps.newHashMap(); + buttons.put(4, new Button() { + public String getName(final Player player) { + return ChatColor.YELLOW + "Back"; + } + + public List getDescription(final Player player) { + return null; + } + + public Material getMaterial(final Player player) { + return Material.PAPER; + } + + public byte getDamageValue(final Player player) { + return 0; + } + + public void clicked(final Player player, final int i, final ClickType clickType) { + player.closeInventory(); + } + }); + return buttons; + } + + public Map getAllPagesButtons(final Player player) { + final Map buttons = Maps.newHashMap(); + int index = 0; + for (Grant g : grants) { + buttons.put(index, new GrantsButton(profile, g)); + ++index; + } + return buttons; + } + + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java new file mode 100644 index 0000000..08acb95 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java @@ -0,0 +1,47 @@ +package rip.bridge.bridge.bukkit.commands.punishment; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +import java.util.ArrayList; +import java.util.List; + +public class AltsCommand { + + @Command(names = {"alts", "dupeip", "identities"}, permission = "bridge.alts", description = "View player's alt accounts", async = true) + public static void alts(CommandSender sender, @Param(name = "player") Profile profile) { + + BridgeGlobal.getMongoHandler().getProfiles(profile.getCurrentIPAddress(), callback -> { + if (callback == null || callback.isEmpty() || callback.size() == 1) { + sender.sendMessage(BukkitAPI.getColor(profile) + profile.getUsername() + ChatColor.RED + " doesn't have any alts"); + return; + } + + sender.sendMessage(ChatColor.YELLOW + "Fetching identities of " + profile.getUsername() + "..."); + sender.sendMessage(ChatColor.WHITE + "[" + ChatColor.GREEN + "Online" + ChatColor.WHITE + ", " + ChatColor.GRAY + "Offline" + ChatColor.WHITE + ", " + ChatColor.DARK_RED + "Blacklisted" + ChatColor.WHITE + ", " + ChatColor.RED + "Banned" + ChatColor.WHITE + ", " + ChatColor.WHITE + "Muted" + ChatColor.WHITE + "]"); + sender.sendMessage(BukkitAPI.getColor(profile) + profile.getUsername() + ChatColor.YELLOW + "'s" + (callback.size() == 1 ? ChatColor.YELLOW + " alt" : ChatColor.YELLOW + " alts") + ChatColor.YELLOW + " (" + ChatColor.RED + callback.size() + ChatColor.YELLOW + ")" + "."); + List formattedName = new ArrayList<>(); + callback.forEach(alt -> { + if (Bukkit.getOfflinePlayer(alt.getUuid()).isOnline()) + formattedName.add(ChatColor.GREEN + alt.getUsername()); + else if (alt.getActivePunishments(PunishmentType.BLACKLIST).size() > 1) + formattedName.add(ChatColor.DARK_RED + alt.getUsername()); + else if (alt.getActivePunishments(PunishmentType.BAN).size() > 1) + formattedName.add(ChatColor.RED + alt.getUsername()); + else if (alt.getActivePunishments(PunishmentType.MUTE).size() > 1) + formattedName.add(ChatColor.GOLD + alt.getUsername()); + else formattedName.add(ChatColor.GRAY + alt.getUsername()); + }); + sender.sendMessage(StringUtils.join(formattedName, ChatColor.WHITE + ", ")); + + }, false); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java new file mode 100644 index 0000000..c91af89 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java @@ -0,0 +1,25 @@ +package rip.bridge.bridge.bukkit.commands.punishment; + +import rip.bridge.bridge.bukkit.commands.punishment.menu.MainPunishmentMenu; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Flag; +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class CheckPunishmentsCommand { + + @Command(names = {"checkpunishments", "cp", "c", "history"}, permission = "bridge.checkpunishments", description = "Check a player's active punishments", async = true) + public static void checkPunishments(Player sender, @Flag(value = {"gui", "menu"}, description = "Check a player's active punishments ingame") boolean gui, @Param(name = "target", extraData = "get") Profile target) { + if (!gui) { + FancyMessage message = new FancyMessage(ChatColor.GREEN + "[Click Here]" + ChatColor.YELLOW + " to view all of " + target.getUsername() + "'s punishments"); + message.tooltip(ChatColor.GRAY + "Click here: https://www.bridge.rip/u/" + target.getUsername() + "/punishments").link("https://www.bridge.rip/u/" + target.getUsername() + "/punishments"); + message.send(sender); + } else { + new MainPunishmentMenu(target.getUuid().toString(), target.getUsername()).openMenu(sender); + } + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java new file mode 100644 index 0000000..755ff63 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java @@ -0,0 +1,15 @@ +package rip.bridge.bridge.bukkit.commands.punishment; + +import rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory.MainStaffPunishmentListMenu; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.entity.Player; + +public class CheckStaffPunishmentsCommand { + + @Command(names = {"staffpunishments", "checkstaffpunishments", "staffhistory", "staffhist"}, permission = "bridge.staffhistory", description = "Check a player's active punishments", async = true) + public static void staffPunishments(Player sender, @Param(name = "target") Profile target){ + new MainStaffPunishmentListMenu(target.getUuid().toString(), target.getUsername()).openMenu(sender); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java new file mode 100644 index 0000000..5d9e304 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java @@ -0,0 +1,35 @@ +package rip.bridge.bridge.bukkit.commands.punishment; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.punishment.menu.MainPunishmentMenu; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Flag; +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +import java.util.HashSet; + +public class ClearPunishmentsCommand { + + @Command(names = {"clearpunishments", "clearhistory"}, permission = "bridge.clearpunishments", description = "Clear player's punishments from the entire network", async = true) + public static void clearPunishments(CommandSender s, @Param(name = "target") Profile target) { + + if (target.getPunishments().isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " does not have any punishments."); + return; + } + s.sendMessage(ChatColor.GREEN + "Successfully cleared " + target.getCurrentGrant().getRank().getColor() + target.getUsername() + ChatColor.GREEN + "'s punishments."); + target.getPunishments().clear(); + target.saveProfile(); + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java new file mode 100644 index 0000000..a0454e3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java @@ -0,0 +1,28 @@ +package rip.bridge.bridge.bukkit.commands.punishment; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class ClearStaffPunishmentsCommand { + + @Command(names = {"clearstaffpunishments", "clearstaffhistory"}, permission = "bridge.clearstaffpunishments", description = "Clear staff member's punishments from the entire network", async = true) + public static void clearPunishments(CommandSender sender, @Param(name = "target") Profile target) { + + if (!target.getCurrentGrant().getRank().isStaff() && target.getRemovedStaffOn() == 0) { + sender.sendMessage(ChatColor.RED + "That player has never been apart of the staff team."); + return; + } + + if (target.getStaffPunishments().isEmpty()) { + sender.sendMessage(ChatColor.RED + target.getUsername() + " does not have any staff punishments."); + return; + } + sender.sendMessage(ChatColor.GREEN + "Successfully cleared " + target.getCurrentGrant().getRank().getColor() + target.getUsername() + ChatColor.GREEN + "'s Staff History."); + target.getStaffPunishments().clear(); + target.saveProfile(); + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java new file mode 100644 index 0000000..8de9fbd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java @@ -0,0 +1,41 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; + +import java.util.HashSet; + +public class BanCommand { + + @Command(names = {"ban", "b", "banish"}, permission = "bridge.ban", description = "Ban a player from the network", async = true) + public static void banCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (target.getActivePunishments(PunishmentType.BAN).size() > 1) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + //empty list instead of int instantly as null + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), false, !silent, clear, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java new file mode 100644 index 0000000..12b1f48 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java @@ -0,0 +1,41 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; + +public class BanIPCommand { + + @Command(names = {"banip", "bip", "baniship"}, permission = "bridge.banip", description = "Ban a player from the network", async = true) + public static void banIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (target.getActivePunishments(PunishmentType.BAN).size() > 1) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), true, !silent, clear, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java new file mode 100644 index 0000000..ff473b1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java @@ -0,0 +1,45 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; + +import java.util.HashSet; + +public class BlacklistCommand { + + @Command(names = {"blacklist", "bl"}, permission = "bridge.blacklist", description = "Blacklist an user from the network. This type of punishment cannot be appealed", async = true) + public static void blacklistCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this blacklist to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getCurrentIPAddress() == null) { + s.sendMessage(ChatColor.RED + "We can't blacklist a player that never joined before."); + return; + } + + if (target.getActivePunishments(PunishmentType.BLACKLIST).size() > 1) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already blacklisted."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BLACKLIST, new HashSet<>(), true, !silent, clear, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java new file mode 100644 index 0000000..6a04d81 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java @@ -0,0 +1,36 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; + +public class KickCommand +{ + @Command(names = { "kick", "k" }, permission = "basic.staff", description = "Kick a player from the server") + public static void pMuteCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this kick to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", defaultValue = "Kicked by a staff member", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.KICK, new HashSet<>(),false, !silent, false, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java new file mode 100644 index 0000000..494f717 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java @@ -0,0 +1,45 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; + +import java.util.HashSet; +import java.util.concurrent.TimeUnit; + +public class MuteCommand { + + @Command(names = {"mute"}, permission = "bridge.mute", description = "Temporarily mute a player, stopping them from talking in public chat", async = true) + public static void muteCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getActivePunishments(PunishmentType.MUTE).size() > 1) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + if (!s.hasPermission("bridge.mute.permanent") && TimeUnit.DAYS.toMillis(31L) < length) { + s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(),reason, PunishmentType.MUTE, new HashSet<>(), false, !silent, false, length); + target.getPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java new file mode 100644 index 0000000..99d2581 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java @@ -0,0 +1,47 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; +import java.util.concurrent.TimeUnit; + +public class MuteIPCommand { + + @Command(names = {"muteip", "ipmute"}, permission = "bridge.muteip", description = "Temporarily mute an user, stopping them from talking in public chat", async = true) + public static void muteIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (pf.getActivePunishments(PunishmentType.MUTE).size() > 0) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + if (!s.hasPermission("bridge.muteip.permanent") && TimeUnit.DAYS.toMillis(31L) < length) { + s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.MUTE, new HashSet<>(), true, !silent, false, length); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java new file mode 100644 index 0000000..3ea758a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java @@ -0,0 +1,41 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; + +public class PermMuteCommand { + + @Command(names = {"pmute", "permmute"}, permission = "bridge.mute.permanent", description = "Permanently mute an user, stopping them from talking in public chat", async = true) + public static void pMuteCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (pf.getActivePunishments(PunishmentType.MUTE).size() > 0) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.MUTE, new HashSet<>(),false, !silent, false, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java new file mode 100644 index 0000000..5feb402 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java @@ -0,0 +1,41 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; + +public class PermMuteIPCommand { + + @Command(names = {"pmuteip", "permmuteip"}, permission = "bridge.muteip.permanent", description = "Permanently mute an user, stopping them from talking in public chat", async = true) + public static void pMuteIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (pf.getActivePunishments(PunishmentType.MUTE).size() > 0) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.MUTE, new HashSet<>(), true, !silent, false, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java new file mode 100644 index 0000000..06002be --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java @@ -0,0 +1,46 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; +import java.util.concurrent.TimeUnit; + +public class TempBanCommand { + + @Command(names = {"tempban", "tban", "tb"}, permission = "bridge.tempban", description = "Temporarily ban a player from the network", async = true) + public static void tBanCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getActivePunishments(PunishmentType.BAN).size() > 1) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + if (!s.hasPermission("bridge.ban") && TimeUnit.DAYS.toMillis(31L) < length) { + s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), false, !silent, clear, length); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java new file mode 100644 index 0000000..128ccdc --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java @@ -0,0 +1,46 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; +import java.util.concurrent.TimeUnit; + +public class TempBanIPCommand { + + @Command(names = {"tempbanip", "tbanip", "tbip"}, permission = "bridge.tempbanip", description = "Temporarily ban a player from the network", async = true) + public static void tBanIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getActivePunishments(PunishmentType.BAN).size() > 1) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned."); + return; + } + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + if (!s.hasPermission("bridge.ban") && TimeUnit.DAYS.toMillis(31L) < length) { + s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), true, !silent, clear, length); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java new file mode 100644 index 0000000..63d2aaf --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java @@ -0,0 +1,36 @@ +package rip.bridge.bridge.bukkit.commands.punishment.create; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.bridge.bukkit.BukkitAPI; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; + +import java.util.HashSet; + +public class WarnCommand { + + @Command(names = {"warn"}, permission = "bridge.warn", description = "Add a warning to an player's account", async = true) + public static void warnCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this warn to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if (!BukkitAPI.canOverride(pf, target)) { + s.sendMessage(ChatColor.RED + "You cannot punish this player."); + return; + } + + Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.WARN, new HashSet<>(), false, !silent, false, Long.MAX_VALUE); + target.getPunishments().add(punishment); + pf.getStaffPunishments().add(punishment); + target.saveProfile(); + pf.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java new file mode 100644 index 0000000..941a35e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java @@ -0,0 +1,98 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu; + +import com.google.common.collect.Maps; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.*; + +public class MainPunishmentMenu extends Menu +{ + private String targetUUID; + private String targetName; + + public String getTitle(Player player) { + return ChatColor.BLUE + "Punishments - " + this.targetName; + } + + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + if (player.hasPermission("bridge.punishments.view.blacklist")) { + buttons.put(0, this.button(PunishmentType.WARN)); + buttons.put(2, this.button(PunishmentType.KICK)); + buttons.put(4, this.button(PunishmentType.MUTE)); + buttons.put(6, this.button(PunishmentType.BAN)); + buttons.put(8, this.button(PunishmentType.BLACKLIST)); + } + else { + buttons.put(1, this.button(PunishmentType.WARN)); + buttons.put(3, this.button(PunishmentType.KICK)); + buttons.put(5, this.button(PunishmentType.MUTE)); + buttons.put(7, this.button(PunishmentType.BAN)); + } + return buttons; + } + + private Button button(PunishmentType type) { + return new Button() { + + public String getName(Player player) { + return ChatColor.RED + type.getDisplayName() + "s"; + + } + + public List getDescription(Player player) { + return null; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + if (type == PunishmentType.WARN) { + return DyeColor.YELLOW.getWoolData(); + } + if (type == PunishmentType.KICK) { + return DyeColor.GRAY.getWoolData(); + } + if (type == PunishmentType.MUTE) { + return DyeColor.ORANGE.getWoolData(); + } + if (type == PunishmentType.BAN) { + return DyeColor.RED.getWoolData(); + } + return DyeColor.BLACK.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + player.closeInventory(); + player.sendMessage(ChatColor.GREEN + "Loading " + MainPunishmentMenu.this.targetName + "'s " + type.getDisplayName() + "s..."); + + List allPunishments = new ArrayList<>(BukkitAPI.getProfile(UUID.fromString(targetUUID)).getPunishments()); + Bukkit.getScheduler().scheduleAsyncDelayedTask(Bridge.getInstance(), () -> { + allPunishments.sort((first, second) -> Long.compare(second.getTime(), first.getTime())); + LinkedHashMap punishments = new LinkedHashMap<>(); + allPunishments.stream().filter(punishment -> punishment.getPunishmentType() == type).forEach(punishment -> punishments.put(punishment, punishment.getTarget().getUsername())); + Bukkit.getScheduler().scheduleSyncDelayedTask(Bridge.getInstance(), () -> new PunishmentMenu(targetUUID, targetName, type, punishments).openMenu(player)); + }); + } + }; + } + + public MainPunishmentMenu(String targetUUID, String targetName) { + this.targetUUID = targetUUID; + this.targetName = targetName; + setAutoUpdate(true); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java new file mode 100644 index 0000000..5bb2964 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java @@ -0,0 +1,81 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu; + +import com.google.common.collect.Maps; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.bukkit.commands.punishment.menu.button.ProofAddButton; +import rip.bridge.bridge.bukkit.commands.punishment.menu.button.ProofButton; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Evidence; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; + +import java.util.List; +import java.util.Map; + +public class ProofMenu extends PaginatedMenu { + + private final Punishment punishment; + private String targetUUID; + private String targetName; + private PunishmentType type; + private Map punishments; + Profile profile; + + public ProofMenu(Punishment punishment, String targetUUID, PunishmentType type, String targetName, Map punishments){ + this.punishment = punishment; + this.targetUUID = targetUUID; + this.targetName = targetName; + this.type = type; + this.punishments = punishments; + profile = punishment.getTarget(); + } + + public Map getGlobalButtons(Player player) { + Map buttons = Maps.newHashMap(); + buttons.put(5, new ProofAddButton(punishment, profile)); + buttons.put(4, new Button() { + public String getName(Player player) { + return ChatColor.YELLOW + "Back"; + } + + public List getDescription(Player player) { + return null; + } + + public Material getMaterial(Player player) { + return Material.PAPER; + } + + public byte getDamageValue(Player player) { + return 0; + } + + public void clicked(Player player, int i, ClickType clickType) { + player.closeInventory(); + new PunishmentMenu(ProofMenu.this.targetUUID, ProofMenu.this.targetName, type, punishments).openMenu(player); + } + }); + return buttons; + } + + @Override + public String getPrePaginatedTitle(Player player) { + return "Proof Editor"; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = Maps.newHashMap(); + int index = 0; + for(Evidence entry : punishment.getProof()){ + buttons.put(index, new ProofButton(punishment, profile, entry)); + index++; + } + return buttons; + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java new file mode 100644 index 0000000..d1dc0ee --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java @@ -0,0 +1,72 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu; + +import com.google.common.collect.Maps; +import rip.bridge.bridge.bukkit.commands.punishment.menu.button.PunishmentButton; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.List; +import java.util.Map; + +public class PunishmentMenu extends PaginatedMenu +{ + private String targetUUID; + private String targetName; + private PunishmentType type; + private Map punishments; + + public String getPrePaginatedTitle(Player player) { + return ChatColor.RED + this.type.getDisplayName() + "s"; + } + + public Map getGlobalButtons(Player player) { + Map buttons = Maps.newHashMap(); + buttons.put(4, new Button() { + public String getName(Player player) { + return ChatColor.YELLOW + "Back"; + } + + public List getDescription(Player player) { + return null; + } + + public Material getMaterial(Player player) { + return Material.PAPER; + } + + public byte getDamageValue(Player player) { + return 0; + } + + public void clicked(Player player, int i, ClickType clickType) { + player.closeInventory(); + new MainPunishmentMenu(PunishmentMenu.this.targetUUID, PunishmentMenu.this.targetName).openMenu(player); + } + }); + return buttons; + } + + public Map getAllPagesButtons(Player player) { + Map buttons = Maps.newHashMap(); + int index = 0; + for (Map.Entry entry : this.punishments.entrySet()) { + buttons.put(index, new PunishmentButton(entry.getKey(), entry.getKey().getPunishmentType(), entry.getKey().getTarget().getUuid().toString(), entry.getKey().getTarget().getUsername(), punishments)); + ++index; + } + return buttons; + } + + public PunishmentMenu(String targetUUID, String targetName, PunishmentType type, Map punishments) { + this.targetUUID = targetUUID; + this.targetName = targetName; + this.punishments = punishments; + this.type = type; + setAutoUpdate(true); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java new file mode 100644 index 0000000..dbd6f56 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java @@ -0,0 +1,88 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu.button; + +import org.bukkit.scheduler.BukkitRunnable; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Evidence; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.qlib.menu.Button; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.conversations.*; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.List; + +public class ProofAddButton extends Button { + + private final Punishment punishment; + private final Profile profile; + + public ProofAddButton(Punishment punishment, Profile profile) { + this.punishment = punishment; + this.profile = profile; + } + + @Override + public String getName(Player player) { + return ChatColor.GREEN + ("Add Proof Entry"); + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return Material.SIGN; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + startAddConversation(player); + } + + private void startAddConversation(Player player) { + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Please type a proof entry to submit, or type " + ChatColor.RED + "cancel " + ChatColor.YELLOW + "to cancel."; + } + + public Prompt acceptInput(ConversationContext context, String input) { + + if (input.equalsIgnoreCase("cancel")) { + context.getForWhom().sendRawMessage(ChatColor.RED + "Proof entry submission process aborted."); + return Prompt.END_OF_CONVERSATION; + } + + if (punishment.getProof().contains(new Evidence(player.getName(), input))) { + player.sendMessage(ChatColor.RED + "This punishment already has a proof entry similar to the one you input."); + return Prompt.END_OF_CONVERSATION; + } + + new BukkitRunnable() { + @Override + public void run() { + punishment.getProof().add(new Evidence(player.getName(), input)); + profile.saveProfile(); + player.sendMessage(ChatColor.GREEN + "Successfully added proof entry: " + ChatColor.RESET + input); + } + }.runTask(Bridge.getInstance()); + + /*punishment.getProof().add(new Evidence(player.getName(), input)); + profile.saveProfile(); + + Bridge.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Bridge.getInstance(), () -> { + + player.sendMessage(ChatColor.GREEN + "Successfully added proof entry: " + ChatColor.RESET + input); + }, 1L);*/ + return Prompt.END_OF_CONVERSATION; + } + }).withLocalEcho(false); + + player.closeInventory(); + player.beginConversation(factory.buildConversation(player)); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java new file mode 100644 index 0000000..6a4633f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java @@ -0,0 +1,113 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu.button; + +import com.google.common.collect.Lists; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.scheduler.BukkitRunnable; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Evidence; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.qlib.menu.Button; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.conversations.*; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.Date; +import java.util.List; + +public class ProofButton extends Button { + + private final Punishment punishment; + private final Profile profile; + private final Evidence entry; + + public ProofButton(Punishment punishment, Profile profile, Evidence entry){ + this.punishment = punishment; + this.profile = profile; + this.entry = entry; + } + + @Override + public String getName(Player player) { + return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(punishment.getTime())); + } + + @Override + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + description.add(ChatColor.YELLOW + "Added by: " + ChatColor.RED + entry.getSender()); + description.add(ChatColor.YELLOW + "Proof: " + ChatColor.RED + entry.getURL()); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + description.add(ChatColor.GREEN.toString() + ChatColor.BOLD + "Left Click to view"); + description.add(ChatColor.GREEN.toString() + ChatColor.BOLD + "this proof"); + description.add(" "); + description.add(ChatColor.RED.toString() + ChatColor.BOLD + "Right Click to remove"); + description.add(ChatColor.RED.toString() + ChatColor.BOLD + "this proof"); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25)); + return description; + } + + @Override + public Material getMaterial(Player player) { + return Material.WOOL; + } + + @Override + public byte getDamageValue(Player player) { + return (byte) 5; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + switch(clickType){ + case LEFT: { + player.sendMessage(ChatColor.YELLOW + entry.getURL()); + break; + }case RIGHT: { + startRemoveConversation(player); + } default: { + + } + } + } + + private void startRemoveConversation(Player player){ + player.closeInventory(); + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Please type " + ChatColor.RED + "confirm" + ChatColor.YELLOW + " to confirm removal of this proof entry, or type " + ChatColor.RED + "cancel " + ChatColor.YELLOW + "to cancel."; + } + + public Prompt acceptInput(ConversationContext context, String input) { + if (input.equalsIgnoreCase("cancel")) { + context.getForWhom().sendRawMessage(ChatColor.RED + "Proof entry removal process aborted."); + return Prompt.END_OF_CONVERSATION; + } else if (input.equalsIgnoreCase("confirm")) { + + + new BukkitRunnable() { + @Override + public void run() { + punishment.getProof().remove(entry); + profile.saveProfile(); + player.sendMessage(ChatColor.GREEN + "Successfully removed the proof entry."); + } + }.runTask(Bridge.getInstance()); + + return Prompt.END_OF_CONVERSATION; + }else{ + Bridge.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Bridge.getInstance(), () -> { + player.sendMessage(ChatColor.RED + "Invalid response; proof entry removal process aborted."); + }, 1L); + return Prompt.END_OF_CONVERSATION; + } + } + }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!"); + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java new file mode 100644 index 0000000..5390c8e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java @@ -0,0 +1,98 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu.button; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.punishment.menu.ProofMenu; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.util.TimeUtils; +import net.md_5.bungee.api.ChatColor; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class PunishmentButton extends Button +{ + private Punishment punishment; + private String targetUUID; + private String targetName; + private PunishmentType type; + private Map punishments; + + public PunishmentButton(Punishment punishment, PunishmentType type, String targetUUID, String targetName, Map punishments){ + this.punishment = punishment; + this.targetUUID = targetUUID; + this.targetName = targetName; + this.type = type; + this.punishments = punishments; + } + + public String getName(Player player) { + return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.punishment.getTime())); + } + + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + String by = punishment.getExecutor().getUsername(); + String actor = "Server" + ChatColor.YELLOW + " : " + ChatColor.RED + (this.punishment.getPunishedServer() != null ? this.punishment.getPunishedServer() : "Website"); + + final String randomID = ChatColor.MAGIC + UUID.randomUUID().toString().substring(0, 8); + description.add(ChatColor.YELLOW + "By: " + ChatColor.RED + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? by : randomID)); + description.add(ChatColor.YELLOW + "Added on: " + ChatColor.RED + actor); + description.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + this.punishment.getReason()); + + + if (this.punishment.isActive()) { + if (!this.punishment.isPermanent()) { + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + description.add(ChatColor.YELLOW + "Time remaining: " + ChatColor.RED + DurationFormatUtils.formatDurationWords(Math.abs(punishment.getRemainingTime()), true, true)); + } + else { + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + description.add(ChatColor.YELLOW + "This is a permanent punishment."); + } + } + else if (this.punishment.isPardoned()) { + String removedBy = this.punishment.getPardonedBy().getUsername(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + description.add(ChatColor.RED + "Removed:"); + description.add(ChatColor.YELLOW + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? removedBy : randomID) + ": " + ChatColor.RED + this.punishment.getPardonedReason()); + description.add(ChatColor.RED + "at " + ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.punishment.getPardonedAt()))); + if (!this.punishment.isPermanent()) { + description.add(""); + description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1)); + } + } + else if (!this.punishment.isPermanent() && this.punishment.getRemainingTime() <= 0) { + description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1)); + description.add(ChatColor.GREEN + "Expired"); + } + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + return description; + } + + @Override + public Material getMaterial(Player player) { + return Material.WOOL; + } + + @Override + public byte getDamageValue(Player player) { + return !this.punishment.isActive() ? DyeColor.RED.getWoolData() : DyeColor.LIME.getWoolData(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { +// new ProofMenu(punishment, PunishmentButton.this.targetUUID,type, PunishmentButton.this.targetName, punishments).openMenu(player); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java new file mode 100644 index 0000000..dce9bc3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java @@ -0,0 +1,97 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory; + +import com.google.common.collect.Maps; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.*; + +public class MainStaffPunishmentListMenu extends Menu { + + private String targetUUID; + private String targetName; + + + public String getTitle(Player player) { + return ChatColor.BLUE + "Staff History - " + this.targetName; + } + + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + if (player.hasPermission("bridge.punishments.view.blacklist")) { + buttons.put(0, this.button(PunishmentType.WARN)); + buttons.put(2, this.button(PunishmentType.KICK)); + buttons.put(4, this.button(PunishmentType.MUTE)); + buttons.put(6, this.button(PunishmentType.BAN)); + buttons.put(8, this.button(PunishmentType.BLACKLIST)); + } + else { + buttons.put(1, this.button(PunishmentType.WARN)); + buttons.put(3, this.button(PunishmentType.KICK)); + buttons.put(5, this.button(PunishmentType.MUTE)); + buttons.put(7, this.button(PunishmentType.BAN)); + } + return buttons; + } + + private Button button(PunishmentType type) { + return new Button() { + public String getName(Player player) { + return ChatColor.RED + type.getDisplayName() + "s"; + } + + public List getDescription(Player player) { + return null; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + if (type == PunishmentType.WARN) { + return DyeColor.YELLOW.getWoolData(); + } + if (type == PunishmentType.KICK) { + return DyeColor.GRAY.getWoolData(); + } + if (type == PunishmentType.MUTE) { + return DyeColor.ORANGE.getWoolData(); + } + if (type == PunishmentType.BAN) { + return DyeColor.RED.getWoolData(); + } + return DyeColor.BLACK.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + player.closeInventory(); + player.sendMessage(ChatColor.GREEN + "Loading " + MainStaffPunishmentListMenu.this.targetName + "'s " + type.getDisplayName() + " Staff History..."); + + List allPunishments = new ArrayList<>(BukkitAPI.getProfile(UUID.fromString(targetUUID)).getStaffPunishments()); + Bukkit.getScheduler().scheduleAsyncDelayedTask(Bridge.getInstance(), () -> { + allPunishments.sort((first, second) -> Long.compare(second.getTime(), first.getTime())); + LinkedHashMap punishments = new LinkedHashMap<>(); + allPunishments.stream().filter(punishment -> punishment.getPunishmentType().equals(type)).forEach(punishment -> punishments.put(punishment, punishment.getTarget().getUsername())); + Bukkit.getScheduler().scheduleSyncDelayedTask(Bridge.getInstance(), () -> new StaffPunishmentListMenu(targetUUID, targetName, type, punishments).openMenu(player)); + }); + } + }; + } + + public MainStaffPunishmentListMenu(String targetUUID, String targetName) { + this.targetUUID = targetUUID; + this.targetName = targetName; + setAutoUpdate(true); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java new file mode 100644 index 0000000..dafd547 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java @@ -0,0 +1,87 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.util.TimeUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +public class StaffPunishmentButton extends Button { + + private final Punishment punishment; + + public StaffPunishmentButton(Punishment punishment){ + this.punishment = punishment; + } + + @Override + public String getName(Player player) { + return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(punishment.getTime())); + } + + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + String by = punishment.getExecutor().getUsername(); + String actor = "Server" + ChatColor.YELLOW + " : " + ChatColor.RED + this.punishment.getPunishedServer(); + + final String randomID = ChatColor.MAGIC + UUID.randomUUID().toString().substring(0, 8); + description.add(ChatColor.YELLOW + "Target: " + ChatColor.RED + punishment.getTarget().getUsername()); + description.add(ChatColor.YELLOW + "By: " + ChatColor.RED + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? by : randomID)); + description.add(ChatColor.YELLOW + "Added on: " + ChatColor.RED + actor); + description.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + this.punishment.getReason()); + + + if (this.punishment.isActive()) { + if (!this.punishment.isPermanent()) { + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + description.add(ChatColor.YELLOW + "Time remaining: " + ChatColor.RED + DurationFormatUtils.formatDurationWords(Math.abs(punishment.getRemainingTime()), true, true)); + } + else { + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + description.add(ChatColor.YELLOW + "This is a permanent punishment."); + } + } + else if (this.punishment.isPardoned()) { + String removedBy = this.punishment.getPardonedBy().getUsername(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + description.add(ChatColor.RED + "Removed:"); + description.add(ChatColor.YELLOW + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? removedBy : randomID) + ": " + ChatColor.RED + this.punishment.getPardonedReason()); + description.add(ChatColor.RED + "at " + ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.punishment.getPardonedAt()))); + if (!this.punishment.isPermanent()) { + description.add(""); + description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1)); + } + } + else if (!this.punishment.isPermanent() && this.punishment.getRemainingTime() <= 0) { + description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1)); + description.add(ChatColor.GREEN + "Expired"); + } + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25)); + return description; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + return !this.punishment.isActive() ? DyeColor.RED.getWoolData() : DyeColor.LIME.getWoolData(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { +// new ProofMenu(punishment, punishment.getTarget().getUuid().toString(), punishment.getPunishmentType(), punishment.getTarget().getUsername().toString(), null).openMenu(player); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java new file mode 100644 index 0000000..433cf50 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java @@ -0,0 +1,74 @@ +package rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory; + +import com.google.common.collect.Maps; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Material; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Map; + +public class StaffPunishmentListMenu extends PaginatedMenu { + + private String targetName; + private String targetUUID; + private PunishmentType type; + private Map punishments; + + + public String getPrePaginatedTitle(Player player) { + return ChatColor.RED + this.type.getDisplayName() + "s"; + } + + public Map getGlobalButtons(Player player) { + Map buttons = Maps.newHashMap(); + buttons.put(4, new Button() { + public String getName(Player player) { + return ChatColor.YELLOW + "Back"; + } + + public List getDescription(Player player) { + return null; + } + + public Material getMaterial(Player player) { + return Material.PAPER; + } + + public byte getDamageValue(Player player) { + return 0; + } + + public void clicked(Player player, int i, ClickType clickType) { + player.closeInventory(); + new MainStaffPunishmentListMenu(StaffPunishmentListMenu.this.targetUUID, StaffPunishmentListMenu.this.targetName).openMenu(player); + } + }); + return buttons; + } + + public Map getAllPagesButtons(Player player) { + Map buttons = Maps.newHashMap(); + int index = 0; + for (Map.Entry entry : this.punishments.entrySet()) { + buttons.put(index, new StaffPunishmentButton(entry.getKey())); + ++index; + } + + return buttons; + } + + public StaffPunishmentListMenu(String targetUUID, String targetName, PunishmentType type, Map punishments) { + this.targetUUID = targetUUID; + this.targetName = targetName; + this.punishments = punishments; + this.type = type; + setAutoUpdate(true); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java new file mode 100644 index 0000000..58c53db --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java @@ -0,0 +1,43 @@ +package rip.bridge.bridge.bukkit.commands.punishment.remove; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class UnBanCommand { + + @Command(names = {"unban"}, permission = "bridge.unban", description = "Remove a player's ban", async = true) + public static void unbanCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this unban to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getActivePunishments(PunishmentType.BAN).isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently banned."); + return; + } + + Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.BAN).toArray()[0]; + + if (punishment.isIP() && !s.hasPermission("bridge.unbanip")) { + s.sendMessage(ChatColor.RED + "You cannot unban " + target.getUsername() + " because they are ip-banned."); + return; + } + + if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) { + s.sendMessage(ChatColor.RED + "You cannot undo this punishment."); + return; + } + + punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent); + target.getPunishments().add(punishment); + target.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java new file mode 100644 index 0000000..55ae9f5 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java @@ -0,0 +1,39 @@ +package rip.bridge.bridge.bukkit.commands.punishment.remove; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class UnBanIPCommand { + + @Command(names = {"unbanip"}, permission = "bridge.unbanip", description = "Remove a player's ban", async = true) + public static void unbanIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Publicly unban the player") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getActivePunishments(PunishmentType.BAN).isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently ip-banned."); + return; + } + + Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.BAN).toArray()[0]; + + if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) { + s.sendMessage(ChatColor.RED + "You cannot undo this punishment."); + return; + } + + punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent); + target.getPunishments().add(punishment); + target.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java new file mode 100644 index 0000000..13767e4 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java @@ -0,0 +1,39 @@ +package rip.bridge.bridge.bukkit.commands.punishment.remove; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class UnBlacklistCommand { + + @Command(names = {"unblacklist", "unbl"}, permission = "bridge.unblacklist", description = "Remove a player's blacklist", async = true) + public static void unblacklistCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this blacklist to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + if (target.getActivePunishments(PunishmentType.BLACKLIST).isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently blacklisted."); + return; + } + + Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.BLACKLIST).toArray()[0]; + + if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) { + s.sendMessage(ChatColor.RED + "You cannot undo this punishment."); + return; + } + + punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent); + target.getPunishments().add(punishment); + target.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java new file mode 100644 index 0000000..0f1b4ee --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java @@ -0,0 +1,44 @@ +package rip.bridge.bridge.bukkit.commands.punishment.remove; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class UnMuteCommand { + + @Command(names = {"unmute"}, permission = "bridge.unmute", description = "Remove a player's mute", async = true) + public static void unmuteCmd(CommandSender s, @Flag(value = { "a", "announce" }, description = "Announce this unmute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if(target.getActivePunishments(PunishmentType.MUTE).isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently muted."); + return; + } + Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.MUTE).toArray()[0]; + + if(punishment.isIP() && !s.hasPermission("bridge.unmuteip")) { + s.sendMessage(ChatColor.RED + "You cannot unmute " + target.getUsername() + " because they are ip-muted."); + return; + } + + if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) { + s.sendMessage(ChatColor.RED + "You cannot undo this punishment."); + return; + } + + punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent); + target.getPunishments().add(punishment); + target.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java new file mode 100644 index 0000000..7aa1367 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java @@ -0,0 +1,40 @@ +package rip.bridge.bridge.bukkit.commands.punishment.remove; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.PunishmentPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Flag; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class UnWarnCommand { + + @Command(names = {"unwarn"}, permission = "bridge.unwarn", description = "Remove a player's warn", async = true) + public static void unbanCmd(CommandSender s, @Flag(value = { "a", "announce" }, description = "Announce this unwarn to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) { + Profile pf = BukkitAPI.getProfile(s); + + if(target.getActivePunishments(PunishmentType.WARN).isEmpty()) { + s.sendMessage(ChatColor.RED + target.getUsername() + " does not have an active warning."); + return; + } + Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.WARN).toArray()[0]; + + if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) { + s.sendMessage(ChatColor.RED + "You cannot undo this punishment."); + return; + } + + punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent); + target.getPunishments().add(punishment); + target.saveProfile(); + PacketHandler.sendToAll(new PunishmentPacket(punishment)); + } + +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java new file mode 100644 index 0000000..26aa736 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java @@ -0,0 +1,27 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankCreatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankCreateCommand { + + @Command(names = {"rank create"}, permission = "bridge.rank", description = "Create a rank", hidden = true, async = true) + public static void RankCreateCmd(CommandSender s, @Param(name = "rank") String name) { + Rank r = BukkitAPI.getRank(name); + if (r != null) { + s.sendMessage("§cThere is already a rank with the name \"" + r.getName() + "\"."); + return; + } + r = BukkitAPI.createRank(name); + PacketHandler.sendToAll(new RankCreatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fCreated rank " + r.getColor() + r.getDisplayName())); + s.sendMessage("§aSuccessfully created the rank " + r.getColor() + r.getName() + "§a!"); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java new file mode 100644 index 0000000..17209aa --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankDeletePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankDeleteCommand { + + @Command(names = {"rank delete", "rank remove"}, permission = "bridge.rank", description = "Delete a rank", hidden = true, async = true) + public static void RankDeleteCmd(CommandSender s, @Param(name = "rank") Rank r) { + s.sendMessage("§aSuccessfully deleted the rank " + r.getColor() + r.getName() + "§a!"); + BridgeGlobal.getMongoHandler().removeRank(r.getUuid(), callback -> { + }, true); + PacketHandler.sendToAll(new RankDeletePacket(r, s.getName(), BridgeGlobal.getServerName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fDeleted rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java new file mode 100644 index 0000000..7fc83d1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java @@ -0,0 +1,36 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankInfoCommand { + + @Command(names = {"rank info"}, permission = "bridge.rank", description = "Get information about a rank", hidden = true, async = true) + public static void RankInfoCmd(CommandSender s, @Param(name = "rank") Rank r) { + s.sendMessage(BukkitAPI.LINE); + s.sendMessage(r.getColor() + r.getDisplayName() + " Rank §7❘ §fInformation"); + s.sendMessage(BukkitAPI.LINE); + s.sendMessage("§6Prefix: §f" + r.getPrefix() + " §7(" + ChatColor.stripColor(r.getPrefix().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Suffix: §f" + r.getSuffix() + " §7(" + ChatColor.stripColor(r.getSuffix().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Priority: §f" + r.getPriority()); + s.sendMessage("§6Staff: §f" + r.isStaff()); + s.sendMessage("§6Media: §f" + r.isMedia()); + s.sendMessage("§6Builder: §f" + r.isBuilder()); + s.sendMessage("§6Default: §f" + r.isDefaultRank()); + s.sendMessage(ChatColor.GOLD + "Permissions (" + r.getPermissions().size() + ChatColor.GOLD + "): "); + if (r.getPermissions().isEmpty()) s.sendMessage(ChatColor.RED + "None..."); + else r.getPermissions().keySet().forEach(str -> { + s.sendMessage(ChatColor.GRAY + " * " + ChatColor.WHITE + str + ChatColor.GRAY + " [" + r.getPermissions().get(str) + "]"); + }); + s.sendMessage(""); + s.sendMessage("§6Inherits (" + r.getInherits().size() + ChatColor.GOLD + "): " + (r.getInherits().isEmpty() ? "§cNone..." : "")); + if (!r.getInherits().isEmpty()) + r.getInherits().forEach(rank -> s.sendMessage(" §7* §f" + rank.getColor() + rank.getDisplayName())); + + s.sendMessage(BukkitAPI.LINE); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java new file mode 100644 index 0000000..21d9dd7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankInheritCommand { + + @Command(names = {"rank inherit"}, permission = "bridge.rank", description = "Add/remove a rank inherit", hidden = true, async = true) + public static void RankPermissionCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "inherit") Rank inhr) { + boolean b = r.toggleInherit(inhr); + r.saveRank(); + s.sendMessage("§aSuccessfully " + (b ? "added" : "removed") + " the inherit of " + inhr.getColor() + inhr.getDisplayName()); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java new file mode 100644 index 0000000..a9a4c9d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java @@ -0,0 +1,57 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; + +import java.util.ArrayList; + +public class RankListCommand { + + @Command(names = {"rank list"}, permission = "bridge.rank", description = "List all ranks", hidden = true, async = true) + public static void RankListCmd(CommandSender s) { + s.sendMessage(BukkitAPI.LINE); + s.sendMessage("§6§lRanks §f(" + BridgeGlobal.getRankHandler().getRanks().size() + ")"); + s.sendMessage(BukkitAPI.LINE); + ArrayList rankList = new ArrayList<>(BridgeGlobal.getRankHandler().getRanks()); + rankList.sort((o1, o2) -> o2.getPriority() - o1.getPriority()); + + rankList.forEach(rank -> { + if (s instanceof Player) { + + ComponentBuilder cp = new ComponentBuilder(rank.getColor() + rank.getDisplayName() + " §7❘ §f" + rank.getName() + (rank.isHidden() ? " §7[Hidden]" : "")).event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText( + "§6Prefix: §f" + rank.getPrefix() + " §7(" + ChatColor.stripColor(rank.getPrefix().replaceAll("§", "&")) + ")" + "\n" + + "§6Suffix: §f" + rank.getSuffix() + " §7(" + ChatColor.stripColor(rank.getSuffix().replaceAll("§", "&")) + ")" + "\n" + + "§6Priority: §f" + rank.getPriority() + "\n" + + "§6Staff: §f" + rank.isStaff() + "\n" + + "§6Media: §f" + rank.isMedia() + "\n" + + "§6Builder: §f" + rank.isBuilder() + "\n" + + "§6Default: §f" + rank.isDefaultRank() + "\n\n" + + "§7§oClick for more information" + ))).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/rank info " + rank.getName())); + ((Player) s).spigot().sendMessage(cp.create()); + } else { + s.sendMessage(rank.getColor() + rank.getDisplayName() + " §7❘ §f" + rank.getName() + (rank.isHidden() ? " §7[Hidden]" : "")); + s.sendMessage("§6Prefix: §f" + rank.getPrefix() + " §7(" + ChatColor.stripColor(rank.getPrefix().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Suffix: §f" + rank.getSuffix() + " §7(" + ChatColor.stripColor(rank.getSuffix().replaceAll("§", "&")) + ")"); + s.sendMessage("§6Priority: §f" + rank.getPriority()); + s.sendMessage("§6Staff: §f" + rank.isStaff()); + s.sendMessage("§6Media: §f" + rank.isMedia()); + s.sendMessage("§6Builder: §f" + rank.isBuilder()); + s.sendMessage("§6Default: §f" + rank.isDefaultRank()); + s.sendMessage(""); + } + }); + s.sendMessage(""); + s.sendMessage(s instanceof Player ? "§7§oHover over the ranks for more information." : "§7§oType /rank info for more information."); + s.sendMessage(BukkitAPI.LINE); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java new file mode 100644 index 0000000..0d28fe3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.commands.rank.menu.RankMenu; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankManageCommand { + + @Command(names = {"rank manage"}, permission = "bridge.rank", description = "Manage a rank", hidden = true, async = true) + public static void RankMangeCmd(CommandSender s, @Param(name = "rank") String name) { + Rank r = BridgeGlobal.getRankHandler().getRankByName(name); + if (r == null) { + s.sendMessage("§cThere is no such rank with the name \"" + name + "\"."); + return; + } + + new RankMenu(r).openMenu((Player) s); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java new file mode 100644 index 0000000..17e5e94 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankPermissionCommand { + + @Command(names = {"rank permission", "rank perm"}, permission = "bridge.rank", description = "Add/remove a permission", hidden = true, async = true) + public static void RankPermissionCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "permission") String perm, @Param(name = "group", defaultValue = "§") String serverGroup) { + String group = serverGroup.equals("§") ? "Global" : serverGroup; + boolean b = r.togglePerm(perm, group); + r.saveRank(); + s.sendMessage("§aSuccessfully " + (b ? "added" : "removed") + " the permission " + perm + " to the scope: " + group); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java new file mode 100644 index 0000000..272aedd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankRenameCommand { + + @Command(names = {"rank rename"}, permission = "bridge.rank", description = "Rename a rank", hidden = true, async = true) + public static void RankRenameCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "name") String name) { + String original = r.getName(); + r.setName(name); + r.saveRank(); + s.sendMessage("§aSuccessfully renamed the rank from " + original + " to " + name + "!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java new file mode 100644 index 0000000..cdc2a36 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetBuilderCommand { + + @Command(names = {"rank setbuilder"}, permission = "bridge.rank", description = "Set a rank staff status", hidden = true, async = true) + public static void RankSetBuilderCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "builder") boolean builder) { + r.setBuilder(builder); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the builder status to " + builder + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java new file mode 100644 index 0000000..07e7ca7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetColorCommand { + @Command(names = {"rank setcolor", "rank setcolour"}, permission = "bridge.rank", description = "Set a ranks color", hidden = true, async = true) + public static void RankSetColorCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "color") String col) { + String color = ChatColor.translateAlternateColorCodes('&', col); + r.setColor(color); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the color to " + color + r.getName() + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java new file mode 100644 index 0000000..2e3c7b8 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetDefaultCommand { + + @Command(names = {"rank setdefault"}, permission = "bridge.rank", description = "Set a rank default status", hidden = true, async = true) + public static void RankSetDefaultCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "default") boolean b) { + r.setDefaultRank(b); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the default status to " + b + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java new file mode 100644 index 0000000..805230f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetDisplayNameCommand { + + @Command(names = {"rank setdisplayname", "rank setname"}, permission = "bridge.rank", description = "Set a ranks display name", hidden = true, async = true) + public static void RankSetDisplayNameCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "displayName", wildcard = true) String displayName) { + r.setDisplayName(displayName); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the display name to " + displayName + "!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java new file mode 100644 index 0000000..8136da8 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetGrantableCommand { + + @Command(names = {"rank setgrantable"}, permission = "bridge.rank", description = "Set a rank grantable status", hidden = true, async = true) + public static void RankSetGrantableCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "grantable") boolean grantable) { + r.setGrantable(grantable); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the grantable status to " + grantable + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java new file mode 100644 index 0000000..f526782 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetHiddenCommand { + + @Command(names = {"rank sethidden"}, permission = "bridge.rank", description = "Set a rank hidden status", hidden = true, async = true) + public static void RankSetHiddenCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "hidden") boolean hidden) { + r.setHidden(hidden); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the hidden status to " + hidden + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java new file mode 100644 index 0000000..e6c5953 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetMediaCommand { + + @Command(names = {"rank setmedia"}, permission = "bridge.rank", description = "Set a rank staff status", hidden = true, async = true) + public static void RankSetMediaCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "media") boolean media) { + r.setMedia(media); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the media status to " + media + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java new file mode 100644 index 0000000..eaccaf0 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetPrefixCommand { + @Command(names = {"rank setprefix"}, permission = "bridge.rank", description = "Set a ranks prefix", hidden = true, async = true) + public static void RankSetPrefixCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "prefix", wildcard = true) String prfx) { + String prefix = ChatColor.translateAlternateColorCodes('&', prfx); + r.setPrefix(prefix); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the prefix to " + prefix + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java new file mode 100644 index 0000000..c9c5088 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetPriorityCommand { + + @Command(names = {"rank setpriority", "rank setweight"}, permission = "bridge.rank", description = "Set a ranks priority", hidden = true, async = true) + public static void RankSetPriorityCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "priority") int priority) { + r.setPriority(priority); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the priority to " + priority + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java new file mode 100644 index 0000000..51185a3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetStaffCommand { + + @Command(names = {"rank setstaff"}, permission = "bridge.rank", description = "Set a rank staff status", hidden = true, async = true) + public static void RankSetStaffCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "staff") boolean staff) { + r.setStaff(staff); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the staff status to " + staff + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java new file mode 100644 index 0000000..9480c4e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.rank; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class RankSetSuffixCommand { + @Command(names = {"rank setsuffix"}, permission = "bridge.rank", description = "Set a ranks suffix", hidden = true, async = true) + public static void RankSetSuffixCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "suffix", wildcard = true) String sfx) { + String suffix = ChatColor.translateAlternateColorCodes('&', sfx); + r.setSuffix(suffix); + r.saveRank(); + s.sendMessage("§aSuccessfully changed the suffix to " + sfx + "§a!"); + PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName())); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName())); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java new file mode 100644 index 0000000..24ce165 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java @@ -0,0 +1,172 @@ +package rip.bridge.bridge.bukkit.commands.rank.menu; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.conversations.*; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.commands.rank.menu.buttons.PermissionButton; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.buttons.BackButton; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class PermissionsMenu extends PaginatedMenu { + + @Getter private Rank rank; + private boolean viewAll = false; + + public PermissionsMenu(Rank rank) { + this.rank = rank; + setAutoUpdate(true); + } + + + @Override + public String getPrePaginatedTitle(Player player) { + String str = rank.getColor() + rank.getDisplayName(); + if(str.length() >= 16) str =str.substring(0, 16); + return str + ChatColor.YELLOW + "'s Perms"; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttonMap = new HashMap<>(); + + buttonMap.put(2, new Button() { + @Override + public String getName(Player player) { + return ChatColor.YELLOW + (viewAll ? "Hide All" : "View All"); + } + + @Override + public List getDescription(Player player) { + return Collections.singletonList(""); + } + + @Override + public Material getMaterial(Player player) { + return viewAll ? Material.REDSTONE_BLOCK : Material.EMERALD_BLOCK; + } + + @Override + public byte getDamageValue(Player var1) { + return 0; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + boolean toggle = !viewAll; + viewAll = toggle; + player.sendMessage(ChatColor.YELLOW + "You are now " + (toggle ? ChatColor.GREEN : ChatColor.RED + "no longer ") + "viewing" + ChatColor.YELLOW + " permissions on all scopes."); + } + }); + + buttonMap.put(4, new BackButton(new RankMenu(rank))); + + buttonMap.put(6, new Button() { + @Override + public String getName(Player player) { + return ChatColor.YELLOW + "Add Permission"; + } + + @Override + public List getDescription(Player player) { + return Collections.singletonList(""); + } + + @Override + public Material getMaterial(Player player) { + return Material.ANVIL; + } + + @Override + public byte getDamageValue(Player var1) { + return 0; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Please type a permission you wish to add, or type" + ChatColor.RED + " cancel " + ChatColor.YELLOW + "to cancel"; + } + + @Override + public Prompt acceptInput(ConversationContext cc, String s) { + if (s.equalsIgnoreCase("cancel")) { + cc.getForWhom().sendRawMessage(ChatColor.RED + "Permission adding process cancelled."); + return Prompt.END_OF_CONVERSATION; + } + defineScope((Player) cc.getForWhom(), s); + return Prompt.END_OF_CONVERSATION; + } + + }).withLocalEcho(false).withEscapeSequence("/no").thatExcludesNonPlayersWithMessage("Go away evil console!"); + + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } + }); + + + return buttonMap; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttonMap = new HashMap<>(); + + AtomicInteger atomicInteger = new AtomicInteger(0); + + if(viewAll) + rank.getPermissions().keySet().forEach(str -> buttonMap.put(atomicInteger.getAndIncrement(), new PermissionButton(rank, str))); + else + rank.getActivePermissions().forEach(str -> buttonMap.put(atomicInteger.getAndIncrement(), new PermissionButton(rank, str))); + + return buttonMap; + + } + + public void defineScope(Player player, String permission) { + ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() { + + public String getPromptText(ConversationContext context) { + return ChatColor.YELLOW + "Type the name of the scope you wish to define this permission to. (Examples: Global, GR|Hub, Hub-1)"; + } + + @Override + public Prompt acceptInput(ConversationContext cc, String s) { + if(rank.hasPermission(permission, s)) { + cc.getForWhom().sendRawMessage(ChatColor.RED + "This rank already has this permission defined to the scope."); + new PermissionsMenu(rank).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + cc.getForWhom().sendRawMessage(ChatColor.YELLOW + "You have added the permission " + ChatColor.RED + permission + ChatColor.YELLOW + " to the scope " + ChatColor.RED + s + ChatColor.YELLOW + ".") ; + rank.togglePerm(permission, s); + rank.saveRank(); + PacketHandler.sendToAll(new RankUpdatePacket(rank, player.getName(), BridgeGlobal.getSystemName())); + new PermissionsMenu(rank).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + }).withLocalEcho(false).withEscapeSequence("/no").thatExcludesNonPlayersWithMessage("Go away evil console!"); + + Conversation con = factory.buildConversation(player); + player.beginConversation(con); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java new file mode 100644 index 0000000..fc653bd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java @@ -0,0 +1,85 @@ +package rip.bridge.bridge.bukkit.commands.rank.menu; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.bukkit.commands.rank.menu.buttons.PlayerButton; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.buttons.BackButton; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class PlayerMenu extends PaginatedMenu { + + @Getter private Rank rank; + private boolean viewAll = false; + + public PlayerMenu(Rank rank) { + this.rank = rank; + setAutoUpdate(true); + } + + + @Override + public String getPrePaginatedTitle(Player player) { + String str = rank.getColor() + rank.getDisplayName(); + if(str.length() >= 16) str =str.substring(0, 16); + return str + ChatColor.YELLOW + "'s Users"; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttonMap = new HashMap<>(); + + buttonMap.put(2, new Button() { + @Override + public String getName(Player player) { + return ChatColor.YELLOW + (viewAll ? "Hide All" : "View All"); + } + + @Override + public List getDescription(Player player) { + return Collections.singletonList(""); + } + + @Override + public Material getMaterial(Player player) { + return viewAll ? Material.REDSTONE_BLOCK : Material.EMERALD_BLOCK; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + boolean toggle = !viewAll; + viewAll = toggle; + player.sendMessage(ChatColor.YELLOW + "You are now " + (toggle ? ChatColor.GREEN : ChatColor.RED + "no longer ") + "viewing" + ChatColor.YELLOW + " grants on all scopes."); + } + }); + + buttonMap.put(6, new BackButton(new RankMenu(rank))); + + return buttonMap; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttonMap = new HashMap<>(); + + AtomicInteger atomicInteger = new AtomicInteger(0); + + if(viewAll) + rank.getProfilesInRank().stream().filter(profile -> profile.hasGrantOf(rank)).forEach(profile -> buttonMap.put(atomicInteger.getAndIncrement(), new PlayerButton(profile))); + else + rank.getProfilesInRank().stream().filter(profile -> profile.hasGrantOf(rank, true)).forEach(profile -> buttonMap.put(atomicInteger.getAndIncrement(), new PlayerButton(profile))); + + return buttonMap; + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java new file mode 100644 index 0000000..2cfdc8d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java @@ -0,0 +1,142 @@ +package rip.bridge.bridge.bukkit.commands.rank.menu; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RankMenu extends Menu { + + @Getter private Rank rank; + + public RankMenu(Rank rank) { + + this.rank = rank; + setAutoUpdate(true); + + } + + @Override + public String getTitle(Player player) { + return rank.getColor() + rank.getDisplayName(); + } + + @Override + public Map getButtons(Player player) { + Map buttonMap = new HashMap<>(); + + buttonMap.put(2, new Button() { + @Override + public String getName(Player player) { + return ChatColor.YELLOW + "Permissions " + ChatColor.GRAY + "(" + rank.getActivePermissions().size() + ")"; + } + + @Override + public List getDescription(Player player) { + return Arrays.asList(ChatColor.GRAY + "Click to view the active", ChatColor.GRAY + "permissions on this rank."); + } + + @Override + public Material getMaterial(Player player) { + return Material.PAPER; + } + + @Override + public byte getDamageValue(Player var1) { + return 0; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + new PermissionsMenu(rank).openMenu(player); + } + }); + + buttonMap.put(4, new Button() { + @Override + public String getName(Player player) { + return rank.getColor() + rank.getDisplayName(); + } + + @Override + public List getDescription(Player player) { + return Arrays.asList( + ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34), + ChatColor.YELLOW + "UUID: " + ChatColor.RED + rank.getUuid().toString(), + ChatColor.YELLOW + "Name: " + ChatColor.RED + rank.getName(), + "", + ChatColor.YELLOW + "Prefix: " + ChatColor.RED + rank.getPrefix().replace("§", "&") + "Color", + ChatColor.YELLOW + "Suffix: " + ChatColor.RED + rank.getSuffix().replace("§", "&") + "Color", + ChatColor.YELLOW + "Color: " + ChatColor.RED + rank.getColor().replace("§", "&") + "Color", + "", + ChatColor.YELLOW + "Priority: " + ChatColor.RED + rank.getPriority(), + ChatColor.YELLOW + "Staff: " + (rank.isStaff() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"), + ChatColor.YELLOW + "Hidden: " + (rank.isHidden() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"), + ChatColor.YELLOW + "Grantable: " + (rank.isGrantable() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"), + ChatColor.YELLOW + "Default: " + (rank.isDefaultRank() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"), + ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34) + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.SIGN; + } + + @Override + public byte getDamageValue(Player var1) { + return 0; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + + } + }); + + buttonMap.put(6, new Button() { + @Override + public String getName(Player player) { + return ChatColor.YELLOW + "Players " + ChatColor.GRAY + "(" + rank.getProfilesInRank().size() + ")"; + } + + @Override + public List getDescription(Player player) { + return Arrays.asList( + ChatColor.GRAY + "List of players that", + ChatColor.GRAY + "currently has this rank." + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.SKULL_ITEM; + } + + @Override + public byte getDamageValue(Player player) { + return 3; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + new PlayerMenu(rank).openMenu(player); + } + }); + + + return buttonMap; + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java new file mode 100644 index 0000000..ceed862 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java @@ -0,0 +1,57 @@ +package rip.bridge.bridge.bukkit.commands.rank.menu.buttons; + +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.RankUpdatePacket; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.menu.Button; + +import java.util.Arrays; +import java.util.List; + +@AllArgsConstructor +public class PermissionButton extends Button { + + private Rank rank; + private String str; + + @Override + public String getName(Player player) { + return ChatColor.YELLOW + str; + } + + @Override + public List getDescription(Player player) { + return Arrays.asList( + ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34), + ChatColor.YELLOW + "Scope: " + ChatColor.RED + rank.getPermissions().get(str), + "", + ChatColor.RED.toString() + ChatColor.BOLD + "Click to remove", + ChatColor.RED.toString() + ChatColor.BOLD + "this permission", + ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34)); + } + + @Override + public Material getMaterial(Player player) { + return Material.PAPER; + } + + @Override + public byte getDamageValue(Player var1) { + return 0; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.sendMessage(ChatColor.YELLOW + "You have removed the permission " + ChatColor.RED + str + ChatColor.YELLOW + ".") ; + rank.togglePerm(str, rank.getPermissions().get(str)); + rank.saveRank(); + PacketHandler.sendToAll(new RankUpdatePacket(rank, player.getName(), BridgeGlobal.getSystemName())); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java new file mode 100644 index 0000000..740ed76 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java @@ -0,0 +1,69 @@ +package rip.bridge.bridge.bukkit.commands.rank.menu.buttons; + +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.grant.menu.grants.GrantsMenu; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.menu.Button; + +import java.util.Arrays; +import java.util.List; + +@AllArgsConstructor +public class PlayerButton extends Button { + + private Profile profile; + + @Override + public String getName(Player player) { + return profile.getColor() + profile.getUsername(); + } + + @Override + public List getDescription(Player player) { + List lore = Arrays.asList( + ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34), + ChatColor.YELLOW + "Rank: " + ChatColor.RED + BukkitAPI.getPlayerRank(profile).getColor() + BukkitAPI.getPlayerRank(profile).getDisplayName(), + ChatColor.YELLOW + "Ranks: "); + + profile.getActiveGrants().forEach(grant -> { + lore.add(ChatColor.GRAY + " * " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.GRAY + "(" + StringUtils.join(grant.getScope(), ", ") + ")"); + }); + lore.addAll(Arrays.asList("", + ChatColor.RED.toString() + ChatColor.BOLD + "Click to open", + ChatColor.RED.toString() + ChatColor.BOLD + "players grants", + ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34))); + return lore; + } + + @Override + public Material getMaterial(Player player) { + return Material.SKULL_ITEM; + } + + @Override + public byte getDamageValue(Player player) { + return 3; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + player.closeInventory(); + List allGrants = profile.getGrants(); + allGrants.sort((first, second) -> { + if (first.getInitialTime() > second.getInitialTime()) { + return -1; + } + else { + return 1; + } + }); + new GrantsMenu(profile, allGrants).openMenu(player); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java new file mode 100644 index 0000000..aaba14c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java @@ -0,0 +1,18 @@ +package rip.bridge.bridge.bukkit.commands.server; + +import lombok.Getter; +import rip.bridge.bridge.bukkit.Bridge; + +public class BanLobby { + + @Getter + private boolean maintenance, restricted, banLobbyEnabled; + + public BanLobby() { + this.banLobbyEnabled = Bridge.getInstance().getConfig().getBoolean("server.ban-lobby"); + } + + //TODO: Do this shit later + +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java new file mode 100644 index 0000000..7b0b8a3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java @@ -0,0 +1,14 @@ +package rip.bridge.bridge.bukkit.commands.server; + +import org.bukkit.entity.Player; +import rip.bridge.bridge.bukkit.commands.server.menu.deployment.DeploymentMenu; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class DeploymentCommand { + + @Command(names = {"deploy", "deployment"}, permission = "bridge.deployment", description = "Deploy a server", hidden = true) + public static void deployCmd(Player s, @Param(name = "serverName") String serverName) { + new DeploymentMenu(serverName).openMenu(s); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java new file mode 100644 index 0000000..4f9dafc --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.bukkit.commands.server; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.qlib.command.Command; + +public class NetworkStatsCommand { + + @Command(names = "networkstats", permission = "bridge.server.stats", description = "View all online servers", hidden = true) + public static void networkstats(Player player) { + player.sendMessage(ChatColor.BLUE + "Network Stats"); + player.sendMessage(ChatColor.YELLOW + "Online: " + ChatColor.WHITE + BridgeGlobal.getServerHandler().getServer("BungeeCord").getOnline()); + player.sendMessage(ChatColor.YELLOW + "Total Profiles: " + ChatColor.WHITE + BridgeGlobal.getMongoHandler().getProfiles().size()); + player.sendMessage(ChatColor.YELLOW + "Total Ranks: " + ChatColor.WHITE + BridgeGlobal.getRankHandler().getRanks().size()); + player.sendMessage(ChatColor.YELLOW + "Online Servers " + ChatColor.WHITE + BridgeGlobal.getServerHandler().getServers().size()); + player.sendMessage(ChatColor.YELLOW + "Disguised Players: " + ChatColor.WHITE + BridgeGlobal.getDisguiseManager().getDisguisePlayers().size()); + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java new file mode 100644 index 0000000..268aa70 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands.server; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.commands.server.menu.server.ServerMenu; +import rip.bridge.qlib.command.Command; + +public class ServersCommand { + + @Command(names = "servers", permission = "bridge.server.list", description = "View all online servers", hidden = true) + public static void servers(Player player) { + if (BridgeGlobal.getServerHandler().getServers().isEmpty()) { + player.sendMessage(ChatColor.RED + "There are no servers found..."); + return; + } + new ServerMenu().openMenu(player); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java new file mode 100644 index 0000000..94a08d6 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.bukkit.commands.server; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.ServerShutdownPacket; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class ShutdownCommand { + + @Command(names = {"shutdown"}, permission = "bridge.server.shutdown", description = "Shutdown a server", hidden = true) + public static void shutdown(Player s, @Param(name = "server") String serverName) { + PacketHandler.sendToAll(new ServerShutdownPacket(serverName)); + if (serverName.equalsIgnoreCase("all")) { + PacketHandler.sendToAll(new NetworkBroadcastPacket("basic.staff", "&8[&eServer Monitor&8] &fRemoving all servers...")); + } else { + PacketHandler.sendToAll(new NetworkBroadcastPacket("basic.staff", "&8[&eServer Monitor&8] &fRemoving server " + serverName + "...")); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java new file mode 100644 index 0000000..f67b7d5 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java @@ -0,0 +1,24 @@ +package rip.bridge.bridge.bukkit.commands.server.group; + +import mkremins.fanciful.FancyMessage; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class GroupInfoCommand { + + @Command(names = {"group info"}, permission = "bridge.group.info", description = "Get information about a server group", hidden = true) + public static void groupList(CommandSender s, @Param(name = "group", wildcard = true) String g) { + if (BridgeGlobal.getServerHandler().getServersInGroup(g) == null) { + s.sendMessage(ChatColor.RED + "There is no such group with the name \"" + g + "\"."); + return; + } + s.sendMessage(StringUtils.repeat(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + "-", 35)); + s.sendMessage(ChatColor.RED + "Servers in the group " + g + ":"); + BridgeGlobal.getServerHandler().getServersInGroup(g).forEach(serv -> new FancyMessage(ChatColor.RED + serv.getName()).tooltip(ChatColor.GRAY + "Click to view information about the server.").command("/serverinfo info " + serv.getName()).send(s)); + s.sendMessage(StringUtils.repeat(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + "-", 35)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java new file mode 100644 index 0000000..948603f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.bukkit.commands.server.group; + +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.command.Command; + +public class GroupListCommand { + + @Command(names = {"group list"}, permission = "bridge.group.list", description = "List all available server groups", hidden = true) + public static void groupList(CommandSender s) { + if (BridgeGlobal.getServerHandler().getGroups() == null) { + s.sendMessage(ChatColor.RED + "There are no server groups..."); + return; + } + FancyMessage m = new FancyMessage(ChatColor.GREEN + "Available Groups: "); + BridgeGlobal.getServerHandler().getGroups().forEach(serv -> m.then(serv + " ").tooltip(ChatColor.GRAY + "Click to view servers in the group.").command("/group info " + serv)); + m.send(s); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java new file mode 100644 index 0000000..7862dbb --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java @@ -0,0 +1,67 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.deployment; + +import com.google.common.collect.Lists; +import net.md_5.bungee.api.ChatColor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.packet.types.ServerDeployPacket; +import rip.bridge.qlib.menu.Button; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class CompleteButton +extends Button { + private DeploymentMenu parent; + private List plugins; + + public String getName(Player player) { + return ChatColor.GREEN + "Confirm and Update"; + } + + public List getDescription(Player player) { + ArrayList description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', (int)30)); + description.add(ChatColor.BLUE + "Click to deploy " + ChatColor.WHITE + this.plugins.size() + " plugins" + ChatColor.BLUE + " to the server " + ChatColor.WHITE + this.parent.getServerName() + ChatColor.BLUE + "."); + description.add(""); + this.plugins.forEach(file -> description.add(ChatColor.GRAY + " * " + ChatColor.WHITE + file.getName() + ' ' + BridgeGlobal.getUpdaterManager().getStatus((File)file).getPrefix())); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', (int)30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.DIAMOND_SWORD; + } + + public byte getDamageValue(Player player) { + return 0; + } + + public void clicked(Player player, int i, ClickType clickType) { + this.update(this.plugins, player); + } + + private void update(List plugins, Player player) { + if (plugins.isEmpty()) { + player.sendMessage(ChatColor.RED + "You must select a plugin you wish to deploy!"); + return; + } + PacketHandler.sendToAll(new ServerDeployPacket(parent.getServerName(), plugins)); + player.sendMessage(ChatColor.GREEN + "Attempting to deploy a server with name \"" + parent.getServerName() + "\" now."); + this.parent.setComplete(true); + PacketHandler.sendToAll(new NetworkBroadcastPacket("basic.staff", "&8[&eServer Monitor&8] &fAdding server " + parent.getServerName() + "...")); + player.closeInventory(); + } + + public CompleteButton(DeploymentMenu parent, List plugins) { + this.parent = parent; + this.plugins = plugins; + } +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java new file mode 100644 index 0000000..1664631 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java @@ -0,0 +1,83 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.deployment; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; + +import java.io.File; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class DeploymentMenu extends Menu { + + private String serverName; + + private Map status; + + private boolean complete; + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public void setStatus(Map status) { + this.status = status; + } + + public void setComplete(boolean complete) { + this.complete = complete; + } + + public Map getStatus() { + return this.status; + } + + public boolean isComplete() { + return this.complete; + } + + public String getTitle(Player player) { + return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Deployment - " + this.serverName; + } + + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + List plugins = BridgeGlobal.getUpdaterManager().getFilesForGroup("ALL"); + int i = 0; + for (File file : plugins) { + this.status.putIfAbsent(file, Boolean.FALSE); + buttons.put(i, new PluginButton(this, file)); + i++; + } + List scopes = Lists.newArrayList(); + scopes.addAll(this.status.keySet().stream().filter(this.status::get).collect(Collectors.toList())); + buttons.put(31, new CompleteButton(this, scopes)); + return buttons; + } + + public void onClose(final Player player) { + (new BukkitRunnable() { + public void run() { + if (!Menu.currentlyOpenedMenus.containsKey(player.getName()) && !DeploymentMenu.this.complete) + player.sendMessage(ChatColor.RED + "Server deployment cancelled."); + } + }).runTaskLater(Bridge.getInstance(), 1L); + } + + public DeploymentMenu(String serverName) { + this.status = Maps.newHashMap(); + this.serverName = serverName; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java new file mode 100644 index 0000000..c1de85d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java @@ -0,0 +1,56 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.deployment; + +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.menu.Button; + +import java.io.File; +import java.util.List; + +@AllArgsConstructor +public class PluginButton extends Button { + + private DeploymentMenu parent; + private File plugin; + + public String getName(Player player) { + boolean status = this.parent.getStatus().get(this.plugin); + return (status ? ChatColor.GREEN : ChatColor.RED) + this.plugin.getName() + " " + BridgeGlobal.getUpdaterManager().getStatus(plugin).getPrefix(); + } + + public List getDescription(Player player) { + boolean status = this.parent.getStatus().get(this.plugin); + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + if (status) { + description.add(ChatColor.BLUE + "Click to " + ChatColor.RED + "remove " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " from the deployment list."); + } + else { + description.add(ChatColor.BLUE + "Click to " + ChatColor.GREEN + "add " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " to the deployment list."); + } + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + boolean status = this.parent.getStatus().get(this.plugin); + return status ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + this.parent.getStatus().put(this.plugin, !this.parent.getStatus().getOrDefault(this.plugin, false)); + } + +} + diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java new file mode 100644 index 0000000..16c5802 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java @@ -0,0 +1,16 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.groups; + +import org.bukkit.entity.Player; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; + +import java.util.Map; + +public class GroupMenu extends Menu { + + @Override + public Map getButtons(Player player) { + return null; + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java new file mode 100644 index 0000000..f48df0d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java @@ -0,0 +1,55 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.server; + +import lombok.AllArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.bukkit.commands.server.menu.server.buttons.DataButton; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.bridge.global.status.start.ServerStartThread; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.buttons.BackButton; +import rip.bridge.qlib.menu.menus.ConfirmMenu; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +@AllArgsConstructor +public class ExtraInformationMenu extends PaginatedMenu { + + private final BridgeServer server; + + @Override + public String getPrePaginatedTitle(Player player) { + return ChatColor.YELLOW + "Extra information: " + server.getName(); + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + buttons.put(4, new BackButton(new ServerMenu())); + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + + AtomicInteger atomicInteger = new AtomicInteger(0); + + try { + server.getMetadata().entrySet().forEach(str -> { + buttons.put(atomicInteger.getAndIncrement(), new DataButton(str.getKey(), server.getMetadata().get(str.getKey()).toString())); + }); + } catch (Exception ex) { + buttons.put(4, Button.placeholder(Material.REDSTONE_BLOCK, ChatColor.RED + "This server has no extra information.")); + } + return buttons; + + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java new file mode 100644 index 0000000..ff483b3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java @@ -0,0 +1,76 @@ + +package rip.bridge.bridge.bukkit.commands.server.menu.server; + +import lombok.AllArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.bridge.global.status.start.ServerStartThread; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.buttons.BackButton; +import rip.bridge.qlib.menu.menus.ConfirmMenu; +import rip.bridge.qlib.menu.pagination.PaginatedMenu; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@AllArgsConstructor +public class ServerActionMenu extends PaginatedMenu { + + private final BridgeServer server; + + @Override + public String getPrePaginatedTitle(Player player) { + return ChatColor.YELLOW + "Server Actions: " + server.getName(); + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttonMap = new HashMap<>(); + buttonMap.put(4, new BackButton(new ServerMenu())); + return buttonMap; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); +// buttons.put(4, Button.placeholder(Material.REDSTONE_BLOCK, ChatColor.RED + "This server has no additional actions.")); + buttons.put(4, new Button() { + @Override + public String getName(Player player) { + return server.isOnline() ? ChatColor.RED + ChatColor.BOLD.toString() + "Shutdown" : ChatColor.GREEN + ChatColor.BOLD.toString() + "Start Up"; + } + + @Override + public List getDescription(Player player) { + return null; + } + + @Override + public Material getMaterial(Player player) { + return server.isOnline() ? Material.REDSTONE_BLOCK : Material.EMERALD_BLOCK; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + new ConfirmMenu("Are you sure?", (b) -> { + if (b) { + if (server.isOnline()) { + new JsonChain().addProperty("server", server.getName()).get(); + } else { + new ServerStartThread(server).start(); + } + } + new ServerMenu().openMenu(player); + }).openMenu(player); + } + }); + + return buttons; + + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java new file mode 100644 index 0000000..bc8193f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java @@ -0,0 +1,39 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.server; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.commands.server.menu.server.buttons.ServerButton; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class ServerMenu extends Menu { + + public ServerMenu() { + super(ChatColor.YELLOW + ChatColor.BOLD.toString() + "Servers"); + setAutoUpdate(true); + } + + @Override + public Map getButtons(Player player) { + Map buttonMap = new HashMap<>(); + AtomicInteger atomicInteger = new AtomicInteger(0); + BridgeGlobal.getServerHandler().getServers().values().stream().sorted(Comparator.comparingLong(this::getStartTime)).forEach(s -> { + buttonMap.put(atomicInteger.getAndIncrement(), new ServerButton(s)); + }); + return buttonMap; + } + + private long getStartTime(BridgeServer server) { + try { + return server.getBootTime(); + } catch (Exception ignored) {} + return System.currentTimeMillis(); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java new file mode 100644 index 0000000..925c65b --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java @@ -0,0 +1,32 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.server.buttons; + +import lombok.AllArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import rip.bridge.qlib.menu.Button; + +import java.util.Collections; +import java.util.List; + +@AllArgsConstructor +public class DataButton extends Button { + + private String data; + private String value; + + @Override + public String getName(Player player) { + return ChatColor.LIGHT_PURPLE + data; + } + + @Override + public List getDescription(Player player) { + return Collections.singletonList(ChatColor.GRAY + value); + } + + @Override + public Material getMaterial(Player player) { + return Material.PAPER; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java new file mode 100644 index 0000000..243f9ff --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java @@ -0,0 +1,82 @@ +package rip.bridge.bridge.bukkit.commands.server.menu.server.buttons; + +import lombok.AllArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.bridge.bridge.bukkit.commands.server.menu.server.ExtraInformationMenu; +import rip.bridge.bridge.bukkit.commands.server.menu.server.ServerActionMenu; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.util.BungeeUtils; +import rip.bridge.qlib.util.TPSUtils; +import rip.bridge.qlib.util.TimeUtil; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@AllArgsConstructor +public class ServerButton extends Button { + + private BridgeServer server; + + @Override + public String getName(Player player) { + return (!server.isOnline() ? ChatColor.RED : server.isWhitelisted() ? ChatColor.WHITE : ChatColor.GREEN) + server.getName(); + } + + @Override + public List getDescription(Player player) { + List lore = new ArrayList<>(); + + if(!server.isOnline()) { + lore.add(ChatColor.RED + "This server has recently gone offline"); + }else { + if(server.getTps() != 0.0) { + lore.add(ChatColor.YELLOW + "TPS: " + ChatColor.WHITE + TPSUtils.formatTPS(server.getTps(), true)); + } + lore.add(ChatColor.YELLOW + "Online: " + ChatColor.WHITE + server.getOnline() + " / " + server.getMaximum()); + lore.add(ChatColor.YELLOW + "Status: " + ChatColor.WHITE + server.formattedStatus(true)); + if(!server.getMotd().isEmpty()) { + lore.add(ChatColor.YELLOW + "MOTD: " + ChatColor.WHITE + server.getMotd()); + } + lore.add(""); + lore.add(ChatColor.YELLOW + "System Type: " + ChatColor.WHITE + server.getSystemType()); + lore.add(ChatColor.YELLOW + "Group: " + ChatColor.WHITE + server.getGroup()); + lore.add(ChatColor.YELLOW + "Provider: " + ChatColor.WHITE + server.getProvider()); + lore.add(""); + lore.add(ChatColor.YELLOW + "Server Started At: " + ChatColor.WHITE + TimeUtils.formatIntoCalendarString(new Date(server.getBootTime()))); + lore.add(ChatColor.YELLOW + "Uptime: " + ChatColor.WHITE + TimeUtil.millisToTimer(System.currentTimeMillis() - server.getBootTime())); + lore.add(ChatColor.YELLOW + "Last Updated: " + ChatColor.WHITE + TimeUtil.millisToTimer(System.currentTimeMillis() - server.getLastHeartbeat())); + lore.add(""); + lore.add(ChatColor.GRAY + "Left click to connect."); + lore.add((server.getMetadata() == null ? ChatColor.RED + "This server has no extra information." : ChatColor.GREEN + "Right click to for more information.")); + } + + return lore; + } + + @Override + public Material getMaterial(Player player) { + if(!server.isOnline()) return Material.REDSTONE_BLOCK; + if(server.getStatus().equals("BOOTING")) return Material.GOLD_BLOCK; + if(server.isWhitelisted()) return Material.GOLD_BLOCK; + if(server.isOnline()) return Material.EMERALD_BLOCK; + + return Material.REDSTONE_BLOCK; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + if(clickType == ClickType.LEFT) { + player.closeInventory(); + BungeeUtils.send(player, server.getName()); + }else if(clickType == ClickType.RIGHT) { + player.closeInventory(); + new ExtraInformationMenu(server).openMenu(player); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java new file mode 100644 index 0000000..445e566 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java @@ -0,0 +1,36 @@ +package rip.bridge.bridge.bukkit.commands.server.serverinfo; + +import mkremins.fanciful.FancyMessage; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.util.TPSUtils; + +public class ServerInfoCommand { + + @Command(names = {"serverinfo info"}, permission = "bridge.server.info", description = "Get information about a server group", hidden = true) + public static void serverInfo(CommandSender s, @Param(name = "server", wildcard = true) String server) { + if (BridgeGlobal.getServerHandler().getServer(server) == null) { + s.sendMessage(ChatColor.RED + "There is no such server with the name \"" + server + "\"."); + return; + } + BridgeServer bridgeServer = BridgeGlobal.getServerHandler().getServer(server); + s.sendMessage(StringUtils.repeat(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + "-", 45)); + s.sendMessage(ChatColor.GOLD + bridgeServer.getName() + ChatColor.GRAY + " [" + bridgeServer.getOnline() + '/' + bridgeServer.getMaximum() + "]"); + s.sendMessage(ChatColor.YELLOW + "Provider: " + ChatColor.RED + bridgeServer.getProvider()); + s.sendMessage(ChatColor.YELLOW + "Status: " + bridgeServer.formattedStatus(true)); + if (!bridgeServer.getMotd().isEmpty()) + s.sendMessage(ChatColor.YELLOW + "MOTD: " + ChatColor.RED + bridgeServer.getMotd()); + if (bridgeServer.getTps() != 0.0) + s.sendMessage(ChatColor.YELLOW + "TPS: " + ChatColor.RED + TPSUtils.formatTPS(bridgeServer.getTps(), true)); + if (bridgeServer.getSystemType().equals("BUKKIT")) { + boolean wl = bridgeServer.isWhitelisted(); + new FancyMessage(ChatColor.YELLOW + "Whitelisted: ").then(ChatColor.RED + (wl ? "True" : "False")).tooltip(ChatColor.AQUA + "Click to change to change whitelist status.").command("/serverinfo whitelist " + bridgeServer.getName()).send(s); + } + s.sendMessage(StringUtils.repeat(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + "-", 45)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java new file mode 100644 index 0000000..06cd826 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.bukkit.commands.server.serverinfo; + +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.command.Command; + +public class ServerInfoListCommand { + + @Command(names = {"serverinfo list"}, permission = "bridge.server.list", description = "List all available server groups", hidden = true) + public static void serverList(CommandSender s) { + if (BridgeGlobal.getServerHandler().getServers().isEmpty()) { + s.sendMessage(ChatColor.RED + "There are no servers found..."); + return; + } + FancyMessage m = new FancyMessage(ChatColor.GREEN + "Available Servers: "); + BridgeGlobal.getServerHandler().getServers().values().forEach(serv -> m.then(serv.getName() + " ").tooltip(ChatColor.GRAY + "Click to view information about the server.").command("/serverinfo info " + serv.getName())); + m.send(s); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java new file mode 100644 index 0000000..2beb321 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.bukkit.util.PluginUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +public class UpdaterDisableCommand { + + @Command(names = "updater disable", permission = "bridge.updater", hidden = true, description = "Disables a specific plugins") + public static void disable(CommandSender sender, @Param(name = "plugin") Plugin plugin) { + PluginUtil.disable(plugin); + sender.sendMessage(ChatColor.GREEN + "Disabled " + plugin.getName() + "."); + } + + @Command(names = "updater disable all", permission = "bridge.updater", hidden = true, description = "Disables all plugins") + public static void disableall(CommandSender sender) { + PluginUtil.disableAll(); + sender.sendMessage(ChatColor.GREEN + "Disabled all plugins."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java new file mode 100644 index 0000000..4da7550 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.bukkit.util.PluginUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +public class UpdaterEnableCommand { + + @Command(names = "updater enable", permission = "bridge.updater", hidden = true, description = "Enables a specific plugin") + public static void enable(CommandSender sender, @Param(name = "plugin") Plugin plugin) { + PluginUtil.enable(plugin); + sender.sendMessage(ChatColor.GREEN + "Enabled " + plugin.getName() + "."); + } + + @Command(names = "updater enable all", permission = "bridge.updater", hidden = true, description = "Enables all plugins") + public static void enableall(CommandSender sender) { + PluginUtil.enableAll(); + sender.sendMessage(ChatColor.GREEN + "Enabled all plugins."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java new file mode 100644 index 0000000..cb4d3ec --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java @@ -0,0 +1,28 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.qlib.command.Command; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.io.File; +import java.util.List; + +public class UpdaterInfoCommand { + + @Command(names = "updater info", permission = "bridge.updater", hidden = true, description = "Check information about the updater.") + public static void info(CommandSender sender) { + sender.sendMessage(BukkitAPI.LINE); + sender.sendMessage("§6§lUpdater §7❘ §fInformation"); + sender.sendMessage(BukkitAPI.LINE); + sender.sendMessage(ChatColor.YELLOW + "Updating for Group: " + ChatColor.WHITE + StringUtils.join(BridgeGlobal.getUpdaterGroups(), ", ") + " & Global"); + sender.sendMessage(ChatColor.YELLOW + "Using Root Directory: " + ChatColor.WHITE + BridgeGlobal.getUpdaterManager().getPluginUpdateDir()); + + List fileList = BridgeGlobal.getUpdaterManager().getFilesForGroup(BridgeGlobal.getUpdaterGroups()); + sender.sendMessage(ChatColor.YELLOW + "Plugins available: " + ChatColor.WHITE + (fileList == null || fileList.isEmpty() ? "N/A" : fileList.size())); + sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.ITALIC + "Use /updater list to list all available plugins..."); + sender.sendMessage(BukkitAPI.LINE); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java new file mode 100644 index 0000000..5c3d5cb --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java @@ -0,0 +1,36 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.updater.UpdateStatus; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +public class UpdaterListCommand { + + @Command(names = "updater list", permission = "bridge.updater", hidden = true, description = "List all files in your group") + public static void list(CommandSender sender, @Param(name = "group", defaultValue = "current") String groupName) { + List files = BridgeGlobal.getUpdaterManager().getFilesForGroup((groupName.equals("current") ? BridgeGlobal.getUpdaterGroups() : Collections.singletonList(groupName))); + sender.sendMessage(BukkitAPI.LINE); + sender.sendMessage("§6§lUpdater §7❘ §fList"); + sender.sendMessage(BukkitAPI.LINE); + if (files == null) { + sender.sendMessage(ChatColor.RED + "The directory for the group does not exist..."); + } else if (files.isEmpty()) { + sender.sendMessage(ChatColor.RED + "No available plugins for this group..."); + } else { + files.forEach(file -> { + UpdateStatus updateStatus = BridgeGlobal.getUpdaterManager().getStatus(file); + sender.sendMessage(ChatColor.YELLOW + file.getName() + ChatColor.GRAY + " (" + file.getPath() + ")" + (file.getAbsolutePath().contains("Global") ? ChatColor.RED + " [Global]" : "") + ' ' + updateStatus.getPrefix()); + }); + } + sender.sendMessage(BukkitAPI.LINE); + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java new file mode 100644 index 0000000..cefc392 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java @@ -0,0 +1,14 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.bukkit.util.PluginUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.command.CommandSender; + +public class UpdaterLoadCommand { + + @Command(names = "updater load", permission = "bridge.updater", hidden = true, description = "Loads a plugin") + public static void load(CommandSender sender, @Param(name = "fileName", wildcard = true) String fileName) { + sender.sendMessage(PluginUtil.load(fileName)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java new file mode 100644 index 0000000..8ffaab7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.bukkit.util.PluginUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +public class UpdaterReloadCommand { + + @Command(names = "updater reload", permission = "bridge.updater", hidden = true, description = "Reloads a specific plugin") + public static void reload(CommandSender sender, @Param(name = "plugin") Plugin plugin) { + PluginUtil.reload(plugin); + sender.sendMessage(ChatColor.GREEN + "Reloaded " + plugin.getName() + "."); + } + + @Command(names = "updater reload all", permission = "bridge.updater", hidden = true, description = "Reloads all plugins") + public static void reloadall(CommandSender sender) { + PluginUtil.reloadAll(); + sender.sendMessage(ChatColor.GREEN + "Reloaded all plugins."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java new file mode 100644 index 0000000..ad85e8a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java @@ -0,0 +1,15 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.bukkit.util.PluginUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +public class UpdaterUnloadCommand { + + @Command(names = "updater unload", permission = "bridge.updater", hidden = true, description = "Unloads a plugin") + public static void load(CommandSender sender, @Param(name = "plugin", wildcard = true) Plugin plugin) { + sender.sendMessage(PluginUtil.unload(plugin)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java new file mode 100644 index 0000000..187270b --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java @@ -0,0 +1,49 @@ +package rip.bridge.bridge.bukkit.commands.updater; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.commands.updater.menu.UpdaterMenu; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +public class UpdaterUpdateCommand { + + @Command(names = "updater update", permission = "bridge.updater", hidden = true, description = "Update specific plugins") + public static void update(CommandSender sender, @Param(name = "pluginname", defaultValue = "none") String pluginName) { + List group = BridgeGlobal.getUpdaterGroups(); + List files = BridgeGlobal.getUpdaterManager().getFilesForGroup(group); + switch (pluginName) { + case "all": { + BridgeGlobal.getUpdaterManager().updatePlugins(files, cons -> sender.sendMessage(ChatColor.BLUE + cons)); + break; + } + + case "none": { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "Sorry ingame only!"); + return; + } + new UpdaterMenu(group).openMenu((Player) sender); + break; + } + + default: { + File pluginFile = files.stream().filter(file -> file.getName().equalsIgnoreCase(pluginName)).findAny().orElse(null); + if (pluginFile == null) { + sender.sendMessage(ChatColor.RED + "There is no such plugin file by the name \"" + pluginName + "\", use /updater list to get a list of plugins."); + return; + } + + sender.sendMessage(ChatColor.GREEN + "Attempting to update " + pluginFile.getName() + "!"); + BridgeGlobal.getUpdaterManager().updatePlugins(Collections.singletonList(pluginFile), cons -> sender.sendMessage(ChatColor.BLUE + cons)); + } + + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java new file mode 100644 index 0000000..3ac5ee2 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java @@ -0,0 +1,27 @@ +package rip.bridge.bridge.bukkit.commands.updater.group; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.List; + +public class UpdaterGroupAddCommand { + + @Command(names = "updater group add", permission = "bridge.updater", hidden = true, description = "Add a group to the update group") + public static void groupadd(CommandSender sender, @Param(name = "group") String group) { + List configGroups = Bridge.getInstance().getConfig().getStringList("updaterGroups"); + if (BridgeGlobal.getUpdaterGroups().stream().anyMatch(s -> s.equalsIgnoreCase(group))) { + sender.sendMessage(ChatColor.RED + "This group is already in the update list."); + return; + } + BridgeGlobal.addUpdaterGroup(group); + configGroups.add(group); + Bridge.getInstance().getConfig().set("updaterGroups", configGroups); + Bridge.getInstance().saveConfig(); + sender.sendMessage(ChatColor.GREEN + "Successfully added the group \"" + group + "\" to the update groups."); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java new file mode 100644 index 0000000..d52ba8e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java @@ -0,0 +1,28 @@ +package rip.bridge.bridge.bukkit.commands.updater.group; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.List; + +public class UpdaterGroupRemoveCommand { + + @Command(names = "updater group remove", permission = "bridge.updater", hidden = true, description = "Remove a group from the update group") + public static void groupremove(CommandSender sender, @Param(name = "group") String group) { + List configGroups = Bridge.getInstance().getConfig().getStringList("updaterGroups"); + if(BridgeGlobal.getUpdaterGroups().stream().noneMatch(s -> s.equalsIgnoreCase(group))) { + sender.sendMessage(ChatColor.RED + "There is no such group in the list with the name \"" + group + "\"."); + return; + } + BridgeGlobal.removeUpdaterGroup(group); + configGroups.remove(group); + Bridge.getInstance().getConfig().set("updaterGroups", configGroups); + Bridge.getInstance().saveConfig(); + sender.sendMessage(ChatColor.GREEN + "Successfully removed the group \"" + group + "\" from the update groups."); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java new file mode 100644 index 0000000..17087e4 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java @@ -0,0 +1,60 @@ +package rip.bridge.bridge.bukkit.commands.updater.menu; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.menu.Button; +import lombok.AllArgsConstructor; +import net.md_5.bungee.api.ChatColor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.io.File; +import java.util.List; + +@AllArgsConstructor +public class CompleteButton extends Button { + + private UpdaterMenu parent; + private List plugins; + + public String getName(Player player) { + return ChatColor.GREEN + "Confirm and Update"; + } + + public List getDescription(Player player) { + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + description.add(ChatColor.BLUE + "Click to update " + ChatColor.WHITE + this.plugins.size() + " plugins" + ChatColor.BLUE + " for the groups " + ChatColor.WHITE + StringUtils.join(this.parent.getGroups(), ", ") + ChatColor.BLUE + "."); + description.add(""); + plugins.forEach(file -> description.add(ChatColor.GRAY + " * " + ChatColor.WHITE + file.getName() + ' ' + BridgeGlobal.getUpdaterManager().getStatus(file).getPrefix())); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.DIAMOND_SWORD; + } + + public byte getDamageValue(Player player) { + return 0; + } + + public void clicked(Player player, int i, ClickType clickType) { + this.update(this.plugins, player); + } + + private void update(List plugins, Player player) { + if(plugins.isEmpty()) { + player.sendMessage(ChatColor.RED + "You must select a plugin you wish to update!"); + return; + } + + BridgeGlobal.getUpdaterManager().updatePlugins(plugins, cons -> player.sendMessage(ChatColor.BLUE + cons)); + player.sendMessage(ChatColor.DARK_RED.toString() + ChatColor.BOLD + "! YOU WILL NEED TO RESTART FOR CHANGES TO TAKE PLACE !"); + this.parent.setComplete(true); + player.closeInventory(); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java new file mode 100644 index 0000000..60c5e6f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java @@ -0,0 +1,54 @@ +package rip.bridge.bridge.bukkit.commands.updater.menu; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.qlib.menu.Button; +import lombok.AllArgsConstructor; +import net.minecraft.util.org.apache.commons.lang3.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; + +import java.io.File; +import java.util.List; + +@AllArgsConstructor +public class PluginButton extends Button { + private UpdaterMenu parent; + private File plugin; + + public String getName(Player player) { + boolean status = this.parent.getStatus().get(this.plugin); + return (status ? ChatColor.GREEN : ChatColor.RED) + this.plugin.getName() + " " + BridgeGlobal.getUpdaterManager().getStatus(plugin).getPrefix(); + } + + public List getDescription(Player player) { + boolean status = this.parent.getStatus().get(this.plugin); + List description = Lists.newArrayList(); + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + if (status) { + description.add(ChatColor.BLUE + "Click to " + ChatColor.RED + "remove " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " from the update list."); + } + else { + description.add(ChatColor.BLUE + "Click to " + ChatColor.GREEN + "add " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " to the update list."); + } + description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30)); + return description; + } + + public Material getMaterial(Player player) { + return Material.WOOL; + } + + public byte getDamageValue(Player player) { + boolean status = this.parent.getStatus().get(this.plugin); + return status ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData(); + } + + public void clicked(Player player, int i, ClickType clickType) { + this.parent.getStatus().put(this.plugin, !this.parent.getStatus().getOrDefault(this.plugin, false)); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java new file mode 100644 index 0000000..6cf5f45 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java @@ -0,0 +1,65 @@ +package rip.bridge.bridge.bukkit.commands.updater.menu; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.updater.UpdateStatus; +import rip.bridge.qlib.menu.Button; +import rip.bridge.qlib.menu.Menu; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Getter @Setter +public class UpdaterMenu extends Menu { + + private List groups; + private Map status; + private boolean complete; + + public String getTitle(Player player) { + return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Updater"; + } + + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + List plugins = BridgeGlobal.getUpdaterManager().getFilesForGroup(groups).stream().filter(file -> { + UpdateStatus updateStatus = BridgeGlobal.getUpdaterManager().getStatus(file); + return updateStatus != UpdateStatus.ERROR && updateStatus != UpdateStatus.LATEST; + }).collect(Collectors.toList()); + + int i = 0; + for (File file : plugins) { + this.status.putIfAbsent(file, false); + buttons.put(i, new PluginButton(this, file)); + ++i; + } + List scopes = Lists.newArrayList(); + scopes.addAll(this.status.keySet().stream().filter(this.status::get).collect(Collectors.toList())); + buttons.put(31, new CompleteButton(this, scopes)); + return buttons; + } + + public void onClose(Player player) { + new BukkitRunnable() { + public void run() { + if (!Menu.currentlyOpenedMenus.containsKey(player.getName()) && !UpdaterMenu.this.complete) { + player.sendMessage(ChatColor.RED + "Updating cancelled."); + } + } + }.runTaskLater(Bridge.getInstance(), 1L); + } + + public UpdaterMenu(List groups) { + this.status = Maps.newHashMap(); + this.groups = groups; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java new file mode 100644 index 0000000..d30cf6c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java @@ -0,0 +1,25 @@ +package rip.bridge.bridge.bukkit.commands.user; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class UserDeleteCommand { + + @Command(names = {"user delete"}, permission = "bridge.user", description = "Delete a players profile", async = true, hidden = true) + public static void UserDeleteCmd(CommandSender s, @Param(name = "player", extraData = "get") Profile pf) { + BridgeGlobal.getMongoHandler().removeProfile(pf.getUuid(), callback -> { + if (callback) { + if (Bukkit.getOfflinePlayer(pf.getUuid()).isOnline()) + Bukkit.getPlayer(pf.getUuid()).kickPlayer("§cYour profile has been deleted - please reconnect."); + BridgeGlobal.getProfileHandler().getProfiles().remove(pf); + s.sendMessage("§aSuccessfully deleted " + pf.getUsername() + "'s Profile."); + } else { + s.sendMessage("§cFailed to delete " + pf.getUsername() + "'s Profile."); + } + }, false); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java new file mode 100644 index 0000000..dcf587e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java @@ -0,0 +1,43 @@ +package rip.bridge.bridge.bukkit.commands.user; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.util.TimeUtil; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.Date; + +public class UserInfoCommand { + + @Command(names = {"user info", "user check"}, permission = "bridge.user", description = "Get information about a players profile", async = true, hidden = true) + public static void UserInfoCmd(CommandSender s, @Param(name = "player", extraData = "get") Profile pf) { + s.sendMessage(BukkitAPI.LINE); + s.sendMessage(BukkitAPI.getColor(pf) + pf.getUsername() + " §7❘ §fProfile Information"); + s.sendMessage(BukkitAPI.LINE); + s.sendMessage("§6UUID: §f" + pf.getUuid()); + s.sendMessage("§6Rank: §f" + pf.getCurrentGrant().getRank().getColor() + pf.getCurrentGrant().getRank().getDisplayName()); + s.sendMessage("§6Grants: §f" + pf.getActiveGrants().size() + " active | " + pf.getGrants().size() + " total"); + s.sendMessage("§6Punishments: §f" + pf.getActivePunishments().size() + " active | " + pf.getPunishments().size() + " total"); + s.sendMessage("§6Permissions (" + pf.getPermissions().size() + ChatColor.GOLD + "): "); + if (pf.getPermissions().isEmpty()) s.sendMessage(ChatColor.RED + "None..."); + else pf.getPermissions().keySet().forEach(str -> { + s.sendMessage(ChatColor.GRAY + " * " + ChatColor.WHITE + str + ChatColor.GRAY + " [" + pf.getPermissions().get(str) + "]"); + }); + s.sendMessage(""); +// s.sendMessage("§6Prefix: §f" + BukkitAPI.getPrefix(pf) + " §7(" + ChatColor.stripColor(BukkitAPI.getPrefix(pf).replace("§", "&")) + ")"); +// s.sendMessage("§6Suffix: §f" + BukkitAPI.getSuffix(pf) + " §7(" + ChatColor.stripColor(BukkitAPI.getSuffix(pf).replace("§", "&")) + ")"); + s.sendMessage("§6First Joined: §f" + TimeUtils.formatIntoCalendarString(new Date(pf.getFirstJoined()))); + if (pf.isOnline()) { + s.sendMessage("§6Connected to: §f" + BridgeGlobal.getServerHandler().findPlayerServer(pf.getUuid()).getName() + (BridgeGlobal.getServerHandler().findPlayerProxy(pf.getUuid()) != null ? " §7[" + BridgeGlobal.getServerHandler().findPlayerProxy(pf.getUuid()).getName() + "]" : "")); + } else { +// s.sendMessage("§6Last Seen: §7(" + TimeUtil.millisToRoundedTime(System.currentTimeMillis() - pf.getLastQuit()) + " ago)"); + s.sendMessage("§6Last Server: §f" + pf.getConnectedServer() + " §7(" + TimeUtil.millisToRoundedTime(System.currentTimeMillis() - pf.getLastQuit()) + " ago)"); + } + s.sendMessage(BukkitAPI.LINE); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java new file mode 100644 index 0000000..f7d91b7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands.user; + +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.bukkit.listener.GeneralListener; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class UserPermissionCommand { + + @Command(names = {"user permission", "user perm"}, permission = "bridge.user", description = "Add/Remove a player's permission", hidden = true, async = true) + public static void UserPermissionCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "permission") String perm, @Param(name = "group", defaultValue = "§") String serverGroup) { + String group = serverGroup.equals("§") ? "Global" : serverGroup; + boolean b = pf.togglePerm(perm, group); + pf.saveProfile(); + GeneralListener.updatePermissions(pf.getUuid()); + s.sendMessage("§aSuccessfully " + (b ? "added" : "removed") + " the permission " + perm + " to the scope: " + group); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java new file mode 100644 index 0000000..de6af15 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands.user; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class UserSetColorCommand { + + @Command(names = {"user setcolor", "user setcolour"}, permission = "bridge.user", description = "Set a players color", async = true, hidden = true) + public static void UserSetColorCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "color") String col) { + String tag = ChatColor.translateAlternateColorCodes('&', col); + if (col.equals("clear")) tag = ""; + pf.setColor(tag); + pf.saveProfile(); + s.sendMessage("§aSuccessfully " + (tag.equals("") ? "cleared" : "set") + " the color of " + pf.getUsername() + (!tag.equals("") ? " to " + tag + pf.getUsername() : "")); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java new file mode 100644 index 0000000..ff2583e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands.user; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class UserSetPrefixCommand { + + @Command(names = {"user setprefix"}, permission = "bridge.user", description = "Set a players prefix", async = true, hidden = true) + public static void UserSetPrefixCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "prefix", wildcard = true) String prefix) { + String tag = ChatColor.translateAlternateColorCodes('&', prefix); + if (prefix.equals("clear")) tag = ""; + pf.setPrefix(tag); + pf.saveProfile(); + s.sendMessage("§aSuccessfully " + (tag.equals("") ? "cleared" : "set") + " the prefix of " + pf.getUsername() + (!tag.equals("") ? " to " + tag : "")); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java new file mode 100644 index 0000000..8502588 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.bukkit.commands.user; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.CommandSender; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.Command; +import rip.bridge.qlib.command.Param; + +public class UserSetSuffixCommand { + + @Command(names = {"user setsuffix"}, permission = "bridge.user", description = "Set a players suffix", async = true, hidden = true) + public static void UserSetSuffixCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "suffix", wildcard = true) String suffix) { + String tag = ChatColor.translateAlternateColorCodes('&', suffix); + if (suffix.equals("clear")) tag = ""; + pf.setSuffix(tag); + pf.saveProfile(); + s.sendMessage("§aSuccessfully " + (tag.equals("") ? "cleared" : "set") + " the suffix of " + pf.getUsername() + (!tag.equals("") ? " to " + tag : "")); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java b/src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java new file mode 100644 index 0000000..8a6a894 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java @@ -0,0 +1,244 @@ +package rip.bridge.bridge.bukkit.listener; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterViolationPacket; +import rip.bridge.bridge.bukkit.util.Chat; +import rip.bridge.bridge.global.handlers.MongoHandler; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.bridge.global.filter.FilterAction; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.updater.UpdateStatus; +import rip.bridge.bridge.global.util.EncryptionHandler; +import rip.bridge.bridge.global.util.Msg; +import rip.bridge.bridge.global.util.Tasks; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.bukkit.commands.punishment.create.MuteCommand; +import rip.bridge.qlib.chat.ChatHandler; +import rip.bridge.qlib.chat.ChatPlayer; +import rip.bridge.qlib.chat.ChatPopulator; +import rip.bridge.qlib.nametag.FrozenNametagHandler; +import rip.bridge.qlib.tab.FrozenTabHandler; +import rip.bridge.qlib.xpacket.FrozenXPacketHandler; +import mkremins.fanciful.FancyMessage; +import net.md_5.bungee.api.ChatColor; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.io.File; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; + +public class BridgeListener implements Listener { + + @EventHandler(priority = EventPriority.LOWEST) + public void onAsyncPlayerPreLoginLOWEST(AsyncPlayerPreLoginEvent event) { + Player player = Bukkit.getPlayer(event.getName()); + + if (player != null) { + BridgeGlobal.getDisguiseManager().undisguise(player, true, true); + //event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, ChatColor.RED + "Someone is already online with your name."); + Tasks.run(() -> player.kickPlayer(ChatColor.RED + "You were kicked because the owner of this disguised name has joined.")); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onLogin(AsyncPlayerPreLoginEvent e) { + UUID uuid = e.getUniqueId(); + String loggedInIP = EncryptionHandler.encryptUsingKey(e.getAddress().getHostAddress()); + AtomicReference atomicReference = new AtomicReference<>(); + + BridgeGlobal.getMongoHandler().loadProfile(uuid.toString(), atomicReference::set, false, MongoHandler.LoadType.UUID); + + Profile profile = atomicReference.get(); + if (profile == null) + (profile = new Profile(e.getName(), uuid, false)).applyGrant(Grant.getDefaultGrant(), null, false); + + if (loggedInIP != null) { + profile.checkTotpLock(profile.getUuid(), loggedInIP); + + if (profile.getCurrentIPAddress() == null) profile.setCurrentIPAddress(loggedInIP); + + if (profile.getActivePunishments(PunishmentType.BAN).size() > 0) { + Punishment punishment = (Punishment) profile.getActivePunishments(PunishmentType.BAN).toArray()[0]; + e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, GeneralListener.getPunishmentMessage(punishment, punishment.isIP() ? loggedInIP : "")); + saveLatestIP(profile, loggedInIP); + return; + } + + if (profile.getActivePunishments(PunishmentType.BLACKLIST).size() > 0) { + Punishment punishment = (Punishment) profile.getActivePunishments(PunishmentType.BLACKLIST).toArray()[0]; + e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, GeneralListener.getPunishmentMessage(punishment, punishment.isIP() ? loggedInIP : "")); + saveLatestIP(profile, loggedInIP); + return; + } + + if (!profile.getCurrentIPAddress().equals(loggedInIP)) { + List altProfiles = BridgeGlobal.getMongoHandler().getProfiles(loggedInIP); + + for (Profile alt : altProfiles) { + if (alt.getActivePunishments(PunishmentType.BAN).size() > 0 || alt.getActivePunishments(PunishmentType.BLACKLIST).size() > 0) { + Punishment punishment = (Punishment) profile.getActivePunishments(PunishmentType.BAN).toArray()[0]; + if (punishment == null) + punishment = (Punishment) profile.getActivePunishments(PunishmentType.BLACKLIST).toArray()[0]; + + e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, GeneralListener.getPunishmentMessage(punishment, punishment.isIP() ? loggedInIP : "")); + return; + } + } + } + } + + BridgeGlobal.getProfileHandler().addProfile(profile); + profile.setCurrentIPAddress(loggedInIP); + profile.getPreviousIPAddresses().add(loggedInIP); + } + + private void saveLatestIP(Profile profile, String loggedInIP) { + profile.setCurrentIPAddress(loggedInIP); + profile.getPreviousIPAddresses().add(loggedInIP); + profile.saveProfile(); + } + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + Player p = e.getPlayer(); + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(e.getPlayer().getUniqueId()); + + if (profile != null) { + profile.refreshCurrentGrant(); + FrozenNametagHandler.reloadPlayer(p); + } + + Bukkit.getScheduler().runTaskAsynchronously(Bridge.getInstance(), () -> { + + if (profile != null) { + if (profile.getFirstJoined() == 0) profile.setFirstJoined(System.currentTimeMillis()); + profile.setLastJoined(System.currentTimeMillis()); + profile.setUsername(p.getName()); + profile.saveProfile(); + + BridgeGlobal.getDisguiseManager().load(profile.getUsername(), profile.getUuid()); + + Runnable runnable = () -> { + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(profile.getUuid()); + + if (disguisePlayer != null) { + if (p.hasPermission("bridge.disguise")) { + try { + if (BridgeGlobal.getDisguiseManager().disguise(p, disguisePlayer, null, true, true, false)) { + p.sendMessage(org.bukkit.ChatColor.GREEN + ""); + } + } catch (Exception ex) { + ex.printStackTrace(); + Msg.logConsole(ChatColor.RED + "Failed to disguise " + p.getName() + "!"); + } + } else { + p.sendMessage(ChatColor.RED + "Since you don't have disguise permission your disguised profile has been removed."); + BridgeGlobal.getDisguiseManager().save(p.getUniqueId(), false); + } + } + }; + + if (FrozenTabHandler.getLayoutProvider() != null) { + Tasks.runAsyncLater(runnable, 10L); + } else { + runnable.run(); + } + + List altProfiles = BridgeGlobal.getMongoHandler().getProfiles(profile.getCurrentIPAddress()); + List formattedName = new ArrayList<>(); + if (!altProfiles.isEmpty() && altProfiles.size() > 1) { + for (Profile alt : altProfiles) { + if (alt.getUuid().equals(profile.getUuid())) return; + if (Bukkit.getOfflinePlayer(alt.getUuid()).isOnline()) + formattedName.add(ChatColor.GREEN + alt.getUsername()); + else if (alt.getActivePunishments(PunishmentType.BLACKLIST).size() > 1) + formattedName.add(ChatColor.DARK_RED + alt.getUsername()); + else if (alt.getActivePunishments(PunishmentType.BAN).size() > 1) + formattedName.add(ChatColor.RED + alt.getUsername()); + else formattedName.add(ChatColor.GRAY + alt.getUsername()); + } + GeneralListener.broadcastMessage("&6&l[Alts] " + BukkitAPI.getColor(profile) + p.getName() + " &eis possibly &cban evading &7(" + (formattedName.size()) + " accounts)" + "\n" + StringUtils.join(formattedName, ChatColor.WHITE + ", "), "bridge.alts.sendmessage"); + } + } +// +// if (p.hasPermission("op") && BridgeGlobal.getUpdaterManager().getFilesForGroup(Objects.requireNonNull(BridgeGlobal.getUpdaterGroups())).stream().anyMatch(file -> BridgeGlobal.getUpdaterManager().getStatus(file).isShouldUpdate())) { +// p.sendMessage(ChatColor.LIGHT_PURPLE.toString() + (int) BridgeGlobal.getUpdaterManager().getFilesForGroup(BridgeGlobal.getUpdaterGroups()).stream().filter(file -> BridgeGlobal.getUpdaterManager().getStatus(file).isShouldUpdate()).count() + ChatColor.YELLOW + " update is available, install with " + ChatColor.LIGHT_PURPLE + "/updater update" + ChatColor.YELLOW + "."); +// List files = BridgeGlobal.getUpdaterManager().getFilesForGroup(BridgeGlobal.getUpdaterGroups()); +// files.forEach(file1 -> { +// UpdateStatus updateStatus = BridgeGlobal.getUpdaterManager().getStatus(file1); +// p.sendMessage(ChatColor.GRAY + "- " + ChatColor.YELLOW + file1.getName() + " " + updateStatus.getPrefix()); +// }); +// } + }); + } + + @EventHandler + public void onChat(AsyncPlayerChatEvent e) { + if (e.getPlayer().hasMetadata("NoSpamCheck")) { + return; + } + Profile profile = BukkitAPI.getProfile(e.getPlayer()); + if (profile == null) { + e.setCancelled(true); + return; + } + + if (profile.isMuted()) { + e.setCancelled(true); + e.getPlayer().sendMessage(ChatColor.RED + "You are currently muted."); + e.getPlayer().sendMessage(ChatColor.RED + (profile.getMute().isPermanent() ? "This mute is permanent." : "Time remaining: " + profile.getMute().getRemainingString())); + return; + } + + Filter filter = BridgeGlobal.getFilterHandler().isViolatingFilter(ChatColor.stripColor(e.getMessage())); + + if (filter != null && !e.getPlayer().hasPermission("basic.staff")) { + if (filter.getFilterAction() == FilterAction.MUTE) + MuteCommand.muteCmd(Bukkit.getConsoleSender(), false, profile, filter.getMuteTime(), " \"" + e.getMessage() + "\""); + FrozenXPacketHandler.sendToAll(new FilterViolationPacket(Bukkit.getServerName(), e.getPlayer().getName(), null, e.getMessage())); + e.setCancelled(true); + + ChatPlayer chatPlayer = ChatHandler.getChatPlayer(e.getPlayer().getUniqueId()); + + ChatPopulator chatPopulator = chatPlayer.getRegisteredPopulators().stream().filter(chatPopulator1 -> chatPopulator1.getChatChar() == e.getMessage().charAt(0)).findFirst().orElse(null); + if (chatPopulator == null) chatPopulator = chatPlayer.getSelectedPopulator(); + + e.getPlayer().sendMessage(chatPopulator.layout(e.getPlayer(), e.getMessage())); + return; + } + + Rank rank = BukkitAPI.getPlayerRank(e.getPlayer()); + e.setMessage(rank.isStaff() ? ChatColor.translateAlternateColorCodes('&', e.getMessage()) : e.getMessage()); + e.setFormat(BukkitAPI.getColor(e.getPlayer()) + BukkitAPI.getPrefix(e.getPlayer()) + e.getPlayer().getName() + BukkitAPI.getSuffix(e.getPlayer()) + "§r: %2$s"); + } + + @EventHandler + public void onQuit(PlayerQuitEvent e) { + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(e.getPlayer().getUniqueId()); + + if (profile != null) { + profile.setLastQuit(System.currentTimeMillis()); + profile.setConnectedServer(BridgeGlobal.getSystemName()); + profile.saveProfile(); + BridgeGlobal.getProfileHandler().getProfiles().remove(profile); + } + + BridgeGlobal.getDisguiseManager().leave(e.getPlayer().getUniqueId()); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java b/src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java new file mode 100644 index 0000000..6dbd025 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java @@ -0,0 +1,129 @@ +package rip.bridge.bridge.bukkit.listener; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.player.*; +import org.bukkit.metadata.MetadataValue; + +public class FreezeListener implements Listener { + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + String command = event.getMessage().toLowerCase(); + boolean whitelistedCommand = command.startsWith("/freezeserver") || command.startsWith("/auth") || command.startsWith("/register") || command.startsWith("/2fasetup") || command.startsWith("/setup2fa"); + if (!whitelistedCommand && event.getPlayer().hasMetadata("Locked")) { + event.getPlayer().sendMessage((event.getPlayer().getMetadata("Locked").get(0)).asString()); + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onAsyncPlayerChat(AsyncPlayerChatEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.getPlayer().sendMessage((event.getPlayer().getMetadata("Locked").get(0)).asString()); + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onPlayerDropItem(PlayerDropItemEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onInventoryOpen(InventoryOpenEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onBlockBreak(BlockBreakEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onBlockPlace(BlockPlaceEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onEntityDamage(EntityDamageByEntityEvent event) { + if (event.getDamager() instanceof Player && event.getDamager().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onPlayerBucketFill(PlayerBucketFillEvent event) { + if (event.getPlayer().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + + @EventHandler( + priority = EventPriority.HIGHEST + ) + public void onInventoryClick(InventoryClickEvent event) { + if (event.getWhoClicked().hasMetadata("Locked")) { + event.setCancelled(true); + } + + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java b/src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java new file mode 100644 index 0000000..a7c3986 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java @@ -0,0 +1,284 @@ +package rip.bridge.bridge.bukkit.listener; + +import org.bukkit.scheduler.BukkitRunnable; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.bukkit.util.BaseEvent; +import rip.bridge.bridge.bukkit.util.Chat; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.bridge.global.ranks.Rank; +import mkremins.fanciful.FancyMessage; +import rip.bridge.bridge.bukkit.BukkitAPI; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.permissions.PermissionAttachment; +import org.spigotmc.SpigotConfig; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.qlib.util.PlayerUtils; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class GeneralListener { + + + public static void updatePermissions(UUID uuid) { + Player player = Bukkit.getPlayer(uuid); + + if (player != null) { + + Profile profile = BukkitAPI.getProfile(uuid); + profile.updateColor(); + PermissionAttachment permissionAttachment = player.addAttachment(Bridge.getInstance()); + List perms = profile.getPermissions().keySet().stream().filter(profile::hasPermission).collect(Collectors.toList()); + profile.getPermissions().keySet().stream().filter(profile::hasPermission).forEach(permission->{ + + if (permission.startsWith("-")) { + permission = permission.substring(1); + permissionAttachment.unsetPermission(permission); + } else { + permissionAttachment.setPermission(permission, true); + } + + }); + + profile.getActiveGrants().forEach(grant->{ + perms.addAll(grant.getRank().getPermissions().keySet().stream().filter(s -> grant.getRank().hasPermission(s)).collect(Collectors.toList())); + grant.getRank().getPermissions().keySet().stream().filter(s -> grant.getRank().hasPermission(s)).forEach(permission->{ + if (permission.startsWith("-")) { + permission = permission.substring(1); + permissionAttachment.unsetPermission(permission); + } else { + permissionAttachment.setPermission(permission, true); + } + }); + grant.getRank().getInherits().forEach(inherit->{ + perms.addAll(inherit.getPermissions().keySet().stream().filter(inherit::hasPermission).collect(Collectors.toList())); + inherit.getPermissions().keySet().stream().filter(inherit::hasPermission).forEach(permission -> { + if (permission.startsWith("-")) { + permission = permission.substring(1); + permissionAttachment.unsetPermission(permission); + } else { + permissionAttachment.setPermission(permission, true); + } + }); + }); + }); + player.recalculatePermissions(); + profile.setActivePermissions(perms); + + String totpMessage = null; + + if (profile.isTotpRequired() && !player.hasMetadata("ForceAuth")) { + if (profile.getSecretKey().isEmpty() && profile.getCurrentGrant().getRank().isStaff()) { + totpMessage = ChatColor.RED + ChatColor.BOLD.toString() + "Please setup your 2FA code"; + } else { + totpMessage = ChatColor.RED + ChatColor.BOLD.toString() + "Please enter your 2FA code"; + } + + player.setMetadata("Locked", new FixedMetadataValue(Bridge.getInstance(), totpMessage)); + } else { + player.removeMetadata("Locked", Bridge.getInstance()); + } + + String finalTotpMessage = totpMessage; + (new BukkitRunnable() { + public void run() { + if (finalTotpMessage != null) { + player.sendMessage(finalTotpMessage); + } + + } + }).runTaskLater(Bridge.getInstance(), 10L); + + } + } + + public static void updateColor(UUID uuid) { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + player.setDisplayName(BukkitAPI.getPlayerRank(player).getColor() + player.getName() + "§r"); + if(player.hasMetadata("RankPrefix")) player.removeMetadata("RankPrefix", Bridge.getInstance()); + player.setMetadata("RankPrefix", new FixedMetadataValue(Bridge.getInstance(), (BukkitAPI.getPlayerRank(player).getPrefix()))); + } + } + + public static String getServerStatus() { + return (Bridge.getInstance().isBooted() ? (Bukkit.hasWhitelist() ? "WHITELISTED" : "ONLINE") : "BOOTING"); + } + + public static void refreshPlayersInRank(Rank rank) { + BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile-> Bukkit.getPlayer(profile.getUuid()) != null && profile.hasActiveGrantOf(rank)).forEach(Profile::refreshCurrentGrant); + } + + public static void logMessages(String msg, boolean packetIncoming) { + if(packetIncoming) Bukkit.getOnlinePlayers().stream().filter(Player::isOp).forEach(player -> player.sendMessage(msg)); + Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', msg)); + if(BridgeGlobal.getProfileHandler() != null && !BridgeGlobal.getProfileHandler().getProfiles().isEmpty()) BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile -> Bukkit.getPlayer(profile.getUuid()) != null && profile.isDebug()).forEach(profile -> Bukkit.getPlayer(profile.getUuid()).sendMessage(msg)); + } + + public static void broadcastMessage(String msg, String permission) { + String m = ChatColor.translateAlternateColorCodes('&', msg); + Bukkit.getConsoleSender().sendMessage(m); + if(permission.equals("")) Bukkit.broadcastMessage(m); + else Bukkit.getOnlinePlayers().stream().filter(p -> p.hasPermission(permission)).forEach(p -> p.sendMessage(m)); + } + + public static void broadcastMessage(String msg) { + broadcastMessage(msg, ""); + } + + public static void broadcastMessage(BaseComponent[] msg, String permission) { + Bukkit.getConsoleSender().sendMessage(TextComponent.toPlainText(msg)); + if(permission.equals("")) { + Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(msg)); + }else { + Bukkit.getOnlinePlayers().stream().filter(p -> p.hasPermission(permission)).forEach(p -> p.spigot().sendMessage(msg)); + } + } + + public static void sendMessage(String msg, List players) { + players.forEach(p -> p.sendMessage(ChatColor.translateAlternateColorCodes('&', msg))); + } + + public static void sendMessage(BaseComponent[] msg, List players) { + players.forEach(p -> p.spigot().sendMessage(msg)); + } + + public static void broadcastMessage(BaseComponent[] msg) { + broadcastMessage(msg, ""); + } + + public static void callEvent(Object cls) { + ((BaseEvent)cls).call(); + } + + public static void shutdown() { + Bukkit.shutdown(); + } + + public static boolean hasPermission(Profile profile, String permisson) { + return Bukkit.getOfflinePlayer(profile.getUuid()).isOp() || profile.getActiveGrants().parallelStream().filter(grant -> grant.isGrantActiveOnScope() && grant.isStillActive()).anyMatch(grant -> grant.getRank().hasPermission(permisson) || profile.hasPermission(permisson) || profile.getActivePermissions().contains(permisson)); + } + + public static boolean isOP(Profile profile) { + if(profile == null || Bukkit.getOfflinePlayer(profile.getUuid()) == null) return false; + return Bukkit.getOfflinePlayer(profile.getUuid()).isOp(); + } + + private boolean isRunningOnBungee(){ + return SpigotConfig.bungee && (!(Bukkit.getServer().getOnlineMode())); + } + + public static void handlePunishment(Punishment punishment, boolean pardon) { + Bukkit.getOnlinePlayers().forEach(p -> { + FancyMessage m = new FancyMessage((punishment.isSilent() ? ChatColor.GRAY + "[Silent] " + ChatColor.GREEN : "") + + BukkitAPI.getColor(punishment.getTarget()) + (punishment.getTarget().getDisguise() != null ? punishment.getTarget().getDisguise().getDisguiseName() : punishment.getTarget().getUsername()) + + ChatColor.GREEN + " was " + punishment.getDisplayName() + + " by " + + (pardon ? BukkitAPI.getColor(punishment.getPardonedBy()) + (punishment.getPardonedBy().getDisguise() != null ? punishment.getPardonedBy().getDisguise().getDisguiseName() : punishment.getPardonedBy().getUsername()) + ChatColor.GREEN + "." : BukkitAPI.getColor(punishment.getExecutor()) + (punishment.getExecutor().getDisguise() != null ? punishment.getExecutor().getDisguise().getDisguiseName() : punishment.getExecutor().getUsername()) + + ChatColor.GREEN + ".")); + m.command("/c " + punishment.getTarget().getUsername()); + + List lore = new ArrayList<>(); + lore.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + (pardon ? punishment.getPardonedReason() : punishment.getReason())); + if(!pardon && !punishment.getPunishmentType().equals(PunishmentType.KICK)) lore.add(ChatColor.YELLOW + "Duration: " + ChatColor.RED + punishment.getRemainingString()); + lore.add(ChatColor.YELLOW + "Click to view on website"); + + + boolean staff = BukkitAPI.getPlayerRank(p, true).isStaff(); + if(staff) m.tooltip(lore); + if(punishment.isSilent()) { + if(staff) m.send(p); + }else { + m.send(p); + } + }); + + if(pardon) { + Punishment p = punishment.getTarget().getPunishmentByID(punishment.getUuid()); + p.setPardoned(pardon); + p.setPardonedAt(punishment.getPardonedAt()); + p.setPardonedBy(punishment.getPardonedBy().getUuid()); + p.setPardonedReason(punishment.getPardonedReason()); + p.setPardonedServer(punishment.getPardonedServer()); + }else { + + if(punishment.isIP()) { + Bukkit.getOnlinePlayers().stream().filter(p -> BukkitAPI.getProfile(p) != null && BukkitAPI.getProfile(p).getCurrentIPAddress().equals(punishment.getTarget().getCurrentIPAddress())).forEach(target -> { + if(target != null) Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> { + BukkitAPI.getProfile(target).getPunishments().add(punishment); + if(punishment.isClear()) PlayerUtils.resetInventory(target); + if(punishment.getPunishmentType() != PunishmentType.WARN && punishment.getPunishmentType() != PunishmentType.MUTE) { + target.kickPlayer(getPunishmentMessage(punishment)); + }else if(punishment.getPunishmentType() == PunishmentType.WARN){ + target.sendMessage(""); + target.sendMessage(""); + target.sendMessage(ChatColor.RED.toString() + ChatColor.BOLD.toString() + "You have been warned: " + ChatColor.YELLOW.toString() + ChatColor.BOLD + punishment.getReason()); + target.sendMessage(""); + target.sendMessage(""); + }else if(punishment.getPunishmentType() == PunishmentType.MUTE) { + target.sendMessage(ChatColor.RED + "You have been muted."); + target.sendMessage(ChatColor.RED + (punishment.isPermanent() ? "This mute is permanent." : "Time remaining: " + TimeUtils.formatIntoDetailedString((int) (punishment.getDuration() / 1000)))); + } + }); + if(punishment.isClear()) PlayerUtils.resetInventory(target); + if(punishment.getPunishmentType() != PunishmentType.WARN && punishment.getPunishmentType() != PunishmentType.MUTE) target.kickPlayer(getPunishmentMessage(punishment)); + }); + }else { + Player target = Bukkit.getPlayer(punishment.getTarget().getUuid()); + if(target != null) Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> { + if(punishment.isClear()) PlayerUtils.resetInventory(target); + if(punishment.getPunishmentType() != PunishmentType.WARN && punishment.getPunishmentType() != PunishmentType.MUTE) { + target.kickPlayer(getPunishmentMessage(punishment)); + }else if(punishment.getPunishmentType() == PunishmentType.WARN){ + target.sendMessage(""); + target.sendMessage(""); + target.sendMessage(ChatColor.RED + ChatColor.BOLD.toString() + "You have been warned: " + ChatColor.YELLOW + ChatColor.BOLD + punishment.getReason()); + target.sendMessage(""); + target.sendMessage(""); + }else if(punishment.getPunishmentType() == PunishmentType.MUTE) { + target.sendMessage(ChatColor.RED + "You have been muted."); + target.sendMessage(ChatColor.RED + (punishment.isPermanent() ? "This mute is permanent." : "Time remaining: " + TimeUtils.formatIntoDetailedString((int) (punishment.getDuration() / 1000)))); + } + }); + } + } + } + + public static String getPunishmentMessage(Punishment punishment, String IP) { + String msg = ""; + switch(punishment.getPunishmentType()) { + case BLACKLIST: { + msg = ChatColor.RED + "Your account has been blacklisted from the " + BridgeGlobal.getServerDisplayName() + "\n\nThis type of punishment cannot be appealed."; + break; + } + case BAN: { + msg = ChatColor.RED + "Your account has been suspended from the " + BridgeGlobal.getServerDisplayName() + (!punishment.isPermanent() ? "\n\nExpires in " + punishment.getRemainingString() + "." : ChatColor.RED + "\n\nAppeal at " + BridgeGlobal.getServerWebsite() + "/appeal"); + break; + } + case KICK: { + msg = ChatColor.RED + "You were kicked: " + punishment.getReason(); + } + } + return msg + (punishment.getPunishmentType() != PunishmentType.BLACKLIST && punishment.isIP() && !IP.equals("") && punishment.getTarget().getCurrentIPAddress().equals(IP) ? "\n\n" + ChatColor.RED + "This punishment is assiciated with " + punishment.getTarget().getUsername() : ""); + } + + public static String getPunishmentMessage(Punishment punishment) { + return getPunishmentMessage(punishment, ""); + } + + + + + + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java new file mode 100644 index 0000000..019f302 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.parameters; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import rip.bridge.qlib.xpacket.XPacket; + + +public class AlertPacket implements XPacket { + + private String message; + private boolean raw; + + public AlertPacket(String message, boolean raw) { + this.message = message; + this.raw = raw; + } + + + @Override + public void onReceive() { + Bukkit.broadcastMessage((raw ? "" : ChatColor.DARK_GRAY + "[" + ChatColor.DARK_RED + "Alert" + ChatColor.DARK_GRAY + "] " + ChatColor.WHITE) + ChatColor.translateAlternateColorCodes('&', message)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java new file mode 100644 index 0000000..56b987b --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.bukkit.parameters; + +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import rip.bridge.qlib.xpacket.XPacket; + + +public class AnnouncePacket implements XPacket { + + private String message; + + public AnnouncePacket(String message) { + this.message = message; + } + + + @Override + public void onReceive() { + Bukkit.broadcastMessage(ChatColor.GRAY + "[" + ChatColor.GREEN + "Alert" + ChatColor.GRAY + "] " + ChatColor.WHITE + ChatColor.translateAlternateColorCodes('&', message)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java new file mode 100644 index 0000000..131e35c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java @@ -0,0 +1,39 @@ +package rip.bridge.bridge.bukkit.parameters; + +import mkremins.fanciful.FancyMessage; +import net.minecraft.util.org.apache.commons.lang3.text.WordUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import rip.bridge.qlib.xpacket.XPacket; + + +public class AnnouncePackets implements XPacket { + + private String message = ""; + private String server; + + + + public AnnouncePackets(String message, String server) { + this.message = message; + this.server = server; + } + + + @Override + public void onReceive() { + FancyMessage fancyMessage = new FancyMessage(ChatColor.GRAY + "[" + ChatColor.GREEN + "Alert" + ChatColor.GRAY + "] " + ChatColor.WHITE + ChatColor.translateAlternateColorCodes('&', message)); + if (this.server.contains("Bunkers")) { + fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the Bunkers Lobby"); + } else if (this.server.contains("MineSG")) { + fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the MineSG Lobby"); + } else if (this.server.contains("UHC-Meetup")) { + fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the UHC Meetup Lobby"); + } else if (this.server.contains("Vault-Battles")) { + fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the Vault Battles Lobby"); + } + fancyMessage.command("/joinfastserver " + server); + Bukkit.getOnlinePlayers().forEach(fancyMessage::send); + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java new file mode 100644 index 0000000..4cc3ebe --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java @@ -0,0 +1,18 @@ +package rip.bridge.bridge.bukkit.parameters; + +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.qlib.nametag.NametagInfo; +import rip.bridge.qlib.nametag.NametagProvider; +import org.bukkit.entity.Player; + +public class BridgeNameTagProvider extends NametagProvider { + + public BridgeNameTagProvider() { + super("Bridge Provider", 1); + } + + @Override + public NametagInfo fetchNametag(Player player, Player viewer) { + return createNametag(BukkitAPI.getColor(player), ""); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java new file mode 100644 index 0000000..01fc9ac --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java @@ -0,0 +1,29 @@ +package rip.bridge.bridge.bukkit.parameters; + +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.qlib.uuid.UUIDCache; + +import java.util.UUID; + +public class BridgeUUIDCache implements UUIDCache { + + @Override + public UUID uuid(String var1) { + return BukkitAPI.getProfile(var1).getUuid(); + } + + @Override + public String name(UUID var1) { + return BukkitAPI.getName(BukkitAPI.getProfile(var1), false); + } + + @Override + public void ensure(UUID var1) { + + } + + @Override + public void update(UUID var1, String var2) { + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java new file mode 100644 index 0000000..340e00b --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java @@ -0,0 +1,65 @@ +package rip.bridge.bridge.bukkit.parameters; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.listener.GeneralListener; +import rip.bridge.bridge.global.util.JsonChain; +import net.minecraft.server.v1_7_R4.MinecraftServer; +import org.bukkit.Bukkit; +import rip.bridge.bridge.global.status.StatusProvider; +import rip.bridge.qlib.uuid.FrozenUUIDCache; + +import java.util.List; +import java.util.stream.Collectors; + +public class BukkitStatusImplementer extends StatusProvider { + + public BukkitStatusImplementer() { + super("Bridge Bukkit Implementer", 1); + } + + @Override + public String serverName() { + return BridgeGlobal.getServerName(); + } + + @Override + public String serverStatus() { + return GeneralListener.getServerStatus(); + } + + @Override + public int online() { + return Bukkit.getOnlinePlayers().size(); + } + + @Override + public int maximum() { + return Bukkit.getMaxPlayers(); + } + + @Override + public String motd() { + return Bukkit.getMotd(); + } + + @Override + public double tps() { + return MinecraftServer.getServer().recentTps[0]; + } + + @Override + public List players() { + return Bukkit.getOnlinePlayers().stream().map(player -> player.getUniqueId().toString()).collect(Collectors.toList()); + } + + @Override + public JsonObject dataPassthrough() { + JsonChain jsonChain = new JsonChain(); + if(BridgeGlobal.getUpdaterManager().getRunningDirectory().contains("/temp/")) + jsonChain.addProperty("tempServer", true).addProperty("runningDirectory", BridgeGlobal.getUpdaterManager().getRunningDirectory()).get(); + jsonChain.addProperty("port", Bukkit.getPort()).addProperty("vanished", new Gson().toJson(Bukkit.getOnlinePlayers().stream().filter(player -> player.hasMetadata("invisible")).map(player -> FrozenUUIDCache.name(player.getUniqueId())).collect(Collectors.toList()))); + return jsonChain.get(); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java new file mode 100644 index 0000000..a4c8e1d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java @@ -0,0 +1,44 @@ +package rip.bridge.bridge.bukkit.parameters; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.DisguiseProfile; +import rip.bridge.qlib.command.ParameterType; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class DisguiseParameter implements ParameterType { + + public static boolean isUUID(String str) { + try { + UUID uuid = UUID.fromString(str); + return true; + } catch (Exception e) { + return false; + } + } + + + @Override + public DisguiseProfile transform(CommandSender sender, String source) { + DisguiseProfile disguiseProfile; + if (isUUID(source)) { + disguiseProfile = BridgeGlobal.getDisguiseManager().getDisguiseProfiles().get(UUID.fromString(source)); + } else { + disguiseProfile = BridgeGlobal.getDisguiseManager().getProfile(source); + } + if (disguiseProfile == null) { + sender.sendMessage("§cThere is no such disguise profile with the " + (isUUID(source) ? "uuid" : "name") + " \"" + source + "\"."); + return null; + } + return disguiseProfile; + } + + @Override + public List tabComplete(Player player, Set set, String s) { + return null; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java new file mode 100644 index 0000000..14f49a9 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java @@ -0,0 +1,16 @@ +package rip.bridge.bridge.bukkit.parameters; + +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import rip.bridge.qlib.xpacket.XPacket; + +@AllArgsConstructor +public class ExecuteCommandPacket implements XPacket { + + public String command; + + @Override + public void onReceive() { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java new file mode 100644 index 0000000..26a9f48 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java @@ -0,0 +1,27 @@ +package rip.bridge.bridge.bukkit.parameters; + +import rip.bridge.bridge.BridgeGlobal; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import rip.bridge.qlib.xpacket.XPacket; + +import java.util.UUID; + +@AllArgsConstructor +public class FoxtrotRevivePacket implements XPacket { + + private String server; + private UUID player; + private int lives; + + @Override + public void onReceive() { + if(BridgeGlobal.getServerName().equalsIgnoreCase(server)) { + if(Bukkit.getPluginManager().getPlugin("HCTeams") != null && Bukkit.getPluginManager().getPlugin("HCF").isEnabled()) { +// Foxtrot.getInstance().getSoulboundLivesMap().setLives(player, lives); +// Foxtrot.getInstance().getDeathbanMap().revive(player); +// System.out.println("[HCTeams] " + UUIDUtils.name(player) + " has used a life and revived themselves through Hub. (Lives: " + lives + ")"); + } + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java new file mode 100644 index 0000000..69a7826 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java @@ -0,0 +1,30 @@ +package rip.bridge.bridge.bukkit.parameters; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import rip.bridge.qlib.command.ParameterType; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class PluginParameter implements ParameterType { + + @Override + public Plugin transform(CommandSender commandSender, String s) { + Plugin plugin = Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(pluginOne -> pluginOne.getName().equalsIgnoreCase(s)).findAny().orElse(null); + + if(plugin == null) commandSender.sendMessage(ChatColor.RED + "There is no such plugin by the name \"" + s + "\"."); + return plugin; + } + + @Override + public List tabComplete(Player player, Set flags, String source) { + return Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(plugin -> StringUtils.startsWithIgnoreCase(plugin.getName(), source)).map(Plugin::getName).collect(Collectors.toList()); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java new file mode 100644 index 0000000..5637f43 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java @@ -0,0 +1,84 @@ +package rip.bridge.bridge.bukkit.parameters; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.util.MojangUtils; +import org.apache.commons.lang.StringUtils; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.qlib.command.ParameterType; +import rip.bridge.qlib.qLib; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class ProfileParamater implements ParameterType { + + public static boolean isUUID(String str) { + try { + UUID uuid = UUID.fromString(str); + return true; + }catch (Exception e) { + return false; + } + } + + @Override + public Profile transform(CommandSender sender, String source) { + + String fixedSource = source.replace("get/", ""); + + Profile pf; + + if(fixedSource.equals("self")) { + pf = BukkitAPI.getProfile(sender); + } + else if(isUUID(fixedSource)) { + pf = BukkitAPI.getProfile(UUID.fromString(fixedSource)); + }else { + + pf = BukkitAPI.getProfile(fixedSource); + + if(!source.startsWith("get/")) { + + if(pf == null) { + UUID playerUUID = null; + try { + playerUUID = MojangUtils.fetchUUID(fixedSource); + if(playerUUID != null) { + pf = BridgeGlobal.getProfileHandler().getNewProfileOrCreate(fixedSource, playerUUID); + }else { + pf = null; + } + } catch (Exception e) { + pf = null; + e.printStackTrace(); + } + } + } + + + + } + if(pf == null) { + sender.sendMessage("§cNo such player with the " + (isUUID(fixedSource) ? "uuid" : "name") + " \"" + fixedSource + "\"."); + return null; + } + return pf; + } + + @Override + public List tabComplete(Player sender, Set flags, String source) { + List completions = new ArrayList<>(); + + for (Player player : qLib.getInstance().getServer().getOnlinePlayers()) { + if (StringUtils.startsWithIgnoreCase(player.getName(), source) && sender.canSee(player) && BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()) != null) { + completions.add(player.getName()); + } + } + return completions; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java new file mode 100644 index 0000000..05b8f48 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java @@ -0,0 +1,47 @@ +package rip.bridge.bridge.bukkit.parameters; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.qlib.command.ParameterType; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class RankParamater implements ParameterType { + + public static boolean isUUID(String str) { + try { + UUID uuid = UUID.fromString(str); + return true; + }catch (Exception e) { + return false; + } + } + + + @Override + public Rank transform(CommandSender sender, String source) { + Rank rank; + if(isUUID(source)) { + rank = BridgeGlobal.getRankHandler().getRankByID(UUID.fromString(source)); + }else { + rank = BridgeGlobal.getRankHandler().getRankByName(source); + } + if(rank == null) { + sender.sendMessage("§cThere is no such rank with the " + (isUUID(source) ? "uuid" : "name") + " \"" + source + "\"."); + return null; + } + return rank; + } + + @Override + public List tabComplete(Player sender, Set flags, String source) { + List ranks = new ArrayList<>(); + BridgeGlobal.getRankHandler().getRanks().forEach(rank -> ranks.add(rank.getName())); + return ranks; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java new file mode 100644 index 0000000..678be8e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java @@ -0,0 +1,38 @@ +package rip.bridge.bridge.bukkit.parameters; + +import org.bukkit.Bukkit; +import rip.bridge.qlib.xpacket.XPacket; + +import java.util.UUID; + + +public class WhitelistPacket implements XPacket { + + private String server; + private boolean whitelist; + private UUID uuid; + + public WhitelistPacket(String server, boolean whitelist) { + this.server = server; + this.whitelist = whitelist; + } + + public WhitelistPacket(String server, UUID uuid) { + this.server = server; + this.uuid = uuid; + } + + @Override + public void onReceive() { + if(uuid == null) { + if(Bukkit.getServerName().equalsIgnoreCase(server)) { + Bukkit.setWhitelist(whitelist); + } + }else { + if(Bukkit.getServerName().equalsIgnoreCase(server)) { + Bukkit.getOfflinePlayer(uuid).setWhitelisted(true); + } + } + + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java new file mode 100644 index 0000000..bb7b3bd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java @@ -0,0 +1,20 @@ +package rip.bridge.bridge.bukkit.parameters.packets.filter; + +import rip.bridge.bridge.BridgeGlobal; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.qlib.xpacket.XPacket; + +@AllArgsConstructor +public class FilterCreatePacket implements XPacket { + + private Filter filter; + private String sender; + + @Override + public void onReceive() { + if(sender.equalsIgnoreCase(Bukkit.getServerName())) return; + BridgeGlobal.getFilterHandler().addFilter(filter); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java new file mode 100644 index 0000000..e9fe391 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.bukkit.parameters.packets.filter; + +import rip.bridge.bridge.BridgeGlobal; +import org.bukkit.Bukkit; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.qlib.xpacket.XPacket; + +public class FilterDeletePacket implements XPacket { + + private String filter; + private String sender; + + public FilterDeletePacket(Filter filter, String sender) { + this.filter = filter.getPattern(); + this.sender = sender; + } + + @Override + public void onReceive() { + if(sender.equalsIgnoreCase(Bukkit.getServerName())) return; + BridgeGlobal.getFilterHandler().removeFilter(BridgeGlobal.getFilterHandler().getFilter(filter)); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java new file mode 100644 index 0000000..ddd4dfd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java @@ -0,0 +1,32 @@ +package rip.bridge.bridge.bukkit.parameters.packets.filter; + +import mkremins.fanciful.FancyMessage; +import rip.bridge.bridge.bukkit.commands.filter.ToggleFilterCommand; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.bridge.qlib.xpacket.XPacket; + +@AllArgsConstructor +public class FilterViolationPacket implements XPacket { + + private String server, usernameOne, usernameTwo, message; + + @Override + public void onReceive() { + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + if(getType(onlinePlayer) == null || getType(onlinePlayer).equalsIgnoreCase("off")) continue; + if(getType(onlinePlayer).equals("server") && !server.equals(Bukkit.getServerName())) continue; + FancyMessage fancyMessage = new FancyMessage("§e[Filter] ").then((getType(onlinePlayer).equals("global") ? "§7[" + server + "] " : "")).command("/server " + server).tooltip(ChatColor.GREEN + "Click here to teleport to " + server).then("§b" + (usernameTwo == null ? usernameOne : "(" + usernameOne + " to " + usernameTwo + ")") + " §c-> §e" + message); +// onlinePlayer.sendMessage(ChatColor.translateAlternateColorCodes('§', "§e[Filter] " + (getType(onlinePlayer).equals("global") ? "§7[" + server + "] " : "") + "§b" + (usernameTwo == null ? usernameOne : "(" + usernameOne + " to " + usernameTwo + ")") + " §c-> §e" + message)); + fancyMessage.send(onlinePlayer); + } + } + + private String getType(Player player) { + if(!player.hasPermission("basic.staff")) return null; + if(!ToggleFilterCommand.getFilter().containsKey(player.getUniqueId())) return "global"; + return ToggleFilterCommand.getFilter().get(player.getUniqueId()); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java new file mode 100644 index 0000000..1b15362 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java @@ -0,0 +1,38 @@ +package rip.bridge.bridge.bukkit.parameters.param.filter; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.global.filter.FilterAction; +import rip.bridge.qlib.command.ParameterType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class FilterActionParameter implements ParameterType { + + @Override + public FilterAction transform(CommandSender sender, String source) { + FilterAction filterAction = null; + try { + filterAction = FilterAction.valueOf(source); + }catch (Exception e) { + sender.sendMessage(ChatColor.RED + "There is no such filter action by the name of \"" + source + "\"."); + } + return filterAction; + } + + @Override + public List tabComplete(Player sender, Set flags, String source) { + List completions = new ArrayList<>(); + + for (FilterAction filterAction : FilterAction.values()) { + if (StringUtils.startsWithIgnoreCase(filterAction.name(), source)) { + completions.add(filterAction.name()); + } + } + return completions; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java new file mode 100644 index 0000000..0621b51 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java @@ -0,0 +1,35 @@ +package rip.bridge.bridge.bukkit.parameters.param.filter; + +import rip.bridge.bridge.BridgeGlobal; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.qlib.command.ParameterType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class FilterParameter implements ParameterType { + + @Override + public Filter transform(CommandSender sender, String source) { + Filter filter = BridgeGlobal.getFilterHandler().getFilter(source); + if(filter == null) sender.sendMessage(ChatColor.RED + "There is no such filter by the pattern of \"" + source + "\"."); + return filter; + } + + @Override + public List tabComplete(Player sender, Set flags, String source) { + List completions = new ArrayList<>(); + + for (Filter filter : BridgeGlobal.getFilterHandler().getFilters()) { + if (StringUtils.startsWithIgnoreCase(filter.getPattern(), source)) { + completions.add(filter.getPattern()); + } + } + return completions; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java new file mode 100644 index 0000000..88de3b6 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java @@ -0,0 +1,38 @@ +package rip.bridge.bridge.bukkit.parameters.param.filter; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.bridge.bridge.global.filter.FilterType; +import rip.bridge.qlib.command.ParameterType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class FilterTypeParameter implements ParameterType { + + @Override + public FilterType transform(CommandSender sender, String source) { + FilterType filterType = null; + try { + filterType = FilterType.valueOf(source); + }catch (Exception e) { + sender.sendMessage(ChatColor.RED + "There is no such filter type by the name of \"" + source + "\"."); + } + return filterType; + } + + @Override + public List tabComplete(Player sender, Set flags, String source) { + List completions = new ArrayList<>(); + + for (FilterType filterType : FilterType.values()) { + if (StringUtils.startsWithIgnoreCase(filterType.name(), source)) { + completions.add(filterType.name()); + } + } + return completions; + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java b/src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java new file mode 100644 index 0000000..1bb8824 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java @@ -0,0 +1,26 @@ +package rip.bridge.bridge.bukkit.util; + +import org.bukkit.Bukkit; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BaseEvent extends Event +{ + private static final HandlerList handlers; + + public HandlerList getHandlers() { + return BaseEvent.handlers; + } + + public static HandlerList getHandlerList() { + return BaseEvent.handlers; + } + + public void call() { + Bukkit.getServer().getPluginManager().callEvent(this); + } + + static { + handlers = new HandlerList(); + } +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java b/src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java new file mode 100644 index 0000000..79cfdc4 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java @@ -0,0 +1,92 @@ +package rip.bridge.bridge.bukkit.util; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bukkit.Bridge; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.event.Listener; + +public class BukkitUtils { + + public static void registerListeners(Class... listeners) { + for (Class listener : listeners) { + if (Listener.class.isAssignableFrom(listener)) { + try { + Bukkit.getServer().getPluginManager().registerEvents(((Listener) listener.newInstance()), Bridge.getInstance()); + BridgeGlobal.sendLog("Successfully registered listener " + listener.getSimpleName() + "!"); + } catch (Exception ex) { + BridgeGlobal.sendLog("Failed to registered listener " + listener.getSimpleName() + ". (" + ex.getClass().getSimpleName() + ": " + ex.getMessage() + ")"); + } + } else { + BridgeGlobal.sendLog("The class: " + listener.getSimpleName() + " does not parameters Listener!"); + } + } + } + + public static Material materialFix(String name) { + Material materialFromDB; + try { + materialFromDB = (Material) Enum.valueOf((Class) Material.class, name); + } catch (IllegalArgumentException ignore) { + materialFromDB = (Material) Enum.valueOf((Class) Material.class, "LEGACY_" + name); + } + return materialFromDB; + + } + + public static int stringToWoolColor(String r) { + String fixed = r.replaceAll("§l", "").replaceAll("§r", "").replaceAll("§k", "").replaceAll("§n", "").replaceAll("§m", "").replaceAll("§o", ""); + switch (fixed) { + case "§1": + return 11; + case "§2": + return 13; + + case "§3": + return 9; + + case "§4": + return 14; + + case "§5": + return 10; + + case "§6": + return 1; + + case "§7": + return 8; + + case "§8": + return 7; + + case "§9": + return 11; + + case "§0": + return 15; + + case "§a": + return 5; + + case "§b": + + return 3; + case "§c": + return 14; + + case "§d": + return 6; + + case "§e": + + return 4; + case "§f": + return 0; + + default: + return 0; + } + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/Chat.java b/src/main/java/rip/bridge/bridge/bukkit/util/Chat.java new file mode 100644 index 0000000..4967dde --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/Chat.java @@ -0,0 +1,43 @@ +package rip.bridge.bridge.bukkit.util; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; + +public class Chat { + + public static String LINE = "--------------------------------"; + public static ChatColor ITALIC = ChatColor.ITALIC; + public static ChatColor BOLD = ChatColor.BOLD; + public static ChatColor LIGHT_GREEN = ChatColor.GREEN; + public static ChatColor LIGHT_BLUE = ChatColor.AQUA; + public static ChatColor LIGHT_RED = ChatColor.RED; + public static ChatColor PINK = ChatColor.LIGHT_PURPLE; + public static ChatColor YELLOW = ChatColor.YELLOW; + public static ChatColor WHITE = ChatColor.WHITE; + public static ChatColor RESET = ChatColor.RESET; + public static ChatColor OBFUSCATION = ChatColor.MAGIC; + public static ChatColor STRIKETHROUGH = ChatColor.STRIKETHROUGH; + public static ChatColor UNDERLINE = ChatColor.UNDERLINE; + public static ChatColor DARK_BLUE = ChatColor.DARK_BLUE; + public static ChatColor DARK_GREEN = ChatColor.DARK_GREEN; + public static ChatColor CYAN = ChatColor.DARK_AQUA; + public static ChatColor DARK_RED = ChatColor.DARK_RED; + public static ChatColor PURPLE = ChatColor.DARK_PURPLE; + public static ChatColor ORANGE = ChatColor.GOLD; + public static ChatColor LIGHT_GRAY = ChatColor.GRAY; + public static ChatColor DARK_GRAY = ChatColor.DARK_GRAY; + public static ChatColor INDIGO = ChatColor.BLUE; + + public static String format(String message){ + return ChatColor.translateAlternateColorCodes('&', message); + } + + public static String unformat(String message){ + return ChatColor.stripColor(message); + } + + public static String repeat(String str, int length){ + return StringUtils.repeat(str, length); + } + +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java b/src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java new file mode 100644 index 0000000..a9db056 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java @@ -0,0 +1,25 @@ +package rip.bridge.bridge.bukkit.util; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class ItemStackBuilder { + + public static ItemStack build(Material item, int amount, short data, String name, List lore) { + ItemStack is = new ItemStack(item, amount, data); + + ItemMeta im = is.getItemMeta(); + im.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + if(lore != null) { + im.setLore(lore); + } + is.setItemMeta(im); + return is; + } + + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java b/src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java new file mode 100644 index 0000000..1588a24 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java @@ -0,0 +1,46 @@ +package rip.bridge.bridge.bukkit.util; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public abstract class PaginatedResult +{ + private int resultsPerPage; + + public PaginatedResult() { + this(9); + } + + public PaginatedResult(int resultsPerPage) { + assert resultsPerPage > 0; + this.resultsPerPage = resultsPerPage; + } + + public void display(CommandSender sender, Collection results, int page) { + this.display(sender, (List)new ArrayList(results), page); + } + + public void display(CommandSender sender, List results, int page) { + if (results.size() == 0) { + sender.sendMessage(ChatColor.RED + "No entries were found."); + return; + } + int maxPages = results.size() / this.resultsPerPage + 1; + if (page <= 0 || page > maxPages) { + sender.sendMessage(ChatColor.RED + "Page '" + page + "' not found. (" + ChatColor.YELLOW + "1 - " + maxPages + ChatColor.RED + ")"); + return; + } + sender.sendMessage(this.getHeader(page, maxPages)); + for (int i = this.resultsPerPage * (page - 1); i < this.resultsPerPage * page && i < results.size(); ++i) { + sender.sendMessage(this.format(results.get(i), i)); + } + } + + public abstract String getHeader(int p0, int p1); + + public abstract String format(T p0, int p1); +} diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java b/src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java new file mode 100644 index 0000000..7b472b1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java @@ -0,0 +1,375 @@ +package rip.bridge.bridge.bukkit.util; + +import com.google.common.base.Joiner; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URLClassLoader; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +import rip.bridge.bridge.bukkit.Bridge; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.event.Event; +import org.bukkit.plugin.*; + +public class PluginUtil { + + public static void enable(Plugin plugin) { + if (plugin != null && !plugin.isEnabled()) { + Bukkit.getPluginManager().enablePlugin(plugin); + } + } + + public static void enableAll() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (!isIgnored(plugin)) { + enable(plugin); + } + } + } + + public static void disable(Plugin plugin) { + if (plugin != null && plugin.isEnabled()) { + Bukkit.getPluginManager().disablePlugin(plugin); + } + } + + public static void disableAll() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (!isIgnored(plugin)) { + disable(plugin); + } + } + } + + public static String getFormattedName(Plugin plugin) { + return getFormattedName(plugin, false); + } + + public static String getFormattedName(Plugin plugin, boolean includeVersions) { + ChatColor color = plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED; + String pluginName = color + plugin.getName(); + if (includeVersions) { + pluginName += " (" + plugin.getDescription().getVersion() + ")"; + } + return pluginName; + } + + public static Plugin getPluginByName(String[] args, int start) { + return getPluginByName(StringUtils.join(args, ' ', start, args.length)); + } + + public static Plugin getPluginByName(String name) { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (name.equalsIgnoreCase(plugin.getName())) { + return plugin; + } + } + return null; + } + + public static List getPluginNames(boolean fullName) { + List plugins = new ArrayList<>(); + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + plugins.add(fullName ? plugin.getDescription().getFullName() : plugin.getName()); + } + return plugins; + } + + public static String getPluginVersion(String name) { + Plugin plugin = getPluginByName(name); + if (plugin != null && plugin.getDescription() != null) { + return plugin.getDescription().getVersion(); + } + return null; + } + + public static String getUsages(Plugin plugin) { + + List parsedCommands = new ArrayList<>(); + + Map commands = plugin.getDescription().getCommands(); + + if (commands != null) { + Iterator commandsIt = commands.entrySet().iterator(); + while (commandsIt.hasNext()) { + Map.Entry thisEntry = (Map.Entry) commandsIt.next(); + if (thisEntry != null) { + parsedCommands.add((String) thisEntry.getKey()); + } + } + } + + if (parsedCommands.isEmpty()) + return "No commands registered."; + + return Joiner.on(", ").join(parsedCommands); + + } + + public static List findByCommand(String command) { + + List plugins = new ArrayList<>(); + + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + + // Map of commands and their attributes. + Map> commands = plugin.getDescription().getCommands(); + + if (commands != null) { + + // Iterator for all the plugin's commands. + Iterator>> commandIterator = commands.entrySet().iterator(); + + while (commandIterator.hasNext()) { + + // Current value. + Map.Entry> commandNext = commandIterator.next(); + + // Plugin name matches - return. + if (commandNext.getKey().equalsIgnoreCase(command)) { + plugins.add(plugin.getName()); + continue; + } + + // No match - let's iterate over the attributes and see if + // it has aliases. + Iterator> attributeIterator = commandNext.getValue().entrySet().iterator(); + + while (attributeIterator.hasNext()) { + + // Current value. + Map.Entry attributeNext = attributeIterator.next(); + + // Has an alias attribute. + if (attributeNext.getKey().equals("aliases")) { + + Object aliases = attributeNext.getValue(); + + if (aliases instanceof String) { + if (((String) aliases).equalsIgnoreCase(command)) { + plugins.add(plugin.getName()); + continue; + } + } else { + + // Cast to a List of Strings. + List array = (List) aliases; + + // Check for matches here. + for (String str : array) { + if (str.equalsIgnoreCase(command)) { + plugins.add(plugin.getName()); + continue; + } + } + + } + + } + + } + } + + } + + } + + // No matches. + return plugins; + + } + + public static boolean isIgnored(Plugin plugin) { + return isIgnored(plugin.getName()); + } + + public static boolean isIgnored(String plugin) { + return false; + } + + private static String load(Plugin plugin) { + return load(plugin.getName()); + } + + public static String load(String name) { + + Plugin target = null; + + File pluginDir = new File("plugins"); + + File pluginFile = new File(pluginDir, name + (!name.endsWith(".jar") ? ".jar" : "")); + + if (!pluginFile.isFile()) { + for (File f : pluginDir.listFiles()) { + if (f.getName().endsWith(".jar")) { + try { + PluginDescriptionFile desc = Bridge.getInstance().getPluginLoader().getPluginDescription(f); + if (desc.getName().equalsIgnoreCase(name)) { + pluginFile = f; + break; + } + } catch (InvalidDescriptionException e) { + return ChatColor.RED + "There is no such file by the name \"" + name + "\"."; + } + } + } + } + + try { + target = Bukkit.getPluginManager().loadPlugin(pluginFile); + } catch (InvalidDescriptionException e) { + e.printStackTrace(); + return ChatColor.RED + "The plugin \"" + name + "\" has an invalid description, so we cannot load."; + } catch (InvalidPluginException e) { + e.printStackTrace(); + return ChatColor.RED + "The plugin \"" + name + "\" is an invalid plugin, so we cannot load."; + } + + target.onLoad(); + Bukkit.getPluginManager().enablePlugin(target); + + return ChatColor.GREEN + "Successfully loaded the plugin \"" + target.getName() + "\"."; + + } + + public static void reload(Plugin plugin) { + if (plugin != null) { + unload(plugin); + load(plugin); + } + } + + public static void reloadAll() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (!isIgnored(plugin)) { + reload(plugin); + } + } + } + + public static String unload(Plugin plugin) { + + String name = plugin.getName(); + + PluginManager pluginManager = Bukkit.getPluginManager(); + + SimpleCommandMap commandMap = null; + + List plugins = null; + + Map names = null; + Map commands = null; + Map> listeners = null; + + boolean reloadlisteners = true; + + if (pluginManager != null) { + + pluginManager.disablePlugin(plugin); + + try { + + Field pluginsField = Bukkit.getPluginManager().getClass().getDeclaredField("plugins"); + pluginsField.setAccessible(true); + plugins = (List) pluginsField.get(pluginManager); + + Field lookupNamesField = Bukkit.getPluginManager().getClass().getDeclaredField("lookupNames"); + lookupNamesField.setAccessible(true); + names = (Map) lookupNamesField.get(pluginManager); + + try { + Field listenersField = Bukkit.getPluginManager().getClass().getDeclaredField("listener"); + listenersField.setAccessible(true); + listeners = (Map>) listenersField.get(pluginManager); + } catch (Exception e) { + reloadlisteners = false; + } + + Field commandMapField = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap"); + commandMapField.setAccessible(true); + commandMap = (SimpleCommandMap) commandMapField.get(pluginManager); + + Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); + knownCommandsField.setAccessible(true); + commands = (Map) knownCommandsField.get(commandMap); + + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + return ChatColor.RED + "Failed to unload the plugin \"" + name + "\"."; + } + + } + + pluginManager.disablePlugin(plugin); + + if (plugins != null) + plugins.remove(plugin); + + if (names != null) + names.remove(name); + + if (listeners != null && reloadlisteners) { + for (SortedSet set : listeners.values()) { + set.removeIf(value -> value.getPlugin() == plugin); + } + } + + if (commandMap != null) { + for (Iterator> it = commands.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + if (entry.getValue() instanceof PluginCommand) { + PluginCommand c = (PluginCommand) entry.getValue(); + if (c.getPlugin() == plugin) { + c.unregister(commandMap); + it.remove(); + } + } + } + } + + // Attempt to close the classloader to unlock any handles on the plugin's jar file. + ClassLoader cl = plugin.getClass().getClassLoader(); + + if (cl instanceof URLClassLoader) { + + try { + + Field pluginField = cl.getClass().getDeclaredField("plugin"); + pluginField.setAccessible(true); + pluginField.set(cl, null); + + Field pluginInitField = cl.getClass().getDeclaredField("pluginInit"); + pluginInitField.setAccessible(true); + pluginInitField.set(cl, null); + + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) { + Logger.getLogger(PluginUtil.class.getName()).log(Level.SEVERE, null, ex); + } + + try { + + ((URLClassLoader) cl).close(); + } catch (IOException ex) { + Logger.getLogger(PluginUtil.class.getName()).log(Level.SEVERE, null, ex); + } + + } + + // Will not work on processes started with the -XX:+DisableExplicitGC flag, but lets try it anyway. + // This tries to get around the issue where Windows refuses to unlock jar files that were previously loaded into the JVM. + System.gc(); + + return ChatColor.GREEN + "Successfully unloaded the plugin \"" + name + "\"."; + + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/ReflectUtil.java b/src/main/java/rip/bridge/bridge/bukkit/util/ReflectUtil.java new file mode 100644 index 0000000..19c21c1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/ReflectUtil.java @@ -0,0 +1,51 @@ +package rip.bridge.bridge.bukkit.util; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public class ReflectUtil { + + public static T get(Field field, Object instance) { + try { + field.setAccessible(true); + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL); + + return (T) field.get(instance); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static Field getField(Class holder, Class type, String name) { + try { + for (Field field : holder.getDeclaredFields()) { + if (!field.getName().equalsIgnoreCase(name) || (type != null && field.getType() != type)) continue; + + field.setAccessible(true); + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL); + + return field; + } + + for (Field field : holder.getFields()) { + if (!field.getName().equalsIgnoreCase(name) || (type != null && field.getType() != type)) continue; + + field.setAccessible(true); + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL); + + return field; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/Reflection.java b/src/main/java/rip/bridge/bridge/bukkit/util/Reflection.java new file mode 100644 index 0000000..e629a06 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/Reflection.java @@ -0,0 +1,324 @@ +package rip.bridge.bridge.bukkit.util; + +import java.lang.reflect.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; + +import org.bukkit.Bukkit; + +import com.google.common.base.Preconditions; + +public class Reflection { + + public static Class getNmsClass(String name) { + String className = "net.minecraft.server.v1_7_R4." + getVersion() + "." + name; + return getClass(className); + } + + public static Class getCbClass(String name) { + String className = "org.bukkit.craftbukkit.v1_7_R4." + getVersion() + "." + name; + return getClass(className); + } + + public static Class getUtilClass(String name) { + try { + return Class.forName(name); //Try before 1.8 first + } catch (ClassNotFoundException ex) { + try { + return Class.forName("net.minecraft.util." + name); //Not 1.8 + } catch (ClassNotFoundException ex2) { + return null; + } + } + } + + public static String getVersion() { + String packageName = Bukkit.getServer().getClass().getPackage().getName(); + return packageName.substring(packageName.lastIndexOf('.') + 1); + } + + public static Object getHandle(Object wrapper) { + Method getHandle = makeMethod(wrapper.getClass(), "getHandle"); + return callMethod(getHandle, wrapper); + } + + //Utils + public static Method makeMethod(Class clazz, String methodName, Class... paramaters) { + try { + return clazz.getDeclaredMethod(methodName, paramaters); + } catch (NoSuchMethodException ex) { + return null; + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + @SuppressWarnings("unchecked") + public static T callMethod(Method method, Object instance, Object... paramaters) { + if (method == null) throw new RuntimeException("No such method"); + method.setAccessible(true); + try { + return (T) method.invoke(instance, paramaters); + } catch (InvocationTargetException ex) { + throw new RuntimeException(ex.getCause()); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + @SuppressWarnings("unchecked") + public static Constructor makeConstructor(Class clazz, Class... paramaterTypes) { + try { + return (Constructor) clazz.getConstructor(paramaterTypes); + } catch (NoSuchMethodException ex) { + return null; + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public static T callConstructor(Constructor constructor, Object... paramaters) { + if (constructor == null) throw new RuntimeException("No such constructor"); + constructor.setAccessible(true); + try { + return (T) constructor.newInstance(paramaters); + } catch (InvocationTargetException ex) { + throw new RuntimeException(ex.getCause()); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public static Field makeField(Class clazz, String name) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException ex) { + return null; + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + @SuppressWarnings("unchecked") + public static T getField(Field field, Object instance) { + if (field == null) throw new RuntimeException("No such field"); + field.setAccessible(true); + try { + return (T) field.get(instance); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public static void setField(Field field, Object instance, Object value) { + if (field == null) throw new RuntimeException("No such field"); + field.setAccessible(true); + try { + field.set(instance, value); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public static Class getClass(String name) { + try { + return Class.forName(name); + } catch (ClassNotFoundException ex) { + return null; + } + } + + public static Class getClass(String name, Class superClass) { + try { + return Class.forName(name).asSubclass(superClass); + } catch (ClassCastException | ClassNotFoundException ex) { + return null; + } + } + + // Fuzzy reflection + + public static Field getOnlyField(Class toGetFrom, Class type) { + Field only = null; + for (Field field : toGetFrom.getDeclaredFields()) { + if (!type.isAssignableFrom(field.getClass())) continue; + Preconditions.checkArgument(only == null, "More than one field of type %s on %s: %s and %s", type.getSimpleName(), toGetFrom.getSimpleName(), field.getName(), only.getName()); + only = field; + } + return only; + } + + public static Method getOnlyMethod(Class toGetFrom, Class returnType, Class... paramSpec) { + Method only = null; + for (Method method : toGetFrom.getDeclaredMethods()) { + if (!returnType.isAssignableFrom(method.getReturnType())) continue; + if (!isParamsMatchSpec(method.getParameterTypes(), paramSpec)) continue; + Preconditions.checkArgument(only == null, "More than one method matching spec on %s" + ((only.getName().equals(method.getName())) ? "" : ": " + only.getName() + " " + method.getName()), toGetFrom.getSimpleName()); + only = method; + } + return only; + } + + public static boolean isParamsMatchSpec(Class[] parameters, Class... paramSpec) { + if (parameters.length > paramSpec.length) return false; + for (int i = 0; i < paramSpec.length; i++) { + Class spec = paramSpec[i]; + if (spec == null) continue; + Class parameter = parameters[i]; + if (!spec.isAssignableFrom(parameter)) return false; + } + return true; + } + + /** + * Used to invoke a field + * @param field The field to invoke + * @param object The object where the field is applicable + * @exception IllegalArgumentException in case we cannot access the field (Should not happen) + * @return invoked field + */ + public static Object invokeField(Field field, Object object) { + try { + return field.get(object); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Used to fetch a field + * @param clazz Class where field is applicable + * @param fieldName Name of the field we're trying to fetch + * @exception IllegalArgumentException in case the field is not found + * @return Optional field + */ + @SuppressWarnings("deprecation") + public static Field fetchField(Class clazz, String fieldName) { + try { + Field field = clazz.getDeclaredField(fieldName); + + if (!field.isAccessible()) + field.setAccessible(true); + + return field; + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Used to fetch a constructor + * @param clazz Class where the constructor is applicable + * @param parameters Constructor in the constructor we're trying to fetch + * @exception IllegalArgumentException in case the constructor is not found + * @return the fetched constructor + */ + public static Constructor fetchConstructor(Class clazz, Class... parameters) { + try { + return clazz.getConstructor(parameters); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Used to invoke a constructor + * @param constructor The constructor to invoke + * @param parameters The parameters we need to use to invoke the constructor + * @exception IllegalArgumentException in case the constructor is not found + * @return invoked constructor + */ + public static Object invokeConstructor(Constructor constructor, Object... parameters) { + try { + return constructor.newInstance(parameters); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Used to fetch a method + * @param clazz Class where the method is applicable + * @param methodName The name of the method we're fetching + * @param parameters The parameters of the method + * @return the fetched method + */ + public static Method fetchMethod(Class clazz, String methodName, Class... parameters) { + try { + return clazz.getDeclaredMethod(methodName, parameters); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException(e); + } + } + + + /** + * Used to invoke a method + * @param method The method to invoke + * @param object The object which contains the method we need to invoke + * @param parameters The parameters needed to invoke the method + * @return The method's returning object + */ + public static Object invokeMethod(Method method, Object object, Object... parameters) { + try { + return method.invoke(object, parameters); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Finds a class and calls it back using a {@link BiConsumer} + * @param name Class' name + * @param callback callback after class is found + */ + public static void getClassCallback(String name, BiConsumer, Throwable> callback) { + CompletableFuture> completableFuture = new CompletableFuture<>(); + + completableFuture.complete(getClass(name)); + completableFuture.whenCompleteAsync(callback); + } + + public static T get(Field field, Object instance) { + try { + field.setAccessible(true); + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL); + + return (T) field.get(instance); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static Field getField(Class holder, Class type, String name) { + try { + for (Field field : holder.getDeclaredFields()) { + if (!field.getName().equalsIgnoreCase(name) || (type != null && field.getType() != type)) continue; + + field.setAccessible(true); + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL); + + return field; + } + + for (Field field : holder.getFields()) { + if (!field.getName().equalsIgnoreCase(name) || (type != null && field.getType() != type)) continue; + + field.setAccessible(true); + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL); + + return field; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/TPSUtil.java b/src/main/java/rip/bridge/bridge/bukkit/util/TPSUtil.java new file mode 100644 index 0000000..83bceab --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bukkit/util/TPSUtil.java @@ -0,0 +1,44 @@ +package rip.bridge.bridge.bukkit.util; + +import org.bukkit.Bukkit; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class TPSUtil { private TPSUtil() { +} + + public static double[] getTPS() { + double[] recentTps; + if (canGetWithPaper()) { + recentTps = getPaperRecentTps(); + } else { + recentTps = getNMSRecentTps(); + } + return recentTps; + } + + private static final Class spigotServerClass = Reflection.getClass("org.bukkit.Server$Spigot"); + private static final Method getSpigotMethod = Reflection.makeMethod(Bukkit.class, "spigot"); + private static final Method getTPSMethod = spigotServerClass != null ? Reflection.makeMethod(spigotServerClass, "getTPS") : null; + private static double[] getPaperRecentTps() { + if (!canGetWithPaper()) throw new UnsupportedOperationException("Can't get TPSUtil from Paper"); + Object server = Reflection.callMethod(getServerMethod, null); // Call static MinecraftServer.getServer() + double[] recent = Reflection.getField(recentTpsField, server); + return recent; + } + + private static boolean canGetWithPaper() { + return getSpigotMethod != null && getTPSMethod != null; + } + + private static final Class minecraftServerClass = Reflection.getNmsClass("MinecraftServer"); + private static final Method getServerMethod = minecraftServerClass != null ? Reflection.makeMethod(minecraftServerClass, "getServer") : null; + private static final Field recentTpsField = minecraftServerClass != null ? Reflection.makeField(minecraftServerClass, "recentTps") : null; + private static double[] getNMSRecentTps() { + if (getServerMethod == null || recentTpsField == null) return null; + Object server = Reflection.callMethod(getServerMethod, null); // Call static MinecraftServer.getServer() + double[] recent = Reflection.getField(recentTpsField, server); + return recent; + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/bungee/BridgeBungee.java b/src/main/java/rip/bridge/bridge/bungee/BridgeBungee.java new file mode 100644 index 0000000..a5632e8 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bungee/BridgeBungee.java @@ -0,0 +1,77 @@ +package rip.bridge.bridge.bungee; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.bungee.implement.BungeeImplementer; +import rip.bridge.bridge.bungee.listener.BridgeBungeeListener; +import com.google.common.io.ByteStreams; +import lombok.Getter; +import net.md_5.bungee.BungeeCord; +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; + +import java.io.*; + +public class BridgeBungee extends Plugin { + + @Getter private static BridgeBungee instance; + @Getter private static Configuration config; + @Getter private File configFile; + + @Override + public void onEnable() { + instance = this; + setupConfig(); + + BridgeGlobal.loadDisguise(true); + + BungeeCord.getInstance().getPluginManager().registerListener(this, new BridgeBungeeListener()); + BridgeGlobal.getServerHandler().registerProvider(new BungeeImplementer()); + } + + @Override + public void onDisable() { + BridgeGlobal.shutdown(); + instance = null; + } + + + public void saveConfig() { + try { + ConfigurationProvider.getProvider(YamlConfiguration.class).save(config, new File(getDataFolder(), "config.yml")); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + private void setupConfig() { + System.out.println("oof"); + configFile = new File(getDataFolder(), "config.yml"); + try { + config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); + } catch (IOException e) { + e.printStackTrace(); + } + if (!getDataFolder().exists()) { + getDataFolder().mkdir(); + } + File configFile = new File(getDataFolder(), "config.yml"); + if (!configFile.exists()) { + try { + configFile.createNewFile(); + try (InputStream is = getResourceAsStream("config.yml"); + OutputStream os = new FileOutputStream(configFile)) { + ByteStreams.copy(is, os); + } + } catch (IOException e) { + throw new RuntimeException("Unable to create configuration file", e); + } + } + if(config != null) { + new BridgeGlobal(); + } + } + +} diff --git a/src/main/java/rip/bridge/bridge/bungee/implement/BungeeImplementer.java b/src/main/java/rip/bridge/bridge/bungee/implement/BungeeImplementer.java new file mode 100644 index 0000000..755c7c1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bungee/implement/BungeeImplementer.java @@ -0,0 +1,56 @@ +package rip.bridge.bridge.bungee.implement; + +import com.google.gson.JsonObject; +import rip.bridge.bridge.BridgeGlobal; +import net.md_5.bungee.BungeeCord; +import rip.bridge.bridge.global.status.StatusProvider; + +import java.util.List; +import java.util.stream.Collectors; + +public class BungeeImplementer extends StatusProvider { + + public BungeeImplementer() { + super("BungeeCord", 10); + } + + @Override + public String serverName() { + return BridgeGlobal.getSystemName(); + } + + @Override + public String serverStatus() { + return "ONLINE"; + } + + @Override + public int online() { + return BungeeCord.getInstance().getOnlineCount(); + } + + @Override + public int maximum() { + return BungeeCord.getInstance().getConfig().getPlayerLimit(); + } + + @Override + public String motd() { + return ""; + } + + @Override + public double tps() { + return 0; + } + + @Override + public List players() { + return BungeeCord.getInstance().getPlayers().stream().map(proxiedPlayer -> proxiedPlayer.getUniqueId().toString()).collect(Collectors.toList()); + } + + @Override + public JsonObject dataPassthrough() { + return null; + } +} diff --git a/src/main/java/rip/bridge/bridge/bungee/listener/BridgeBungeeListener.java b/src/main/java/rip/bridge/bridge/bungee/listener/BridgeBungeeListener.java new file mode 100644 index 0000000..be9d5c7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bungee/listener/BridgeBungeeListener.java @@ -0,0 +1,59 @@ +package rip.bridge.bridge.bungee.listener; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.handlers.MongoHandler; +import rip.bridge.bridge.global.grant.Grant; +import net.md_5.bungee.api.event.LoginEvent; +import net.md_5.bungee.api.event.PlayerDisconnectEvent; +import net.md_5.bungee.api.event.PostLoginEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; + +import java.util.UUID; + +public class BridgeBungeeListener implements Listener { + + @EventHandler + public void onLogin(PostLoginEvent e) { + UUID uuid = e.getPlayer().getUniqueId(); + if (BridgeGlobal.getProfileHandler().getProfileByUUID(uuid) == null) { + BridgeGlobal.getMongoHandler().loadProfile(uuid.toString(), callback -> { + if (callback == null) { + BridgeGlobal.getProfileHandler().addProfile(new Profile(e.getPlayer().getName(), uuid, false)).applyGrant(Grant.getDefaultGrant(), null, false); + } else { + BridgeGlobal.getProfileHandler().addProfile(callback); + } + }, true, MongoHandler.LoadType.UUID); + } else { + BridgeGlobal.getProfileHandler().getProfileByUUID(uuid).refreshCurrentGrant(); + } + } + + @EventHandler(priority = 100) + public void onJoin(LoginEvent e) { + UUID uuid = e.getConnection().getUniqueId(); + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(e.getConnection().getUniqueId()); + if (profile != null) { + profile.refreshCurrentGrant(); + + }else { + BridgeGlobal.getMongoHandler().loadProfile(uuid.toString(), callback -> { + if (callback == null) { + BridgeGlobal.getProfileHandler().addProfile(new Profile(e.getConnection().getName(), uuid, false)).applyGrant(Grant.getDefaultGrant(), null, false); + } else { + BridgeGlobal.getProfileHandler().addProfile(callback); + } + }, true, MongoHandler.LoadType.UUID); + } + + } + + @EventHandler + public void onQuit(PlayerDisconnectEvent e) { + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(e.getPlayer().getUniqueId()); + if (profile != null) { + BridgeGlobal.getProfileHandler().getProfiles().remove(profile); + } + } +} diff --git a/src/main/java/rip/bridge/bridge/bungee/listener/GeneralBungeeListener.java b/src/main/java/rip/bridge/bridge/bungee/listener/GeneralBungeeListener.java new file mode 100644 index 0000000..37e7504 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/bungee/listener/GeneralBungeeListener.java @@ -0,0 +1,20 @@ +package rip.bridge.bridge.bungee.listener; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import rip.bridge.qlib.xpacket.FrozenXPacketHandler; + +import java.io.File; +import java.net.InetSocketAddress; + +public class GeneralBungeeListener { + + public static void logMessages(String msg) { + BungeeCord.getInstance().getLogger().info(ChatColor.translateAlternateColorCodes('&', msg)); + } + + +} diff --git a/src/main/java/rip/bridge/bridge/global/GlobalAPI.java b/src/main/java/rip/bridge/bridge/global/GlobalAPI.java new file mode 100644 index 0000000..680e232 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/GlobalAPI.java @@ -0,0 +1,171 @@ +package rip.bridge.bridge.global; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.MojangUtils; +import rip.bridge.bridge.global.profile.Profile; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class GlobalAPI { + + + public static Rank getRank(String name) { + return BridgeGlobal.getRankHandler().getRankByName(name); + } + + public static Rank getRank(UUID uuid) { + return BridgeGlobal.getRankHandler().getRankByID(uuid); + } + + public static Rank createRank(String name) { + if(BridgeGlobal.getRankHandler().getRankByName(name) != null) { + return null; + } + Rank r = new Rank(UUID.randomUUID(), name, false); + r.saveRank(); + BridgeGlobal.getRankHandler().addRank(r); + return r; + } + + public static Profile getProfile(UUID uuid) { + if(uuid == null) return Profile.getConsoleProfile(); + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid); + } + + public static Profile getProfile(String uuid) { + if(uuid.equalsIgnoreCase("Console")) return Profile.getConsoleProfile(); + return BridgeGlobal.getProfileHandler().getProfileByUsernameOrCreate(uuid); + } + + + public static Profile getProfileNotCreate(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUID(uuid); + } + + + + + public static Profile getProfileOrCreateNew(UUID uuid) { + String name; + try { + name = MojangUtils.fetchName(uuid); + }catch(Exception e) { + return null; + } + return BridgeGlobal.getProfileHandler().getNewProfileOrCreate(name, uuid); + } + + public static Profile getProfileOrCreateNew(String username, UUID uuid) { + return BridgeGlobal.getProfileHandler().getNewProfileOrCreate(username, uuid); + } + + + public static Rank getPlayerRank(UUID uuid) { + if(getProfile(uuid).getDisguisedRank() != null) { + return getProfile(uuid).getDisguisedRank(); + } + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getCurrentGrant().getRank(); + } + + + public static Rank getPlayerRank(Profile profile) { + if(profile.getDisguisedRank() != null) { + return profile.getDisguisedRank(); + } + return profile.getCurrentGrant().getRank(); + } + + + public static Rank getPlayerRank(UUID uuid, boolean ignoreDisguise) { + if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getCurrentGrant().getRank(); + + else if(getProfile(uuid).getDisguisedRank() != null) { + return getProfile(uuid).getDisguisedRank(); + } + return null; + } + + + public static Rank getPlayerRank(Profile profile, boolean ignoreDisguise) { + if(ignoreDisguise) return profile.getCurrentGrant().getRank(); + + else if(profile.getDisguisedRank() != null) { + return profile.getDisguisedRank(); + } + return null; + } + + + public static String getColor(UUID player) { + if(!getProfile(player).getColor().equals("")) { + return getProfile(player).getColor(); + }else { + return getPlayerRank(player).getColor(); + } + } + + public static String getColor(Profile profile) { + if(!profile.getColor().equals("")) { + return profile.getColor(); + }else { + return getPlayerRank(profile).getColor(); + } + } + + public static String getPrefix(UUID player) { + if(!getProfile(player).getPrefix().equals("")) { + return getProfile(player).getPrefix(); + }else { + return getPlayerRank(player).getPrefix(); + } + } + + public static String getPrefix(Profile profile) { + if(!profile.getPrefix().equals("")) { + return profile.getPrefix(); + }else { + return getPlayerRank(profile).getPrefix(); + } + } + + + public static String getSuffix(UUID player) { + if(!getProfile(player).getSuffix().equals("")) { + return getProfile(player).getSuffix(); + }else { + return getPlayerRank(player).getSuffix(); + } + } + + public static String getSuffix(Profile profile) { + if(!profile.getSuffix().equals("")) { + return profile.getSuffix(); + }else { + return getPlayerRank(profile).getSuffix(); + } + } + + + public static List getActiveGrants(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getActiveGrants(); + } + + + public static List getActiveGrants(Profile profile) { + return profile.getActiveGrants(); + } + + public static List getCurrentScopeRanks(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList()); + } + + public static List getAllGrants(UUID uuid) { + return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getGrants(); + } + + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/deployment/DeploymentHandler.java b/src/main/java/rip/bridge/bridge/global/deployment/DeploymentHandler.java new file mode 100644 index 0000000..b5e3de5 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/deployment/DeploymentHandler.java @@ -0,0 +1,154 @@ +package rip.bridge.bridge.global.deployment; + +import net.md_5.bungee.api.ProxyServer; +import rip.bridge.bridge.BridgeGlobal; +import net.md_5.bungee.BungeeCord; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; + +import java.io.*; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class DeploymentHandler { + + public static void createServer(String serverName, int port, List plugins) { + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Finding file"); + File directory = new File(BridgeGlobal.getServerDeploymentDir() + File.separator + serverName); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Creating file"); + directory.mkdir(); + + if (sendBunkerserver(directory)) { + try { + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Modifying Bridge's Config"); + PropertiesConfiguration configuration = new PropertiesConfiguration(new File(directory + File.separator + "config" + File.separator + "Bridge" + File.separator + "config.yml")); + configuration.setProperty("serverName", serverName); + configuration.setProperty("serverGroup", serverName); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Modified Bridge's Config"); + configuration.save(); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Saved Bridge's Config"); + + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Modifying server.properties"); + PropertiesConfiguration conf = new PropertiesConfiguration(new File(directory + File.separator + "config" + File.separator + "server" + File.separator + "server.properties")); + conf.setProperty("server-port", port); + conf.setProperty("online-mode", false); + conf.setProperty("server-name", serverName); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Modified server.properties"); + conf.save(); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Saved server.properties"); + } catch (ConfigurationException e) { + BridgeGlobal.sendLog(e.getMessage()); + } + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Sending plugins"); + sendPlugins(directory, plugins, BridgeGlobal::sendLog); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Saving to BungeeCord"); + ProxyServer.getInstance().getServers().put(serverName, ProxyServer.getInstance().constructServerInfo(serverName, new InetSocketAddress("localhost", port), "", false)); + BridgeGlobal.sendLog("[Deployment] \"" + serverName + "\" Completed server deployment"); + } + } + + public static boolean doesServerExit(String serverName) { + return new File(BridgeGlobal.getServerDeploymentDir() + File.separator + serverName).exists(); + } + + private static File getTemplateDirectory() { + return new File(BridgeGlobal.getServerTemplateDir()); + } + + public static void copyFolder(File source, File destination) { + if (source.isDirectory()) { + if (!destination.exists()) { + destination.mkdirs(); + } + + String files[] = source.list(); + + for (String file : files) { + File srcFile = new File(source, file); + File destFile = new File(destination, file); + + copyFolder(srcFile, destFile); + } + } else { + InputStream in = null; + OutputStream out = null; + + try { + in = new FileInputStream(source); + out = new FileOutputStream(destination); + + byte[] buffer = new byte[1024]; + + int length; + while ((length = in.read(buffer)) > 0) { + out.write(buffer, 0, length); + } + } + catch (Exception e) { + try { + in.close(); + } + catch (IOException e1) { + e1.printStackTrace(); + } + + try { + out.close(); + } + catch (IOException e1) { + e1.printStackTrace(); + } + } + } + } + + private static boolean sendBunkerserver(File directory) { + File file = new File(getTemplateDirectory() + File.separator + "spigot"); + if (!file.exists()) { + BungeeCord.getInstance().broadcast("Error whilst trying to deploy server to \"" + directory.getName() + "\" template folder not found."); + return false; + } + BridgeGlobal.sendLog("[Deployment] \"" + directory.getName() + "\" Copying Files"); + copyFolder(file, directory); + + BridgeGlobal.sendLog("[Deployment] \"" + directory.getName() + "\" Copied Files"); + + return true; + } + + private static void sendPlugins(File directory, List plugins, Consumer consumer) { + AtomicInteger success = new AtomicInteger(); + List failed = new ArrayList<>(); + plugins.forEach(file -> { + InputStream inputStream = null; + OutputStream outputStream = null; + try { + File outputFile = new File(directory + File.separator + "plugins" + File.separator + file.getName()); + inputStream = new FileInputStream(file); + if (outputFile.exists() && !outputFile.delete()) + return; + outputStream = new FileOutputStream(outputFile); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) > 0) + outputStream.write(buffer, 0, length); + success.getAndIncrement(); + } catch (IOException e) { + e.printStackTrace(); + failed.add(file); + } finally { + try { + inputStream.close(); + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + consumer.accept((success.get() == 0) ? "All plugins failed to update, check console for errors!" : (failed.isEmpty() ? ("Successfully updated all plugins (" + success.get() + " plugins)") : ("Updated " + success.get() + " plugins, the following plugins failed to update: " + failed.stream().map(File::getName).collect(Collectors.joining())))); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/disguise/DisguiseManager.java b/src/main/java/rip/bridge/bridge/global/disguise/DisguiseManager.java new file mode 100644 index 0000000..990e141 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/disguise/DisguiseManager.java @@ -0,0 +1,400 @@ +package rip.bridge.bridge.global.disguise; + +import com.google.common.collect.Maps; +import com.google.gson.JsonObject; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.ReplaceOptions; +import lombok.Getter; +import net.minecraft.server.v1_7_R4.MinecraftServer; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.properties.Property; +import org.bson.Document; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.disguise.runnable.DisguiseRunnable; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.DisguisePacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.Msg; +import rip.bridge.bridge.global.util.Tasks; +import rip.bridge.bridge.global.util.mojang.GameProfileUtil; +import rip.bridge.bridge.global.util.mojang.UUIDFetcher; +import rip.bridge.qlib.nametag.FrozenNametagHandler; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public class DisguiseManager { + + private static final DisguisePlayer DEFAULT_PLAYER = new DisguisePlayer(null); + + @Getter + private final Map disguisePlayers; + + @Getter + private final Map disguiseProfiles; + + public DisguiseManager(boolean bungee) { + this.disguisePlayers = Maps.newConcurrentMap(); + this.disguiseProfiles = Maps.newHashMap(); + + if(!bungee) { + Tasks.runAsync(this::loadProfiles); + } + } + + public DisguiseProfile getRandomDisguiseProfile() { + List profiles = new ArrayList<>(this.disguiseProfiles.values()); + return profiles.get(ThreadLocalRandom.current().nextInt(profiles.size())); + } + + public DisguiseProfile getProfile(String name) { + DisguiseProfile profile = this.disguiseProfiles.get(name); + return profile != null ? profile : this.disguiseProfiles.values().stream() + .filter(p -> p.getName().equalsIgnoreCase(name)) + .findFirst().orElse(null); + } + + public boolean addProfile(String name, String skin) { + DisguiseProfile profile = new DisguiseProfile(name); + profile.setSkinName(skin); + + DisguisePlayerSkin disguisePlayerSkin = this.loadProfileSkin(name, skin); + + if(disguisePlayerSkin != null) { + profile.setSkin(disguisePlayerSkin); + + this.disguiseProfiles.put(name, profile); + + Tasks.runAsync(() -> this.saveProfiles(false)); + return true; + } + + return false; + } + + public boolean removeProfile(String name) { + DisguiseProfile profile = this.disguiseProfiles.remove(name); + + Tasks.runAsync(() -> this.saveProfiles(false)); + + return profile != null; + } + + private void loadProfiles() { + for (Document document : BridgeGlobal.getMongoHandler().getDisguiseSkinCollection().find()) { + DisguiseProfile profile = new DisguiseProfile(document.getString("name")); + profile.setSkinName(document.getString("nameSkin")); + profile.setDisplayName(document.getString("displayName")); + + try { + profile.setSkin(DisguisePlayerSkin.fromJson(document, "skin")); + } catch (Exception e) { + Msg.logConsole("[Disguise] Skin of " + profile.getName() + " didn't load properly! Trying to load with mojang api."); + Msg.logConsole(document.toString()); + + DisguisePlayerSkin skin = this.loadProfileSkin(profile.getName(), profile.getSkinName()); + + if(skin == null) { + continue; + } + + profile.setSkin(skin); + } + + if(profile.getName() != null && profile.getSkinName() != null && profile.getSkin() != null) { + this.disguiseProfiles.put(profile.getName(), profile); + } + } + } + + private DisguisePlayerSkin loadProfileSkin(String name, String skinName) { + GameProfile gameProfile = GameProfileUtil.getSkinCache().get(skinName); + + if(gameProfile == null) { + Map fetched; + + try { + fetched = new UUIDFetcher(Collections.singletonList(skinName)).call(); + } catch (Exception ignored) { + Msg.logConsole("[Disguise] Failed to fetch skin properties of " + skinName + '!'); + return null; + } + + Optional fetchedUuid = fetched.values().stream().findFirst(); + + if(!fetchedUuid.isPresent()) { + Msg.logConsole("[Disguise] Failed to load skin with Mojang API of " + name + "!"); + return null; + } + + gameProfile = GameProfileUtil.loadGameProfile(fetchedUuid.get(), skinName); + } + + DisguisePlayerSkin skin = this.setupDisguiseSkin(gameProfile); + + if(skin == null) { + Msg.logConsole("[Disguise] The skin was found and loaded with Mojang API but something went wrong while setting it up."); + return null; + } + + return skin; + } + + public void saveProfiles(boolean async) { + for(DisguiseProfile profile : this.disguiseProfiles.values()) { + Document document = new Document(); + + document.put("name", profile.getName()); + document.put("nameSkin", profile.getSkinName()); + document.put("displayName", profile.getDisplayName()); + + DisguisePlayerSkin.toJson(document, "skin", profile.getSkin()); + + BridgeGlobal.getMongoHandler().getDisguiseSkinCollection().replaceOne(Filters.eq("name", profile.getName()), document, new ReplaceOptions().upsert(true)); + } + } + + public void load(String name, UUID uuid) { + JsonObject object = BridgeGlobal.getPlayerData(uuid, "disguise"); + + if(object != null) { + + DisguisePlayer player = new DisguisePlayer(name); + player.setDisguiseRank(object.get("disguiseRank") != null ? BridgeGlobal.getRankHandler().getRankByName(object.get("disguiseRank").getAsString()) : BridgeGlobal.getRankHandler().getDefaultRank()); + player.setDisguiseName(object.get("disguiseName").getAsString()); + player.setDisguiseSkin(object.get("disguiseSkin").getAsString()); + + try { + player.setRealSkin(DisguisePlayerSkin.fromJson(object, "real")); + player.setFakeSkin(DisguisePlayerSkin.fromJson(object, "fake")); + } catch (Exception e) { + Msg.logConsole("[Disguise] Deleted data of " + name + " because it didn't load properly!"); + BridgeGlobal.deletePlayerData("disguise", uuid); + e.printStackTrace(); + return; + } + + this.disguisePlayers.put(uuid, player); + } + } + + public void save(UUID uuid) { + this.save(uuid, false); + } + + public void save(UUID uuid, boolean async) { + DisguisePlayer player = this.disguisePlayers.get(uuid); + + if(player != null) { + JsonObject object = new JsonObject(); + JsonObject data = new JsonObject(); + + data.addProperty("disguiseRank", player.getDisguiseRank().getName()); + data.addProperty("disguiseName", player.getDisguiseName()); + data.addProperty("disguiseSkin", player.getDisguiseSkin()); + + DisguisePlayerSkin.toJson(data, "real", player.getRealSkin()); + DisguisePlayerSkin.toJson(data, "fake", player.getFakeSkin()); + + object.add("data", data); + + Tasks.run(() -> BridgeGlobal.savePlayerData("disguise", uuid, object), async); + } + } + + public void deleteData(UUID uuid) { + this.deleteData(uuid, false); + } + + public void deleteData(UUID uuid, boolean async) { + this.disguisePlayers.remove(uuid); + Tasks.run(() -> BridgeGlobal.deletePlayerData("disguise", uuid), async); + } + + public void leave(UUID uuid) { + this.disguisePlayers.remove(uuid); + } + + public DisguisePlayer getAndCreatePlayer(UUID uuid, String name) { + this.disguisePlayers.putIfAbsent(uuid, new DisguisePlayer(name)); + return this.disguisePlayers.get(uuid); + } + + public DisguisePlayer getPlayer(UUID uuid) { + return this.disguisePlayers.getOrDefault(uuid, DEFAULT_PLAYER); + } + + public boolean disguise(Player player, DisguisePlayer disguisePlayer, String profileName, boolean join, boolean full, boolean checkName) throws Exception { + String disguiseName = disguisePlayer.getDisguiseName(); + + if (checkName && Bukkit.getPlayer(disguiseName) != null) { + player.sendMessage(ChatColor.RED + "Failed to disguise you because the player that you were assigned as is already online."); + this.deleteData(player.getUniqueId()); + return false; + } + + GameProfile profile; + if (join) { + DisguisePlayerSkin fakeSkin = disguisePlayer.getFakeSkin(); + + profile = new GameProfile(fakeSkin.getProfileUuid(), disguisePlayer.getDisguiseName()); + profile.getProperties().put("textures", fakeSkin.getProperty()); + } else { + DisguisePlayerSkin realSkin = this.setupDisguiseSkin(((CraftPlayer) player).getProfile()); + + if (realSkin == null) { + player.sendMessage(ChatColor.RED + "Failed to disguise you because the properties of real skin are missing! Contact developer."); + return false; + } + + DisguisePlayer dpOld = this.disguisePlayers.get(player.getUniqueId()); + disguisePlayer.setRealSkin(dpOld != null ? dpOld.getRealSkin() : realSkin); + + String skin = disguisePlayer.getDisguiseSkin(); + DisguisePlayerSkin fakeSkin; + + DisguiseProfile disguiseProfile = this.disguiseProfiles.values() + .stream() + .filter(dp -> dp.getName().equalsIgnoreCase(profileName != null ? profileName : skin)) + .findFirst() + .orElse(null); + + // if disguise profile is made get it from cache, if not load it or get it from other cache + if (disguiseProfile != null) { + fakeSkin = disguiseProfile.getSkin(); + +// Msg.logConsole(""); +// Msg.logConsole("Found fake skin:"); +// Msg.logConsole(" - Name: " + disguiseProfile.getName()); +// Msg.logConsole(" - Skin Name: " + disguiseProfile.getSkinName()); +// Msg.logConsole(" - Skin UUID: " + fakeSkin.getProfileUuid().toString()); +// Msg.logConsole(" - Value: " + fakeSkin.getProperty().getValue()); +// Msg.logConsole(" - Signature: " + fakeSkin.getProperty().getSignature()); + + profile = new GameProfile(fakeSkin.getProfileUuid(), disguisePlayer.getDisguiseName()); + profile.getProperties().put("textures", fakeSkin.getProperty()); + } else { + profile = GameProfileUtil.getSkinCache().get(skin.toLowerCase()); + + Msg.logConsole("Loading skin or getting from cache -> " + skin); + + if (profile == null) { + Map fetched = new UUIDFetcher(Collections.singletonList(skin)).call(); + + Optional fetchedUuid = fetched.values().stream().findFirst(); + if (fetchedUuid.isPresent()) { + profile = GameProfileUtil.loadGameProfile(fetchedUuid.get(), skin); + } else { + profile = GameProfileUtil.loadGameProfile(UUID.fromString("8667ba71-b85a-4004-af54-457a9734eed7"), "Steve"); + } + } + + fakeSkin = this.setupDisguiseSkin(profile); + } + + if (fakeSkin == null) { + player.sendMessage(ChatColor.RED + "Failed to disguise you because the properties of fake skin are missing! Contact developer."); + return false; + } + + disguisePlayer.setFakeSkin(fakeSkin); + + this.disguisePlayers.put(player.getUniqueId(), disguisePlayer); + } + + if(full) { + GameProfile finalProfile = profile; + Tasks.run(() -> { + new DisguiseRunnable(player, finalProfile, disguiseName).run(); + + Profile playerProfile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + player.setPlayerListName(disguisePlayer.getDisguiseRank().getColor() + disguiseName); + player.setDisplayName(disguisePlayer.getDisguiseRank().getColor() + disguiseName); + player.setCustomName(disguisePlayer.getDisguiseRank().getColor() + disguiseName); + playerProfile.updateColor(); + playerProfile.saveProfile(); + PacketHandler.sendToAll(new DisguisePacket("&9[Staff] &7[" + playerProfile.getConnectedServer() + "] " + playerProfile.getCurrentGrant().getRank().getColor() + playerProfile.getUsername() + " &bdisguised as " + disguisePlayer.getDisguiseRank().getColor() + disguiseName)); + }); + } else { + Profile playerProfile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + player.setPlayerListName(disguisePlayer.getDisguiseRank().getColor() + disguiseName); + player.setDisplayName(disguisePlayer.getDisguiseRank().getColor() + disguiseName); + player.setCustomName(disguisePlayer.getDisguiseRank().getColor() + disguiseName); + playerProfile.updateColor(); + playerProfile.saveProfile(); + } + + if(!join) { + this.save(player.getUniqueId()); + } + + Tasks.run(() -> { + FrozenNametagHandler.reloadPlayer(player); + FrozenNametagHandler.reloadOthersFor(player); + }); + + return true; + } + + public void undisguise(Player player, boolean full, boolean quit) { + DisguisePlayer disguisePlayer = this.disguisePlayers.get(player.getUniqueId()); + + if(disguisePlayer != null) { + DisguisePlayerSkin realSkin = disguisePlayer.getRealSkin(); + Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()); + + GameProfile originalProfile = new GameProfile(realSkin.getProfileUuid(), profile.getUsername()); + originalProfile.getProperties().put("textures", realSkin.getProperty()); + + if (full) { + Tasks.run(new DisguiseRunnable(player, originalProfile, profile.getUsername())); + } + + this.deleteData(player.getUniqueId()); + + Rank rank = profile.getCurrentGrant().getRank(); + profile.updateColor(); + player.setPlayerListName(rank.getColor() + profile.getUsername()); + player.setDisplayName(rank.getColor() + profile.getUsername()); + player.setCustomName(rank.getColor() + profile.getUsername()); + profile.saveProfile(); + PacketHandler.sendToAll(new DisguisePacket("&9[Staff] &7[" + profile.getConnectedServer() + "] " + profile.getCurrentGrant().getRank().getColor() + profile.getUsername() + " &bundisguised")); + + if(!quit) { + MinecraftServer.getServer().getPlayerList().playerMap.put(profile.getUsername(), ((CraftPlayer) player).getHandle()); +// Bukkit.broadcastMessage("Putting " + profile.getUsername()); + } + + MinecraftServer.getServer().getPlayerList().playerMap.remove(player.getName()); + +// Bukkit.broadcastMessage("Removing " + profile.getUsername()); + + Tasks.run(() -> { + FrozenNametagHandler.reloadPlayer(player); + FrozenNametagHandler.reloadOthersFor(player); + }); + } + } + + public DisguisePlayerSkin setupDisguiseSkin(GameProfile profile) { + DisguisePlayerSkin skin = new DisguisePlayerSkin(); + skin.setProfileUuid(profile.getId()); + + Collection properties = profile.getProperties().get("textures"); + + if(properties == null || properties.isEmpty()) { + return null; + } + + for(Property property : properties) { + skin.setProperty(property); + } + + return skin; + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayer.java b/src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayer.java new file mode 100644 index 0000000..32e0146 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayer.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.global.disguise; + +import rip.bridge.bridge.global.ranks.Rank; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class DisguisePlayer { + + private final String name; + + private Rank disguiseRank; + private String disguiseName; + private String disguiseSkin; + + private DisguisePlayerSkin realSkin; + private DisguisePlayerSkin fakeSkin; +} diff --git a/src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayerSkin.java b/src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayerSkin.java new file mode 100644 index 0000000..8abbb5e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayerSkin.java @@ -0,0 +1,55 @@ +package rip.bridge.bridge.global.disguise; + +import com.google.gson.JsonObject; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.minecraft.util.com.mojang.authlib.properties.Property; +import org.bson.Document; + +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class DisguisePlayerSkin { + + private UUID profileUuid; + private Property property; + + public static void toJson(Document document, String type, DisguisePlayerSkin skin) { + document.put(type + "ProfileUuid", skin.getProfileUuid().toString()); + + Property property = skin.getProperty(); + + document.put(type + "Name", property.getName()); + document.put(type + "Value", property.getValue()); + document.put(type + "Signature", property.getSignature()); + } + + public static DisguisePlayerSkin fromJson(Document document, String type) { + return new DisguisePlayerSkin( + UUID.fromString(document.getString(type + "ProfileUuid")), + new Property(document.getString(type + "Name"), document.getString(type + "Value"), + document.getString(type + "Signature"))); + } + + public static void toJson(JsonObject data, String type, DisguisePlayerSkin skin) { + data.addProperty(type + "ProfileUuid", skin.getProfileUuid().toString()); + + Property property = skin.getProperty(); + + data.addProperty(type + "Name", property.getName()); + data.addProperty(type + "Value", property.getValue()); + data.addProperty(type + "Signature", property.getSignature()); + } + + public static DisguisePlayerSkin fromJson(JsonObject object, String type) { + return new DisguisePlayerSkin( + UUID.fromString(object.get(type + "ProfileUuid").getAsString()), + new Property(object.get(type + "Name").getAsString(), object.get(type + "Value").getAsString(), + object.get(type + "Signature").getAsString())); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/disguise/DisguiseProfile.java b/src/main/java/rip/bridge/bridge/global/disguise/DisguiseProfile.java new file mode 100644 index 0000000..2d8dd8c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/disguise/DisguiseProfile.java @@ -0,0 +1,16 @@ +package rip.bridge.bridge.global.disguise; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class DisguiseProfile { + + private final String name; + private String displayName; + private String skinName; + private DisguisePlayerSkin skin; +} diff --git a/src/main/java/rip/bridge/bridge/global/disguise/runnable/DisguiseRunnable.java b/src/main/java/rip/bridge/bridge/global/disguise/runnable/DisguiseRunnable.java new file mode 100644 index 0000000..8337126 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/disguise/runnable/DisguiseRunnable.java @@ -0,0 +1,156 @@ +package rip.bridge.bridge.global.disguise.runnable; + +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack; +import rip.bridge.bridge.global.util.Tasks; +import rip.bridge.bridge.global.util.mojang.GameProfileUtil; +import lombok.AllArgsConstructor; +import rip.bridge.qlib.nametag.FrozenNametagHandler; +import rip.bridge.qlib.qLib; +import net.minecraft.server.v1_7_R4.*; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; + +import java.lang.reflect.Field; + +@AllArgsConstructor +public class DisguiseRunnable implements Runnable { + + private static Field ENTITY_HUMAN_I; + + static { + try { + ENTITY_HUMAN_I = EntityHuman.class.getDeclaredField("i"); + ENTITY_HUMAN_I.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private Player player; + private GameProfile newProfileData; + private String name; + + @Override + public void run() { + MinecraftServer.getServer().getPlayerList().playerMap.remove(this.player.getName()); + MinecraftServer.getServer().getPlayerList().playerMap.put(this.name, ((CraftPlayer) this.player).getHandle()); + +// Bukkit.broadcastMessage("DR -> Removing " + this.player.getName()); +// Bukkit.broadcastMessage("DR -> Adding " + this.name); + + EntityPlayer entityPlayer = ((CraftPlayer) this.player).getHandle(); + GameProfile currentProfile = entityPlayer.getProfile(); + currentProfile.getProperties().clear(); + + this.newProfileData.getProperties().values() + .forEach(property -> currentProfile.getProperties().put(property.getName(), property)); + + GameProfileUtil.setName(currentProfile, this.name); + + try { + ENTITY_HUMAN_I.set(entityPlayer, currentProfile); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + Tasks.run(() -> { + Entity vehicle = this.player.getVehicle(); + + if(vehicle != null) { + vehicle.eject(); + } + + // this will not reload a skin for 1.7 player itself + int playerId = entityPlayer.getId(); + Location location = this.player.getLocation(); + + PacketPlayOutPlayerInfo removeInfo = PacketPlayOutPlayerInfo.removePlayer(entityPlayer); + + PacketPlayOutEntityDestroy removeEntity = new PacketPlayOutEntityDestroy(playerId); + + PacketPlayOutNamedEntitySpawn addNamed = new PacketPlayOutNamedEntitySpawn(entityPlayer); + + PacketPlayOutPlayerInfo addInfo = PacketPlayOutPlayerInfo.addPlayer(entityPlayer); + + PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(((WorldServer) entityPlayer.getWorld()).dimension, + entityPlayer.getWorld().difficulty, entityPlayer.getWorld().worldData.getType(), + EnumGamemode.getById(this.player.getGameMode().getValue())); + + PacketPlayOutPosition pos = new PacketPlayOutPosition(location.getX(), location.getY(), location.getZ(), location.getYaw(), + location.getPitch(), false); + + PacketPlayOutEntityEquipment itemhand = new PacketPlayOutEntityEquipment(playerId, 0, + CraftItemStack.asNMSCopy(this.player.getItemInHand())); + + PacketPlayOutEntityEquipment helmet = new PacketPlayOutEntityEquipment(playerId, 4, + CraftItemStack.asNMSCopy(this.player.getInventory().getHelmet())); + + PacketPlayOutEntityEquipment chestplate = new PacketPlayOutEntityEquipment(playerId, 3, + CraftItemStack.asNMSCopy(this.player.getInventory().getChestplate())); + + PacketPlayOutEntityEquipment leggings = new PacketPlayOutEntityEquipment(playerId, 2, + CraftItemStack.asNMSCopy(this.player.getInventory().getLeggings())); + + PacketPlayOutEntityEquipment boots = new PacketPlayOutEntityEquipment(playerId, 1, + CraftItemStack.asNMSCopy(this.player.getInventory().getBoots())); + + PacketPlayOutHeldItemSlot slot = new PacketPlayOutHeldItemSlot(this.player.getInventory().getHeldItemSlot()); + + for(Player worldPlayer : this.player.getWorld().getPlayers()) { + CraftPlayer craftOnline = (CraftPlayer) worldPlayer; + PlayerConnection connection = craftOnline.getHandle().playerConnection; + + if(worldPlayer.getUniqueId().equals(this.player.getUniqueId())) { + connection.sendPacket(removeInfo); + connection.sendPacket(addInfo); + connection.sendPacket(respawn); + connection.sendPacket(pos); + connection.sendPacket(slot); + + craftOnline.updateScaledHealth(); + craftOnline.getHandle().triggerHealthUpdate(); + craftOnline.updateInventory(); + + Tasks.run(() -> craftOnline.getHandle().updateAbilities()); + continue; + } + + connection.sendPacket(removeEntity); + connection.sendPacket(removeInfo); + + if(worldPlayer.canSee(this.player)) { + connection.sendPacket(addInfo); + connection.sendPacket(addNamed); + connection.sendPacket(itemhand); + connection.sendPacket(helmet); + connection.sendPacket(chestplate); + connection.sendPacket(leggings); + connection.sendPacket(boots); + } + } + + this.player.updateInventory(); + this.player.setGameMode(this.player.getGameMode()); + this.player.getInventory().setHeldItemSlot(this.player.getInventory().getHeldItemSlot()); + this.player.setFoodLevel(this.player.getFoodLevel()); + this.player.setSaturation(this.player.getSaturation()); + this.player.setMaxHealth(this.player.getMaxHealth()); + this.player.setHealth(this.player.getHealth()); + this.player.setExp(this.player.getExp()); + this.player.setTotalExperience(this.player.getTotalExperience()); + this.player.setWalkSpeed(this.player.getWalkSpeed()); + this.player.hidePlayer(this.player); + this.player.showPlayer(this.player); + if (FrozenNametagHandler.isInitiated()) { + this.player.setMetadata("qLibNametag-LoggedIn", new FixedMetadataValue(qLib.getInstance(), true)); + //FrozenNametagHandler.initiatePlayer(this.player); + FrozenNametagHandler.reloadPlayer(this.player); + FrozenNametagHandler.reloadOthersFor(this.player); + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/filter/Filter.java b/src/main/java/rip/bridge/bridge/global/filter/Filter.java new file mode 100644 index 0000000..800ba98 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/filter/Filter.java @@ -0,0 +1,64 @@ +package rip.bridge.bridge.global.filter; + +import rip.bridge.bridge.BridgeGlobal; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; +import java.util.regex.Pattern; + +@Getter +@AllArgsConstructor +public class Filter { + + private final UUID uuid; + private final FilterType filterType; + private final FilterAction filterAction; + private final String pattern; + private final long muteTime; + + public Filter(FilterType filterType, String pattern) { + this.uuid = UUID.randomUUID(); + this.filterType = filterType; + this.filterAction = FilterAction.HIDE; + this.pattern = pattern; + this.muteTime = -1L; + } + + public Filter(FilterType filterType, String pattern, long muteTime) { + this.uuid = UUID.randomUUID(); + this.filterType = filterType; + this.filterAction = FilterAction.MUTE; + this.pattern = pattern; + this.muteTime = muteTime; + } + + public boolean isViolatingFilter(String message) { + if(getFilterType() == FilterType.REGEX) { + return Pattern.compile(getPattern(), Pattern.CASE_INSENSITIVE).matcher(message).find(); + } + return message.toLowerCase().contains(getPattern().toLowerCase()); + } + + public void save() { + BridgeGlobal.getMongoHandler().saveFilter(this, callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully saved the filter §f" + getUuid() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save the filter §f" + getUuid() + "§c."); + } + }, true); + } + + public void delete() { + BridgeGlobal.getMongoHandler().removeFilter(getUuid(), callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully removed the filter §f" +getUuid() + "§a."); + BridgeGlobal.getFilterHandler().getFilters().remove(this); + } else { + BridgeGlobal.sendLog("§cFailed to remove the filter §f" + getUuid() + "§c."); + } + }, true); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/filter/FilterAction.java b/src/main/java/rip/bridge/bridge/global/filter/FilterAction.java new file mode 100644 index 0000000..9323898 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/filter/FilterAction.java @@ -0,0 +1,8 @@ +package rip.bridge.bridge.global.filter; + +public enum FilterAction { + + HIDE, + MUTE + +} diff --git a/src/main/java/rip/bridge/bridge/global/filter/FilterType.java b/src/main/java/rip/bridge/bridge/global/filter/FilterType.java new file mode 100644 index 0000000..82371d8 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/filter/FilterType.java @@ -0,0 +1,8 @@ +package rip.bridge.bridge.global.filter; + +public enum FilterType { + + REGEX, + STRING + +} diff --git a/src/main/java/rip/bridge/bridge/global/grant/Grant.java b/src/main/java/rip/bridge/bridge/global/grant/Grant.java new file mode 100644 index 0000000..ba88c27 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/grant/Grant.java @@ -0,0 +1,179 @@ +package rip.bridge.bridge.global.grant; + +import net.md_5.bungee.api.ChatColor; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.util.OtherUtils; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.TimeUtil; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import rip.bridge.qlib.util.TimeUtils; + +import java.text.SimpleDateFormat; +import java.util.*; + +@Getter +public class Grant { + + @Getter private static final Grant defaultGrant = new Grant(BridgeGlobal.getRankHandler().getDefaultRank(), Long.MAX_VALUE, Collections.singletonList("Global"), "", "N/A", BridgeGlobal.getSystemName()); + + private final UUID uuid; + private final Rank rank; + private final long length; + private final long initialTime; + private final List scope; + private final String reason; + private final String grantedBy; + private final String grantedOn; + + @Setter private boolean removed; + @Setter private long removedAt; + @Setter private String removedReason, removedBy, removedOn; + + public Grant(Rank rank, long length, List scope, String reason, String grantedBy, String grantedOn) { + this.uuid = UUID.randomUUID(); + this.rank = rank; + this.scope = scope; + this.length = length; + this.initialTime = System.currentTimeMillis(); + this.reason = reason; + this.grantedBy = grantedBy; + this.grantedOn = grantedOn; + this.removed = false; + this.removedAt = -1L; + this.removedBy = ""; + this.removedOn = ""; + this.removedReason = ""; + } + + public Grant(UUID uuid, Rank rank, long length, long initialTime, List scope, String reason, String grantedBy, String grantedOn) { + this.uuid = uuid; + this.rank = rank; + this.length = length; + this.initialTime = initialTime; + this.scope = scope; + this.reason = reason; + this.grantedBy = grantedBy; + this.grantedOn = grantedOn; + } + + public Grant(UUID uuid, Rank rank, long length, long initialTime, List scope, String reason, String grantedBy, String grantedOn, boolean removed, long removedAt, String removedReason, String removedBy, String removedOn) { + this.uuid = uuid; + this.rank = rank; + this.length = length; + this.initialTime = initialTime; + this.scope = scope; + this.reason = reason; + this.grantedBy = grantedBy; + this.grantedOn = grantedOn; + this.removed = removed; + this.removedAt = removedAt; + this.removedReason = removedReason; + this.removedBy = removedBy; + this.removedOn = removedOn; + } + + public static Grant deserialize(String grant) { + JsonObject object = new JsonParser().parse(grant).getAsJsonObject(); + return new Grant( + UUID.fromString(object.get("uuid").getAsString()), + BridgeGlobal.getRankHandler().getRankByID(UUID.fromString(object.get("rank").getAsString())), + object.get("length").getAsLong(), + object.get("initialTime").getAsLong(), + new ArrayList<>(Arrays.asList(object.get("scope").getAsString().split(","))), + object.get("reason").getAsString(), + object.get("grantedBy").getAsString(), + object.get("grantedOn").getAsString(), + object.get("removed").getAsBoolean(), + object.get("removedAt").getAsLong(), + object.get("removedBy").getAsString(), + object.get("removedOn").getAsString(), + object.get("removedReason").getAsString()); + } + + public static JsonObject serialize(Grant grant) { + + return new JsonChain() + .addProperty("uuid", grant.getUuid().toString()) + .addProperty("rank", grant.getRank().getUuid().toString()) + .addProperty("length", grant.getLength()) + .addProperty("initialTime", grant.getInitialTime()) + .addProperty("scope", StringUtils.join(grant.getScope(), ',')) + .addProperty("reason", grant.getReason()) + .addProperty("grantedBy", grant.grantedBy) + .addProperty("grantedOn", grant.getGrantedOn()) + .addProperty("removed", grant.isRemoved()) + .addProperty("removedAt", grant.getRemovedAt()) + .addProperty("removedReason", grant.getRemovedReason()) + .addProperty("removedBy", grant.removedBy) + .addProperty("removedOn", grant.getRemovedOn()) + .get(); + } + + public String formatGrantedTime(long time) { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yy HH:mmaa"); + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(time); + return dateFormat.format(cal.getTime()) + " (" + TimeUtil.getTimeZoneShortName(cal.getTimeZone().getDisplayName()) + ")"; + } + + public long getActiveUntil() { + return length == Long.MAX_VALUE ? Long.MAX_VALUE : (initialTime + length); + } + + public boolean isStillActive() { + return getActiveUntil() > System.currentTimeMillis() && !removed; + } + + public String getGrantedBy() { + if(OtherUtils.isUUID(grantedBy)) { + Profile pf = BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(UUID.fromString(grantedBy)); + return (pf == Profile.getConsoleProfile() ? pf.getColor() : pf.getCurrentGrant().getRank().getColor()) + pf.getUsername(); + }else { + return grantedBy; + } + } + + public String getGrantedByColorless() { + if(OtherUtils.isUUID(grantedBy)) { + Profile pf = BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(UUID.fromString(grantedBy)); + return (pf == Profile.getConsoleProfile() ? ChatColor.LIGHT_PURPLE : ChatColor.LIGHT_PURPLE) + pf.getUsername(); + }else { + return grantedBy; + } + } + + public String getRemovedBy() { + if(OtherUtils.isUUID(removedBy)) { + Profile pf = BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(UUID.fromString(removedBy)); + return (pf == Profile.getConsoleProfile() ? pf.getColor(): pf.getCurrentGrant().getRank().getColor() ) + pf.getUsername(); + }else { + return removedBy; + } + } + + + public boolean isGrantActiveOnScope() { + switch (BridgeGlobal.getSystemType()) { + case BUNGEE: { + return getScope().stream().anyMatch(s -> (s.equalsIgnoreCase("global") || s.equalsIgnoreCase("bungeecord") || s.equalsIgnoreCase("gr-bungeecord"))); + } + case BUKKIT: { + return getScope().stream().anyMatch(s -> (s.equalsIgnoreCase("global") || s.equalsIgnoreCase(BridgeGlobal.getSystemName()) || s.equalsIgnoreCase("gr-" + BridgeGlobal.getFromConfig("servergroup")))); + } + default: { + return getScope().contains("Global"); + } + } + } + + public String getDate() { + return TimeUtils.formatIntoCalendarStringNoTime(new Date(getInitialTime())); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/handlers/FilterHandler.java b/src/main/java/rip/bridge/bridge/global/handlers/FilterHandler.java new file mode 100644 index 0000000..41fe594 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/handlers/FilterHandler.java @@ -0,0 +1,71 @@ +package rip.bridge.bridge.global.handlers; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.filter.Filter; +import lombok.Getter; + +import java.util.*; + +public class FilterHandler { + + @Getter private final Set filters = new HashSet<>(); + + public void init() { + filters.clear(); + + List filterList = new ArrayList<>(); + try { + BridgeGlobal.getMongoHandler().getFiltersInDB(callback-> { + + BridgeGlobal.sendLog("§aFound " + callback.size() + " filters in the database."); + + + for (int i = 0; i < callback.size(); i++) { + UUID uuid = callback.get(i); + BridgeGlobal.getMongoHandler().loadFilter(uuid, cback -> { + if (cback == null) { + System.out.println("Welp. thats a null."); + return; + } + + filterList.add(cback); + }, false); + + if(callback.size() == filterList.size()) { + filters.addAll(filterList); + BridgeGlobal.sendLog("§aLoaded all filters."); + } + } + + }); + + } catch (Exception ex) { + BridgeGlobal.sendLog("§cFailed to initialize the filter manager."); + ex.printStackTrace(); + BridgeGlobal.sendLog(ex.getClass().getSimpleName() + " - " + ex.getMessage()); + } + } + + public Filter getFilter(UUID uuid) { + return filters.stream().filter(filter -> filter.getUuid().equals(uuid)).findFirst().orElse(null); + } + + public Filter getFilter(String pattern) { + return filters.stream().filter(filter -> filter.getPattern().equalsIgnoreCase(pattern)).findFirst().orElse(null); + } + + public Filter addFilter(Filter filter) { + filters.stream().filter(filter1 -> filter1.getUuid().equals(filter.getUuid())).findFirst().ifPresent(filters::remove); + filters.add(filter); + return filter; + } + + public boolean removeFilter(Filter filter) { + return filters.remove(filter); + } + + public Filter isViolatingFilter(String message) { + return filters.stream().filter(filter -> filter.isViolatingFilter(message)).findFirst().orElse(null); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/handlers/MongoHandler.java b/src/main/java/rip/bridge/bridge/global/handlers/MongoHandler.java new file mode 100644 index 0000000..864fbcb --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/handlers/MongoHandler.java @@ -0,0 +1,448 @@ +package rip.bridge.bridge.global.handlers; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.mongodb.MongoClient; +import com.mongodb.MongoClientURI; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.ReplaceOptions; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.ranks.Rank; +import lombok.AllArgsConstructor; +import lombok.Getter; +import rip.bridge.bridge.global.filter.Filter; +import rip.bridge.bridge.global.filter.FilterAction; +import rip.bridge.bridge.global.filter.FilterType; +import rip.bridge.bridge.global.punishment.Punishment; +import org.bson.Document; + +import javax.print.Doc; +import java.util.*; +import java.util.function.Consumer; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class MongoHandler { + + + @Getter + private final MongoClient mongoClient; + @Getter + private MongoDatabase database; + @Getter + private MongoCollection rankCollection; + @Getter + private MongoCollection profileCollection; + @Getter + private MongoCollection punishmentCollection; + @Getter + private MongoCollection filterCollection; + @Getter + private MongoCollection disguiseSkinCollection; + @Getter + private MongoCollection prefixesCollection; + + + public MongoHandler() { + String userPart = ""; + if (BridgeGlobal.isMongoAuth()) { + userPart = BridgeGlobal.getMongoUsername() + ":" + BridgeGlobal.getMongoPassword() + "@"; + } + mongoClient = new MongoClient(new MongoClientURI("mongodb://" + userPart + BridgeGlobal.getMongoHost() + ":" + BridgeGlobal.getMongoPort() + (BridgeGlobal.isMongoAuth() ? "/admin" : ""))); + + try { + database = mongoClient.getDatabase(BridgeGlobal.getMongoDatabase()); + rankCollection = database.getCollection("ranks"); + profileCollection = database.getCollection("profiles"); + punishmentCollection = database.getCollection("punishments"); + filterCollection = database.getCollection("filters"); + disguiseSkinCollection = database.getCollection("disguiseSkins"); + prefixesCollection = database.getCollection("prefixes"); + } catch (Exception ex) { + BridgeGlobal.sendLog("§cFailed to initialize backend."); + BridgeGlobal.sendLog(ex.getClass().getSimpleName() + " - " + ex.getMessage()); + } + } + + /*/ + Rank - MongoDB + /*/ + + public void getRanksInDB(Consumer> callback) { + Set ranks = new HashSet<>(); + for (Document document : rankCollection.find()) { + ranks.add(UUID.fromString(document.get("uuid").toString())); + } + callback.accept(ranks); + } + + public Document getPunishmentByUUID(UUID uuid) { + return this.punishmentCollection.find(Filters.eq("uuid", uuid.toString())).first(); + } + + public void loadRank(UUID id, Consumer callback, boolean async) { + if (async) { + new Thread(() -> loadRank(id, callback, false)).start(); + return; + } + Rank rank; + if (BridgeGlobal.getRankHandler().getRankByID(id) != null) { + rank = BridgeGlobal.getRankHandler().getRankByID(id); + } else { + rank = new Rank(id, false); + } + + Document document = rankCollection.find(Filters.eq("uuid", id.toString())).first(); + + if (document == null) { + callback.accept(null); + return; + } + rank.setName(document.getString("name")); + rank.setDisplayName(document.getString("displayName")); + rank.setPriority(document.getInteger("priority")); + rank.setStaff(document.getBoolean("staff")); + rank.setMedia(document.getBoolean("media")); + rank.setHidden(document.getBoolean("hidden")); + rank.setGrantable(document.getBoolean("grantable")); + rank.setDefaultRank(document.getBoolean("defaultRank")); + rank.setColor(document.getString("color")); + rank.setPrefix(document.getString("prefix")); + rank.setSuffix(document.getString("suffix")); + + /*/ old perms /*/ + if (document.get("permissions") != null) { + List oldPerms = document.getList("permissions", String.class); + oldPerms.forEach(s -> rank.getPermissions().put(s, "Global")); + } + + if (document.get("permission") != null) { + rank.getPermissions().putAll(new Gson().fromJson(document.getString("permission"), new TypeToken>() { + }.getType())); + } + if (document.get("metadata") != null) { + rank.getMetaData().putAll(new Gson().fromJson(document.getString("metadata"), new TypeToken>() { + }.getType())); + } + + ArrayList inherits = new ArrayList<>(); + document.getList("inheritance", String.class).forEach(rankID -> inherits.add(UUID.fromString(rankID))); + rank.setInherits(inherits); + callback.accept(rank); + } + + public void saveRank(Rank rank, Consumer callback, boolean async) { + if (async) { + new Thread(() -> saveRank(rank, callback, false)).start(); + return; + } + + Document document = new Document() + .append("uuid", rank.getUuid().toString()) + .append("name", rank.getName()) + .append("displayName", rank.getDisplayName()) + .append("priority", rank.getPriority()) + .append("staff", rank.isStaff()) + .append("media", rank.isMedia()) + .append("builder", rank.isBuilder()) + .append("hidden", rank.isHidden()) + .append("grantable", rank.isGrantable()) + .append("defaultRank", rank.isDefaultRank()) + .append("color", rank.getColor()) + .append("prefix", rank.getPrefix()) + .append("suffix", rank.getSuffix()) + .append("permission", new Gson().toJson(rank.getPermissions())) + .append("metadata", new Gson().toJson(rank.getMetaData())) + .append("inheritance", rank.getInherits().stream().map(rankIn -> rankIn.getUuid().toString()).collect(Collectors.toList())); + + rankCollection.replaceOne(Filters.eq("uuid", rank.getUuid().toString()), document, new ReplaceOptions().upsert(true)); + callback.accept(true); + } + + public void removeRank(UUID id, Consumer callback, boolean async) { + if (async) { + new Thread(() -> removeRank(id, callback, false)).start(); + return; + } + Rank rank = BridgeGlobal.getRankHandler().getRankByID(id); + if (rank == null) { + callback.accept(false); + return; + } + + rankCollection.deleteOne(Filters.eq("uuid", rank.getUuid().toString())); + BridgeGlobal.getRankHandler().getRanks().remove(rank); + callback.accept(true); + } + + public void getRankInherits(Rank rank, Consumer> callback, boolean async) { + if (async) { + new Thread(() -> getRankInherits(rank, callback, false)).start(); + return; + } + Document document = rankCollection.find(Filters.eq("uuid", rank.getUuid().toString())).first(); + + if (document == null) { + callback.accept(null); + return; + } + List inherits = new ArrayList<>(); + + document.getList("inheritance", String.class).forEach(id -> inherits.add(UUID.fromString(id))); + callback.accept(inherits); + } + + /*/ + Prefixes - MongoDB + /*/ + +// public void savePrefix(){ +// Document filter = new Document("id", this.id); +// Document old = BridgeGlobal.getMongoHandler().getPrefixes().find(filter).first(); +// if(old == null) return; +// Document replace = new Document("id", this.id) +// .append("displayName", this.displayName) +// .append("prefix", this.prefix) +// .append("color", this.color) +// .append("priority", this.priority); +// BridgeGlobal.getMongoHandler().getPrefixes().replaceOne(old, replace); +// } + + + /*/ + Profile - MongoDB + /*/ + + public void getProfilesInDB(Consumer> callback) { + Set profiles = new HashSet<>(); + for (Document document : profileCollection.find()) { + profiles.add(UUID.fromString(document.get("uuid").toString())); + } + callback.accept(profiles); + } + + public void loadProfile(String input, Consumer callback, boolean async, LoadType loadType) { + if (async) { + new Thread(() -> loadProfile(input, callback, false, loadType)).start(); + return; + } + if (loadType == LoadType.UUID) { + try { + UUID uuid = UUID.fromString(input); + } catch (Exception e) { + callback.accept(null); + return; + } + } + + Document document = profileCollection.find(Filters.regex(loadType.getObjectName(), Pattern.compile("^" + input + "$", Pattern.CASE_INSENSITIVE))).first(); + if (document == null) { + callback.accept(null); + return; + } + + Profile profile = new Profile(document.getString("name"), UUID.fromString(document.getString("uuid")), false); + if (document.get("permission") != null) { + profile.getPermissions().putAll(new Gson().fromJson(document.getString("permission"), new TypeToken>() { + }.getType())); + } + List grants = new ArrayList<>(); + + document.getList("grants", String.class).forEach(grantStr -> grants.add(Grant.deserialize(grantStr))); + + profile.getGrants().addAll(grants); + if (document.containsKey("prefix")) profile.setPrefix(document.getString("prefix")); + if (document.containsKey("suffix")) profile.setSuffix(document.getString("suffix")); + if (document.containsKey("color")) profile.setColor(document.getString("color")); + + if (document.containsKey("currentIP")) profile.setCurrentIPAddress(document.getString("currentIP")); + if (document.containsKey("previousIPs")) + profile.setPreviousIPAddresses(new Gson().fromJson(document.getString("previousIPs"), new TypeToken>() { + }.getType())); + if (document.containsKey("bypassPunishmentAccounts")) + profile.setBypassPunishmentAccounts(new Gson().fromJson(document.getString("bypassPunishmentAccounts"), new TypeToken>() { + }.getType())); + if (document.containsKey("punishments")) + profile.setPunishments(new Gson().fromJson(document.getString("punishments"), new TypeToken>() { + }.getType())); + + if (document.containsKey("staffPunishments")) + profile.setStaffPunishments(new Gson().fromJson(document.getString("staffPunishments"), new TypeToken>() { + }.getType())); + + if (document.get("firstJoined") instanceof Integer) { + profile.setFirstJoined(System.currentTimeMillis()); + } else { + profile.setFirstJoined(document.getLong("firstJoined")); + } + + if (document.get("lastJoined") != null) profile.setLastJoined(document.getLong("lastJoined")); + if (document.get("lastQuit") != null) profile.setLastQuit(document.getLong("lastQuit")); + if (document.get("connectedServer") != null) profile.setConnectedServer(document.getString("connectedServer")); + if (document.get("metadata") != null) { + profile.getMetaData().putAll(new Gson().fromJson(document.getString("metadata"), new TypeToken>() { + }.getType())); + } + if(document.get("secretKey") != null) profile.setSecretKey(document.getString("secretKey")); + if(document.get("becameStaffOn") != null) profile.setBecameStaffOn(document.getLong("becameStaffOn")); + if(document.get("removedStaffOn") != null) profile.setRemovedStaffOn(document.getLong("removedStaffOn")); + callback.accept(profile); + } + + + public void saveProfile(Profile profile, Consumer callback, boolean async) { + if (async) { + new Thread(() -> saveProfile(profile, callback, false)).start(); + return; + } + List allGrants = new ArrayList<>(); + profile.getGrants().forEach(grant -> allGrants.add(Grant.serialize(grant).toString())); + Document document = new Document() + .append("uuid", profile.getUuid().toString()) + .append("name", profile.getUsername()) + .append("prefix", profile.getPrefix()) + .append("suffix", profile.getSuffix()) + .append("color", profile.getColor()) + .append("permission", new Gson().toJson(profile.getPermissions())) + .append("grants", allGrants) + + .append("currentIP", profile.getCurrentIPAddress()) + .append("previousIPs", new Gson().toJson(profile.getPreviousIPAddresses())) + .append("bypassPunishmentAccounts", new Gson().toJson(profile.getBypassPunishmentAccounts())) + .append("punishments", new Gson().toJson(profile.getPunishments())) + .append("staffPunishments", new Gson().toJson(profile.getStaffPunishments())) + + .append("firstJoined", profile.getFirstJoined()) + .append("lastJoined", profile.getLastJoined()) + .append("lastQuit", profile.getLastQuit()) + .append("connectedServer", profile.getConnectedServer()) + .append("metadata", new Gson().toJson(profile.getMetaData())) + .append("secretKey", profile.getSecretKey().isEmpty() ? "" : profile.getSecretKey()) + .append("becameStaffOn", profile.getBecameStaffOn()) + .append("removedStaffOn", profile.getRemovedStaffOn()); + + profileCollection.replaceOne(Filters.eq("uuid", profile.getUuid().toString()), document, new ReplaceOptions().upsert(true)); + callback.accept(true); + } + + public void removeProfile(UUID uuid, Consumer callback, boolean async) { + if (async) { + new Thread(() -> removeProfile(uuid, callback, false)).start(); + return; + } + profileCollection.deleteOne(Filters.eq("uuid", uuid.toString())); + callback.accept(true); + } + + @SuppressWarnings("This should never be ran on the main-thread!") + public List getProfiles() { + List profiles = new ArrayList<>(); + for (Document document : BridgeGlobal.getMongoHandler().getProfileCollection().find()) { + BridgeGlobal.getMongoHandler().loadProfile(document.getString("name"), profiles::add, false, LoadType.USERNAME); + } + return profiles; + } + + @SuppressWarnings("This should never be ran on the main-thread!") + public List getProfiles(String ip) { + List profiles = new ArrayList<>(); + BridgeGlobal.getMongoHandler().getProfiles(ip, profiles::addAll, false); + + return profiles; + } + + public void getProfiles(String ip, Consumer> callback, boolean async) { + if (async) { + new Thread(() -> getProfiles(ip, callback, false)).start(); + return; + } + if (ip == null || ip.equals("N/A")) { + callback.accept(null); + return; + } + boolean shouldGetAll = ip.toLowerCase().equals("*"); + FindIterable document = (shouldGetAll ? profileCollection.find() : profileCollection.find(Filters.eq("currentIP", ip))); + List profiles = new ArrayList<>(); + for (Document doc : document) { + if (doc == null) { + continue; + } + profiles.add(BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(UUID.fromString(doc.getString("uuid")))); + } + callback.accept(profiles); + } + + @AllArgsConstructor + @Getter + public enum LoadType { + + USERNAME("name"), + IP("currentIP"), + UUID("uuid"); + + private final String objectName; + + } + + /* + Filters - MongoDB + */ + + public void getFiltersInDB(Consumer> callback) { + ArrayList filters = new ArrayList<>(); + for (Document document : filterCollection.find()) { + filters.add(UUID.fromString(document.get("uuid").toString())); + } + callback.accept(filters); + } + + public void loadFilter(UUID uuid, Consumer callback, boolean async) { + if (async) { + new Thread(() -> loadFilter(uuid, callback, false)).start(); + return; + } + + Document document = filterCollection.find(Filters.regex("uuid", uuid.toString())).first(); + if (document == null) { + callback.accept(null); + return; + } + + callback.accept(new Filter(uuid, + FilterType.valueOf(document.getString("filterType")), + FilterAction.valueOf(document.getString("filterAction")), + document.getString("pattern"), + document.getLong("muteTime"))); + } + + + public void saveFilter(Filter filter, Consumer callback, boolean async) { + if (async) { + new Thread(() -> saveFilter(filter, callback, false)).start(); + return; + } + Document document = new Document() + .append("uuid", filter.getUuid().toString()) + .append("filterType", filter.getFilterType().name()) + .append("filterAction", filter.getFilterAction().name()) + .append("pattern", filter.getPattern()) + .append("muteTime", filter.getMuteTime()); + + filterCollection.replaceOne(Filters.eq("uuid", filter.getUuid().toString()), document, new ReplaceOptions().upsert(true)); + callback.accept(true); + } + + public void removeFilter(UUID uuid, Consumer callback, boolean async) { + if (async) { + new Thread(() -> removeFilter(uuid, callback, false)).start(); + return; + } + filterCollection.deleteOne(Filters.eq("uuid", uuid.toString())); + callback.accept(true); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/handlers/PacketLogHandler.java b/src/main/java/rip/bridge/bridge/global/handlers/PacketLogHandler.java new file mode 100644 index 0000000..81e9f41 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/handlers/PacketLogHandler.java @@ -0,0 +1,34 @@ +package rip.bridge.bridge.global.handlers; + +import com.google.common.collect.Maps; +import net.minecraft.server.v1_7_R4.Packet; +import org.bukkit.entity.Player; +import rip.bridge.bridge.bukkit.Bridge; +import rip.bridge.bridge.global.packetlogger.PacketLog; + +import java.util.ArrayList; +import java.util.Map; +import java.util.UUID; + +public class PacketLogHandler { + private Map> packetlog = Maps.newHashMap(); + + + public void log (Player player, Packet packet) { + ArrayList packetLogs; + if (!packetlog.containsKey(player.getUniqueId())) { + packetLogs = new ArrayList<>(); + } else { + packetLogs = packetlog.get(player.getUniqueId()); + } + packetLogs.add(new PacketLog(packet, player.getLocation(), System.currentTimeMillis(), Bridge.getInstance().getBlockedPackets().contains(packet))); + packetlog.put(player.getUniqueId(), packetLogs); + Bridge.getInstance().getBlockedPackets().remove(packet); + } + public ArrayList getLog(UUID uuid) { + if (!packetlog.containsKey(uuid)) { + return new ArrayList<>(); + } + return packetlog.get(uuid); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/handlers/PrefixHandler.java b/src/main/java/rip/bridge/bridge/global/handlers/PrefixHandler.java new file mode 100644 index 0000000..d9fbe1c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/handlers/PrefixHandler.java @@ -0,0 +1,77 @@ +package rip.bridge.bridge.global.handlers; + +import com.google.common.collect.Lists; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.prefix.Prefix; +import org.bson.Document; + +import java.util.List; + +public class PrefixHandler { + + private List prefixes = Lists.newArrayList(); + + private final MongoHandler mongoHandler = BridgeGlobal.getMongoHandler(); + + public void init(){ + int index = 0; + for(Document document : mongoHandler.getPrefixesCollection().find()){ + prefixes.add(parsePrefix(document)); + index++; + } +// BridgeGlobal.sendLog(Chat.LIGHT_GREEN + "Loaded a total of " + Chat.YELLOW + index + " prefix" + (index == 1 ? "" : "s") + Chat.LIGHT_GREEN + "."); + } + + public void recalculatePrefixes(){ + List temp = Lists.newArrayList(); + for(Document document : mongoHandler.getPrefixesCollection().find()){ + temp.add(parsePrefix(document)); + } + this.prefixes = temp; + } + + public List getPrefixesInOrder(){ + List prefixes = Lists.newArrayList(this.prefixes); + prefixes.sort((o1, o2) -> o2.getPriority() - o1.getPriority()); + return prefixes; + } + + public Prefix getPrefix(String id){ + for(Prefix prefix : prefixes){ + if(prefix.getId().equalsIgnoreCase(id.toLowerCase())){ + return prefix; + } + } + return null; + } + + public boolean prefixExists(String id){ + for(Prefix prefix : prefixes){ + if(prefix.getId().equals(id.toLowerCase())){ + return true; + } + } + return false; + } + + public void createPrefix(String name){ + mongoHandler.getPrefixesCollection().insertOne(parsePrefixToDocument(new Prefix(name.toLowerCase(), name, "&7[&f" + name + "&7]&f", "&f", 1))); + } + + public void deletePrefix(Prefix prefix){ + mongoHandler.getPrefixesCollection().deleteOne(parsePrefixToDocument(prefix)); + } + + public Prefix parsePrefix(Document document){ + return new Prefix(document.getString("id"), document.getString("displayName"), document.getString("prefix"), document.getString("color"), document.getInteger("priority")); + } + + public Document parsePrefixToDocument(Prefix prefix){ + return new Document("id", prefix.getId()) + .append("displayName", prefix.getDisplayName()) + .append("prefix", prefix.getPrefix()) + .append("color", prefix.getColor()) + .append("priority", prefix.getPriority()); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/handlers/ProfileHandler.java b/src/main/java/rip/bridge/bridge/global/handlers/ProfileHandler.java new file mode 100644 index 0000000..204e050 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/handlers/ProfileHandler.java @@ -0,0 +1,127 @@ +package rip.bridge.bridge.global.handlers; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.util.SystemType; +import lombok.Getter; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static java.lang.Thread.sleep; + +public class ProfileHandler { + + @Getter private Set profiles = new HashSet<>(); + + public void init() { + profiles.clear(); + new Thread(() -> { + + while(true) { + try { + sleep(TimeUnit.SECONDS.toMillis(10)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Iterator profileIterator = profiles.iterator(); + while (profileIterator.hasNext()) { + Profile profile = profileIterator.next(); + if(!profile.isOnline()) { + if(BridgeGlobal.getSystemType() == SystemType.BUKKIT) profile.saveProfile(); + profileIterator.remove(); + } + } + } + + }).start(); + } + + public Profile getProfileByUUID(UUID id) { + if (id == null) return null; + if(id.toString().equals(Profile.getConsoleProfile().getUuid().toString())) return Profile.getConsoleProfile(); + return profiles.stream().filter(rank->rank.getUuid().toString().equalsIgnoreCase(id.toString())).findFirst().orElse(null); + } + + public Profile getProfileByUsername(String id) { + if (id == null) return null; + if(id.equalsIgnoreCase("Console")) return Profile.getConsoleProfile(); + return profiles.stream().filter(rank->rank.getUsername().equalsIgnoreCase(id)).findFirst().orElse(null); + } + + public Profile getProfileByIP(String ip) { + return profiles.stream().filter(rank-> rank.getCurrentIPAddress().equals(ip)).findFirst().orElse(null); + } + + public Profile addProfile(Profile profile) { + profile.refreshCurrentGrant(); + profiles.add(profile); + return profile; + } + + public void save() { + profiles.forEach(profile -> { + BridgeGlobal.getMongoHandler().saveProfile(profile, callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully saved §f" + profile.getUsername() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save §f" + profile.getUsername() + "§c."); + } + }, true); + }); + } + + public void saveDisable() { + profiles.forEach(profile -> { + profile.setLastQuit(System.currentTimeMillis()); + BridgeGlobal.getMongoHandler().saveProfile(profile, callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully saved §f" + profile.getUsername() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save §f" + profile.getUsername() + "§c."); + } + }, false); + }); + } + + public Profile getProfileByUUIDOrCreate(UUID id) { + if(id == null) return null; + AtomicReference prof = new AtomicReference<>(getProfileByUUID(id)); + if (prof.get() == null) { + try { + BridgeGlobal.getMongoHandler().loadProfile(id.toString(), prof::set, false, MongoHandler.LoadType.UUID); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } + return prof.get(); + } + + public Profile getProfileByUsernameOrCreate(String id) { + if(id == null) return null; + AtomicReference prof = new AtomicReference<>(getProfileByUsername(id)); + if (prof.get() == null) { + try { + BridgeGlobal.getMongoHandler().loadProfile(id, prof::set, false, MongoHandler.LoadType.USERNAME); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } + return prof.get(); + } + + public Profile getNewProfileOrCreate(String name, UUID op) { + + Profile prof = getProfileByUUIDOrCreate(op); + if(prof == null) { + BridgeGlobal.getProfileHandler().addProfile(new Profile(name, op,false)).applyGrant(Grant.getDefaultGrant(), null, false); + prof = getProfileByUUID(op); + } + return prof; + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/handlers/RankHandler.java b/src/main/java/rip/bridge/bridge/global/handlers/RankHandler.java new file mode 100644 index 0000000..304248f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/handlers/RankHandler.java @@ -0,0 +1,105 @@ +package rip.bridge.bridge.global.handlers; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.ranks.Rank; +import lombok.Getter; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class RankHandler { + + @Getter private Set ranks = new HashSet<>(); + + public void init() { + ranks.clear(); + + try { + BridgeGlobal.getMongoHandler().getRanksInDB(callback-> { + + BridgeGlobal.sendLog("§aFound " + callback.size() + " ranks in database."); + + List rankList = new ArrayList<>(); + + AtomicInteger done = new AtomicInteger(); + + Rank rank; + for (UUID uuid : callback) { + rankList.add(new Rank(uuid, true, cbck -> { + Rank r = getRankByID(uuid); + if (r != null) { + r.load(); + done.getAndIncrement(); + } + })); + } + ranks.addAll(rankList); + if (done.get() == callback.size() && getDefaultRank() == null) { + Rank defaultRank = new Rank(UUID.randomUUID(), "Default", false); + defaultRank.setDefaultRank(true); + defaultRank.setHidden(false); + defaultRank.setColor("§f"); + ranks.add(defaultRank); + } + }); + BridgeGlobal.sendLog("§aSuccessfully loaded all ranks."); + } catch (Exception ex) { + BridgeGlobal.sendLog("§cFailed to initialize the rank manager."); + ex.printStackTrace(); + BridgeGlobal.sendLog(ex.getClass().getSimpleName() + " - " + ex.getMessage()); + } + } + + public Rank getRankByName(String name) { + return ranks.stream().filter(rank->rank.getName().equalsIgnoreCase(name)).findFirst().orElse(null); + } + + public Rank getRankByDisplayName(String name) { + return ranks.stream().filter(rank->rank.getDisplayName().equalsIgnoreCase(name)).findFirst().orElse(null); + } + + public Rank getRankByID(UUID id) { + for (Rank rank : ranks) { + if(rank.getUuid().equals(id)) return rank; + } + return null; + } + + public Rank addRank(Rank rank) { + Rank foundRank = ranks.stream().filter(rank1 -> rank1.getUuid().equals(rank.getUuid())).findFirst().orElse(null);; + if(foundRank != null) ranks.remove(foundRank); + ranks.add(rank); + return rank; + } + + public void save() { + ranks.forEach(rank -> { + BridgeGlobal.getMongoHandler().saveRank(rank, callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully saved rank §f" + rank.getColor() + rank.getName() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save rank §f" + rank.getColor() + rank.getName() + "§c."); + } + }, true); + }); + } + + public void saveDisable() { + ranks.forEach(rank -> { + if(rank.getName().equals("")) return; + BridgeGlobal.getMongoHandler().saveRank(rank, callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully saved rank §f" + rank.getColor() + rank.getName() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save rank §f" + rank.getColor() + rank.getName() + "§c."); + } + }, false); + }); + } + + public Rank getDefaultRank() { + return ranks.stream().filter(Rank::isDefaultRank).findFirst().orElse(null); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/packet/Packet.java b/src/main/java/rip/bridge/bridge/global/packet/Packet.java new file mode 100644 index 0000000..98605e3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/Packet.java @@ -0,0 +1,6 @@ +package rip.bridge.bridge.global.packet; + +public interface Packet { + public void onReceive(); +} + diff --git a/src/main/java/rip/bridge/bridge/global/packet/PacketHandler.java b/src/main/java/rip/bridge/bridge/global/packet/PacketHandler.java new file mode 100644 index 0000000..acf4e0a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/PacketHandler.java @@ -0,0 +1,74 @@ +package rip.bridge.bridge.global.packet; + +import com.google.gson.Gson; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +public final class PacketHandler { + + private static JedisPool jedisPool; + private static String jedisChannel; + + public static void init(JedisPool pool, String channel) { + jedisPool = pool; + jedisChannel = channel; + connectToServer(pool); + } + + public static void connectToServer(JedisPool connectTo) { + Thread subscribeThread = new Thread(() -> { + while (true) { + try { + Jedis jedis = connectTo.getResource(); + Throwable throwable = null; + try { + PacketPubSub pubSub = new PacketPubSub(); + jedis.subscribe(pubSub, jedisChannel); + } + catch (Throwable pubSub) { + throwable = pubSub; + throw pubSub; + } + finally { + if (jedis == null) continue; + if (throwable != null) { + try { + jedis.close(); + } + catch (Throwable pubSub) { + throwable.addSuppressed(pubSub); + } + continue; + } + jedis.close(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, "Bridge - Packet Subscribe Thread"); + subscribeThread.setDaemon(true); + subscribeThread.start(); + } + + public static void sendToAll(Packet packet) { + PacketHandler.send(packet, jedisPool); + } + + public static void send(Packet packet, JedisPool sendOn) { + + new Thread(() -> { + try (Jedis jedis = sendOn.getResource();){ + String encodedPacket = packet.getClass().getName() + "||" + new Gson().toJson(packet); + jedis.publish(jedisChannel, encodedPacket); + } + }).start(); + + } + + private PacketHandler() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packet/PacketPubSub.java b/src/main/java/rip/bridge/bridge/global/packet/PacketPubSub.java new file mode 100644 index 0000000..b35b5c1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/PacketPubSub.java @@ -0,0 +1,29 @@ +package rip.bridge.bridge.global.packet; + +import com.google.gson.Gson; +import redis.clients.jedis.JedisPubSub; + +final class PacketPubSub +extends JedisPubSub { + PacketPubSub() { + } + + @Override + public void onMessage(String channel, String message) { + Class packetClass; + int packetMessageSplit = message.indexOf("||"); + String packetClassStr = message.substring(0, packetMessageSplit); + String messageJson = message.substring(packetMessageSplit + "||".length()); + try { + packetClass = Class.forName(packetClassStr); + } + catch (ClassNotFoundException ignored) { + return; + } + Packet packet = (Packet) new Gson().fromJson(messageJson, packetClass); + if(packet != null) { + packet.onReceive(); + } + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/DisguisePacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/DisguisePacket.java new file mode 100644 index 0000000..3ea263c --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/DisguisePacket.java @@ -0,0 +1,20 @@ +package rip.bridge.bridge.global.packet.types; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.Packet; + +public class DisguisePacket implements Packet { + + public String message; + + public DisguisePacket(String message) { + this.message = message; + } + + @Override + public void onReceive() { + Bukkit.getOnlinePlayers().stream().filter(player -> BukkitAPI.getProfile(player).getCurrentGrant().getRank().isStaff()).forEach(player -> player.sendMessage(ChatColor.translateAlternateColorCodes('&', message))); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/GrantCreatePacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/GrantCreatePacket.java new file mode 100644 index 0000000..17e85d3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/GrantCreatePacket.java @@ -0,0 +1,32 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.packet.Packet; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.profile.Profile; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.bukkit.ChatColor; + +import java.util.UUID; + +@AllArgsConstructor @NoArgsConstructor +public class GrantCreatePacket implements Packet { + + private Grant grant; + private UUID target; + private String creator, server; + + @Override + public void onReceive() { + if(server.equals(BridgeGlobal.getSystemName())) return; + Profile pf = BridgeGlobal.getProfileHandler().getProfileByUUID(target); + if(pf == null) { + return; + } + pf.applyGrant(grant, null); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fSuccessfully granted " + pf.getColor() + pf.getUsername() + ChatColor.WHITE + " the " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.WHITE + " rank.")); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/NetworkBroadcastPacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/NetworkBroadcastPacket.java new file mode 100644 index 0000000..7f2265a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/NetworkBroadcastPacket.java @@ -0,0 +1,22 @@ +package rip.bridge.bridge.global.packet.types; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.bridge.global.packet.Packet; + +public class NetworkBroadcastPacket implements Packet { + + public String permission; + public String message; + + public NetworkBroadcastPacket(String permission, String message) { + this.permission = permission; + this.message = message; + } + + @Override + public void onReceive() { + Bukkit.getOnlinePlayers().stream().filter(player -> BukkitAPI.getProfile(player).hasPermission(permission)).forEach(player -> player.sendMessage(ChatColor.translateAlternateColorCodes('&', message))); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/PunishmentPacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/PunishmentPacket.java new file mode 100644 index 0000000..59d602d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/PunishmentPacket.java @@ -0,0 +1,21 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.Packet; +import rip.bridge.bridge.global.util.SystemType; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import rip.bridge.bridge.bukkit.listener.GeneralListener; +import rip.bridge.bridge.global.punishment.Punishment; + +@AllArgsConstructor @NoArgsConstructor +public class PunishmentPacket implements Packet { + + private Punishment punishment; + + @Override + public void onReceive() { + if(BridgeGlobal.getSystemType() == SystemType.BUKKIT) GeneralListener.handlePunishment(punishment, punishment.isPardoned()); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/RankCreatePacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/RankCreatePacket.java new file mode 100644 index 0000000..c4056d9 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/RankCreatePacket.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.Packet; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.ranks.Rank; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@AllArgsConstructor @NoArgsConstructor +public class RankCreatePacket implements Packet { + + private Rank rank; + private String creator, server; + + @Override + public void onReceive() { + if(server.equals(BridgeGlobal.getSystemName())) return; + BridgeGlobal.getRankHandler().addRank(rank); + BridgeGlobal.sendLog("Created rank " + rank.getDisplayName() + " (Executed by " + creator + " on " + server + ")"); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/RankDeletePacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/RankDeletePacket.java new file mode 100644 index 0000000..0800ab7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/RankDeletePacket.java @@ -0,0 +1,30 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.Packet; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.ranks.Rank; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@AllArgsConstructor @NoArgsConstructor +public class RankDeletePacket implements Packet { + + private Rank rank; + private String creator, server; + + @Override + public void onReceive() { + rank.removeRank(); + BridgeGlobal.getRankHandler().getRanks().remove(rank); + BridgeGlobal.getProfileHandler().getProfiles().forEach(profile -> { + profile.getActiveGrants().forEach(grant -> { + if (grant.getRank().getUuid().toString().equals(rank.toString())) { + profile.refreshCurrentGrant(); + } + }); + }); + BridgeGlobal.sendLog("Deleted rank " + rank.getDisplayName() + " (Executed by " + creator + " on " + server + ")"); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/RankUpdatePacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/RankUpdatePacket.java new file mode 100644 index 0000000..05dbdd3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/RankUpdatePacket.java @@ -0,0 +1,29 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.Packet; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.ranks.Rank; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import rip.bridge.bridge.bukkit.listener.GeneralListener; + +@AllArgsConstructor @NoArgsConstructor +public class RankUpdatePacket implements Packet { + + private Rank rank; + private String creator, server; + + @Override + public void onReceive() { + if(server.equals(BridgeGlobal.getSystemName())) { + rank.getOnlineProfilesInRank().forEach(profile -> GeneralListener.updatePermissions(profile.getUuid())); + return; + } + BridgeGlobal.getRankHandler().addRank(rank); + BridgeGlobal.sendLog("Refreshed rank " + rank.getDisplayName() + " (Executed by " + creator + " on " + server + ")"); + rank.getOnlineProfilesInRank().forEach(profile -> GeneralListener.updatePermissions(profile.getUuid())); + + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/ServerCommandPacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/ServerCommandPacket.java new file mode 100644 index 0000000..23d8865 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/ServerCommandPacket.java @@ -0,0 +1,24 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.global.packet.Packet; +import org.bukkit.Bukkit; + +public class ServerCommandPacket implements Packet { + + private final String server; + private final String command; + + public ServerCommandPacket(String server, String command) { + this.server = server; + this.command = command; + } + + @Override + public void onReceive() { + if (Bukkit.getServerName().equals(server)) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } else if (server.equals("globally")) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/ServerDeployPacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/ServerDeployPacket.java new file mode 100644 index 0000000..98a1cd2 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/ServerDeployPacket.java @@ -0,0 +1,40 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.deployment.DeploymentHandler; +import rip.bridge.bridge.global.packet.Packet; +import net.md_5.bungee.BungeeCord; +import rip.bridge.bridge.global.packet.PacketHandler; + +import java.io.File; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class ServerDeployPacket implements Packet { + + private String serverName; + private List plugins; + + @Override + public void onReceive() { + if (!BridgeGlobal.isHandleServerDeployment()) { + BridgeGlobal.sendLog("debug"); + return; + } + if (DeploymentHandler.doesServerExit(serverName)) { + BridgeGlobal.sendLog("Server with name already exists deploy failed."); + return; + } + + DeploymentHandler.createServer(serverName, BungeeCord.getInstance().getServers().values().stream().sorted(Comparator.comparingInt(o -> o.getAddress().getPort())).collect(Collectors.toList()).get(0).getAddress().getPort() + 1, plugins); + BridgeGlobal.sendLog("Attempting to deploy server with name \"" + serverName + "\" now."); + PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&aAttempting to deploy server with name \"" + serverName + "\" now.")); + } + + public ServerDeployPacket(String serverName, List plugins) { + this.serverName = serverName; + this.plugins = plugins; + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/ServerGroupCommandPacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/ServerGroupCommandPacket.java new file mode 100644 index 0000000..94f040d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/ServerGroupCommandPacket.java @@ -0,0 +1,23 @@ +package rip.bridge.bridge.global.packet.types; + +import org.bukkit.Bukkit; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.Packet; + +public class ServerGroupCommandPacket implements Packet { + + private final String serverGroup; + private final String command; + + public ServerGroupCommandPacket(String serverGroup, String command) { + this.serverGroup = serverGroup; + this.command = command; + } + + @Override + public void onReceive() { + if (BridgeGlobal.getServerHandler().getServer(Bukkit.getServerName()).getGroup().equals(serverGroup)) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/packet/types/ServerShutdownPacket.java b/src/main/java/rip/bridge/bridge/global/packet/types/ServerShutdownPacket.java new file mode 100644 index 0000000..a265132 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packet/types/ServerShutdownPacket.java @@ -0,0 +1,27 @@ +package rip.bridge.bridge.global.packet.types; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.packet.Packet; +import rip.bridge.bridge.global.util.Tasks; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.bukkit.Bukkit; + +@AllArgsConstructor @NoArgsConstructor +public class ServerShutdownPacket implements Packet { + + private String serverName; + + @Override + public void onReceive() { + if(this.serverName.equalsIgnoreCase("all") || BridgeGlobal.getSystemName().equalsIgnoreCase(this.serverName)) { + System.out.println("Received Shutdown Packet! Closing server."); + Tasks.run(() -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "stop")); + } else { + if (this.serverName.equalsIgnoreCase("all") || this.serverName.equalsIgnoreCase("BungeeCord")) { + System.out.println("Received Shutdown Packet! Closing server."); + Tasks.run(() -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "end")); + } + } + } +} diff --git a/src/main/java/rip/bridge/bridge/global/packetlogger/PacketLog.java b/src/main/java/rip/bridge/bridge/global/packetlogger/PacketLog.java new file mode 100644 index 0000000..efb7bd6 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packetlogger/PacketLog.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.global.packetlogger; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.minecraft.server.v1_7_R4.Packet; +import org.bukkit.Location; + +@AllArgsConstructor +@Getter @Setter +@NoArgsConstructor +public class PacketLog { + private Packet packet; + private Location location; + private long time; + private boolean flagged; +} diff --git a/src/main/java/rip/bridge/bridge/global/packets/GrantCreatePacket.java b/src/main/java/rip/bridge/bridge/global/packets/GrantCreatePacket.java new file mode 100644 index 0000000..b3781c5 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/GrantCreatePacket.java @@ -0,0 +1,71 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.JsonObject; +import java.util.UUID; + +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +public class GrantCreatePacket +implements Packet { + private Grant grant; + private UUID target; + private String granter; + private String server; + + public GrantCreatePacket() { + } + + public GrantCreatePacket(Grant grant, UUID target, String granter, String server) { + this.grant = grant; + this.target = target; + this.granter = granter; + this.server = server; + } + + @Override + public void onReceive() { + + } + + public int id() { + return 3; + } + + public String sentFrom() { + return this.server; + } + + public boolean selfRecieve() { + return false; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("grant", Grant.serialize(this.grant).toString()).addProperty("target", this.target.toString()).addProperty("granter", this.granter).addProperty("server", this.server).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.grant = Grant.deserialize(jsonObject.get("grant").getAsString()); + this.target = UUID.fromString(jsonObject.get("target").getAsString()); + this.granter = jsonObject.get("granter").getAsString(); + this.server = jsonObject.get("server").getAsString(); + } + + public Grant getGrant() { + return this.grant; + } + + public UUID getTarget() { + return this.target; + } + + public String getGranter() { + return this.granter; + } + + public String getServer() { + return this.server; + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packets/GrantRemovePacket.java b/src/main/java/rip/bridge/bridge/global/packets/GrantRemovePacket.java new file mode 100644 index 0000000..0a7fd63 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/GrantRemovePacket.java @@ -0,0 +1,71 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.JsonObject; +import java.util.UUID; + +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +public class GrantRemovePacket +implements Packet { + private Grant grant; + private UUID target; + private String granter; + private String server; + + public GrantRemovePacket() { + } + + public GrantRemovePacket(Grant grant, UUID target, String remover, String server) { + this.grant = grant; + this.target = target; + this.granter = this.granter; + this.server = server; + } + + public int id() { + return 911; + } + + public String sentFrom() { + return this.server; + } + + public boolean selfRecieve() { + return false; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("grant", Grant.serialize(this.grant).toString()).addProperty("target", this.target.toString()).addProperty("granter", this.granter).addProperty("server", this.server).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.grant = Grant.deserialize(jsonObject.get("grant").getAsString()); + this.target = UUID.fromString(jsonObject.get("target").getAsString()); + this.granter = jsonObject.get("granter").getAsString(); + this.server = jsonObject.get("server").getAsString(); + } + + public Grant getGrant() { + return this.grant; + } + + public UUID getTarget() { + return this.target; + } + + public String getGranter() { + return this.granter; + } + + public String getServer() { + return this.server; + } + + @Override + public void onReceive() { + + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packets/PunishmentPacket.java b/src/main/java/rip/bridge/bridge/global/packets/PunishmentPacket.java new file mode 100644 index 0000000..0d14a8a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/PunishmentPacket.java @@ -0,0 +1,48 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.JsonObject; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +public class PunishmentPacket +implements Packet { + private String json; + + public PunishmentPacket() { + } + + public int id() { + return 5; + } + + public String sentFrom() { + return BridgeGlobal.getSystemName(); + } + + public boolean selfRecieve() { + return true; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("json", this.json).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.json = jsonObject.get("json").getAsString(); + } + + public String getJson() { + return this.json; + } + + public PunishmentPacket(String json) { + this.json = json; + } + + @Override + public void onReceive() { + + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packets/RankCreatePacket.java b/src/main/java/rip/bridge/bridge/global/packets/RankCreatePacket.java new file mode 100644 index 0000000..db086a7 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/RankCreatePacket.java @@ -0,0 +1,63 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.JsonObject; +import java.util.UUID; + +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +public class RankCreatePacket +implements Packet { + private UUID rank; + private String creator; + private String server; + + public RankCreatePacket() { + } + + public RankCreatePacket(UUID rank, String creator, String server) { + this.rank = rank; + this.creator = creator; + this.server = server; + } + + @Override + public void onReceive() { + + } + + public int id() { + return 0; + } + + public String sentFrom() { + return this.server; + } + + public boolean selfRecieve() { + return false; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("rank", this.rank.toString()).addProperty("creator", this.creator).addProperty("server", this.server).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.rank = UUID.fromString(jsonObject.get("rank").getAsString()); + this.creator = jsonObject.get("creator").getAsString(); + this.server = jsonObject.get("server").getAsString(); + } + + public UUID getRank() { + return this.rank; + } + + public String getCreator() { + return this.creator; + } + + public String getServer() { + return this.server; + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packets/RankDeletePacket.java b/src/main/java/rip/bridge/bridge/global/packets/RankDeletePacket.java new file mode 100644 index 0000000..174feac --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/RankDeletePacket.java @@ -0,0 +1,63 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.JsonObject; +import java.util.UUID; + +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +public class RankDeletePacket +implements Packet { + private UUID rank; + private String creator; + private String server; + + public RankDeletePacket() { + } + + public RankDeletePacket(UUID rank, String creator, String server) { + this.rank = rank; + this.creator = creator; + this.server = server; + } + + @Override + public void onReceive() { + + } + + public int id() { + return 1; + } + + public String sentFrom() { + return this.server; + } + + public boolean selfRecieve() { + return false; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("rank", this.rank.toString()).addProperty("creator", this.creator).addProperty("server", this.server).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.rank = UUID.fromString(jsonObject.get("rank").getAsString()); + this.creator = jsonObject.get("creator").getAsString(); + this.server = jsonObject.get("server").getAsString(); + } + + public UUID getRank() { + return this.rank; + } + + public String getCreator() { + return this.creator; + } + + public String getServer() { + return this.server; + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packets/RankUpdatePacket.java b/src/main/java/rip/bridge/bridge/global/packets/RankUpdatePacket.java new file mode 100644 index 0000000..947090e --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/RankUpdatePacket.java @@ -0,0 +1,63 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +public class RankUpdatePacket +implements Packet { + private Rank rank; + private String creator; + private String server; + + public RankUpdatePacket() { + } + + public RankUpdatePacket(Rank rank, String creator, String server) { + this.rank = rank; + this.creator = creator; + this.server = server; + } + + @Override + public void onReceive() { + + } + + public int id() { + return 2; + } + + public String sentFrom() { + return this.server; + } + + public boolean selfRecieve() { + return false; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("rank", new Gson().toJson(this.rank)).addProperty("creator", this.creator).addProperty("server", this.server).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.rank = new Gson().fromJson(jsonObject.get("rank").getAsString(), Rank.class); + this.creator = jsonObject.get("creator").getAsString(); + this.server = jsonObject.get("server").getAsString(); + } + + public Rank getRank() { + return this.rank; + } + + public String getCreator() { + return this.creator; + } + + public String getServer() { + return this.server; + } +} + diff --git a/src/main/java/rip/bridge/bridge/global/packets/ServerDeployPacket.java b/src/main/java/rip/bridge/bridge/global/packets/ServerDeployPacket.java new file mode 100644 index 0000000..e650401 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/packets/ServerDeployPacket.java @@ -0,0 +1,47 @@ +package rip.bridge.bridge.global.packets; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import rip.bridge.bridge.global.util.JsonChain; +import rip.bridge.bridge.global.packet.Packet; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +public class ServerDeployPacket + implements Packet { + private String serverName; + private List plugins; + + @Override + public void onReceive() { + + } + + public ServerDeployPacket(String serverName, List plugins) { + this.serverName = serverName; + this.plugins = plugins; + } + + public boolean selfRecieve() { + return false; + } + + public JsonObject serialize() { + return new JsonChain().addProperty("serverName", serverName).addProperty("plugins", new Gson().toJson(plugins)).get(); + } + + public void deserialize(JsonObject jsonObject) { + this.serverName = jsonObject.get("serverName").getAsString(); + this.plugins = Arrays.asList(new Gson().fromJson(jsonObject.get("plugins").getAsString(), File[].class)); + } + + public String getServerName() { + return this.serverName; + } + + public List getPlugins() { + return this.plugins; + } +} diff --git a/src/main/java/rip/bridge/bridge/global/prefix/Prefix.java b/src/main/java/rip/bridge/bridge/global/prefix/Prefix.java new file mode 100644 index 0000000..afc289a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/prefix/Prefix.java @@ -0,0 +1,30 @@ +package rip.bridge.bridge.global.prefix; + +import rip.bridge.bridge.BridgeGlobal; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.bson.Document; + +@Data +@AllArgsConstructor +public class Prefix { + + private String id; + private String displayName; + private String prefix; + private String color; + private int priority; + + public void save(){ + Document filter = new Document("id", this.id); + Document old = BridgeGlobal.getMongoHandler().getPrefixesCollection().find(filter).first(); + if(old == null) return; + Document replace = new Document("id", this.id) + .append("displayName", this.displayName) + .append("prefix", this.prefix) + .append("color", this.color) + .append("priority", this.priority); + BridgeGlobal.getMongoHandler().getPrefixesCollection().replaceOne(old, replace); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/profile/Profile.java b/src/main/java/rip/bridge/bridge/global/profile/Profile.java new file mode 100644 index 0000000..0c62fa1 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/profile/Profile.java @@ -0,0 +1,283 @@ +package rip.bridge.bridge.global.profile; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.GlobalAPI; +import lombok.Getter; +import lombok.Setter; +import rip.bridge.bridge.bukkit.listener.GeneralListener; +import rip.bridge.bridge.global.handlers.MongoHandler; +import rip.bridge.bridge.global.disguise.DisguisePlayer; +import rip.bridge.bridge.global.grant.Grant; +import rip.bridge.bridge.global.punishment.Punishment; +import rip.bridge.bridge.global.punishment.PunishmentType; +import rip.bridge.bridge.global.ranks.Rank; +import rip.bridge.bridge.global.util.SystemType; + +import java.util.*; +import java.util.stream.Collectors; + +@Getter +@Setter +public class Profile { + + @Getter + private static Profile consoleProfile = new Profile(UUID.fromString("00000000-0000-0000-0000-000000000000"), "Console", "§8[§4§lCONSOLE§8] §4", "§f", "§4§l"); + + private UUID uuid; + private String username, prefix = "", suffix = "", color = "", connectedServer; + private List grants; + private Rank tagRank = null; + private List activePermissions; + private HashMap permissions; + private boolean debug = false; + private long firstJoined = System.currentTimeMillis(), lastJoined = System.currentTimeMillis(), lastQuit = System.currentTimeMillis(); + private Map metaData; + + private String currentIPAddress; + private HashSet previousIPAddresses; + private HashSet bypassPunishmentAccounts; + private HashSet punishments; + private HashSet staffPunishments; + + private boolean totpRequired; + private String secretKey = ""; + + private long becameStaffOn; // Still active + private long returnedOn; // Returned + private long removedStaffOn; // Resigned + + public Profile(String username, UUID uuid, boolean load) { + this.username = username; + this.uuid = uuid; + this.grants = new ArrayList<>(); + this.permissions = new HashMap<>(); + this.activePermissions = new ArrayList<>(); + this.metaData = new HashMap<>(); + this.previousIPAddresses = new HashSet<>(); + this.bypassPunishmentAccounts = new HashSet<>(); + this.punishments = new HashSet<>(); + this.staffPunishments = new HashSet<>(); + this.totpRequired = false; + + if (load) { + BridgeGlobal.getMongoHandler().loadProfile(this.uuid.toString(), profile -> { + if (profile != null) { + this.importSettings(profile); + } + }, true, MongoHandler.LoadType.UUID); + } + } + + public Profile(UUID uuid, String username, String prefix, String suffix, String color) { + this.uuid = uuid; + this.username = username; + this.prefix = prefix; + this.suffix = suffix; + this.color = color; + } + + public void importSettings(Profile profile) { + this.grants = profile.getGrants(); + this.permissions = profile.getPermissions(); + + this.firstJoined = profile.getFirstJoined(); + this.lastJoined = profile.getLastJoined(); + this.lastQuit = profile.getLastQuit(); + + this.connectedServer = profile.getConnectedServer(); + this.metaData = profile.getMetaData(); + + this.currentIPAddress = profile.getCurrentIPAddress(); + this.previousIPAddresses = profile.getPreviousIPAddresses(); + this.bypassPunishmentAccounts = profile.getBypassPunishmentAccounts(); + this.punishments = profile.getPunishments(); + this.staffPunishments = profile.getStaffPunishments(); + + this.secretKey = profile.getSecretKey(); + this.becameStaffOn = profile.getBecameStaffOn(); + this.removedStaffOn = profile.getRemovedStaffOn(); + refreshCurrentGrant(); + } + + public void checkTotpLock(UUID uuid, String ip) { + Profile p = BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid); + if (getCurrentGrant().getRank().isStaff() && !p.currentIPAddress.equals(ip)) { + this.totpRequired = true; + } else { + this.totpRequired = false; + } + + } + + public void saveProfile() { + BridgeGlobal.getMongoHandler().saveProfile(this, callback -> { + if (callback) { + BridgeGlobal.sendLog("§aSuccessfully saved §f" + getUsername() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save §f" + getUsername() + "§c."); + } + }, true); + } + + public List getActiveGrants() { + List active = new ArrayList<>(); + + if (grants == null) // Fix console NPE + return active; + + grants.removeIf(grant -> grant.getRank() == null || GlobalAPI.getRank(grant.getRank().getUuid()) == null); + for (Grant grant : grants) { + + if (grant.isStillActive() && grant.isGrantActiveOnScope()) { + active.add(grant); + } + } + active.sort(Comparator.comparingInt(o -> o.getRank().getPriority())); + return active; + } + + public Grant getCurrentGrant() { + Grant grant = null; + + for (Grant activeGrant : getActiveGrants()) { + if (grant == null) { + grant = activeGrant; + continue; + } + if (activeGrant.getRank().getPriority() > grant.getRank().getPriority()) { + grant = activeGrant; + } + } + + if (grant == null) { + applyGrant(Grant.getDefaultGrant(), null, false); + for (Grant activeGrant : getActiveGrants()) { + if (grant == null) { + grant = activeGrant; + continue; + } + if (activeGrant.getRank().getPriority() > grant.getRank().getPriority()) { + grant = activeGrant; + } + } + } + + return grant; + } + + + public Rank getDisguisedRank() { + DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(this.uuid); + return disguisePlayer != null ? disguisePlayer.getDisguiseRank() : null; + } + + public DisguisePlayer getDisguise() { + return BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(this.uuid); + } + + public boolean isOnline() { + return BridgeGlobal.getServerHandler().findPlayerServer(getUuid()) != null; + } + + public String getConnectedServer() { + return (BridgeGlobal.getServerHandler().findPlayerServer(getUuid()) == null ? (this.connectedServer == null ? "N/A" : this.connectedServer) : BridgeGlobal.getServerHandler().findPlayerServer(getUuid()).getName()); + } + + public void applyGrant(Grant grant, UUID executor, boolean shouldGetCurrentGrant) { + if (grants == null) return; // Fix console NPE + + if (grant.getRank().isStaff() && getBecameStaffOn() == 0) becameStaffOn = grant.getInitialTime(); + + grants.add(grant); + if (shouldGetCurrentGrant && getCurrentGrant().getUuid().toString().equalsIgnoreCase(grant.getUuid().toString())) { + refreshCurrentGrant(); + } + BridgeGlobal.sendLog("Successfully applied " + getUsername() + "'s Grant of the " + grant.getRank().getName() + " Rank"); + } + + public void refreshCurrentGrant() { + if (BridgeGlobal.getSystemType() == SystemType.BUKKIT) GeneralListener.updatePermissions(getUuid()); + } + + public void updateColor() { + GeneralListener.updateColor(getUuid()); + } + + public void applyGrant(Grant grant, UUID executor) { + applyGrant(grant, executor, true); + } + + public boolean hasGrantOf(Rank rank, boolean onScope) { + if (onScope) + return getGrants().stream().filter(grant -> grant.getUuid().toString().equalsIgnoreCase(rank.getUuid().toString()) && grant.isGrantActiveOnScope()).findFirst().orElse(null) != null; + return getGrants().stream().filter(grant -> grant.getUuid().toString().equalsIgnoreCase(rank.getUuid().toString())).findFirst().orElse(null) != null; + } + + public boolean hasGrantOf(Rank rank) { + return hasGrantOf(rank, false); + } + + public boolean hasActiveGrantOf(Rank rank) { + return getActiveGrants().stream().filter(grant -> grant.getUuid().toString().equalsIgnoreCase(rank.getUuid().toString())).findFirst().orElse(null) != null; + } + + /* + Punishments + */ + + public Punishment getPunishmentByID(UUID id) { + return punishments.stream().filter(punishment -> punishment.getUuid().toString().equals(id.toString())).findFirst().orElse(null); + } + + public Set getActivePunishments() { + return this.punishments.stream().filter(Punishment::isActive).collect(Collectors.toSet()); + } + + public Set getActivePunishments(PunishmentType punishmentType) { + return this.punishments.stream().filter(punishment -> punishment.getPunishmentType() == punishmentType && punishment.isActive()).collect(Collectors.toSet()); + } + + public Set getAltActivePunishments(PunishmentType punishmentType) { + Set punishments = new HashSet<>(); + if (currentIPAddress == null) return punishments; + + for (Profile alt : BridgeGlobal.getMongoHandler().getProfiles(currentIPAddress)) { + punishments.addAll(alt.getActivePunishments()); + } + + return punishments; + + } + + public Set getPunishments(PunishmentType punishmentType) { + return this.punishments.stream().filter(punishment -> punishment.getPunishmentType() == punishmentType).collect(Collectors.toSet()); + } + + public boolean isMuted() { + return getActivePunishments(PunishmentType.MUTE).size() > 0; + } + + public Punishment getMute() { + return (Punishment) getActivePunishments(PunishmentType.MUTE).toArray()[0]; + } + + public boolean hasPermission(String str) { + return hasPermission(str, BridgeGlobal.getServerName()) || hasPermission(str, "GR|" + BridgeGlobal.getGroupName()); + } + + public boolean hasPermission(String str, String serverOrGroup) { + if (getPermissions().containsKey("*") && (getPermissions().get("*").equalsIgnoreCase("Global") || getPermissions().get("*").equalsIgnoreCase(serverOrGroup))) + return true; + return getActiveGrants().stream().filter(grant -> grant.isGrantActiveOnScope() && grant.isStillActive()).anyMatch(grant -> grant.getRank().hasPermission(str, serverOrGroup)) || getPermissions().containsKey(str) && (getPermissions().get(str).equalsIgnoreCase(serverOrGroup) || getPermissions().get(str).equalsIgnoreCase("Global")); + } + + public boolean togglePerm(String str, String serverOrGroup) { + if (hasPermission(str, serverOrGroup)) { + getPermissions().remove(str); + return false; + } else { + getPermissions().put(str, serverOrGroup); + return true; + } + } +} diff --git a/src/main/java/rip/bridge/bridge/global/profile/ProfileWeightComparator.java b/src/main/java/rip/bridge/bridge/global/profile/ProfileWeightComparator.java new file mode 100644 index 0000000..365cddd --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/profile/ProfileWeightComparator.java @@ -0,0 +1,12 @@ +package rip.bridge.bridge.global.profile; + +import java.util.Comparator; + +public class ProfileWeightComparator implements Comparator { + + @Override + public int compare(Profile profile,Profile otherProfile) { + return Integer.compare(profile.getCurrentGrant().getRank().getPriority(),otherProfile.getCurrentGrant().getRank().getPriority()); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/punishment/Evidence.java b/src/main/java/rip/bridge/bridge/global/punishment/Evidence.java new file mode 100644 index 0000000..797a18d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/punishment/Evidence.java @@ -0,0 +1,12 @@ +package rip.bridge.bridge.global.punishment; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public class Evidence { + + @Getter + String sender; + @Getter String URL; +} diff --git a/src/main/java/rip/bridge/bridge/global/punishment/Punishment.java b/src/main/java/rip/bridge/bridge/global/punishment/Punishment.java new file mode 100644 index 0000000..9edc585 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/punishment/Punishment.java @@ -0,0 +1,147 @@ +package rip.bridge.bridge.global.punishment; + +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.util.TimeUtil; +import lombok.Getter; +import lombok.Setter; +import rip.bridge.bridge.bukkit.BukkitAPI; +import rip.bridge.qlib.util.TimeUtils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; + +@Getter @Setter +public class Punishment { + + private UUID uuid; + private UUID target, executor, pardonedBy; + private PunishmentType punishmentType; + private boolean pardoned, isIP, silent, clear; + private String punishedServer, reason, pardonedServer, pardonedReason; + private long time, duration, pardonedAt; + private HashSet proof; + + public Punishment(Profile target, Profile executor, String punishedServer, String reason, PunishmentType punishmentType,HashSet proof, boolean isIP, boolean silent, boolean clear, long duration) { + this.uuid = UUID.randomUUID(); + this.target = target.getUuid(); + this.executor = executor.getUuid(); + this.punishedServer = punishedServer; + this.reason = reason; + this.punishmentType = punishmentType; + this.isIP = isIP; + this.silent = silent; + this.clear = clear; + this.time = System.currentTimeMillis(); + this.duration = duration; + this.proof = proof; + } + + public Punishment(UUID uuid, Profile target, Profile executor, Profile pardonedBy, PunishmentType punishmentType, HashSet proof, boolean pardoned, boolean isIP, boolean silent, boolean clear, String punishedServer, String reason, String pardonedServer, String pardonedReason, long time, long duration, long pardonedAt, Profile profile) { + this.uuid = uuid; + this.target = target.getUuid(); + this.executor = executor.getUuid(); + this.pardonedBy = pardonedBy.getUuid(); + this.punishmentType = punishmentType; + this.pardoned = pardoned; + this.isIP = isIP; + this.silent = silent; + this.clear = clear; + this.punishedServer = punishedServer; + this.reason = reason; + this.pardonedServer = pardonedServer; + this.pardonedReason = pardonedReason; + this.time = time; + this.duration = duration; + this.pardonedAt = pardonedAt; + this.proof = proof; + } + + public Punishment(UUID uuid, Profile target, Profile executor, Profile profile, PunishmentType punishmentType, Boolean pardoned, Boolean isIP, Boolean silent, Boolean clear, String punishedServer, String reason, String pardonedServer, String pardonedReason, Long time, Long duration, Long pardonedAt) { + } + + + public boolean isPermanent() { + return this.punishmentType == PunishmentType.BLACKLIST || this.duration == Long.MAX_VALUE; + } + + public long getRemainingTime() { + return System.currentTimeMillis() - (this.time + this.duration); + } + + public boolean isActive() { + return !this.pardoned && (this.isPermanent() || this.getRemainingTime() < 0L); + } + + public void pardon(Profile pardonedBy, String pardonedServer, String pardonedReason, boolean silent) { + this.pardoned = true; + this.pardonedAt = System.currentTimeMillis(); + this.pardonedBy = pardonedBy.getUuid(); + this.pardonedServer = pardonedServer; + this.pardonedReason = pardonedReason; + this.silent = silent; + } + + public String getRemainingString() { + if (this.pardoned) { + return "Pardoned"; + } + if (this.isPermanent()) { + return "Permanent"; + } + if (!this.isActive()) { + return "Expired"; + } + return TimeUtils.formatIntoDetailedString((int) ((this.time + this.duration - System.currentTimeMillis()) / 1000)); + } + + public String getStatusString() { + if (this.pardoned) { + return "Pardoned"; + } + if (this.isPermanent()) { + return "Permanent"; + } + if (!this.isActive()) { + return "Expired"; + } + return "Active"; + } + + public String getDurationString() { + if (this.isPermanent()) { + return "Permanent"; + } + return TimeUtil.millisToRoundedTime(this.duration); + } + + public String getDisplayName() { + if (this.punishmentType != PunishmentType.BAN && this.punishmentType != PunishmentType.MUTE) { + return this.pardoned ? this.punishmentType.getUndoPunishmentName() : this.punishmentType.getPunishmentName(); + } + if (this.isPermanent()) { + return this.pardoned ? this.punishmentType.getUndoPunishmentName() : (this.punishmentType.getPunishmentName()); + } + return this.pardoned ? this.punishmentType.getUndoPunishmentName() : ("temporarily " + this.punishmentType.getPunishmentName()); + } + + public Profile getTarget() { + return BukkitAPI.getProfile(target); + } + + public Profile getExecutor() { + return BukkitAPI.getProfile(executor); + } + + public Profile getPardonedBy() { + return BukkitAPI.getProfile(pardonedBy); + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/punishment/PunishmentType.java b/src/main/java/rip/bridge/bridge/global/punishment/PunishmentType.java new file mode 100644 index 0000000..72dccfe --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/punishment/PunishmentType.java @@ -0,0 +1,19 @@ +package rip.bridge.bridge.global.punishment; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter @AllArgsConstructor +public enum PunishmentType { + + WARN("Warn", "warned", "unwarned"), + KICK("Kick", "kicked", null), + MUTE("Mute", "muted", "unmuted"), + BAN("Ban", "banned", "unbanned"), + BLACKLIST("Blacklist", "blacklisted", "unblacklisted"); + + private String displayName; + private String punishmentName; + private String undoPunishmentName; + +} diff --git a/src/main/java/rip/bridge/bridge/global/ranks/Rank.java b/src/main/java/rip/bridge/bridge/global/ranks/Rank.java new file mode 100644 index 0000000..99a204d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/ranks/Rank.java @@ -0,0 +1,205 @@ +package rip.bridge.bridge.global.ranks; + +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.GlobalAPI; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; +import rip.bridge.bridge.global.profile.Profile; +import rip.bridge.bridge.global.util.SystemType; +import rip.bridge.bridge.bukkit.listener.GeneralListener; +import lombok.Getter; +import lombok.Setter; + +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +@Getter @Setter +public class Rank { + + private UUID uuid; + private String name = "", prefix = "§f", suffix = "§f", color = "§f", displayName = ""; + private int priority = 0; + private boolean staff = false, media = false, builder = false, hidden = false, grantable = true, defaultRank = false; + private ArrayList inherits; + private Map permissions, metaData; + @Getter + private static List ranks = new ArrayList<>(); + + public Rank(UUID id, boolean imp) { + this(id, imp, callback -> {}); + } + + public Rank(UUID id, boolean imp, Consumer callback) { + this.uuid = id; + this.permissions = new HashMap<>(); + this.metaData = new HashMap<>(); + this.inherits = new ArrayList<>(); + if (imp) { + BridgeGlobal.getMongoHandler().loadRank(this.uuid, rank -> { + if (rank != null) { + this.importSettings(rank); + callback.accept(true); + } else { + callback.accept(false); + } + }, true); + } else { + callback.accept(true); + } + } + + public Rank(UUID id, String name, boolean imp) { + this.uuid = id; + this.name = name; + this.displayName = name; + this.permissions = new HashMap<>(); + this.metaData = new HashMap<>(); + this.inherits = new ArrayList<>(); + if (imp) { + BridgeGlobal.getMongoHandler().loadRank(this.uuid, rank -> { + if (rank != null) { + this.importSettings(rank); + } + }, true); + } + } + + + public Rank(UUID id, String name, String prefix, String suffix, String displayName, int priority, boolean staff, boolean media, boolean builder, boolean hidden, boolean grantable, boolean defaultRank, String color) { + this.uuid = id; + this.name = name; + this.prefix = prefix; + this.suffix = suffix; + this.priority = priority; + this.staff = staff; + this.media = media; + this.builder = builder; + this.hidden = hidden; + this.grantable = grantable; + this.displayName = displayName; + this.defaultRank = defaultRank; + this.color = color; + this.permissions = new HashMap<>(); + this.metaData = new HashMap<>(); + this.inherits = new ArrayList<>(); + } + + public void load() { + + } + + public void importSettings(Rank rank) { + if (rank == null) return; + this.name = rank.getName(); + this.prefix = rank.getPrefix(); + this.suffix = rank.getSuffix(); + this.priority = rank.getPriority(); + this.staff = rank.isStaff(); + this.media = rank.isMedia(); + this.media = rank.isBuilder(); + this.hidden = rank.isHidden(); + this.grantable = rank.isGrantable(); + this.displayName = rank.getDisplayName(); + this.defaultRank = rank.isDefaultRank(); + this.color = rank.getColor(); + this.permissions = rank.getPermissions(); + this.metaData = rank.getMetaData(); + this.inherits = rank.inherits; + } + + public void removeRank() { + + BridgeGlobal.getMongoHandler().removeRank(this.getUuid(), callback -> { + if(callback != null) { + BridgeGlobal.sendLog("§aSuccessfully deleted rank §r" + this.getColor() + this.getName() + "§a."); + for (Profile profile : BridgeGlobal.getProfileHandler().getProfiles()) { + profile.getGrants().removeIf(grant -> grant.getRank() == null); + profile.refreshCurrentGrant(); + } + }else { + BridgeGlobal.sendLog("§cFailed to delete rank §r" + this.getColor() + this.getName() + "§a."); + } + }, true); + + } + + public boolean hasPermission(String str, String serverOrGroup) { + if(getPermissions().containsKey("*") && (getPermissions().get("*").equalsIgnoreCase("Global") || getPermissions().get("*").equalsIgnoreCase(serverOrGroup))) return true; + return getPermissions().containsKey(str) && (getPermissions().get(str).equalsIgnoreCase("Global") || getPermissions().get(str).equalsIgnoreCase(serverOrGroup) || getPermissions().containsKey(str)) || hasInheritPermission(str, serverOrGroup); + } + + public boolean hasInheritPermission(String str, String serverOrGroup) { + for (Rank inherit : getInherits()) { + return inherit.hasPermission(str, serverOrGroup); + } + return false; + } + + public static Rank getRankByName(String name) { + for (Rank rank : ranks) { + if (rank.getName().equalsIgnoreCase(name)) { + return rank; + } + } + + return null; + } + + + public boolean hasPermission(String str) { + return hasPermission(str, BridgeGlobal.getServerName()) || hasPermission(str, "GR|" + BridgeGlobal.getGroupName()); + } + + public List getActivePermissions() { + return getPermissions().keySet().stream().filter(str -> getPermissions().get(str).equalsIgnoreCase("Global") || getPermissions().get(str).equalsIgnoreCase("GR|" + BridgeGlobal.getGroupName()) || getPermissions().get(str).equalsIgnoreCase(BridgeGlobal.getServerName())).collect(Collectors.toList()); + } + + public boolean hasInherit(Rank inhr) { + return inherits.contains(inhr.getUuid()); + } + + public List getInherits() { + return inherits.stream().map(GlobalAPI::getRank).collect(Collectors.toList()); + } + + public boolean togglePerm(String str, String serverOrGroup) { + if(hasPermission(str, serverOrGroup)) { + getPermissions().remove(str); + return false; + }else { + getPermissions().put(str, serverOrGroup); + return true; + } + } + + public boolean toggleInherit(Rank inhr) { + if(hasInherit(inhr)) { + inherits.remove(inhr.getUuid()); + return false; + }else { + inherits.add(inhr.getUuid()); + return true; + } + } + + public void saveRank() { + if(BridgeGlobal.getSystemType() == SystemType.BUKKIT) GeneralListener.refreshPlayersInRank(this); + BridgeGlobal.getMongoHandler().saveRank(this, callback -> { + if (callback != null) { + BridgeGlobal.sendLog("§aSuccessfully saved rank §r" + this.getColor() + this.getName() + "§a."); + } else { + BridgeGlobal.sendLog("§cFailed to save rank §r" + this.getColor() + this.getName() + "§c."); + } + }, true); + } + + public List getOnlineProfilesInRank() { + return BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile -> profile.getActiveGrants().stream().anyMatch(grant -> grant.isStillActive() && grant.getRank() == this)).collect(Collectors.toList()); + } + + public List getProfilesInRank() { + return BridgeGlobal.getMongoHandler().getProfiles().parallelStream().filter(profile -> profile.getActiveGrants().parallelStream().anyMatch(grant -> grant.isStillActive() && grant.getRank() == this)).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/rip/bridge/bridge/global/status/BridgeServer.java b/src/main/java/rip/bridge/bridge/global/status/BridgeServer.java new file mode 100644 index 0000000..8a55357 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/status/BridgeServer.java @@ -0,0 +1,88 @@ + +package rip.bridge.bridge.global.status; + +import com.google.gson.JsonObject; +import rip.bridge.bridge.BridgeGlobal; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.apache.commons.lang.WordUtils; +import rip.bridge.bridge.global.packet.PacketHandler; +import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Data +@AllArgsConstructor +public class BridgeServer { + + private String name, provider, group, status, motd = "", systemType; + public String screenName; + private long lastHeartbeat, bootTime; + private int online, maximum; + private double tps; + private List users; + private JsonObject metadata; + + public BridgeServer(String name, String provider, String group, String status, String motd, String systemType, long lastHeartbeat, long bootTime, int online, int maximum, double tps, List users) { + this.name = name; + this.provider = provider; + this.group = group; + this.status = status; + this.motd = motd; + this.systemType = systemType; + this.lastHeartbeat = lastHeartbeat; + this.bootTime = bootTime; + this.online = online; + this.maximum = maximum; + this.tps = tps; + this.users = users; + } + + public BridgeServer(String name, String provider, String group, String status, String systemType, long lastHeartbeat, long bootTime, int online, int maximum, double tps, List users) { + this.name = name; + this.provider = provider; + this.group = group; + this.status = status; + this.systemType = systemType; + this.lastHeartbeat = lastHeartbeat; + this.bootTime = bootTime; + this.online = online; + this.maximum = maximum; + this.tps = tps; + this.users = users; + } + + public boolean isOnline() { + return System.currentTimeMillis() - lastHeartbeat <= TimeUnit.SECONDS.toMillis(5); + } + + public boolean isWhitelisted() { + return status.equalsIgnoreCase("WHITELISTED"); + } + + public String formattedStatus(boolean color) { + switch(status.toLowerCase()) { + case "online": { + return (color ? "§a" : "") + "Online"; + } + case "whitelisted": { + return (color ? "§f" : "") + "Whitelisted"; + } + case "offline": { + return (color ? "§c" : "") + "Offline"; + } + case "booting": { + return (color ? "§6" : "" + "Booting"); + } + default: { + return (color ? "§9" : "") + WordUtils.capitalize(status.toLowerCase()); + } + } + } + + public StatusProvider getStatusProvider() { + return BridgeGlobal.getServerHandler().getProvider(); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/status/ServerHandler.java b/src/main/java/rip/bridge/bridge/global/status/ServerHandler.java new file mode 100644 index 0000000..222409d --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/status/ServerHandler.java @@ -0,0 +1,80 @@ +package rip.bridge.bridge.global.status; + +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.status.threads.StatusFetchThread; +import rip.bridge.bridge.global.status.threads.StatusUpdateThread; +import lombok.Getter; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +public class ServerHandler { + + @Getter private final List providers = new ArrayList<>(); + @Getter private final Map servers = new ConcurrentHashMap<>(); + @Getter private boolean initiated = false; + + + public void init() { + Preconditions.checkState(!initiated); + this.initiated = true; + registerProvider(new StatusProvider.DefaultStatusProvider()); + servers.put(BridgeGlobal.getSystemName().toLowerCase(), new BridgeServer(BridgeGlobal.getSystemName(), this.providers.get(0).getName(), BridgeGlobal.getGroupName(), "ONLINE", BridgeGlobal.getSystemType().name(), System.currentTimeMillis(), BridgeGlobal.getStartTime(), 0, 0, 0.0, new ArrayList<>())); + new StatusUpdateThread().start(); + new StatusFetchThread().start(); + } + + public void registerProvider(StatusProvider newProvider) { + providers.add(newProvider); + providers.sort((a, b) -> Ints.compare(b.getWeight(), a.getWeight())); + } + + public StatusProvider getProvider(String name) { + return this.providers.stream().filter(statusProvider -> statusProvider.getName().equalsIgnoreCase(name)).findFirst().orElse(null); + } + + public StatusProvider getProvider() { + return this.providers.get(0); + } + + + public BridgeServer getServer(String name) { + return servers.get(name.toLowerCase()); + } + + public BridgeServer getServer() { + return getServer(BridgeGlobal.getSystemName()); + } + + public void updateServer(String name, BridgeServer bridgeServer) { + if(servers.containsKey(name.toLowerCase())) servers.replace(name.toLowerCase(), bridgeServer); + else servers.put(name.toLowerCase(), bridgeServer); + } + + public boolean doesGroupExist(String g) { + return getServersInGroup(g) != null && !getServersInGroup(g).isEmpty(); + } + + public List getServersInGroup(String group) { + return servers.values().stream().filter(bridgeServer -> bridgeServer.getGroup().equals(group)).collect(Collectors.toList()); + } + + public Set getGroups() { + Set groups = new HashSet<>(); + servers.values().stream().filter(bridgeServer -> !bridgeServer.getGroup().equals("N/A")).forEach(bridgeServer -> groups.add(bridgeServer.getGroup())); + if(groups.isEmpty()) return null; + return groups; + } + + public BridgeServer findPlayerProxy(UUID uuid) { + return servers.values().stream().filter(bridgeServer -> bridgeServer.getSystemType().toLowerCase().contains("bungee") && bridgeServer.getUsers().contains(uuid.toString())).findFirst().orElse(null); + } + + public BridgeServer findPlayerServer(UUID uuid) { + return servers.values().stream().filter(bridgeServer -> bridgeServer.getSystemType().toLowerCase().contains("bukkit") && bridgeServer.getUsers().contains(uuid.toString())).findFirst().orElse(null); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/status/StatusProvider.java b/src/main/java/rip/bridge/bridge/global/status/StatusProvider.java new file mode 100644 index 0000000..0df3a58 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/status/StatusProvider.java @@ -0,0 +1,85 @@ +package rip.bridge.bridge.global.status; + +import com.google.gson.JsonObject; +import rip.bridge.bridge.BridgeGlobal; + +import java.beans.ConstructorProperties; +import java.util.List; + +public abstract class StatusProvider { + + private final String name; + private final int weight; + + public abstract String serverName(); + public abstract String serverStatus(); + public abstract int online(); + public abstract int maximum(); + public abstract String motd(); + public abstract double tps(); + public abstract List players(); + public abstract JsonObject dataPassthrough(); + + @ConstructorProperties(value={"plugin", "name", "weight"}) + public StatusProvider(String name, int weight) { + this.name = name; + this.weight = weight; + } + + public String getName() { + return this.name; + } + + public int getWeight() { + return this.weight; + } + + protected static final class DefaultStatusProvider + extends StatusProvider { + + public DefaultStatusProvider() { + super("Default Provider", 0); + } + + @Override + public String serverName() { + return BridgeGlobal.getSystemName(); + } + + @Override + public String serverStatus() { + return "ONLINE"; + } + + @Override + public int online() { + return 0; + } + + @Override + public int maximum() { + return 0; + } + + @Override + public String motd() { + return ""; + } + + @Override + public double tps() { + return 0; + } + + @Override + public List players() { + return null; + } + + @Override + public JsonObject dataPassthrough() { + return null; + } + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/status/start/ServerStartThread.java b/src/main/java/rip/bridge/bridge/global/status/start/ServerStartThread.java new file mode 100644 index 0000000..c85b532 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/status/start/ServerStartThread.java @@ -0,0 +1,26 @@ +package rip.bridge.bridge.global.status.start; + +import lombok.AllArgsConstructor; +import rip.bridge.bridge.global.status.BridgeServer; + +import java.io.IOException; + +@AllArgsConstructor +public class ServerStartThread extends Thread { + + private BridgeServer server; + + @Override + public void run() { + try { + runInScreen(server.getScreenName(), "./start.sh"); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private Process runInScreen(String sessionName, String command) throws IOException { + return new ProcessBuilder("screen", "-DmS", sessionName, "bash", "-c", command).inheritIO().start(); + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/status/threads/StatusFetchThread.java b/src/main/java/rip/bridge/bridge/global/status/threads/StatusFetchThread.java new file mode 100644 index 0000000..9e91373 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/status/threads/StatusFetchThread.java @@ -0,0 +1,70 @@ + +package rip.bridge.bridge.global.status.threads; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.status.BridgeServer; +import redis.clients.jedis.Jedis; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class StatusFetchThread extends Thread { + + public StatusFetchThread() { + super("Bridge - Status Fetch Thread"); + setDaemon(true); + } + + @Override + public void run() { + while(BridgeGlobal.getJedisPool() != null && !BridgeGlobal.getJedisPool().isClosed()) { + if(BridgeGlobal.isShutdown()) return; + try (Jedis jedis = BridgeGlobal.getJedisPool().getResource()) { + for (String keyName : jedis.keys("bridgeserver:*")) { + Map data = jedis.hgetAll(keyName); + String name = keyName.split(":")[1]; + long lastHeartbeat = Long.parseLong(data.get("lastHeartbeat")); + if((System.currentTimeMillis() - lastHeartbeat) > TimeUnit.MINUTES.toMillis(1)) { + System.out.println("[Bridge - Status Handler] Removing server: " + name + " from Redis and Bridge due to it being inactive for over a minute."); + deleteData(name); + continue; + } + BridgeServer bridgeServer = new BridgeServer( + name, + data.get("tab"), + data.get("group"), + data.get("status"), + data.get("motd"), + data.get("systemType"), + lastHeartbeat, + Long.parseLong(data.get("bootTime")), + Integer.parseInt(data.get("online")), + Integer.parseInt(data.get("maximum")), + Double.parseDouble(data.get("tps")), + new Gson().fromJson(data.get("users"), List.class) + ); + if (data.containsKey("metadata")) + bridgeServer.setMetadata(new JsonParser().parse(data.get("metadata")).getAsJsonObject()); + BridgeGlobal.getServerHandler().updateServer(name.toLowerCase(), bridgeServer); + + } + Thread.sleep(TimeUnit.SECONDS.toMillis(1)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void deleteData(String serverName) { + try(Jedis jedis = BridgeGlobal.getJedisPool().getResource()) { + jedis.del("bridgeserver:" + serverName); + BridgeGlobal.getServerHandler().getServers().remove(serverName.toLowerCase()); + }catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/status/threads/StatusUpdateThread.java b/src/main/java/rip/bridge/bridge/global/status/threads/StatusUpdateThread.java new file mode 100644 index 0000000..114476f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/status/threads/StatusUpdateThread.java @@ -0,0 +1,71 @@ +package rip.bridge.bridge.global.status.threads; + +import com.google.gson.Gson; +import rip.bridge.bridge.BridgeGlobal; +import rip.bridge.bridge.global.status.BridgeServer; +import rip.bridge.bridge.global.status.StatusProvider; +import redis.clients.jedis.Jedis; + +import java.util.concurrent.TimeUnit; + +public class StatusUpdateThread extends Thread { + + public StatusUpdateThread() { + super("Bridge - Status Update Thread"); + setDaemon(true); + } + + @Override + public void run() { + while(BridgeGlobal.getJedisPool() != null && !BridgeGlobal.getJedisPool().isClosed()) { + try(Jedis jedis = BridgeGlobal.getJedisPool().getResource()) { + if(BridgeGlobal.isShutdown()) return; + BridgeServer bridgeServer = BridgeGlobal.getServerHandler().getServer(); + StatusProvider statusProvider = bridgeServer.getStatusProvider(); + bridgeServer.setProvider(statusProvider.getName()); + bridgeServer.setGroup(BridgeGlobal.getGroupName()); + bridgeServer.setStatus(statusProvider.serverStatus()); + bridgeServer.setMotd(statusProvider.motd()); + bridgeServer.setLastHeartbeat(System.currentTimeMillis()); + bridgeServer.setBootTime(BridgeGlobal.getStartTime()); + bridgeServer.setOnline(statusProvider.online()); + bridgeServer.setMaximum(statusProvider.maximum()); + bridgeServer.setTps(statusProvider.tps()); + bridgeServer.setUsers(statusProvider.players()); + bridgeServer.setSystemType(BridgeGlobal.getSystemType().name()); + if(statusProvider.dataPassthrough() != null) bridgeServer.setMetadata(statusProvider.dataPassthrough()); + + BridgeGlobal.getServerHandler().updateServer(bridgeServer.getName(), bridgeServer); + + Gson gson = new Gson(); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "tab", bridgeServer.getStatusProvider().getName()); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "group", bridgeServer.getGroup()); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "status", bridgeServer.getStatus()); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "motd", bridgeServer.getMotd()); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "systemType", bridgeServer.getSystemType()); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "lastHeartbeat", String.valueOf(bridgeServer.getLastHeartbeat())); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "bootTime", String.valueOf(BridgeGlobal.getStartTime())); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "online", String.valueOf(bridgeServer.getOnline())); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "maximum", String.valueOf(bridgeServer.getMaximum())); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "users", gson.toJson(bridgeServer.getUsers())); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "tps", String.valueOf(bridgeServer.getTps())); + if(bridgeServer.getMetadata() != null) jedis.hset("bridgeserver:" + bridgeServer.getName(), "metadata", bridgeServer.getMetadata().toString()); + + Thread.sleep(TimeUnit.SECONDS.toMillis(1)); + }catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void saveShutdown() { + BridgeServer bridgeServer = BridgeGlobal.getServerHandler().getServer(); + try(Jedis jedis = BridgeGlobal.getJedisPool().getResource()) { + jedis.hset("bridgeserver:" + bridgeServer.getName(), "status", "OFFLINE"); + jedis.hset("bridgeserver:" + bridgeServer.getName(), "online", String.valueOf(0)); + }catch (Exception e) { + e.printStackTrace(); + } + + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/updater/UpdateStatus.java b/src/main/java/rip/bridge/bridge/global/updater/UpdateStatus.java new file mode 100644 index 0000000..d57d2f2 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/updater/UpdateStatus.java @@ -0,0 +1,18 @@ +package rip.bridge.bridge.global.updater; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor @Getter +public enum UpdateStatus { + + + NOT_INSTALLED("Not Installed", "§b[Not Installed]", true), + NEW_UPDATE("New Update", "§9[New Update]", true), + LATEST("Latest", "§a[Latest]", false), + ERROR("Error", "§4§l[ERROR!]", false); + + private String name; + private String prefix; + private boolean shouldUpdate; +} diff --git a/src/main/java/rip/bridge/bridge/global/updater/UpdaterManager.java b/src/main/java/rip/bridge/bridge/global/updater/UpdaterManager.java new file mode 100644 index 0000000..560d03f --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/updater/UpdaterManager.java @@ -0,0 +1,155 @@ +package rip.bridge.bridge.global.updater; + +import rip.bridge.bridge.BridgeGlobal; + +import java.io.*; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class UpdaterManager { + + + public String getPluginUpdateDir() { + String dir; + if(BridgeGlobal.getPluginUpdateDir() == null || BridgeGlobal.getPluginUpdateDir().isEmpty()) { + dir = "%user_home%/Bridge/updater"; + }else { + dir = BridgeGlobal.getPluginUpdateDir(); + } + return dir.replace("%user_home%", System.getProperty("user.home")); + } + + public File getPluginDirFile() { + File f = new File(getPluginUpdateDir()); + + if(!f.exists() || !f.isDirectory()) { + boolean b = f.mkdir(); + if(!b) return null; + } + + return f; + } + + public List getFilesForGroup(String group) { + return getFilesForGroup(Collections.singletonList(group)); + } + + public List getFilesForGroup(List group) { + List files = new ArrayList<>(); + + if(group.contains("ALL")) { + + for (File file : getPluginDirFile().listFiles()) { + if(file.isFile()) continue; + for (File listFile : file.listFiles()) { + if(listFile.isFile()) { + files.add(listFile); + } + } + } + + return files; + } + + + /*/ Global Files /*/ + + File folder = new File(getPluginUpdateDir() + "/Global"); + if(!folder.exists() || !folder.isDirectory()) return null; + + + for (File file : folder.listFiles()) { + if(file.isFile()) { + files.add(file); + } + } + + /*/ Group Files /*/ + + for (String s : group) { + folder = new File(getPluginUpdateDir() + "/" + s); + if(!folder.exists() || !folder.isDirectory()) continue; + + + for (File file : folder.listFiles()) { + if(file.isFile()) { + files.add(file); + } + } + } + + return files; + } + + public String getRunningDirectory() { + try { + return BridgeGlobal.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath().replace("/Bridge.jar", ""); + } catch (URISyntaxException e) { + e.printStackTrace(); + return null; + } + } + + public UpdateStatus getStatus(File file) { + String runningDir = getRunningDirectory(); + if(runningDir == null) { + return UpdateStatus.ERROR; + } + + File selectedFile = new File(runningDir + "/" + file.getName()); + if(!selectedFile.exists()) { + return UpdateStatus.NOT_INSTALLED; + }else { + if(selectedFile.length() != file.length()) { + return UpdateStatus.NEW_UPDATE; + }else { + return UpdateStatus.LATEST; + } + } + } + + public void updatePlugins(List plugins, Consumer consumer) { + + AtomicInteger success = new AtomicInteger(); + List failed = new ArrayList<>(); + + plugins.forEach(file -> { + InputStream inputStream = null; + OutputStream outputStream = null; + try { + File outputFile = new File(getRunningDirectory() + "/" + file.getName()); + inputStream = new FileInputStream(file); + if(outputFile.exists()) if(!outputFile.delete()) return; + + outputStream = new FileOutputStream(outputFile); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0 ,length); + } + success.getAndIncrement(); + } catch (IOException e) { + e.printStackTrace(); + failed.add(file); + } finally { + try { + inputStream.close(); + outputStream.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + + consumer.accept(success.get() == 0 ? "All plugins failed to update, check console for errors!" : (failed.isEmpty() ? "Successfully updated all plugins (" + success.get() + " plugins)" : "Updated " + success.get() + " plugins, the following plugins failed to update: " + failed.stream().map(File::getName).collect(Collectors.joining()))); + + } + + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/util/Callback.java b/src/main/java/rip/bridge/bridge/global/util/Callback.java new file mode 100644 index 0000000..100d246 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/Callback.java @@ -0,0 +1,3 @@ +package rip.bridge.bridge.global.util; + +public interface Callback { void call(T result); } diff --git a/src/main/java/rip/bridge/bridge/global/util/Color.java b/src/main/java/rip/bridge/bridge/global/util/Color.java new file mode 100644 index 0000000..44b5e25 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/Color.java @@ -0,0 +1,10 @@ +package rip.bridge.bridge.global.util; + +import org.bukkit.*; + +public class Color +{ + public static String msg(String s) { + return ChatColor.translateAlternateColorCodes('&', s); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/util/EncryptionHandler.java b/src/main/java/rip/bridge/bridge/global/util/EncryptionHandler.java new file mode 100644 index 0000000..02f2043 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/EncryptionHandler.java @@ -0,0 +1,100 @@ +package rip.bridge.bridge.global.util; + +import org.bson.internal.Base64; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; + +public class EncryptionHandler { + + private Cipher ecipher, dcipher; + private static String key = "bcD@g@s3%92B&#Zq"; + + public EncryptionHandler(SecretKey key) throws Exception { + ecipher = Cipher.getInstance("AES"); + dcipher = Cipher.getInstance("AES"); + ecipher.init(Cipher.ENCRYPT_MODE, key); + dcipher.init(Cipher.DECRYPT_MODE, key); + } + + + public String encrypt(String str) throws Exception { + byte[] utf8 = str.getBytes(StandardCharsets.UTF_8); + byte[] enc = ecipher.doFinal(utf8); + + return Base64.encode(enc); + } + + public String decrypt(String str) throws Exception { + byte[] dec = Base64.decode(str); + byte[] utf8 = dcipher.doFinal(dec); + + return new String(utf8, StandardCharsets.UTF_8); + } + + public static String encryptUsingKey(String str) { + SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES"); + EncryptionHandler encrypter; + + try { + encrypter = new EncryptionHandler(secretKey); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + String encrypted; + try { + encrypted = encrypter.encrypt(str); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + return encrypted; + } + + public static String decryptUsingKey(String str) { + SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES"); + EncryptionHandler encrypter; + try { + encrypter = new EncryptionHandler(secretKey); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + try { + return encrypter.decrypt(str); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + // Hash and Salt - Use this! + +// public static byte[] getSalt() { +// return key.getBytes(); +// } +// +// public static byte[] getSaltedHash512(String input, byte[] salt) { +// try { +// MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); +// messageDigest.update(salt); +// byte[] byteData = messageDigest.digest(input.getBytes()); +// messageDigest.reset(); +// +// return byteData; +// }catch (Exception e) { +// e.printStackTrace(); +// return null; +// } +// } +// +// public static byte[] getSaltedHash(String input) { +// return getSaltedHash512(input, getSalt()); +// } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/util/JsonChain.java b/src/main/java/rip/bridge/bridge/global/util/JsonChain.java new file mode 100644 index 0000000..68ba83a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/JsonChain.java @@ -0,0 +1,44 @@ +package rip.bridge.bridge.global.util; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class JsonChain { + private JsonObject json = new JsonObject(); + + public JsonChain() { + } + + public JsonChain(JsonObject object) { + this.json = object; + } + + public JsonChain addProperty(String property, String value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Number value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Boolean value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Character value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain add(String property, JsonElement element) { + this.json.add(property, element); + return this; + } + + public JsonObject get() { + return this.json; + } +} diff --git a/src/main/java/rip/bridge/bridge/global/util/MojangUtils.java b/src/main/java/rip/bridge/bridge/global/util/MojangUtils.java new file mode 100644 index 0000000..c9725e0 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/MojangUtils.java @@ -0,0 +1,78 @@ +package rip.bridge.bridge.global.util; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.UUID; + +public class MojangUtils { + + public static UUID fetchUUID(String playerName) throws Exception { + URL url = new URL("https://api.minetools.eu/uuid/" + playerName); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.connect(); + + InputStream inputStream = connection.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + JsonElement element = new JsonParser().parse(bufferedReader); + JsonObject object = element.getAsJsonObject(); + String status = object.get("status").getAsString(); + if(status.equalsIgnoreCase("ERR")) { + return null; + } + + String uuidAsString = object.get("id").getAsString(); + + return parseUUIDFromString(uuidAsString); + } + + public static String fetchName(UUID uuid) throws Exception { + URL url = new URL("https://api.minetools.eu/profile/" + uuid.toString().replace("-", "")); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.connect(); + + InputStream inputStream = connection.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + JsonElement element = new JsonParser().parse(bufferedReader); + JsonObject object = element.getAsJsonObject(); + JsonElement raw = object.get("raw"); + JsonObject rawObject = raw.getAsJsonObject(); + String status = rawObject.get("status").getAsString(); + if(status == null) { + return null; + } + return rawObject.get("name").getAsString(); + + } + + private static UUID parseUUIDFromString(String uuidAsString) { + String[] parts = { + "0x" + uuidAsString.substring(0, 8), + "0x" + uuidAsString.substring(8, 12), + "0x" + uuidAsString.substring(12, 16), + "0x" + uuidAsString.substring(16, 20), + "0x" + uuidAsString.substring(20, 32) + }; + + long mostSigBits = Long.decode(parts[0]); + mostSigBits <<= 16; + mostSigBits |= Long.decode(parts[1]); + mostSigBits <<= 16; + mostSigBits |= Long.decode(parts[2]); + + long leastSigBits = Long.decode(parts[3]); + leastSigBits <<= 48; + leastSigBits |= Long.decode(parts[4]); + + return new UUID(mostSigBits, leastSigBits); + } + +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/util/Msg.java b/src/main/java/rip/bridge/bridge/global/util/Msg.java new file mode 100644 index 0000000..6fdbc11 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/Msg.java @@ -0,0 +1,11 @@ +package rip.bridge.bridge.global.util; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; + +public class Msg { + + public static void logConsole(String message) { + Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', message)); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/util/OtherUtils.java b/src/main/java/rip/bridge/bridge/global/util/OtherUtils.java new file mode 100644 index 0000000..6a4aae6 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/OtherUtils.java @@ -0,0 +1,15 @@ +package rip.bridge.bridge.global.util; + +import java.util.UUID; + +public class OtherUtils { + + public static boolean isUUID(String str) { + try { + UUID uuid = UUID.fromString(str); + return true; + }catch (Exception e) { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/rip/bridge/bridge/global/util/SystemType.java b/src/main/java/rip/bridge/bridge/global/util/SystemType.java new file mode 100644 index 0000000..e380344 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/SystemType.java @@ -0,0 +1,9 @@ +package rip.bridge.bridge.global.util; + +public enum SystemType { + + BUKKIT, + BUNGEE, + UNKNOWN; + +} diff --git a/src/main/java/rip/bridge/bridge/global/util/Tasks.java b/src/main/java/rip/bridge/bridge/global/util/Tasks.java new file mode 100644 index 0000000..83e23a3 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/Tasks.java @@ -0,0 +1,50 @@ +package rip.bridge.bridge.global.util; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import rip.bridge.bridge.bukkit.Bridge; +import org.bukkit.scheduler.BukkitScheduler; + +import java.util.concurrent.ThreadFactory; + +public class Tasks { + + public static ThreadFactory newThreadFactory(String name) { + return new ThreadFactoryBuilder().setNameFormat(name).build(); + } + + public static void run(Runnable runnable, boolean async) { + if(async) { + Bridge.getInstance().getServer().getScheduler().runTaskAsynchronously(Bridge.getInstance(), runnable); + } else { + runnable.run(); + } + } + + public static void run(Runnable runnable) { + Bridge.getInstance().getServer().getScheduler().runTask(Bridge.getInstance(), runnable); + } + + public static void runAsync(Runnable runnable) { + Bridge.getInstance().getServer().getScheduler().runTaskAsynchronously(Bridge.getInstance(), runnable); + } + + public static void runLater(Runnable runnable, long delay) { + Bridge.getInstance().getServer().getScheduler().runTaskLater(Bridge.getInstance(), runnable, delay); + } + + public static void runAsyncLater(Runnable runnable, long delay) { + Bridge.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Bridge.getInstance(), runnable, delay); + } + + public static void runTimer(Runnable runnable, long delay, long interval) { + Bridge.getInstance().getServer().getScheduler().runTaskTimer(Bridge.getInstance(), runnable, delay, interval); + } + + public static void runAsyncTimer(Runnable runnable, long delay, long interval) { + Bridge.getInstance().getServer().getScheduler().runTaskTimerAsynchronously(Bridge.getInstance(), runnable, delay, interval); + } + + public static BukkitScheduler getScheduler() { + return Bridge.getInstance().getServer().getScheduler(); + } +} diff --git a/src/main/java/rip/bridge/bridge/global/util/TimeUtil.java b/src/main/java/rip/bridge/bridge/global/util/TimeUtil.java new file mode 100644 index 0000000..67ff4f0 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/TimeUtil.java @@ -0,0 +1,180 @@ +package rip.bridge.bridge.global.util; + +import org.apache.commons.lang.time.DurationFormatUtils; + +import java.text.*; +import java.util.*; +import java.sql.*; +import java.util.Date; +import java.util.regex.*; + +public class TimeUtil { + + public static String millisToTimer(long millis) { + long seconds = millis / 1000L; + if (seconds > 3600L) { + return String.format("%02d:%02d:%02d", seconds / 3600L, seconds % 3600L / 60L, seconds % 60L); + } + return String.format("%02d:%02d", seconds / 60L, seconds % 60L); + } + + public static String millisToSeconds(long millis) { + return new DecimalFormat("#0.0").format(millis / 1000.0f); + } + + public static String dateToString(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.getTime().toString(); + } + + public static Timestamp addDuration(long duration) { + return truncateTimestamp(new Timestamp(System.currentTimeMillis() + duration)); + } + + public static String formatDuration(long time) { + return DurationFormatUtils.formatDurationWords(time, true, true); + } + + public static Timestamp truncateTimestamp(Timestamp timestamp) { + if (timestamp.toLocalDateTime().getYear() > 2037) { + timestamp.setYear(2037); + } + return timestamp; + } + + public static Timestamp addDuration(Timestamp timestamp) { + return truncateTimestamp(new Timestamp(System.currentTimeMillis() + timestamp.getTime())); + } + + public static Timestamp fromMillis(long millis) { + return new Timestamp(millis); + } + + public static Timestamp getCurrentTimestamp() { + return new Timestamp(System.currentTimeMillis()); + } + + public static String getTimeZoneShortName(String displayName) { + + String[] stz = displayName.split(" "); + + StringBuilder sName = new StringBuilder(); + + for (String s : stz) { + sName.append(s.charAt(0)); + } + return sName.toString(); + } + + public static String millisToRoundedTime(long millis) { + if(millis == Long.MAX_VALUE) { + return "Permanent"; + } + ++millis; + long seconds = millis / 1000L; + long minutes = seconds / 60L; + long hours = minutes / 60L; + long days = hours / 24L; + long weeks = days / 7L; + long months = weeks / 4L; + long years = months / 12L; + if (years > 0L) { + return years + " year" + ((years == 1L) ? "" : "s"); + } + if (months > 0L) { + return months + " month" + ((months == 1L) ? "" : "s"); + } + if (weeks > 0L) { + return weeks + " week" + ((weeks == 1L) ? "" : "s"); + } + if (days > 0L) { + return days + " day" + ((days == 1L) ? "" : "s"); + } + if (hours > 0L) { + return hours + " hour" + ((hours == 1L) ? "" : "s"); + } + if (minutes > 0L) { + return minutes + " minute" + ((minutes == 1L) ? "" : "s"); + } + return seconds + " second" + ((seconds == 1L) ? "" : "s"); + } + + + public static String parseToTime(String in) { + in = in.toLowerCase(); + in = in.replaceAll(" ", ""); + in = in.replaceAll("seconds", "s"); + in = in.replaceAll("second", "s"); + + in = in.replaceAll("minutes", "m"); + in = in.replaceAll("minute", "m"); + + in = in.replaceAll("hours", "h"); + in = in.replaceAll("hour", "h"); + + in = in.replaceAll("days", "d"); + in = in.replaceAll("day", "d"); + + in = in.replaceAll("weeks", "w"); + in = in.replaceAll("week", "w"); + + in = in.replaceAll("months", "M"); + in = in.replaceAll("month", "M"); + + in = in.replaceAll("years", "y"); + in = in.replaceAll("year", "y"); + return in; + } + + public static long parseTime(String time) { + long totalTime = 0L; + boolean found = false; + Matcher matcher = Pattern.compile("\\d+\\D+").matcher(time); + while (matcher.find()) { + String s = matcher.group(); + Long value = Long.parseLong(s.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)")[0]); + String s2; + String type = s2 = s.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)")[1]; + switch (s2) { + case "s": { + totalTime += value; + found = true; + continue; + } + case "m": { + totalTime += value * 60L; + found = true; + continue; + } + case "h": { + totalTime += value * 60L * 60L; + found = true; + continue; + } + case "d": { + totalTime += value * 60L * 60L * 24L; + found = true; + continue; + } + case "w": { + totalTime += value * 60L * 60L * 24L * 7L; + found = true; + continue; + } + case "M": { + totalTime += value * 60L * 60L * 24L * 30L; + found = true; + continue; + } + case "y": { + totalTime += value * 60L * 60L * 24L * 365L; + found = true; + continue; + } + } + } + if (time.equalsIgnoreCase("perm")) return Long.MAX_VALUE; + return found ? (totalTime * 1000L) : -1L; + } +} diff --git a/src/main/java/rip/bridge/bridge/global/util/mojang/GameProfileUtil.java b/src/main/java/rip/bridge/bridge/global/util/mojang/GameProfileUtil.java new file mode 100644 index 0000000..385a440 --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/mojang/GameProfileUtil.java @@ -0,0 +1,135 @@ +package rip.bridge.bridge.global.util.mojang; + +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import rip.bridge.bridge.BridgeGlobal; +import lombok.Getter; +import net.minecraft.server.v1_7_R4.MinecraftServer; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.properties.Property; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class GameProfileUtil { + + @Getter + private static final Map skinCache = Maps.newHashMap(); + + public static GameProfile loadGameProfile(UUID uniqueId, String skinName) { + GameProfile profile = skinCache.get(skinName.toLowerCase()); + + BufferedReader reader = null; + try { + if(profile == null || !profile.getProperties().containsKey("textures")) { + URL url = new URL( "https://sessionserver.mojang.com/session/minecraft/profile/" + uniqueId.toString().replace("-", "") + "?unsigned=false"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.addRequestProperty("User-Agent", "Core"); + connection.setDoOutput(true); + connection.connect(); + + if(connection.getResponseCode() == 200) { + reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + + String line; + List lines = Lists.newArrayList(); + + while ((line = reader.readLine()) != null) { + lines.add(line); + } + + String response = Joiner.on("\n").join(lines); + + JsonObject object = new JsonParser().parse(response).getAsJsonObject(); + skinName = object.get("name").getAsString(); + + if(profile == null) { + profile = new GameProfile(uniqueId, skinName); + } + + JsonArray array = object.get("properties").getAsJsonArray(); + for(Object obj : array) { + JsonObject property = (JsonObject) obj; + String propertyName = property.get("name").getAsString(); + + profile.getProperties().put(propertyName, new Property(propertyName, property.get("value").getAsString(), property.get("signature").getAsString())); + } + + skinCache.put(skinName.toLowerCase(), profile); + MinecraftServer.getServer().getUserCache().a(profile); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if(reader != null) { + try { + reader.close(); + } catch (IOException ignored) { + + } + } + } + + return profile; + } + + public static GameProfile setName(GameProfile gameProfile, String newName) { + try { + Field modifiersField = Field.class.getDeclaredField("modifiers"); + + AccessController.doPrivileged((PrivilegedAction) () -> { + modifiersField.setAccessible(true); + return null; + }); + + Field nameField = GameProfile.class.getDeclaredField("name"); + modifiersField.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL); + nameField.setAccessible(true); + nameField.set(gameProfile, newName); + } catch (Exception e) { + e.printStackTrace(); + } + + return gameProfile; + } + + public static GameProfile clone(GameProfile gameProfile) { + GameProfile newProfile = new GameProfile(gameProfile.getId(), gameProfile.getName()); + newProfile.getProperties().putAll(gameProfile.getProperties()); + return newProfile; + } + + public static String getRealName(String name) { + try { + URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + name); + InputStreamReader reader = new InputStreamReader(url.openStream()); + JsonElement element = BridgeGlobal.getParser().parse(reader); + + if (element != null && element.isJsonObject()) { + String realName = element.getAsJsonObject().get("name").getAsString(); + + if(realName != null) { + return realName; + } + } + } catch (IOException ignored) {} + + return null; + } +} diff --git a/src/main/java/rip/bridge/bridge/global/util/mojang/UUIDFetcher.java b/src/main/java/rip/bridge/bridge/global/util/mojang/UUIDFetcher.java new file mode 100644 index 0000000..070c00a --- /dev/null +++ b/src/main/java/rip/bridge/bridge/global/util/mojang/UUIDFetcher.java @@ -0,0 +1,102 @@ +package rip.bridge.bridge.global.util.mojang; + +import com.google.common.collect.ImmutableList; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.Callable; + +/** + * Interface to Mojang's API to fetch player UUIDs from player names. + *

+ * Thanks to evilmidget38: http://forums.bukkit.org/threads/player-name-uuid-fetcher.250926/ + */ +public class UUIDFetcher implements Callable> { + + private static final double PROFILES_PER_REQUEST = 100; + private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; + private final JSONParser jsonParser = new JSONParser(); + private final List names; + private final boolean rateLimiting; + + public UUIDFetcher(List names, boolean rateLimiting) { + this.names = ImmutableList.copyOf(names); + this.rateLimiting = rateLimiting; + } + + public UUIDFetcher(List names) { + this(names, true); + } + + private static void writeBody(HttpURLConnection connection, String body) throws Exception { + OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + } + + private static HttpURLConnection createConnection() throws Exception { + URL url = new URL(PROFILE_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + return connection; + } + + private static UUID getUUID(String id) { + return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); + } + + public static byte[] toBytes(UUID uuid) { + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } + + public static UUID fromBytes(byte[] array) { + if(array.length != 16) { + throw new IllegalArgumentException("Illegal byte array length: " + array.length); + } + ByteBuffer byteBuffer = ByteBuffer.wrap(array); + long mostSignificant = byteBuffer.getLong(); + long leastSignificant = byteBuffer.getLong(); + return new UUID(mostSignificant, leastSignificant); + } + + public static UUID getUUIDOf(String name) throws Exception { + return new UUIDFetcher(Arrays.asList(name)).call().get(name); + } + + public Map call() throws Exception { + Map uuidMap = new HashMap<>(); + int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); + for (int i = 0; i < requests; i++) { + HttpURLConnection connection = createConnection(); + String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); + writeBody(connection, body); + JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); + for (Object profile : array) { + JSONObject jsonProfile = (JSONObject) profile; + String id = (String) jsonProfile.get("id"); + String name = (String) jsonProfile.get("name"); + UUID uuid = UUIDFetcher.getUUID(id); + uuidMap.put(name, uuid); + } + if(rateLimiting && i != requests - 1) { + Thread.sleep(100L); + } + } + return uuidMap; + } +} diff --git a/src/main/resources/bungee.yml b/src/main/resources/bungee.yml new file mode 100644 index 0000000..ad1d248 --- /dev/null +++ b/src/main/resources/bungee.yml @@ -0,0 +1,4 @@ +name: Bridge +version: ${git.commit.id.abbrev} +author: Bridge Development Team +main: rip.bridge.bridge.bungee.BridgeBungee \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..8116392 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,32 @@ +redis: + host: "127.0.0.1" + port: "6379" + password: "" + db: "1" + channel: "bridgepacket" + +mongo: + host: "localhost" + port: "27017" + database: "Bridge" + auth: + enabled: "false" + username: "" + password: "" + +serverDisplayName: "Bridge Network" +serverWebsite: "Bridge.rip" +AllowBannedJoins: "false" + +server: + ban-lobby: false + +serverName: "BridgeServer" +serverGroup: "Bridge" + +pluginUpdateDirectory: "%user_home%/Bridge/updater" +updaterGroups: [] + +handleServerDeployment: "true" +serverDeploymentDirectory: "%user_home%/Bridge/servers" +serverTemplateDirectory: "%user_home%/Bridge/templates" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..32ff27c --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,5 @@ +name: Bridge +version: ${git.commit.id.abbrev} +author: Bridge Development Team +main: rip.bridge.bridge.bukkit.Bridge +depend: [ qLib ] \ No newline at end of file