ezz
This commit is contained in:
Brandon 2020-01-31 12:28:56 +00:00
parent f1a70a0ea9
commit 2a3d6d9f9f
287 changed files with 23189 additions and 1 deletions

18
stark/.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
# IntelliJ
.idea/
*.iml
*.iws
# Mac
.DS_Store
# Maven
log/
target/
dependency-reduced-pom.xml
# Java
*.jar
# JRebel
rebel.xml

167
stark/bukkit/pom.xml Normal file
View File

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>net.evilblock.stark</groupId>
<artifactId>stark-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bukkit</artifactId>
<repositories>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>net.hylist</groupId>
<artifactId>spigot-server</artifactId>
<version>1.7.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.hylist</groupId>
<artifactId>spigot-api</artifactId>
<version>1.7.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.evilblock.stark</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mkremins</groupId>
<artifactId>fanciful</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>C:/Users/sindr/Desktop/1v1club/fancy boy/target/fanciful-0.4.0-SNAPSHOT.jar</systemPath>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.3.41</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>1.3.41</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>Stark</finalName>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>scriptus</artifactId>
<version>0.2</version>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<format>git-Stark-%s</format>
<descriptionProperty>bukkit.desc</descriptionProperty>
</configuration>
<goals>
<goal>describe</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.3.41</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,342 @@
package net.evilblock.stark
import com.comphenix.protocol.ProtocolLibrary
import com.google.common.util.concurrent.ThreadFactoryBuilder
import com.google.gson.GsonBuilder
import mkremins.fanciful.FancyMessage
import net.evilblock.stark.availability.AvailabilityHeartbeatRunnable
import net.evilblock.stark.availability.AvailabilityListeners
import net.evilblock.stark.config.ConfigMemory
import net.evilblock.stark.core.StarkCore
import net.evilblock.stark.core.mongo.MongoCredentials
import net.evilblock.stark.core.profile.ProfileHandler
import net.evilblock.stark.core.rank.Rank
import net.evilblock.stark.core.rank.runnable.RankLoadRunnable
import net.evilblock.stark.core.redis.RedisCredentials
import net.evilblock.stark.core.uuid.UUIDCacheLoadRunnable
import net.evilblock.stark.engine.command.CommandHandler
import net.evilblock.stark.engine.command.defaults.*
import net.evilblock.stark.engine.menu.ButtonListeners
import net.evilblock.stark.engine.protocol.InventoryAdapter
import net.evilblock.stark.engine.protocol.LagCheck
import net.evilblock.stark.engine.protocol.PingAdapter
import net.evilblock.stark.messaging.MessagingManager
import net.evilblock.stark.messaging.command.*
import net.evilblock.stark.modsuite.ModSuiteMessageListeners
import net.evilblock.stark.modsuite.command.*
import net.evilblock.stark.modsuite.options.ModOptionsListeners
import net.evilblock.stark.profile.*
import net.evilblock.stark.profile.grant.ProfileGrantListeners
import net.evilblock.stark.profile.grant.command.GrantCommand
import net.evilblock.stark.profile.grant.command.GrantsCommand
import net.evilblock.stark.profile.grant.command.RankCommand
import net.evilblock.stark.profile.punishment.command.create.BanCommand
import net.evilblock.stark.profile.punishment.command.create.BlacklistCommand
import net.evilblock.stark.profile.punishment.command.create.MuteCommand
import net.evilblock.stark.profile.punishment.command.create.TempBanCommand
import net.evilblock.stark.profile.punishment.command.remove.UnbanCommand
import net.evilblock.stark.profile.punishment.command.remove.UnblacklistCommand
import net.evilblock.stark.profile.punishment.command.remove.UnmuteCommand
import net.evilblock.stark.profile.runnable.ProfileHeartbeatRunnable
import net.evilblock.stark.rank.RankParameterType
import net.evilblock.stark.rank.RankCommands
import net.evilblock.stark.reboot.RebootCommands
import net.evilblock.stark.reboot.RebootHandler
import net.evilblock.stark.reboot.RebootListener
import net.evilblock.stark.server.ServerHandler
import net.evilblock.stark.server.ServerSyncRunnable
import net.evilblock.stark.server.command.*
import net.evilblock.stark.server.listener.*
import net.evilblock.stark.util.event.HourEvent
import net.evilblock.stark.util.serialization.*
import net.evilblock.stark.uuid.UUIDListeners
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.potion.PotionEffect
import org.bukkit.util.BlockVector
import org.bukkit.util.Vector
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
class Stark : JavaPlugin() {
lateinit var core: StarkCore<BukkitProfile>
val serverHandler: ServerHandler = ServerHandler()
val messagingManager: MessagingManager = MessagingManager()
val rebootHandler: RebootHandler = RebootHandler()
val commandHandler: CommandHandler = CommandHandler()
var enabledAt: Long = -1
override fun onEnable() {
instance = this
enabledAt = System.currentTimeMillis()
ConfigMemory.load()
try {
saveDefaultConfig()
core = object : StarkCore<BukkitProfile>(logger) {
val profileHandler = object : ProfileHandler<BukkitProfile>() {
override fun createProfileInstance(uuid: UUID): BukkitProfile {
return BukkitProfile(uuid)
}
}
override fun isPrimaryThread(): Boolean {
return Bukkit.isPrimaryThread()
}
override fun getProfileHandler(): ProfileHandler<BukkitProfile> {
return profileHandler
}
}
core.load(config.getString("TimeZone"),
getRedisCredentials("Local"),
getRedisCredentials("Backbone"),
getMongoCredentials())
if (!core.servers.getServerByName(Bukkit.getServerName()).isPresent) {
core.servers.loadOrCreateServer(Bukkit.getServerName(), Bukkit.getPort())
}
checkForServerMismatch()
core.globalMessageChannel.registerListener(ModSuiteMessageListeners())
core.globalMessageChannel.registerListener(ProfileMessageListeners())
loadEngine()
registerListeners()
registerCommands()
setupHourEvents()
server.scheduler.runTaskTimerAsynchronously(this, ProfileHeartbeatRunnable(), 20L * 30, 20L * 30)
server.scheduler.runTaskTimerAsynchronously(this, UUIDCacheLoadRunnable(), 20L * 120 * 2, 20L * 120)
server.scheduler.runTaskTimerAsynchronously(this, RankLoadRunnable(), 20L * 60, 20L * 60)
server.scheduler.runTaskTimerAsynchronously(this, AvailabilityHeartbeatRunnable(), 20L * 3, 20L * 3)
server.scheduler.runTaskTimerAsynchronously(this, ServerSyncRunnable(), 40L, 40L)
server.messenger.registerOutgoingPluginChannel(this, "BungeeCord")
logger.info("Finished loading stark in ${((System.currentTimeMillis() - enabledAt) / 1000)}ms")
} catch (e: Exception) {
logger.severe("An error occurred on startup")
e.printStackTrace()
server.shutdown()
}
// hijack logging filter to suppress the server's complaints about commands being dispatched async
Bukkit.getLogger().setFilter {
return@setFilter !it.message.contains("Command Dispatched Async")
}
// hook into vault
if (server.pluginManager.getPlugin("Vault") != null) {
Class.forName(this::class.java.`package`.name + ".hook.VaultHook").getMethod("hook").invoke(null)
}
}
override fun onDisable() {
core.redis.close()
core.mongo.close()
}
private fun loadEngine() {
serverHandler.load()
rebootHandler.load()
commandHandler.load()
val pingAdapter = PingAdapter()
ProtocolLibrary.getProtocolManager().addPacketListener(pingAdapter)
ProtocolLibrary.getProtocolManager().addPacketListener(InventoryAdapter())
server.pluginManager.registerEvents(pingAdapter, this)
LagCheck().runTaskTimerAsynchronously(this, 100L, 100L)
}
private fun registerListeners() {
val pm = Bukkit.getPluginManager()
pm.registerEvents(ButtonListeners(), this)
pm.registerEvents(UUIDListeners(), this)
pm.registerEvents(AvailabilityListeners(), this)
pm.registerEvents(ProfileListeners(), this)
pm.registerEvents(ProfileGrantListeners(), this)
pm.registerEvents(RebootListener(), this)
pm.registerEvents(DisallowedCommandsListeners(), this)
pm.registerEvents(FreezeListeners(), this)
pm.registerEvents(FrozenServerListeners(), this)
pm.registerEvents(FrozenPlayerListeners(), this)
pm.registerEvents(HeadNameListeners(), this)
pm.registerEvents(ColoredSignListeners(), this)
pm.registerEvents(TeleportationListeners(), this)
pm.registerEvents(ModOptionsListeners(), this)
pm.registerEvents(ChatFilterListeners(), this)
}
private fun registerCommands() {
commandHandler.registerParameterType(BukkitProfile::class.java, ProfileParameterType())
commandHandler.registerParameterType(Rank::class.java, RankParameterType())
// punishment commands
commandHandler.registerClass(BanCommand::class.java)
commandHandler.registerClass(TempBanCommand::class.java)
commandHandler.registerClass(UnbanCommand::class.java)
commandHandler.registerClass(BlacklistCommand::class.java)
commandHandler.registerClass(UnblacklistCommand::class.java)
commandHandler.registerClass(MuteCommand::class.java)
commandHandler.registerClass(UnmuteCommand::class.java)
commandHandler.registerClass(KickCommand::class.java)
// essential commands
commandHandler.registerClass(BroadcastCommand::class.java)
commandHandler.registerClass(BuildCommand::class.java)
commandHandler.registerClass(ClearCacheCommand::class.java)
commandHandler.registerClass(ClearCommand::class.java)
commandHandler.registerClass(CraftCommand::class.java)
commandHandler.registerClass(EnchantCommand::class.java)
commandHandler.registerClass(FeedCommand::class.java)
commandHandler.registerClass(FlyCommand::class.java)
commandHandler.registerClass(FreezeCommand::class.java)
commandHandler.registerClass(GamemodeCommands::class.java)
commandHandler.registerClass(HeadCommand::class.java)
commandHandler.registerClass(HealCommand::class.java)
commandHandler.registerClass(KillCommand::class.java)
commandHandler.registerClass(ListCommand::class.java)
commandHandler.registerClass(MoreCommand::class.java)
commandHandler.registerClass(RenameCommand::class.java)
commandHandler.registerClass(RepairCommand::class.java)
commandHandler.registerClass(SetSlotsCommand::class.java)
commandHandler.registerClass(SetSpawnCommand::class.java)
commandHandler.registerClass(SpawnerCommand::class.java)
commandHandler.registerClass(SpeedCommand::class.java)
commandHandler.registerClass(SudoCommands::class.java)
commandHandler.registerClass(TeleportationCommands::class.java)
commandHandler.registerClass(UptimeCommand::class.java)
commandHandler.registerClass(WorldCommand::class.java)
// messaging commands
commandHandler.registerClass(IgnoreCommand::class.java)
commandHandler.registerClass(IgnoreListClearCommand::class.java)
commandHandler.registerClass(IgnoreListCommand::class.java)
commandHandler.registerClass(IgnoreRemoveCommand::class.java)
commandHandler.registerClass(MessageCommand::class.java)
commandHandler.registerClass(ReplyCommand::class.java)
commandHandler.registerClass(SpyCommand::class.java)
commandHandler.registerClass(ToggleMessagesCommand::class.java)
commandHandler.registerClass(ToggleSoundsCommand::class.java)
// staff commands
commandHandler.registerClass(AltsCommand::class.java)
commandHandler.registerClass(ReportCommand::class.java)
commandHandler.registerClass(RequestCommand::class.java)
commandHandler.registerClass(StaffChatCommand::class.java)
commandHandler.registerClass(ToggleStaffChatCommand::class.java)
commandHandler.registerClass(ToggleRequestsCommand::class.java)
// profile commands
commandHandler.registerClass(ProfileCommands::class.java)
commandHandler.registerClass(GrantCommand::class.java)
commandHandler.registerClass(GrantsCommand::class.java)
commandHandler.registerClass(RankCommand::class.java)
// server management commands
commandHandler.registerClass(RankCommands::class.java)
commandHandler.registerClass(RebootCommands::class.java)
commandHandler.registerClass(ClearChatCommand::class.java)
commandHandler.registerClass(FreezeServerCommand::class.java)
commandHandler.registerClass(MuteChatCommand::class.java)
commandHandler.registerClass(SlowChatCommand::class.java)
commandHandler.registerClass(WhitelistCommands::class.java)
}
private fun checkForServerMismatch() {
if (!core.servers.checkNamePortMatch(Bukkit.getServerName(), Bukkit.getPort())) {
logger.severe("********************************************************")
logger.severe("Can't start server because server.properties config doesn't match the bungee config.yml.")
logger.severe("Make sure the `server-id` value in `server.properties` matches the server-id assigned to")
logger.severe("this server's port in your bungee config.yml.")
logger.severe("********************************************************")
server.pluginManager.disablePlugin(this)
server.shutdown()
}
}
private fun setupHourEvents() {
val executor = Executors.newSingleThreadScheduledExecutor(ThreadFactoryBuilder().setNameFormat("stark - Hour Event Thread").setDaemon(true).build())
val minOfHour = Calendar.getInstance().get(12)
val minToHour = 60 - minOfHour
executor.scheduleAtFixedRate({ instance.server.scheduler.runTask(instance) { Bukkit.getPluginManager().callEvent(HourEvent(Calendar.getInstance().get(11))) } }, minToHour.toLong(), 60L, TimeUnit.MINUTES)
}
private fun getRedisCredentials(prefix: String): RedisCredentials {
val builder = RedisCredentials.Builder()
.host(config.getString("${prefix}Redis.Host"))
.port(config.getInt("${prefix}Redis.Port"))
if (config.contains("${prefix}Redis.Password")) {
builder.password(config.getString("${prefix}Redis.Password"))
}
if (config.contains("${prefix}Redis.DbId")) {
builder.dbId(config.getInt("${prefix}Redis.DbId"))
}
return builder.build()
}
private fun getMongoCredentials(): MongoCredentials {
val builder = MongoCredentials.Builder()
.host(config.getString("Mongo.Host"))
.port(config.getInt("Mongo.Port"))
if (config.contains("Mongo.Username")) {
builder.username(config.getString("Mongo.Username"))
}
if (config.contains("Mongo.Password")) {
builder.password(config.getString("Mongo.Password"))
}
return builder.build()
}
companion object {
@JvmStatic
lateinit var instance: Stark
@JvmStatic
val gson = GsonBuilder()
.registerTypeHierarchyAdapter(PotionEffect::class.java, PotionEffectAdapter())
.registerTypeHierarchyAdapter(ItemStack::class.java, ItemStackAdapter())
.registerTypeHierarchyAdapter(Location::class.java, LocationAdapter())
.registerTypeHierarchyAdapter(org.bukkit.util.Vector::class.java, VectorAdapter())
.registerTypeAdapter(BlockVector::class.java, BlockVectorAdapter())
.setPrettyPrinting()
.serializeNulls()
.create()
@JvmStatic
val plainGson = GsonBuilder()
.registerTypeHierarchyAdapter(PotionEffect::class.java, PotionEffectAdapter())
.registerTypeHierarchyAdapter(ItemStack::class.java, ItemStackAdapter())
.registerTypeHierarchyAdapter(Location::class.java, LocationAdapter())
.registerTypeHierarchyAdapter(Vector::class.java, VectorAdapter())
.registerTypeAdapter(BlockVector::class.java, BlockVectorAdapter())
.serializeNulls()
.create()
}
}

View File

@ -0,0 +1,14 @@
package net.evilblock.stark.availability
import net.evilblock.stark.Stark
import org.bukkit.Bukkit
class AvailabilityHeartbeatRunnable : Runnable {
override fun run() {
Stark.instance.server.onlinePlayers.forEach { player ->
Stark.instance.core.availabilityHandler.update(player.uniqueId, true, null, Bukkit.getServerId())
}
}
}

View File

@ -0,0 +1,22 @@
package net.evilblock.stark.availability
import net.evilblock.stark.Stark
import org.bukkit.Bukkit
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.AsyncPlayerPreLoginEvent
import org.bukkit.event.player.PlayerQuitEvent
class AvailabilityListeners : Listener {
@EventHandler
fun onAsyncPlayerPreLoginEvent(event: AsyncPlayerPreLoginEvent) {
Stark.instance.core.availabilityHandler.update(event.uniqueId, true, null, Bukkit.getServerId())
}
@EventHandler
fun onPlayerQuitEvent(event: PlayerQuitEvent) {
Stark.instance.core.availabilityHandler.update(event.player.uniqueId, false, null, Bukkit.getServerId())
}
}

View File

@ -0,0 +1,25 @@
package net.evilblock.stark.config
import net.evilblock.stark.Stark
import net.evilblock.stark.core.config.ConfigReader
import java.io.File
object ConfigMemory {
var langConfig: Map<String, Any>? = null
fun load() {
langConfig = ConfigReader.readJsonToMap(ensureFileExists("lang.json"))
}
private fun ensureFileExists(fileName: String): File {
val file = File(Stark.instance.dataFolder, fileName)
if (!file.exists()) {
Stark.instance.saveResource(fileName, false)
}
return file
}
}

View File

@ -0,0 +1,16 @@
package net.evilblock.stark.config
import net.evilblock.stark.core.config.ConfigEntry
import net.evilblock.stark.core.config.ConfigEntryTransformer
class LangConfigEntry<T>(transformer: ConfigEntryTransformer<T>, key: String) : ConfigEntry<T>(transformer, key) {
override fun getCachedObject(): Map<String, Any> {
return ConfigMemory.langConfig!!
}
companion object {
val REBOOT_LINES: ConfigEntry<List<String>> = LangConfigEntry(ConfigEntryTransformer.STRING_LIST, "reboot.broadcast-lines")
}
}

View File

@ -0,0 +1,10 @@
package net.evilblock.stark.engine.command
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Command(val names: Array<String>,
val permission: String = "",
val hidden: Boolean = false,
val async: Boolean = false,
val description: String = "",
val logToConsole: Boolean = true)

View File

@ -0,0 +1,195 @@
package net.evilblock.stark.engine.command
import net.evilblock.stark.core.util.mojanguser.MojangUser
import net.evilblock.stark.engine.command.bukkit.ExtendedCommand
import net.evilblock.stark.engine.command.bukkit.ExtendedCommandMap
import net.evilblock.stark.engine.command.bukkit.ExtendedHelpTopic
import net.evilblock.stark.engine.command.data.method.MethodProcessor
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import net.evilblock.stark.engine.command.data.parameter.impl.*
import net.evilblock.stark.engine.command.data.parameter.impl.filter.NormalFilter
import net.evilblock.stark.engine.command.data.parameter.impl.filter.StrictFilter
import net.evilblock.stark.engine.command.data.parameter.impl.offlineplayer.OfflinePlayerWrapper
import net.evilblock.stark.engine.command.data.parameter.impl.offlineplayer.OfflinePlayerWrapperParameterType
import net.evilblock.stark.engine.command.defaults.*
import net.evilblock.stark.engine.command.data.parameter.impl.*
import net.evilblock.stark.engine.command.defaults.*
import net.evilblock.stark.util.ClassUtils
import org.bukkit.Bukkit
import org.bukkit.GameMode
import org.bukkit.OfflinePlayer
import org.bukkit.World
import org.bukkit.command.Command
import org.bukkit.command.CommandMap
import org.bukkit.command.SimpleCommandMap
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.EntityType
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.Plugin
import org.bukkit.plugin.java.JavaPlugin
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.util.*
import kotlin.collections.HashMap
class CommandHandler {
companion object {
val rootNode: CommandNode = CommandNode()
}
val parameterTypeMap: MutableMap<Class<*>, ParameterType<*>> = HashMap()
private val commandMap: CommandMap
private val knownCommands: MutableMap<String, Command>
init {
val commandMapField = Bukkit.getServer().javaClass.getDeclaredField("commandMap")
commandMapField.setAccessible(true)
commandMap = commandMapField.get(Bukkit.getServer()) as CommandMap
val knownCommandsField = SimpleCommandMap::class.java.getDeclaredField("knownCommands")
knownCommandsField.setAccessible(true)
knownCommands = knownCommandsField.get(commandMap) as MutableMap<String, Command>
}
fun load() {
registerParameterType(Boolean::class.java, BooleanParameterType())
registerParameterType(Integer::class.java, IntegerParameterType())
registerParameterType(Int::class.java, IntegerParameterType())
registerParameterType(Double::class.java, DoubleParameterType())
registerParameterType(Float::class.java, FloatParameterType())
registerParameterType(String::class.java, StringParameterType())
registerParameterType(GameMode::class.java, GameModeParameterType())
registerParameterType(EntityType::class.java, EntityTypeParameterType())
registerParameterType(Player::class.java, PlayerParameterType())
registerParameterType(World::class.java, WorldParameterType())
registerParameterType(ItemStack::class.java, ItemStackParameterType())
registerParameterType(Enchantment::class.java, EnchantmentParameterType())
registerParameterType(OfflinePlayer::class.java, OfflinePlayerParameterType())
registerParameterType(OfflinePlayerWrapper::class.java, OfflinePlayerWrapperParameterType())
registerParameterType(MojangUser::class.java, MojangUserParameterType())
registerParameterType(UUID::class.java, UUIDParameterType())
registerParameterType(NormalFilter::class.java, NormalFilter())
registerParameterType(StrictFilter::class.java, StrictFilter())
registerClass(BroadcastCommand::class.java)
registerClass(BuildCommand::class.java)
registerClass(ClearCommand::class.java)
registerClass(CraftCommand::class.java)
registerClass(EnchantCommand::class.java)
registerClass(FeedCommand::class.java)
registerClass(FlyCommand::class.java)
registerClass(FreezeCommand::class.java)
registerClass(GamemodeCommands::class.java)
registerClass(HeadCommand::class.java)
registerClass(HealCommand::class.java)
registerClass(KickCommand::class.java)
registerClass(KillCommand::class.java)
registerClass(ListCommand::class.java)
registerClass(MoreCommand::class.java)
registerClass(RenameCommand::class.java)
registerClass(RepairCommand::class.java)
registerClass(SetSlotsCommand::class.java)
registerClass(SetSpawnCommand::class.java)
registerClass(SpawnerCommand::class.java)
registerClass(SpeedCommand::class.java)
registerClass(SudoCommands::class.java)
registerClass(TeleportationCommands::class.java)
registerClass(UptimeCommand::class.java)
registerClass(WorldCommand::class.java)
swapCommandMap()
}
fun registerParameterType(clazz: Class<*>, parameterType: ParameterType<*>) {
parameterTypeMap[clazz] = parameterType
}
fun getParameterType(clazz: Class<*>): ParameterType<*>? {
return parameterTypeMap[clazz]
}
private fun swapCommandMap() {
val commandMapField = Bukkit.getServer().javaClass.getDeclaredField("commandMap")
commandMapField.setAccessible(true)
val oldCommandMap = commandMapField.get(Bukkit.getServer())
val newCommandMap = ExtendedCommandMap(Bukkit.getServer())
val knownCommandsField = SimpleCommandMap::class.java.getDeclaredField("knownCommands")
knownCommandsField.setAccessible(true)
val modifiersField = Field::class.java.getDeclaredField("modifiers")
modifiersField.setAccessible(true)
modifiersField.setInt(knownCommandsField, knownCommandsField.modifiers and -0x11)
knownCommandsField.set(newCommandMap, knownCommandsField.get(oldCommandMap))
commandMapField.set(Bukkit.getServer(), newCommandMap)
}
fun registerClass(clazz: Class<*>) {
for (method in clazz.methods) {
registerMethod(method)
}
}
private fun registerMethod(method: Method) {
method.setAccessible(true)
val nodes = MethodProcessor().process(method)
if (nodes != null) {
nodes.forEach { node ->
val command = ExtendedCommand(node, JavaPlugin.getProvidingPlugin(method.declaringClass))
register(command)
node.children.values.forEach { child ->
registerHelpTopic(child, node.aliases)
}
}
}
}
private fun register(command: ExtendedCommand) {
val iterator = knownCommands.iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
if (entry.value.name.equals(command.name, true)) {
entry.value.unregister(commandMap)
iterator.remove()
}
}
command.aliases.forEach { alias ->
knownCommands[alias] = command
}
command.register(commandMap)
knownCommands[command.name] = command
}
private fun registerHelpTopic(node: CommandNode, aliases: Set<String>?) {
if (node.method != null) {
Bukkit.getHelpMap().addTopic(ExtendedHelpTopic(node, aliases))
}
if (node.hasCommands()) {
node.children.values.forEach { child ->
registerHelpTopic(child, null)
}
}
}
fun registerPackage(plugin: Plugin, packageName: String) {
ClassUtils.getClassesInPackage(plugin, packageName).forEach(this::registerClass)
}
fun registerAll(plugin: Plugin) {
registerPackage(plugin, plugin::class.java.`package`.name)
}
}

View File

@ -0,0 +1,366 @@
package net.evilblock.stark.engine.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.data.Data
import net.evilblock.stark.engine.command.data.argument.Arguments
import net.evilblock.stark.engine.command.data.flag.FlagData
import net.evilblock.stark.engine.command.data.parameter.ParameterData
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import com.google.common.base.Strings
import mkremins.fanciful.FancyMessage
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
import org.bukkit.command.CommandException
import org.bukkit.command.CommandSender
import org.bukkit.command.ConsoleCommandSender
import org.bukkit.entity.Player
import org.spigotmc.SpigotConfig
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.util.*
import java.util.stream.Collectors
import kotlin.collections.ArrayList
class CommandNode(var name: String?,
var permission: String?,
var description: String?) {
var async: Boolean = false
var hidden: Boolean = false
val aliases: MutableSet<String> = HashSet()
val children: MutableMap<String, CommandNode> = TreeMap()
var validFlags: MutableList<String> = mutableListOf()
var parameters: MutableList<Data> = mutableListOf()
var parent: CommandNode? = null
var logToConsole: Boolean = false
var method: Method? = null
var owningClass: Class<*>? = null
constructor(clazz: Class<*>) : this(null, null, "ROOT NODE") {
owningClass = clazz
}
constructor() : this(null, null, null)
constructor(name: String) : this(name, null, "")
constructor(name: String, permission: String?) : this(name, permission, "")
fun registerCommand(commandNode: CommandNode) {
if (commandNode.name != null) {
commandNode.parent = this
children[commandNode.name!!] = commandNode
} else {
throw IllegalArgumentException("Cannot register command without a name to root node")
}
}
fun hasCommand(name: String): Boolean = children.containsKey(name.toLowerCase())
fun getCommand(name: String): CommandNode? = children[name.toLowerCase()]
fun hasCommands(): Boolean = children.isNotEmpty()
fun findCommand(arguments: Arguments): CommandNode {
if (arguments.arguments.isNotEmpty()) {
val trySub = arguments.arguments[0]
if (hasCommand(trySub)) {
arguments.arguments.removeAt(0)
val returnNode = getCommand(trySub) as CommandNode
return returnNode.findCommand(arguments)
}
}
return this
}
fun isValidFlag(test: String): Boolean {
return if (test.length == 1) {
validFlags.contains(test)
} else {
validFlags.contains(test.toLowerCase())
}
}
fun canUse(sender: CommandSender): Boolean {
if (permission == null) {
return true
}
return when (permission) {
"console" -> {
sender is ConsoleCommandSender
}
"op" -> {
sender.isOp
}
"" -> {
true
}
else -> {
sender.hasPermission(this.permission)
}
}
}
fun getUsage(realLabel: String): FancyMessage {
val usage = FancyMessage("Usage: /$realLabel").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
val flags = mutableListOf<FlagData>()
flags.addAll(this.parameters.stream().filter { data -> data is FlagData }.map { data -> data as FlagData }.collect(Collectors.toList()))
val parameters = mutableListOf<ParameterData>()
parameters.addAll(this.parameters.stream().filter { data -> data is ParameterData }.map { data -> data as ParameterData }.collect(Collectors.toList()))
var flagFirst = true
if (flags.isNotEmpty()) {
usage.then("(").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
for (flag in flags) {
val name = flag.names[0]
if (!flagFirst) {
usage.then(" | ").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
}
flagFirst = false
usage.then("-$name").color(ChatColor.AQUA)
usage.tooltip("${ChatColor.GRAY}${flag.description}")
}
usage.then(") ").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
}
if (parameters.isNotEmpty()) {
for (index in parameters.indices) {
val parameter = parameters[index]
val required = parameter.defaultValue.isEmpty()
usage.then((if (required) "<" else "[") + parameter.name + (if (parameter.wildcard) "..." else "") + (if (required) ">" else "]") + if (index != parameters.size - 1) " " else "").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
}
}
return usage
}
fun getUsage(): FancyMessage {
val usage = FancyMessage("")
val flags = mutableListOf<FlagData>()
flags.addAll(parameters.stream().filter { data -> data is FlagData }.map { data -> data as FlagData }.collect(Collectors.toList()))
val parameters = mutableListOf<ParameterData>()
parameters.addAll(parameters.stream().filter { data -> data is ParameterData }.map { data -> data as ParameterData }.collect(Collectors.toList()))
var flagFirst = true
if (flags.isNotEmpty()) {
usage.then("(").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
for (flag in flags) {
val name = flag.names[0]
if (!flagFirst) {
usage.then(" | ").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
}
flagFirst = false
usage.then("-$name").color(ChatColor.AQUA)
usage.tooltip("${ChatColor.GRAY}${flag.description}")
}
usage.then(") ").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
}
if (parameters.isNotEmpty()) {
for (index in parameters.indices) {
val parameter = parameters[index]
val required = parameter.defaultValue.isEmpty()
usage.then((if (required) "<" else "[") + parameter.name + (if (parameter.wildcard) "..." else "") + (if (required) ">" else "]") + if (index != parameters.size - 1) " " else "").color(ChatColor.RED)
usage.tooltip("${ChatColor.YELLOW}$description")
}
}
return usage
}
@Throws(CommandException::class)
operator fun invoke(sender: CommandSender, arguments: Arguments): Boolean {
if (method == null) {
if (hasCommands()) {
if (getSubCommands(sender, true).isEmpty()) {
if (hidden) {
sender.sendMessage(SpigotConfig.unknownCommandMessage)
} else {
sender.sendMessage("${ChatColor.RED}No permission.")
}
}
} else {
sender.sendMessage(SpigotConfig.unknownCommandMessage)
}
return true
}
val methodParamCount = method!!.parameterCount
val objects = ArrayList<Any>(methodParamCount)
objects.add(sender)
var index = 0
for (data in this.parameters) {
if (data is FlagData) {
var value = data.defaultValue
for (s in data.names) {
if (arguments.hasFlag(s)) {
value = !value
break
}
}
objects.add(data.methodIndex, value)
} else {
if (data !is ParameterData) {
continue
}
var argument: String?
argument = if (index < arguments.arguments.size) {
arguments.arguments[index]
} else {
if (data.defaultValue.isEmpty()) {
return false
} else {
data.defaultValue
}
}
if (data.wildcard && (argument.isEmpty() || argument != data.defaultValue)) {
argument = arguments.join(index)
}
var type: ParameterType<*>? = Stark.instance.commandHandler.getParameterType(data.type)
if (data.parameterType != null) {
try {
type = data.parameterType.newInstance() as ParameterType<*>
} catch (e1: InstantiationException) {
throw CommandException("Failed to create ParameterType instance: " + data.parameterType.name, e1)
} catch (e2: IllegalAccessException) {
throw CommandException("Failed to create ParameterType instance: " + data.parameterType.name, e2)
}
}
if (type == null) {
sender.sendMessage("${ChatColor.RED}No data type found: ${(data.parameterType
?: data.type).simpleName}")
return true
}
val result = type.transform(sender, argument) ?: return true
objects.add(data.methodIndex, result)
++index
}
}
try {
val start = System.currentTimeMillis()
if (method!!.declaringClass.kotlin.isCompanion) {
method!!.invoke(method!!.declaringClass.kotlin.objectInstance, *objects.toTypedArray())
} else {
method!!.invoke(null, *objects.toTypedArray())
}
val stop = System.currentTimeMillis()
val executionThreshold = 10 // command threshold
if (!async && logToConsole && stop - start >= executionThreshold) {
Stark.instance.logger.warning("Command '/" + getFullLabel() + "' took " + (stop - start) + "ms!")
}
return true
} catch (e1: IllegalAccessException) {
throw CommandException("An error occurred while executing the command", e1)
} catch (e2: InvocationTargetException) {
throw CommandException("An error occurred while executing the command", e2)
}
}
fun getSubCommands(sender: CommandSender, print: Boolean): List<String> {
val commands = ArrayList<String>()
if (canUse(sender)) {
val command = (if (sender is Player) "/" else "") + this.getFullLabel() + " " + getUsage().toOldMessageFormat() + if (Strings.isNullOrEmpty(this.description)) "" else "${ChatColor.GRAY} - $description"
if (parent == null) {
commands.add(command)
} else if (parent?.name != null && CommandHandler.rootNode.getCommand(this.parent!!.name!!) !== this.parent) {
commands.add(command)
}
if (this.hasCommands()) {
for (n in children.values) {
commands.addAll(n.getSubCommands(sender, false))
}
}
}
if (commands.isNotEmpty() && print) {
sender.sendMessage(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 35))
for (command2 in commands) {
sender.sendMessage("${ChatColor.RED} $command2")
}
sender.sendMessage(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 35))
}
return commands
}
fun getRealAliases(): Set<String> {
aliases.remove(name)
return aliases
}
fun getFullLabel(): String {
val labels = ArrayList<String>()
var node: CommandNode? = this
while (node != null) {
val name = node.name
if (name != null) {
labels.add(name)
}
node = node.parent
}
labels.reverse()
labels.removeAt(0)
val builder = StringBuilder()
labels.forEach { s -> builder.append(s).append(' ') }
return builder.toString().trim { it <= ' ' }
}
fun getUsageForHelpTopic(): String {
return if (method != null) {
"/" + getFullLabel() + " " + ChatColor.stripColor(getUsage().toOldMessageFormat())
} else ""
}
}

View File

@ -0,0 +1,242 @@
package net.evilblock.stark.engine.command.bukkit
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.CommandNode
import net.evilblock.stark.engine.command.data.argument.ArgumentProcessor
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.parameter.ParameterData
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.apache.commons.lang.StringUtils
import org.apache.commons.lang.exception.ExceptionUtils
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandException
import org.bukkit.command.CommandSender
import org.bukkit.command.PluginIdentifiableCommand
import org.bukkit.entity.Player
import org.bukkit.plugin.Plugin
import org.bukkit.plugin.java.JavaPlugin
import org.spigotmc.SpigotConfig
import java.lang.StringBuilder
import java.util.*
import java.util.stream.Collectors
import kotlin.collections.ArrayList
class ExtendedCommand(val node: CommandNode, private val plugin: JavaPlugin) : Command(node.name, "", "/", node.getRealAliases().toList()), PluginIdentifiableCommand {
override fun getPlugin(): Plugin {
return plugin
}
override fun execute(sender: CommandSender, label: String, args: Array<String>): Boolean {
val label = label.replace("${plugin.name.toLowerCase()}:", "")
val newArgs = concat(label, args)
val arguments = ArgumentProcessor().process(newArgs)
val executionNode = node.findCommand(arguments)
val realLabel = getFullLabel(executionNode)
if (executionNode.canUse(sender)) {
if (executionNode.async) {
plugin.server.scheduler.runTaskAsynchronously(plugin) {
try {
if (!executionNode.invoke(sender, arguments)) {
executionNode.getUsage(realLabel).send(sender)
}
} catch (e: CommandException) {
e.printStackTrace()
executionNode.getUsage(realLabel).send(sender)
sender.sendMessage("${ChatColor.RED}An error occurred while processing your command.")
if (sender.isOp) {
sendStackTrace(sender, e)
}
}
}
} else {
try {
if (!executionNode.invoke(sender, arguments)) {
executionNode.getUsage(realLabel).send(sender)
}
} catch (e: CommandException) {
e.printStackTrace()
executionNode.getUsage(realLabel).send(sender)
sender.sendMessage("${ChatColor.RED}An error occurred while processing your command.")
if (sender.isOp) {
sendStackTrace(sender, e)
}
}
}
} else if (executionNode.hidden) {
sender.sendMessage(SpigotConfig.unknownCommandMessage)
} else {
sender.sendMessage("${ChatColor.RED}No permission.")
}
return true
}
fun tabComplete(sender: CommandSender, cmdLine: String): List<String> {
if (sender !is Player) {
return listOf()
}
val rawArgs = cmdLine.replace("${plugin.name.toLowerCase()}:", "").split(" ")
if (rawArgs.isEmpty()) {
if (!node.canUse(sender)) {
return listOf()
}
return listOf()
} else {
val arguments = ArgumentProcessor().process(rawArgs.toTypedArray())
val realNode = node.findCommand(arguments)
if (!realNode.canUse(sender)) {
return listOf()
}
val realArgs = arguments.arguments
var currentIndex = realArgs.size - 1
if (currentIndex < 0) {
currentIndex = 0
}
if (cmdLine.endsWith(" ") && realArgs.size >= 1) {
++currentIndex;
}
if (currentIndex < 0) {
return listOf()
}
val completions: ArrayList<String> = arrayListOf()
if (realNode.hasCommands()) {
val name = if (realArgs.size == 0) "" else realArgs[realArgs.size - 1]
completions.addAll(realNode.children.values.stream().filter { node -> node.name != null && node.canUse(sender) && (StringUtils.startsWithIgnoreCase(node.name, name) || StringUtils.isEmpty(name)) }.map { node -> node.name }.collect(Collectors.toList<String>()))
if (completions.isNotEmpty()) {
return completions
}
}
if (rawArgs[rawArgs.size - 1].equals(realNode.name, true) && !cmdLine.endsWith(" ")) {
return listOf()
}
if (realNode.validFlags.isNotEmpty()) {
for (flag in realNode.validFlags) {
val arg = rawArgs[rawArgs.size - 1]
if (Flag.FLAG_PATTERN.matcher(arg).matches() || arg == "-" && (StringUtils.startsWithIgnoreCase(flag, arg.substring(1, arg.length))) || arg == "-") {
completions.add("-$flag")
}
}
if (completions.isNotEmpty()) {
return completions
}
}
try {
val params = realNode.parameters.stream().filter { param -> param is ParameterData }.map { param -> param as ParameterData }.collect(Collectors.toList())
val fixed = Math.max(0, currentIndex - 1)
if (params.isEmpty()) {
return emptyList()
}
val data: ParameterData = params[fixed]!!
val parameterType: ParameterType<*>? = Stark.instance.commandHandler.getParameterType(data.type)
if (parameterType != null) {
if (currentIndex < realArgs.size && realArgs[currentIndex].equals(realNode.name, true)) {
realArgs.add("")
++currentIndex
}
val argumentBeingCompleted = (if (currentIndex >= realArgs.size || realArgs.size == 0) "" else realArgs[currentIndex]).trim()
val suggested = parameterType.tabComplete(sender, data.tabCompleteFlags, argumentBeingCompleted)
completions.addAll(suggested.stream().filter { s -> StringUtils.startsWithIgnoreCase(s, argumentBeingCompleted) }.collect(Collectors.toList()))
}
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
return completions
}
}
private fun concat(label: String, args: Array<String>): Array<String> {
val list = arrayListOf(label)
list.addAll(args.toList().stream().filter { it != null }.collect(Collectors.toList<String>()))
return list.toTypedArray()
}
private fun getFullLabel(node: CommandNode?): String {
var workingNode = node
val labels = arrayListOf<String>()
while (workingNode != null) {
val name = workingNode.name
if (name != null) {
labels.add(name)
}
workingNode = workingNode.parent
}
labels.reverse()
labels.removeAt(0)
val builder = StringBuilder()
labels.forEach { s ->
builder.append(s).append(' ')
}
return builder.toString()
}
private fun sendStackTrace(sender: CommandSender, exception: Exception) {
val rootCauseMessage = ExceptionUtils.getRootCauseMessage(exception)
sender.sendMessage("${ChatColor.RED}Message: $rootCauseMessage")
val cause = ExceptionUtils.getStackTrace(exception)
val tokenizer = StringTokenizer(cause)
var exceptionType = ""
var details = ""
var parsingNeeded = false
while (tokenizer.hasMoreTokens()) {
val token = tokenizer.nextToken()
if (token.equals("Caused", true)) {
tokenizer.nextToken()
parsingNeeded = true
exceptionType = tokenizer.nextToken()
} else {
if (token.equals("at", true) && parsingNeeded) {
details = tokenizer.nextToken()
break
}
continue
}
}
sender.sendMessage("${ChatColor.RED}Exception: ${exceptionType.replace(":", "")}")
sender.sendMessage("${ChatColor.RED}Details:")
sender.sendMessage("${ChatColor.RED}$details")
}
}

View File

@ -0,0 +1,95 @@
package net.evilblock.stark.engine.command.bukkit
import java.util.Collections
import net.evilblock.stark.engine.command.CommandNode
import org.bukkit.Server
import org.bukkit.command.Command
import org.bukkit.command.CommandException
import org.bukkit.entity.Player
import java.util.ArrayList
import org.bukkit.command.CommandSender
import org.bukkit.command.SimpleCommandMap
import org.bukkit.util.StringUtil
class ExtendedCommandMap(server: Server) : SimpleCommandMap(server) {
override fun tabComplete(sender: CommandSender, cmdLine: String): List<String>? {
checkNotNull(sender as Any) { "Sender cannot be null" }
checkNotNull(cmdLine as Any) { "Command line cannot be null" }
val spaceIndex = cmdLine.indexOf(' ')
if (spaceIndex == -1) {
val completions = ArrayList<String>()
val knownCommands = knownCommands as Map<String, Command>
val prefix = if (sender is Player) "/" else ""
for ((name, command) in knownCommands) {
if (StringUtil.startsWithIgnoreCase(name, cmdLine)) {
if (command is ExtendedCommand) {
var executionNode = command.node.getCommand(name)
if (executionNode == null) {
executionNode = command.node
}
if (!executionNode.hasCommands()) {
var testNode: CommandNode? = executionNode.getCommand(name)
if (testNode == null) {
testNode = command.node.getCommand(name)
}
if (!testNode!!.canUse(sender)) {
continue
}
completions.add(prefix + name)
} else {
if (executionNode.getSubCommands(sender, false).isEmpty()) {
continue
}
completions.add(prefix + name)
}
} else {
if (!command.testPermissionSilent(sender)) {
continue
}
completions.add(prefix + name)
}
}
}
Collections.sort(completions, String.CASE_INSENSITIVE_ORDER)
return completions
}
val commandName = cmdLine.substring(0, spaceIndex)
val target = getCommand(commandName) ?: return null
if (!target.testPermissionSilent(sender)) {
return null
}
val argLine = cmdLine.substring(spaceIndex + 1, cmdLine.length)
val args = argLine.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
try {
val completions = if (target is ExtendedCommand) target.tabComplete(sender, cmdLine) else target.tabComplete(sender, commandName, args)
if (completions != null) {
Collections.sort(completions, String.CASE_INSENSITIVE_ORDER)
}
return completions
} catch (ex: CommandException) {
throw ex
} catch (ex2: Throwable) {
throw CommandException("Unhandled exception executing tab-completer for '$cmdLine' in $target", ex2)
}
}
}

View File

@ -0,0 +1,48 @@
package net.evilblock.stark.engine.command.bukkit
import org.bukkit.help.HelpTopic
import org.bukkit.command.CommandSender
import net.evilblock.stark.engine.command.CommandNode
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
class ExtendedHelpTopic(private val node: CommandNode, aliases: Set<String>?) : HelpTopic() {
init {
name = "/" + node.name!!
val description = node.description
shortText = if (description!!.length < 32) {
description
} else {
description.substring(0, 32)
}
val sb = StringBuilder()
sb.append(ChatColor.GOLD)
sb.append("Description: ")
sb.append(ChatColor.WHITE)
sb.append(node.description)
sb.append("\n")
sb.append(ChatColor.GOLD)
sb.append("Usage: ")
sb.append(ChatColor.WHITE)
sb.append(node.getUsageForHelpTopic())
if (aliases != null && aliases.isNotEmpty()) {
sb.append("\n")
sb.append(ChatColor.GOLD)
sb.append("Aliases: ")
sb.append(ChatColor.WHITE)
sb.append(StringUtils.join(aliases as Collection<*>?, ", "))
}
fullText = sb.toString()
}
override fun canSee(commandSender: CommandSender): Boolean {
return node.canUse(commandSender)
}
}

View File

@ -0,0 +1,3 @@
package net.evilblock.stark.engine.command.data
interface Data

View File

@ -0,0 +1,7 @@
package net.evilblock.stark.engine.command.data
import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Type(val value: KClass<*>)

View File

@ -0,0 +1,44 @@
package net.evilblock.stark.engine.command.data.argument
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.processor.Processor
import java.util.ArrayList
class ArgumentProcessor : Processor<Array<String>, Arguments> {
override fun process(type: Array<String>): Arguments {
val flags = ArrayList<String>()
val arguments = ArrayList<String>()
for (s in type) {
if (s.isNotEmpty()) {
if (s[0] == '-' && s != "-" && matches(s)) {
val flag = getFlagName(s)
if (flag != null) {
flags.add(flag)
}
} else {
arguments.add(s)
}
}
}
return Arguments(arguments, flags)
}
private fun getFlagName(flag: String): String? {
val matcher = Flag.FLAG_PATTERN.matcher(flag)
if (matcher.matches()) {
val name = matcher.replaceAll("$2$3")
return if (name.length == 1) name else name.toLowerCase()
}
return null
}
private fun matches(flag: String): Boolean {
return Flag.FLAG_PATTERN.matcher(flag).matches()
}
}

View File

@ -0,0 +1,42 @@
package net.evilblock.stark.engine.command.data.argument
class Arguments(val arguments: MutableList<String>, val flags: ArrayList<String>) {
fun hasFlag(flag: String): Boolean {
return this.flags.contains(flag.toLowerCase())
}
fun join(from: Int, to: Int, delimiter: Char): String {
var to = to
if (to > this.arguments.size - 1 || to < 1) {
to = this.arguments.size - 1
}
val builder = StringBuilder()
for (i in from..to) {
builder.append(this.arguments[i])
if (i != to) {
builder.append(delimiter)
}
}
return builder.toString()
}
fun join(from: Int, delimiter: Char): String {
return this.join(from, -1, delimiter)
}
fun join(from: Int): String {
return this.join(from, ' ')
}
fun join(delimiter: Char): String {
return this.join(0, delimiter)
}
fun join(): String {
return this.join(' ')
}
}

View File

@ -0,0 +1,13 @@
package net.evilblock.stark.engine.command.data.flag
import java.util.regex.Pattern
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Flag(vararg val value: String, val defaultValue: Boolean = false, val description: String = "") {
companion object {
val FLAG_PATTERN: Pattern = Pattern.compile("(-)([a-zA-Z])([\\w]*)?")
}
}

View File

@ -0,0 +1,8 @@
package net.evilblock.stark.engine.command.data.flag
import net.evilblock.stark.engine.command.data.Data
data class FlagData(val names: List<String>,
val description: String,
val defaultValue: Boolean,
val methodIndex: Int) : Data

View File

@ -0,0 +1,139 @@
package net.evilblock.stark.engine.command.data.method
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.CommandHandler
import net.evilblock.stark.engine.command.CommandNode
import net.evilblock.stark.engine.command.data.Data
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.flag.FlagData
import net.evilblock.stark.engine.command.data.parameter.Param
import net.evilblock.stark.engine.command.data.parameter.ParameterData
import net.evilblock.stark.engine.command.data.processor.Processor
import org.bukkit.command.CommandSender
import java.lang.IllegalArgumentException
import java.lang.reflect.Method
import kotlin.collections.HashSet
class MethodProcessor : Processor<Method, Set<CommandNode>?> {
override fun process(type: Method): Set<CommandNode>? {
if (type.isAnnotationPresent(Command::class.java)) {
if (type.parameterCount >= 1 && CommandSender::class.java.isAssignableFrom(type.parameterTypes[0])) {
val command = type.getAnnotation(Command::class.java)
val owningClass = type.declaringClass
val flagNames = mutableListOf<String>()
val allParams = mutableListOf<Data>()
if (type.parameterCount > 1) {
for (i in 1 until type.parameterCount) {
val parameter = type.parameters[i]
if (parameter.isAnnotationPresent(Param::class.java)) {
val param: Param = parameter.getAnnotation(Param::class.java)
val hash = setOf(*param.tabCompleteFlags)
val data = ParameterData(param.name, param.defaultValue, parameter.type, param.wildcard, i, hash, Stark.instance.commandHandler.parameterTypeMap[parameter.type]?.javaClass)
allParams.add(data)
} else {
if (!parameter.isAnnotationPresent(Flag::class.java)) {
throw IllegalArgumentException("Every data, other than the sender, must be annotated with Param")
}
val flag: Flag = parameter.getAnnotation(Flag::class.java)
val flagData = FlagData(flag.value.toList(), flag.description, flag.defaultValue, i)
allParams.add(flagData)
flagNames.addAll(listOf(*flag.value))
}
}
}
val registered = HashSet<CommandNode>()
for (name in command.names) {
val qualifiedName = name.toLowerCase().trim()
var hadChild = false
var cmdNames: Array<String> = arrayOf(qualifiedName)
if (qualifiedName.contains(" ")) {
cmdNames = qualifiedName.split(" ").toTypedArray()
}
val primaryName = cmdNames[0]
var workingNode = CommandNode(owningClass)
if (CommandHandler.rootNode.hasCommand(primaryName)) {
workingNode = CommandHandler.rootNode.getCommand(primaryName)!!
workingNode.aliases.add(primaryName)
} else {
workingNode.name = primaryName
}
var parentNode = CommandNode(owningClass)
if (workingNode.hasCommand(primaryName)) {
parentNode = workingNode.getCommand(primaryName)!!
} else {
parentNode.name = primaryName
parentNode.permission = ""
}
if (cmdNames.size > 1) {
hadChild = true
workingNode.registerCommand(parentNode)
var childNode = CommandNode(owningClass)
for (i in 1 until cmdNames.size) {
val subName = cmdNames[i]
childNode.name = subName
if (parentNode.hasCommand(subName)) {
childNode = parentNode.getCommand(subName)!!
}
parentNode.registerCommand(childNode)
if (i == cmdNames.size - 1) {
childNode.method = type
childNode.async = command.async
childNode.hidden = command.hidden
childNode.permission = command.permission
childNode.description = command.description
childNode.validFlags = flagNames
childNode.parameters = allParams
childNode.logToConsole = command.logToConsole
} else {
parentNode = childNode
childNode = CommandNode(owningClass)
}
}
}
if (!hadChild) {
parentNode.method = type
parentNode.async = command.async
parentNode.hidden = command.hidden
parentNode.permission = command.permission
parentNode.description = command.description
parentNode.validFlags = flagNames
parentNode.parameters = allParams
parentNode.logToConsole = command.logToConsole
workingNode.registerCommand(parentNode)
}
CommandHandler.rootNode.registerCommand(workingNode)
registered.add(workingNode)
}
return registered
}
}
return null
}
}

View File

@ -0,0 +1,8 @@
package net.evilblock.stark.engine.command.data.parameter
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Param(val name: String,
val defaultValue: String = "",
val tabCompleteFlags: Array<String> = [],
val wildcard: Boolean = false)

View File

@ -0,0 +1,11 @@
package net.evilblock.stark.engine.command.data.parameter
import net.evilblock.stark.engine.command.data.Data
data class ParameterData(val name: String,
val defaultValue: String,
val type: Class<*>,
val wildcard: Boolean,
val methodIndex: Int,
val tabCompleteFlags: Set<String>,
val parameterType: Class<*>?) : Data

View File

@ -0,0 +1,12 @@
package net.evilblock.stark.engine.command.data.parameter
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
interface ParameterType<T> {
fun transform(sender: CommandSender, source: String): T
fun tabComplete(player: Player, flags: Set<String>, source: String): List<String>
}

View File

@ -0,0 +1,34 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import java.util.ArrayList
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.ChatColor
class BooleanParameterType : ParameterType<Boolean?> {
private val map: MutableMap<String, Boolean> = mutableMapOf()
init {
map["on"] = true
map["yes"] = true
map["false"] = false
map["off"] = false
map["no"] = false
}
override fun transform(sender: CommandSender, source: String): Boolean? {
if (!this.map.containsKey(source.toLowerCase())) {
sender.sendMessage("${ChatColor.RED} $source is not a valid boolean.")
return null
}
return this.map[source.toLowerCase()]
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
return ArrayList(this.map.keys)
}
}

View File

@ -0,0 +1,36 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
class DoubleParameterType : ParameterType<Double?> {
override fun transform(sender: CommandSender, value: String): Double? {
if (value.toLowerCase().contains("e")) {
sender.sendMessage(ChatColor.RED.toString() + value + " is not a valid number.")
return null
}
try {
val parsed = java.lang.Double.parseDouble(value)
if (java.lang.Double.isNaN(parsed) || !java.lang.Double.isFinite(parsed)) {
sender.sendMessage(ChatColor.RED.toString() + value + " is not a valid number.")
return null
}
return parsed
} catch (exception: NumberFormatException) {
sender.sendMessage(ChatColor.RED.toString() + value + " is not a valid number.")
return null
}
}
override fun tabComplete(sender: Player, flags: Set<String>, prefix: String): List<String> {
return listOf()
}
}

View File

@ -0,0 +1,50 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import net.evilblock.stark.util.enchantment.EnchantmentWrapper
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
class EnchantmentParameterType : ParameterType<Enchantment?> {
override fun transform(sender: CommandSender, source: String): Enchantment? {
val enchantment = EnchantmentWrapper.parse(source)
if (enchantment == null) {
sender.sendMessage("${ChatColor.RED}No enchantment with the name " + source + " found.")
return null
}
return enchantment.bukkitEnchantment
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
outer@ for (enchantment in EnchantmentWrapper.values()) {
for (str in enchantment.parse) {
if (StringUtils.startsWithIgnoreCase(str, source)) {
completions.add(str)
continue@outer
}
}
if (StringUtils.startsWithIgnoreCase(enchantment.friendlyName, source)) {
completions.add(enchantment.friendlyName.toLowerCase())
continue
}
if (StringUtils.startsWithIgnoreCase(enchantment.bukkitEnchantment.name, source)) {
completions.add(enchantment.friendlyName.toLowerCase())
}
continue
}
return completions
}
}

View File

@ -0,0 +1,50 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import net.evilblock.stark.util.EntityUtils
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.EntityType
import org.bukkit.entity.Player
import java.util.*
class EntityTypeParameterType : ParameterType<EntityType?> {
override fun transform(sender: CommandSender, source: String): EntityType? {
val type = EntityUtils.parse(source)
if (type == null) {
for (possibleType in EntityType.values()) {
if (possibleType.name.equals(source, ignoreCase = true)) {
return possibleType
}
if (possibleType.typeId.toString().equals(source, ignoreCase = true)) {
return possibleType
}
if (StringUtils.startsWithIgnoreCase(possibleType.name, source)) {
return possibleType
}
}
}
if (type == null) {
sender.sendMessage("${ChatColor.RED}No entity type with the name " + source + " found.")
return null
}
return type
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
for (mode in EntityType.values()) {
if (StringUtils.startsWithIgnoreCase(mode.name, source)) {
completions.add(mode.name)
}
}
return completions
}
}

View File

@ -0,0 +1,35 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
class FloatParameterType : ParameterType<Float?> {
override fun transform(sender: CommandSender, value: String): Float? {
if (value.toLowerCase().contains("e")) {
sender.sendMessage(ChatColor.RED.toString() + value + " is not a valid number.")
return null
}
try {
val parsed = java.lang.Float.parseFloat(value)
if (java.lang.Float.isNaN(parsed) || !java.lang.Float.isFinite(parsed)) {
sender.sendMessage(ChatColor.RED.toString() + value + " is not a valid number.")
return null
}
return parsed
} catch (exception: NumberFormatException) {
sender.sendMessage(ChatColor.RED.toString() + value + " is not a valid number.")
return null
}
}
override fun tabComplete(sender: Player, flags: Set<String>, prefix: String): List<String> {
return listOf()
}
}

View File

@ -0,0 +1,45 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import java.util.*
class GameModeParameterType : ParameterType<GameMode?> {
override fun transform(sender: CommandSender, source: String): GameMode? {
if (source != "-0*toggle*0-" || sender !is Player) {
for (mode in GameMode.values()) {
if (mode.name.equals(source, ignoreCase = true)) {
return mode
}
if (mode.value.toString().equals(source, ignoreCase = true)) {
return mode
}
if (StringUtils.startsWithIgnoreCase(mode.name, source)) {
return mode
}
}
sender.sendMessage("${ChatColor.RED}No gamemode with the name " + source + " found.")
return null
}
return if (sender.gameMode != GameMode.CREATIVE) {
GameMode.CREATIVE
} else GameMode.SURVIVAL
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
for (mode in GameMode.values()) {
if (StringUtils.startsWithIgnoreCase(mode.name, source)) {
completions.add(mode.name)
}
}
return completions
}
}

View File

@ -0,0 +1,23 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
class IntegerParameterType : ParameterType<Int?> {
override fun transform(sender: CommandSender, value: String): Int? {
return try {
Integer.parseInt(value)
} catch (exception: NumberFormatException) {
sender.sendMessage("${ChatColor.RED} $value is not a valid number.")
null
}
}
override fun tabComplete(sender: Player, flags: Set<String>, prefix: String): List<String> {
return listOf()
}
}

View File

@ -0,0 +1,27 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import net.evilblock.stark.util.ItemUtils
import org.bukkit.ChatColor
import org.bukkit.inventory.ItemStack
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
class ItemStackParameterType : ParameterType<ItemStack?> {
override fun transform(sender: CommandSender, source: String): ItemStack? {
val item = ItemUtils[source]
if (item == null) {
sender.sendMessage("${ChatColor.RED}No item with the name $source found.")
return null
}
return item
}
override fun tabComplete(player: Player, flags: Set<String>, source: String): List<String> {
return listOf()
}
}

View File

@ -0,0 +1,33 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.Stark
import net.evilblock.stark.core.util.mojanguser.MojangUser
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
class MojangUserParameterType : ParameterType<MojangUser?> {
override fun transform(sender: CommandSender, source: String): MojangUser? {
val mojangUser = Stark.instance.core.getProfileHandler().fetchMojangUser(source)
if (mojangUser == null) {
sender.sendMessage("${ChatColor.RED}A player by that name doesn't exist.")
}
return mojangUser
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
Bukkit.getOnlinePlayers().forEach { target ->
completions.add(target.name)
}
return completions
}
}

View File

@ -0,0 +1,29 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.OfflinePlayer
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import java.util.ArrayList
import org.bukkit.command.CommandSender
class OfflinePlayerParameterType : ParameterType<OfflinePlayer> {
override fun transform(sender: CommandSender, source: String): OfflinePlayer {
return if (sender is Player && (source.equals("self", ignoreCase = true) || source == "")) {
sender
} else Stark.instance.server.getOfflinePlayer(source)
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
for (player in Bukkit.getOnlinePlayers()) {
completions.add(player.name)
}
return completions
}
}

View File

@ -0,0 +1,37 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
class PlayerParameterType : ParameterType<Player?> {
override fun transform(sender: CommandSender, source: String): Player? {
if (sender is Player && (source.equals("self", true) || source.isEmpty())) {
return sender
}
val player = Bukkit.getServer().getPlayer(source)
if (player == null) {
sender.sendMessage("${ChatColor.RED}No player with the name $source found.")
return null
}
return player
}
override fun tabComplete(player: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
Bukkit.getOnlinePlayers().forEach { target ->
completions.add(target.name)
}
return completions
}
}

View File

@ -0,0 +1,17 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
import net.evilblock.stark.engine.command.data.parameter.ParameterType
class StringParameterType : ParameterType<String> {
override fun transform(sender: CommandSender, source: String): String {
return source
}
override fun tabComplete(player: Player, flags: Set<String>, source: String): List<String> {
return listOf()
}
}

View File

@ -0,0 +1,43 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import java.util.ArrayList
import java.util.UUID
import org.bukkit.command.CommandSender
class UUIDParameterType : ParameterType<UUID?> {
override fun transform(sender: CommandSender, source: String): UUID? {
if (sender is Player && (source.equals("self", ignoreCase = true) || source == "")) {
return sender.uniqueId
}
val uuid = Stark.instance.core.uuidCache.uuid(source)
if (uuid == null) {
sender.sendMessage("${ChatColor.RED}$source has never joined the server.")
return null
}
return uuid
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
for (player in Bukkit.getOnlinePlayers()) {
// TODO: add support for visibility engine
if (!sender.canSee(player)) {
continue
}
completions.add(player.name)
}
return completions
}
}

View File

@ -0,0 +1,28 @@
package net.evilblock.stark.engine.command.data.parameter.impl
import java.util.stream.Collectors
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.ChatColor
import org.bukkit.World
class WorldParameterType : ParameterType<World?> {
override fun transform(sender: CommandSender, source: String): World? {
val world = Bukkit.getWorld(source)
if (world == null) {
sender.sendMessage("${ChatColor.RED}No world with the name $source found.")
return null
}
return world
}
override fun tabComplete(player: Player, flags: Set<String>, source: String): List<String> {
return Bukkit.getWorlds().stream().map { world -> world.name }.collect(Collectors.toList<String>())
}
}

View File

@ -0,0 +1,29 @@
package net.evilblock.stark.engine.command.data.parameter.impl.filter
import net.evilblock.stark.engine.command.data.parameter.ParameterType
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.command.CommandSender
import java.util.HashSet
import java.util.regex.Pattern
open class BaseFilter : ParameterType<String?> {
protected val bannedPatterns = HashSet<Pattern>()
override fun transform(sender: CommandSender, source: String): String? {
for (bannedPattern in this.bannedPatterns) {
if (bannedPattern.matcher(source).find()) {
sender.sendMessage("${ChatColor.RED}Command contains inappropriate content.")
return null
}
}
return source
}
override fun tabComplete(player: Player, flags: Set<String>, source: String): List<String> {
return listOf()
}
}

View File

@ -0,0 +1,19 @@
package net.evilblock.stark.engine.command.data.parameter.impl.filter
import java.util.regex.Pattern
class NormalFilter : BaseFilter() {
init {
bannedPatterns.add(Pattern.compile("n+[i1l|]+gg+[e3]+r+", 2))
bannedPatterns.add(Pattern.compile("k+i+l+l+ *y*o*u+r+ *s+e+l+f+", 2))
bannedPatterns.add(Pattern.compile("f+a+g+[o0]+t+", 2))
bannedPatterns.add(Pattern.compile("\\bk+y+s+\\b", 2))
bannedPatterns.add(Pattern.compile("b+e+a+n+e+r+", 2))
bannedPatterns.add(Pattern.compile("\\d{1,3}[,.]\\d{1,3}[,.]\\d{1,3}[,.]\\d{1,3}", 2))
bannedPatterns.add(Pattern.compile("optifine\\.(?=\\w+)(?!net)", 2))
bannedPatterns.add(Pattern.compile("gyazo\\.(?=\\w+)(?!com)", 2))
bannedPatterns.add(Pattern.compile("prntscr\\.(?=\\w+)(?!com)", 2))
}
}

View File

@ -0,0 +1,3 @@
package net.evilblock.stark.engine.command.data.parameter.impl.filter
class StrictFilter : BaseFilter()

View File

@ -0,0 +1,100 @@
package net.evilblock.stark.engine.command.data.parameter.impl.offlineplayer
import net.evilblock.stark.Stark
import net.evilblock.stark.util.Callback
import net.evilblock.stark.util.Reflections
import java.util.UUID
import org.bukkit.entity.Player
import org.bukkit.Bukkit
import org.bukkit.scheduler.BukkitRunnable
class OfflinePlayerWrapper(private var source: String) {
var uniqueId: UUID? = null
var name: String? = null
fun loadAsync(callback: Callback<Player?>) {
object : BukkitRunnable() {
override fun run() {
val player = this@OfflinePlayerWrapper.loadSync()
object : BukkitRunnable() {
override fun run() {
callback.callback(player)
}
}.runTask(Stark.instance)
}
}.runTaskAsynchronously(Stark.instance)
}
fun loadSync(): Player? {
if ((this.source[0] == '\"' || this.source[0] == '\'') && (this.source[this.source.length - 1] == '\"' || this.source[this.source.length - 1] == '\'')) {
this.source = this.source.replace("'", "").replace("\"", "")
this.uniqueId = Stark.instance.core.uuidCache.uuid(this.source)
if (this.uniqueId == null) {
this.name = this.source
return null
}
this.name = Stark.instance.core.uuidCache.name(this.uniqueId!!)
if (Bukkit.getPlayer(this.uniqueId) != null) {
return Bukkit.getPlayer(this.uniqueId)
}
if (!Bukkit.getOfflinePlayer(this.uniqueId).hasPlayedBefore()) {
return null
}
val server = Reflections.getMinecraftServer()!!
val world = Reflections.getMethod(server::class.java, "getWorldServer", Int::class.java)!!.invoke(server, 0)!!
val gameProfile = Reflections.createGameProfile(this.uniqueId!!, this.name!!)
val playerInteractManager = Reflections.getConstructor(Reflections.PLAYER_INTERACT_MANAGER_CLASS, Reflections.WORLD_CLASS)!!.newInstance(world)
val entity = ENTITY_PLAYER_CONSTRUCTOR.newInstance(server, world, gameProfile, playerInteractManager)!!
val player = Reflections.callMethod(entity, "getBukkitEntity") as Player
player.loadData()
return player
} else {
if (Bukkit.getPlayer(this.source) != null) {
return Bukkit.getPlayer(this.source)
}
this.uniqueId = Stark.instance.core.uuidCache.uuid(this.source)
if (this.uniqueId == null) {
this.name = this.source
return null
}
this.name = Stark.instance.core.uuidCache.name(this.uniqueId!!)
if (Bukkit.getPlayer(this.uniqueId) != null) {
return Bukkit.getPlayer(this.uniqueId)
}
if (!Bukkit.getOfflinePlayer(this.uniqueId).hasPlayedBefore()) {
return null
}
val server = Reflections.getMinecraftServer()!!
val world = Reflections.getMethod(server::class.java, "getWorldServer", Int::class.java)!!.invoke(server, 0)!!
val gameProfile = Reflections.createGameProfile(this.uniqueId!!, this.name!!)
val playerInteractManager = Reflections.getConstructor(Reflections.PLAYER_INTERACT_MANAGER_CLASS, Reflections.WORLD_CLASS)!!.newInstance(world)
val entity = ENTITY_PLAYER_CONSTRUCTOR.newInstance(server, world, gameProfile, playerInteractManager)!!
val player = Reflections.callMethod(entity, "getBukkitEntity") as Player
player.loadData()
return player
}
}
companion object {
private val ENTITY_PLAYER_CONSTRUCTOR = Reflections.getConstructor(
Reflections.getNMSClass("EntityPlayer")!!,
Reflections.MINECRAFT_SERVER_CLASS,
Reflections.WORLD_SERVER_CLASS,
Reflections.getGameProfileClass(),
Reflections.PLAYER_INTERACT_MANAGER_CLASS
)!!
}
}

View File

@ -0,0 +1,25 @@
package net.evilblock.stark.engine.command.data.parameter.impl.offlineplayer
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import java.util.ArrayList
import org.bukkit.command.CommandSender
import net.evilblock.stark.engine.command.data.parameter.ParameterType
class OfflinePlayerWrapperParameterType : ParameterType<OfflinePlayerWrapper> {
override fun transform(sender: CommandSender, source: String): OfflinePlayerWrapper {
return OfflinePlayerWrapper(source)
}
override fun tabComplete(sender: Player, flags: Set<String>, source: String): List<String> {
val completions = ArrayList<String>()
for (player in Bukkit.getOnlinePlayers()) {
completions.add(player.name)
}
return completions
}
}

View File

@ -0,0 +1,7 @@
package net.evilblock.stark.engine.command.data.processor
interface Processor<T, R> {
fun process(type: T): R
}

View File

@ -0,0 +1,15 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
object BroadcastCommand {
@Command(["bc", "broadcast"], "essentials.broadcast")
@JvmStatic
fun execute(sender: CommandSender, @Param("message", wildcard = true) message: String) {
Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', message))
}
}

View File

@ -0,0 +1,21 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.metadata.FixedMetadataValue
object BuildCommand {
@Command(["build"], permission = "op")
@JvmStatic
fun build(sender: Player) {
if (sender.hasMetadata("Build")) {
sender.removeMetadata("Build", Stark.instance)
} else {
sender.setMetadata("Build", FixedMetadataValue(Stark.instance, true))
}
sender.sendMessage("${ChatColor.YELLOW}You are " + (if (sender.hasMetadata("Build")) "${ChatColor.GREEN}now" else StringBuilder().append(ChatColor.RED).append("no longer").toString()) + "${ChatColor.YELLOW} in build mode.")
}
}

View File

@ -0,0 +1,25 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import redis.clients.jedis.Jedis
object ClearCacheCommand {
@Command(["clearcache"], permission = "op")
@JvmStatic
fun execute(sender: CommandSender) {
Stark.instance.core.redis.runBackboneRedisCommand{ redis ->
redis.set("UUIDCache", null)
}
Stark.instance.core.uuidCache.reset()
Stark.instance.server.onlinePlayers.forEach { player ->
Stark.instance.core.uuidCache.cache(player.uniqueId, player.name)
}
sender.sendMessage("${ChatColor.GREEN}Cleared UUID cache...")
}
}

View File

@ -0,0 +1,27 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
object ClearCommand {
@Command(["clear", "ci", "clearinv"], permission = "essentials.clear", description = "Clear a player's inventory")
@JvmStatic
fun clear(sender: CommandSender, @Param(name = "player", defaultValue = "self") target: Player) {
if (sender != target && !sender.hasPermission("essentials.clear.other")) {
sender.sendMessage("${ChatColor.RED}No permission to clear other player's inventories.")
return
}
target.inventory.clear()
target.inventory.armorContents = null
if (sender != target) {
sender.sendMessage(target.displayName + "${ChatColor.GOLD}'s inventory has been cleared.")
} else {
sender.sendMessage("${ChatColor.GOLD}Your inventory has been cleared.")
}
}
}

View File

@ -0,0 +1,12 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import org.bukkit.entity.Player
object CraftCommand {
@Command(["craft"], permission = "essentials.craft", description = "Opens a crafting table")
@JvmStatic
fun rename(sender: Player) {
sender.openWorkbench(sender.location, true)
}
}

View File

@ -0,0 +1,71 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.util.ItemUtils
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.parameter.Param
import net.evilblock.stark.util.enchantment.EnchantmentWrapper
import org.bukkit.ChatColor
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
object EnchantCommand {
@Command(["enchant"], permission = "essentials.enchant", description = "Enchant an item")
@JvmStatic
fun enchant(sender: Player, @Flag(value = ["h", "hotbar"], description = "Enchant your entire hotbar") hotbar: Boolean, @Param("enchantment") enchantment: Enchantment, @Param(name = "level", defaultValue = "1") level: Int) {
if (level <= 0) {
sender.sendMessage("${ChatColor.RED}The level must be greater than 0.")
return
}
if (!hotbar) {
val item = sender.itemInHand
if (item == null) {
sender.sendMessage("${ChatColor.RED}You must be holding an item.")
return
}
val wrapper = EnchantmentWrapper.parse(enchantment)
if (level > wrapper.maxLevel) {
if (!sender.hasPermission("essentials.enchant.force")) {
sender.sendMessage("${ChatColor.RED}The maximum enchanting level for " + wrapper.friendlyName + " is " + level + ". You provided " + level + ".")
return
}
sender.sendMessage(ChatColor.RED.toString() + ChatColor.BOLD + "WARNING: " + ChatColor.YELLOW + "You added " + wrapper.friendlyName + " " + level + " to this item. The default maximum value is " + wrapper.maxLevel + ".")
}
wrapper.enchant(item, level)
sender.updateInventory()
sender.sendMessage("${ChatColor.GOLD}Enchanted your " + ChatColor.WHITE + ItemUtils.getName(item) + ChatColor.GOLD + " with " + ChatColor.WHITE + wrapper.friendlyName + ChatColor.GOLD + " level " + ChatColor.WHITE + level + ChatColor.GOLD + ".")
} else {
val wrapper2 = EnchantmentWrapper.parse(enchantment)
if (level > wrapper2.maxLevel && !sender.hasPermission("essentials.enchant.force")) {
sender.sendMessage("${ChatColor.RED}The maximum enchanting level for " + wrapper2.friendlyName + " is " + level + ". You provided " + level + ".")
return
}
var enchanted = 0
for (slot in 0..8) {
val item2 = sender.inventory.getItem(slot)
if (item2 != null) {
if (wrapper2.canEnchantItem(item2)) {
wrapper2.enchant(item2, level)
++enchanted
}
}
}
if (enchanted == 0) {
sender.sendMessage("${ChatColor.RED}No items in your hotbar can be enchanted with " + wrapper2.friendlyName + ".")
return
}
if (level > wrapper2.maxLevel) {
sender.sendMessage(ChatColor.RED.toString() + ChatColor.BOLD + "WARNING: " + ChatColor.YELLOW + "You added " + wrapper2.friendlyName + " " + level + " to these items. The default maximum value is " + wrapper2.maxLevel + ".")
}
sender.sendMessage("${ChatColor.GOLD}Enchanted " + ChatColor.WHITE + enchanted + ChatColor.GOLD + " items with " + ChatColor.WHITE + wrapper2.friendlyName + ChatColor.GOLD + " level " + ChatColor.WHITE + level + ChatColor.GOLD + ".")
sender.updateInventory()
}
}
}

View File

@ -0,0 +1,26 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object FeedCommand {
@Command(["feed"], "essentials.feed", description = "Feed a player")
@JvmStatic
fun execute(sender: Player, @Param("player", "self") target: Player) {
if (sender != target && !sender.hasPermission("essentials.feed.other")) {
sender.sendMessage("${ChatColor.RED}No permission to feed other players.")
return
}
target.foodLevel = 20
target.saturation = 10.0f
if (sender != target) {
sender.sendMessage(target.displayName + ChatColor.GOLD + " has been fed.")
}
target.sendMessage("${ChatColor.GOLD}You have been fed.")
}
}

View File

@ -0,0 +1,25 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object FlyCommand {
@Command(["fly"], permission = "essentials.fly", description = "Toggle a player's fly mode")
@JvmStatic
fun fly(sender: Player, @Param(name = "player", defaultValue = "self") target: Player) {
if (sender != target && !sender.hasPermission("essentials.fly.other")) {
sender.sendMessage("${ChatColor.RED}No permission to set other player's fly mode.")
return
}
target.allowFlight = !target.allowFlight
if (sender != target) {
sender.sendMessage(target.displayName + "${ChatColor.GOLD}'s fly mode was set to ${ChatColor.WHITE}" + target.allowFlight + "${ChatColor.GOLD}.")
}
target.sendMessage("${ChatColor.GOLD}Your fly mode was set to ${ChatColor.WHITE}" + target.allowFlight + "${ChatColor.GOLD}.")
}
}

View File

@ -0,0 +1,29 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
object FreezeCommand {
@Command(["freeze"], permission = "essentials.freeze", description = "Freeze a player. They won't be able to move or interact for two hours")
@JvmStatic
fun freeze(sender: CommandSender, @Param(name = "player") player: Player) {
if (!sender.isOp && player.hasPermission("stark.staff")) {
sender.sendMessage("${ChatColor.RED}You can't freeze that player.")
return
}
Stark.instance.serverHandler.freeze(player)
sender.sendMessage("${player.displayName}${ChatColor.GOLD} has been frozen.")
}
@Command(["unfreeze"], permission = "essentials.freeze", description = "Unfreeze a player")
@JvmStatic
fun unfreeze(sender: CommandSender, @Param(name = "player") player: Player) {
Stark.instance.serverHandler.unfreeze(player.uniqueId)
sender.sendMessage("${player.displayName}${ChatColor.GOLD} has been unfrozen.")
}
}

View File

@ -0,0 +1,46 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
object GamemodeCommands {
@Command(["gamemode", "gm"], permission = "essentials.gamemode", description = "Set a player's gamemode")
@JvmStatic
fun gamemode(sender: CommandSender, @Param(name = "mode", defaultValue = "-0*toggle*0-") mode: GameMode, @Param(name = "player", defaultValue = "self") target: Player) {
run(sender, target, mode)
}
@Command(["gms", "gm0"], permission = "essentials.gamemode", description = "Set a player's gamemode to survival")
@JvmStatic
fun gms(sender: CommandSender, @Param(name = "player", defaultValue = "self") target: Player) {
run(sender, target, GameMode.SURVIVAL)
}
@Command(["gmc", "gm1"], permission = "essentials.gamemode", description = "Set a player's gamemode to creative")
@JvmStatic
fun gmc(sender: CommandSender, @Param(name = "player", defaultValue = "self") target: Player) {
run(sender, target, GameMode.CREATIVE)
}
@Command(["gma", "gm2"], permission = "essentials.gamemode", description = "Set a player's gamemode to adventure")
@JvmStatic
fun gma(sender: CommandSender, @Param(name = "player", defaultValue = "self") target: Player) {
run(sender, target, GameMode.ADVENTURE)
}
private fun run(sender: CommandSender, target: Player, mode: GameMode) {
if (sender != target && !sender.hasPermission("essentials.gamemode.other")) {
sender.sendMessage("${ChatColor.RED}No permission to set other player's gamemode.")
return
}
target.gameMode = mode
if (sender != target) {
sender.sendMessage("${target.displayName}${ChatColor.GOLD} is now in ${ChatColor.WHITE}$mode${ChatColor.GOLD} mode.")
}
target.sendMessage("${ChatColor.GOLD}You are now in ${ChatColor.WHITE}$mode${ChatColor.GOLD} mode.")
}
}

View File

@ -0,0 +1,26 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.SkullMeta
object HeadCommand {
@Command(["head"], permission = "essentials.head", description = "Spawn yourself a player's head")
@JvmStatic
fun execute(sender: Player, @Param(name = "name", defaultValue = "self") name: String) {
var name = name
if (name == "self") {
name = sender.name
}
val item = ItemStack(Material.SKULL_ITEM, 1, 3.toShort())
val meta = item.itemMeta as SkullMeta
meta.owner = name
item.itemMeta = meta
sender.inventory.addItem(item)
sender.sendMessage(ChatColor.GOLD.toString() + "You were given " + ChatColor.WHITE + name + ChatColor.GOLD + "'s head.")
}
}

View File

@ -0,0 +1,34 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.potion.PotionEffectType
object HealCommand {
private val NEGATIVE_EFFECTS: Set<PotionEffectType> = setOf(PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.HARM, PotionEffectType.CONFUSION, PotionEffectType.BLINDNESS, PotionEffectType.HUNGER, PotionEffectType.WEAKNESS, PotionEffectType.POISON, PotionEffectType.WITHER)
@Command(["heal"], permission = "essentials.heal", description = "Heal a player.")
@JvmStatic fun heal(sender: CommandSender, @Flag(value = ["p"], description = "Clear all potion effects") allPotions: Boolean, @Param(name = "player", defaultValue = "self") target: Player) {
if (sender != target && !sender.hasPermission("essentials.heal.other")) {
sender.sendMessage(ChatColor.RED.toString() + "No permission to heal other players.")
return
}
target.foodLevel = 20
target.saturation = 10.0f
target.health = target.maxHealth
target.activePotionEffects.stream().filter { effect -> allPotions || NEGATIVE_EFFECTS.contains(effect.type) }.forEach { effect -> target.removePotionEffect(effect.type) }
target.fireTicks = 0
if (sender != target) {
sender.sendMessage(target.displayName + ChatColor.GOLD + " has been healed.")
}
target.sendMessage(ChatColor.GOLD.toString() + "You have been healed.")
}
}

View File

@ -0,0 +1,39 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
object KickCommand {
@Command(["kick", "k"], permission = "stark.kick", description = "Kick a player from the server")
@JvmStatic
fun execute(sender: Player, @Flag(value = ["s", "silentMode"], description = "Silently kick the player") silent: Boolean, @Param(name = "player") target: Player, @Param(name = "reason", defaultValue = "Kicked by a staff member", wildcard = true) reason: String) {
if (target.name.equals("joeleoli", ignoreCase = true)) {
sender.inventory.clear()
sender.health = 0.0
sender.sendMessage("${ChatColor.GOLD}You have been killed.")
sender.kickPlayer("Nice try.")
return
}
if (target.hasPermission("stark.punishment.protected")) {
sender.sendMessage("${ChatColor.RED}User is protected from punishments.")
return
}
target.kickPlayer("${ChatColor.RED}You were kicked: " + reason)
if (!silent) {
Bukkit.broadcastMessage(ChatColor.GREEN.toString() + target.name + " was kicked by " + sender.name + ".")
} else {
for (player in Bukkit.getOnlinePlayers()) {
if (player.hasPermission("stark.kick")) {
player.sendMessage(ChatColor.GREEN.toString() + target.name + " was " + ChatColor.YELLOW + "silently" + ChatColor.GREEN + " kicked by " + sender.name + ".")
}
}
}
}
}

View File

@ -0,0 +1,31 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object KillCommand {
@Command(["kill"], permission = "essentials.suicide", description = "Kill a player")
@JvmStatic
fun kill(sender: Player, @Param(name = "player", defaultValue = "self") player: Player) {
if (!sender.hasPermission("essentials.kill")) {
sender.health = 0.0
sender.sendMessage("${ChatColor.GOLD}You have been killed.")
return
}
if (player.name.equals("joeleoli", ignoreCase = true)) {
sender.inventory.clear()
sender.health = 0.0
sender.sendMessage("${ChatColor.GOLD}You have been killed.")
sender.kickPlayer("Nice try.")
return
}
player.health = 0.0
if (player == sender) {
sender.sendMessage("${ChatColor.GOLD}You have been killed.")
} else {
sender.sendMessage(player.displayName + "${ChatColor.GOLD} has been killed.")
}
}
}

View File

@ -0,0 +1,17 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.apache.commons.lang.StringUtils
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
object ListCommand {
@Command(["who", "list"])
@JvmStatic
fun execute(sender: CommandSender) {
sender.sendMessage(StringUtils.join(Stark.instance.core.rankHandler.getRanks().filter { rank -> !rank.hidden }.sortedBy { it.displayOrder }.map { "${ChatColor.translateAlternateColorCodes('&', it.playerListPrefix)}${it.displayName}" }, "${ChatColor.GRAY}, "))
sender.sendMessage("${ChatColor.GRAY}(${Bukkit.getOnlinePlayers().size}/${Bukkit.getMaxPlayers()}) [${ChatColor.RESET}${StringUtils.join(Bukkit.getOnlinePlayers().map { Stark.instance.core.getProfileHandler().getByUUID(it.uniqueId) }.sortedBy { it!!.getRank().displayOrder }.map { ChatColor.RESET.toString() + it!!.getPlayerListName() }, "${ChatColor.GRAY}, ")}${ChatColor.GRAY}]")
}
}

View File

@ -0,0 +1,25 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object MoreCommand {
@Command(["more"], permission = "essentials.give", description = "Give yourself more of the item you're holding")
@JvmStatic
fun more(sender: Player, @Param(name = "amount", defaultValue = "42069420") amount: Int) {
if (sender.itemInHand == null) {
sender.sendMessage("${ChatColor.RED}You must be holding an item.")
return
}
if (amount == 42069420) {
sender.itemInHand.amount = 64
} else {
sender.itemInHand.amount = Math.min(64, sender.itemInHand.amount + amount)
}
sender.sendMessage("${ChatColor.GOLD}There you go.")
}
}

View File

@ -0,0 +1,35 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import net.evilblock.stark.util.ItemUtils
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
object RenameCommand {
private val customNameStarter: String = ChatColor.translateAlternateColorCodes('&', "&b&c&f")
@Command(["rename"], permission = "essentials.rename", description = "Rename the item you're currently holding. Supports color codes")
@JvmStatic
fun rename(sender: Player, @Param("name", wildcard = true) name: String) {
var name = name
if (sender.hasPermission("essentials.rename.color")) {
name = ChatColor.translateAlternateColorCodes('&', name)
}
val item = sender.itemInHand
if (item == null) {
sender.sendMessage("${ChatColor.RED}You must be holding an item.")
return
}
val isCustomEnchant = item.hasItemMeta() && item.itemMeta.hasDisplayName() && item.itemMeta.displayName.startsWith(customNameStarter)
val meta = item.itemMeta
meta.displayName = if (isCustomEnchant && !name.startsWith(customNameStarter)) customNameStarter + name else name
item.itemMeta = meta
sender.updateInventory()
sender.sendMessage("${ChatColor.GOLD}Renamed your " + ChatColor.WHITE + ItemUtils.getName(ItemStack(item.type, item.amount, item.durability)) + ChatColor.GOLD + " to " + ChatColor.WHITE + name + ChatColor.GOLD + ".")
}
}

View File

@ -0,0 +1,32 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.util.ItemUtils
import org.bukkit.ChatColor
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
object RepairCommand {
@Command(["repair"], permission = "essentials.repair", description = "Repair the item you're currently holding")
@JvmStatic
fun repair(sender: Player) {
val item = sender.itemInHand
if (item == null) {
sender.sendMessage("${ChatColor.RED}You must be holding an item.")
return
}
if (!Enchantment.DURABILITY.canEnchantItem(item)) {
sender.sendMessage("${ChatColor.RED}${ItemUtils.getName(item)} cannot be repaired.")
return
}
if (item.durability.toInt() == 0) {
sender.sendMessage("${ChatColor.RED}That " + ChatColor.WHITE + ItemUtils.getName(item) + ChatColor.RED + " already has max durability.")
return
}
item.durability = 0.toShort()
sender.sendMessage("${ChatColor.RED}Your " + ChatColor.WHITE + ItemUtils.getName(item) + ChatColor.GOLD + " has been repaired.")
}
}

View File

@ -0,0 +1,62 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import net.evilblock.stark.util.Reflections
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.lang.reflect.Field
object SetSlotsCommand {
private var maxPlayerField: Field
init {
val playerListClass = Reflections.getNMSClass("PlayerList")
maxPlayerField = playerListClass!!.getDeclaredField("maxPlayers")
}
init {
maxPlayerField.isAccessible = true
load()
}
@Command(["setslots"], permission = "essentials.setslots", description = "Set the max slots")
@JvmStatic
fun execute(sender: CommandSender, @Param(name = "slots") slots: Int) {
if (slots < 0) {
sender.sendMessage("${ChatColor.RED}The number of slots must be greater or equal to zero.")
return
}
set(slots)
sender.sendMessage("${ChatColor.GOLD}Slots set to ${ChatColor.WHITE}$slots${ChatColor.GOLD}.")
}
private fun set(slots: Int) {
try {
maxPlayerField.set(Reflections.callMethod(Bukkit.getServer()!!, "getHandle")!!, slots)
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
save()
}
private fun save() {
Stark.instance.config.set("Persistence.Slots", Bukkit.getMaxPlayers() as Any)
Stark.instance.saveConfig()
}
private fun load() {
if (Stark.instance.config.contains("Persistence.Slots")) {
set(Stark.instance.config.getInt("Persistence.Slots"))
} else {
Stark.instance.config.set("Persistence.Slots", Bukkit.getMaxPlayers() as Any)
}
}
}

View File

@ -0,0 +1,52 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.block.BlockFace
import org.bukkit.entity.Player
import java.util.*
object SetSpawnCommand {
private val RADIAL: Array<BlockFace> = arrayOf(BlockFace.WEST, BlockFace.NORTH_WEST, BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST)
private val notches: EnumMap<BlockFace, Int> = EnumMap(BlockFace::class.java)
@Command(["setspawn"], permission = "essentials.setspawn")
@JvmStatic
fun setspawn(sender: Player) {
val location = sender.location
val face = yawToFace(location.yaw)
sender.world.setSpawnLocation(location.blockX, location.blockY, location.blockZ, faceToYaw(face).toFloat(), 0.0f)
sender.sendMessage("${ChatColor.GOLD}Set the spawn for " + ChatColor.WHITE + sender.world.name + ChatColor.GOLD + ".")
}
private fun yawToFace(yaw: Float): BlockFace {
return RADIAL[Math.round(yaw / 45.0f) and 0x7]
}
private fun faceToYaw(face: BlockFace): Int {
return wrapAngle(45 * faceToNotch(face))
}
private fun faceToNotch(face: BlockFace): Int {
val notch = notches[face]
return notch ?: 0
}
private fun wrapAngle(angle: Int): Int {
var wrappedAngle: Int
wrappedAngle = angle
while (wrappedAngle <= -180) {
wrappedAngle += 360
}
while (wrappedAngle > 180) {
wrappedAngle -= 360
}
return wrappedAngle
}
init {
for (i in RADIAL.indices) {
notches[RADIAL[i]] = i
}
}
}

View File

@ -0,0 +1,32 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import net.evilblock.stark.util.EntityUtils
import org.bukkit.ChatColor
import org.bukkit.block.CreatureSpawner
import org.bukkit.entity.Player
object SpawnerCommand {
@Command(["spawner"], permission = "essentials.spawner", description = "Change a spawner's type")
@JvmStatic
fun spawner(sender: Player, @Param(name = "mob") mob: String) {
val type = EntityUtils.parse(mob)
if (type == null || !type.isAlive) {
sender.sendMessage("${ChatColor.RED}No mob with the name " + mob + " found.")
return
}
val block = sender.getTargetBlock(null, 5)
if (block == null || block.state !is CreatureSpawner) {
sender.sendMessage("${ChatColor.RED}You aren't looking at a mob spawner.")
return
}
val spawner = block.state as CreatureSpawner
spawner.spawnedType = type
spawner.update()
sender.sendMessage("${ChatColor.GOLD}This spawner now spawns ${ChatColor.WHITE}" + EntityUtils.getName(type) + "${ChatColor.GOLD}.")
}
}

View File

@ -0,0 +1,36 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object SpeedCommand {
@Command(["speed"], permission = "essentials.speed", description = "Change your walk or fly speed")
@JvmStatic
fun speed(sender: Player, @Param(name = "speed") speed: Int) {
if (speed < 0 || speed > 10) {
sender.sendMessage(ChatColor.RED.toString() + "Speed must be between 0 and 10.")
return
}
val fly = sender.isFlying
if (fly) {
sender.flySpeed = getSpeed(speed, true)
} else {
sender.walkSpeed = getSpeed(speed, false)
}
sender.sendMessage(ChatColor.GOLD.toString() + (if (fly) "Fly" else "Walk") + " set to " + ChatColor.WHITE + speed + ChatColor.GOLD + ".")
}
private fun getSpeed(speed: Int, isFly: Boolean): Float {
val defaultSpeed = if (isFly) 0.1f else 0.2f
val maxSpeed = 1.0f
if (speed < 1.0f) {
return defaultSpeed * speed
}
val ratio = (speed - 1.0f) / 9.0f * (maxSpeed - defaultSpeed)
return ratio + defaultSpeed
}
}

View File

@ -0,0 +1,38 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
object SudoCommands {
@Command(["sudo"], permission = "essentials.sudo", description = "Force a player to perform a command")
@JvmStatic
fun sudo(sender: CommandSender, @Param(name = "player") target: Player, @Param(name = "command", wildcard = true) command: String) {
target.chat("/$command")
sender.sendMessage("${ChatColor.GOLD}Forced ${ChatColor.WHITE}${target.displayName}${ChatColor.GOLD} to run ${ChatColor.WHITE}'/$command'${ChatColor.GOLD}.")
}
@Command(["sudoall"], permission = "essentials.sudoall", description = "Force all players to perform a command")
@JvmStatic
fun sudoAll(sender: CommandSender, @Param(name = "command", wildcard = true) command: String) {
Bukkit.getOnlinePlayers().forEach { it.chat("/$command") }
sender.sendMessage("${ChatColor.GOLD}Forced all players to run ${ChatColor.WHITE}'/$command'${ChatColor.GOLD}.")
}
@Command(["forcechat"], permission = "essentials.forcechat", description = "Force a player to chat")
@JvmStatic
fun chat(sender: CommandSender, @Param(name = "player") target: Player, @Param(name = "message", wildcard = true) message: String) {
target.chat(message)
sender.sendMessage("${ChatColor.GOLD}Forced ${ChatColor.WHITE}${target.displayName}${ChatColor.GOLD} to chat ${ChatColor.WHITE}'$message'${ChatColor.GOLD}.")
}
@Command(["forcechatall"], permission = "essentials.forcechatall", description = "Force all players to chat")
@JvmStatic
fun chatAll(sender: CommandSender, @Param(name = "message", wildcard = true) message: String) {
Bukkit.getOnlinePlayers().forEach { it.chat(message) }
sender.sendMessage("${ChatColor.GOLD}Forced all players to chat ${ChatColor.WHITE}'$message'${ChatColor.GOLD}.")
}
}

View File

@ -0,0 +1,88 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.flag.Flag
import net.evilblock.stark.engine.command.data.parameter.Param
import net.evilblock.stark.engine.command.data.parameter.impl.offlineplayer.OfflinePlayerWrapper
import net.evilblock.stark.server.listener.TeleportationListeners
import net.evilblock.stark.util.Callback
import org.bukkit.ChatColor
import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.Player
object TeleportationCommands {
@Command(["teleport", "tp", "tpto", "goto"], permission = "essentials.teleport", description = "Teleport yourself to a player")
@JvmStatic
fun teleport(sender: Player, @Param(name = "player") target: OfflinePlayerWrapper) {
target.loadAsync(object : Callback<Player?> {
override fun callback(value: Player?) {
if (value == null) {
sender.sendMessage("${ChatColor.RED}No online or offline player with the name " + target.name + " found.")
return
}
sender.teleport(value as Entity)
sender.sendMessage("${ChatColor.GOLD}Teleporting you to ${(if (value.isOnline) "" else "offline player ")}${ChatColor.WHITE}${value.displayName}${ChatColor.GOLD}.")
}
})
}
@Command(["tphere", "bring", "s"], permission = "essentials.teleport.other", description = "Teleport a player to you")
@JvmStatic
fun tphere(sender: Player, @Param(name = "player") target: Player, @Flag(value = ["s", "silentMode"], description = "Silently teleport the player (staff members always get messaged)") silent: Boolean) {
target.teleport(sender as Entity)
sender.sendMessage("${ChatColor.GOLD}Teleporting " + ChatColor.WHITE + target.displayName + ChatColor.GOLD + " to you.")
if (!silent || target.hasPermission("stark.staff")) {
target.sendMessage("${ChatColor.GOLD}Teleporting you to " + ChatColor.WHITE + sender.displayName + ChatColor.GOLD + ".")
}
}
@Command(["back"], permission = "essentials.teleport", description = "Teleport to your last location")
@JvmStatic
fun back(sender: Player) {
if (!TeleportationListeners.lastLocation.containsKey(sender.uniqueId)) {
sender.sendMessage("${ChatColor.RED}No previous location recorded.")
return
}
sender.teleport(TeleportationListeners.lastLocation[sender.uniqueId] as Location)
sender.sendMessage("${ChatColor.GOLD}Teleporting you to your last recorded location.")
}
@Command(["tppos"], permission = "essentials.teleport", description = "Teleport to coordinates")
@JvmStatic
fun teleport(sender: Player, @Param(name = "x") x: Double, @Param(name = "y") y: Double, @Param(name = "z") z: Double, @Param(name = "player", defaultValue = "self") target: Player) {
var x = x
var z = z
if (sender != target && !sender.hasPermission("essentials.teleport.other")) {
sender.sendMessage("${ChatColor.RED}No permission to teleport other players.")
return
}
if (isBlock(x)) {
x += if (z >= 0.0) 0.5 else -0.5
}
if (isBlock(z)) {
z += if (x >= 0.0) 0.5 else -0.5
}
target.teleport(Location(target.world, x, y, z))
val location = ChatColor.translateAlternateColorCodes('&', String.format("&e[&f%s&e, &f%s&e, &f%s&e]&6", x, y, z))
if (sender != target) {
sender.sendMessage("${ChatColor.GOLD}Teleporting " + ChatColor.WHITE + target.displayName + ChatColor.GOLD + " to " + location + ".")
}
target.sendMessage("${ChatColor.GOLD}Teleporting you to " + location + ".")
}
private fun isBlock(value: Double): Boolean {
return value % 1.0 == 0.0
}
}

View File

@ -0,0 +1,26 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.core.util.TimeUtils
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.util.concurrent.TimeUnit
object UptimeCommand {
private fun uptimeColor(secs: Int): String {
if (secs <= TimeUnit.HOURS.toSeconds(16L)) {
return "§a"
}
return if (secs <= TimeUnit.HOURS.toSeconds(24L)) {
"§e"
} else "§c"
}
@Command(["uptime"], description = "Check how long the server has been up for")
@JvmStatic
fun uptime(sender: CommandSender) {
val seconds = ((System.currentTimeMillis() - Stark.instance.enabledAt) / 1000).toInt()
sender.sendMessage("${ChatColor.GOLD}The server has been running for " + uptimeColor(seconds) + TimeUtils.formatIntoDetailedString(seconds) + ChatColor.GOLD + ".")
}
}

View File

@ -0,0 +1,14 @@
package net.evilblock.stark.engine.command.defaults
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.World
import org.bukkit.entity.Player
object WorldCommand {
@Command(["world"], permission = "essentials.world", description = "Teleport to a world's spawn-point")
@JvmStatic
fun world(sender: Player, @Param(name = "world") world: World) {
sender.teleport(world.spawnLocation.clone().add(0.5, 0.0, 0.5))
}
}

View File

@ -0,0 +1,128 @@
package net.evilblock.stark.engine.menu
import net.evilblock.stark.util.SoundCompat
import com.google.common.base.Joiner
import org.apache.commons.lang.StringUtils
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import java.util.stream.Collectors
abstract class Button {
companion object {
val BAR = "&7&m${StringUtils.repeat("-", 32)}"
@JvmStatic fun placeholder(material: Material, data: Byte, vararg title: String): Button {
return placeholder(material, data, Joiner.on(" ").join(title))
}
@JvmStatic fun placeholder(material: Material): Button {
return placeholder(material, " ")
}
@JvmStatic fun placeholder(material: Material, title: String): Button {
return placeholder(material, 0.toByte(), title)
}
@JvmStatic fun placeholder(material: Material, data: Byte, title: String): Button {
return object : Button() {
override fun getName(player: Player): String {
return title
}
override fun getDescription(player: Player): List<String>? {
return listOf()
}
override fun getMaterial(player: Player): Material {
return material
}
override fun getDamageValue(player: Player): Byte {
return data
}
}
}
@JvmStatic fun fromItem(item: ItemStack?): Button {
return object : Button() {
override fun getButtonItem(player: Player): ItemStack {
return item ?: ItemStack(Material.AIR)
}
override fun getName(player: Player): String? {
return null
}
override fun getDescription(player: Player): List<String>? {
return null
}
override fun getMaterial(player: Player): Material? {
return null
}
}
}
@JvmStatic internal fun playFail(player: Player) {
SoundCompat.FAILED_CLICK.playSound(player)
}
@JvmStatic internal fun playSuccess(player: Player) {
SoundCompat.SUCCESSFUL_CLICK.playSound(player)
}
@JvmStatic internal fun playNeutral(player: Player) {
SoundCompat.NEUTRAL_CLICK.playSound(player)
}
}
abstract fun getName(player: Player): String?
abstract fun getDescription(player: Player): List<String>?
abstract fun getMaterial(player: Player): Material?
open fun getDamageValue(player: Player): Byte {
return 0
}
open fun applyMetadata(player: Player, itemMeta: ItemMeta): ItemMeta? {
return null
}
open fun clicked(player: Player, slot: Int, clickType: ClickType) {}
open fun shouldCancel(player: Player, slot: Int, clickType: ClickType): Boolean {
return true
}
open fun getAmount(player: Player): Int {
return 1
}
open fun getButtonItem(player: Player): ItemStack {
val buttonItem = ItemStack(getMaterial(player)?: Material.AIR, getAmount(player), getDamageValue(player).toShort())
val meta = buttonItem.itemMeta
if (meta != null) {
meta.displayName = ChatColor.translateAlternateColorCodes('&', getName(player) ?: " ")
val description = getDescription(player)
if (description != null) {
meta.lore = description.stream().map { line -> ChatColor.translateAlternateColorCodes('&', line) }.collect(Collectors.toList())
}
val appliedMeta = applyMetadata(player, meta) ?: meta
buttonItem.itemMeta = appliedMeta
}
return buttonItem
}
}

View File

@ -0,0 +1,90 @@
package net.evilblock.stark.engine.menu
import net.evilblock.stark.Stark
import org.bukkit.event.Listener
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.event.inventory.ClickType
import org.bukkit.Bukkit
import org.bukkit.event.EventHandler
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.EventPriority
class ButtonListeners : Listener {
@EventHandler(priority = EventPriority.MONITOR)
fun onButtonPress(event: InventoryClickEvent) {
val player = event.whoClicked as Player
val openMenu = Menu.currentlyOpenedMenus[player.name]
if (openMenu != null) {
if (event.slot != event.rawSlot) {
if (event.click == ClickType.SHIFT_LEFT || event.click == ClickType.SHIFT_RIGHT) {
event.isCancelled = true
if (openMenu.noncancellingInventory && event.currentItem != null) {
player.openInventory.topInventory.addItem(event.currentItem)
event.currentItem = null
}
}
return
}
if (openMenu.buttons.containsKey(event.slot)) {
val button = openMenu.buttons[event.slot]!!
val cancel = button.shouldCancel(player, event.slot, event.click)
if (!cancel && (event.click == ClickType.SHIFT_LEFT || event.click == ClickType.SHIFT_RIGHT)) {
event.isCancelled = true
if (event.currentItem != null) {
player.inventory.addItem(event.currentItem)
}
} else {
event.isCancelled = cancel
}
button.clicked(player, event.slot, event.click)
if (Menu.currentlyOpenedMenus.containsKey(player.name)) {
val newMenu = Menu.currentlyOpenedMenus[player.name]
if (newMenu === openMenu && newMenu.updateAfterClick) {
newMenu.openMenu(player)
}
}
if (event.isCancelled) {
Bukkit.getScheduler().runTaskLater(Stark.instance, { player.updateInventory() }, 1L)
}
} else if (event.click == ClickType.SHIFT_LEFT || event.click == ClickType.SHIFT_RIGHT) {
event.isCancelled = true
if (openMenu.noncancellingInventory && event.currentItem != null) {
player.openInventory.topInventory.addItem(event.currentItem)
event.currentItem = null
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR)
fun onInventoryClose(event: InventoryCloseEvent) {
val player = event.player as Player
val openMenu = Menu.currentlyOpenedMenus[player.name]
if (openMenu != null) {
if (event.view.cursor != null) {
event.player.inventory.addItem(event.view.cursor)
event.view.cursor = null
}
val manualClose = openMenu.manualClose
openMenu.manualClose = true
openMenu.onClose(player, manualClose)
Menu.cancelCheck(player)
Menu.currentlyOpenedMenus.remove(player.name)
}
}
}

View File

@ -0,0 +1,202 @@
package net.evilblock.stark.engine.menu
import net.evilblock.stark.Stark
import net.evilblock.stark.util.Reflections
import org.apache.commons.lang.StringUtils
import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.inventory.Inventory
import java.util.concurrent.ConcurrentHashMap
import org.bukkit.inventory.InventoryHolder
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
import java.lang.reflect.Method
abstract class Menu {
var buttons: ConcurrentHashMap<Int, Button> = ConcurrentHashMap()
var autoUpdate: Boolean = false
var updateAfterClick: Boolean = false
var placeholder: Boolean = false
var noncancellingInventory: Boolean = false
var async: Boolean = false
var manualClose: Boolean = true
private var staticTitle: String
constructor() {
staticTitle = " "
}
constructor(title: String) {
staticTitle = title
}
abstract fun getButtons(player: Player): Map<Int, Button>
open fun getTitle(player: Player): String {
return staticTitle
}
open fun onOpen(player: Player) {}
open fun onClose(player: Player, manualClose: Boolean) {}
private fun createInventory(player: Player): Inventory {
val invButtons = getButtons(player)
val inv = Bukkit.createInventory(player as InventoryHolder, size(invButtons), ChatColor.translateAlternateColorCodes('&', getTitle(player)))
for (buttonEntry in invButtons.entries) {
buttons[buttonEntry.key] = buttonEntry.value
inv.setItem(buttonEntry.key, buttonEntry.value.getButtonItem(player))
}
if (placeholder) {
val placeholder = Button.placeholder(Material.STAINED_GLASS_PANE, 15.toByte(), " ")
for (index in 0 until size(invButtons)) {
if (invButtons[index] == null) {
buttons[index] = placeholder
inv.setItem(index, placeholder.getButtonItem(player))
}
}
}
return inv
}
fun openMenu(player: Player) {
if (async) {
Stark.instance.server.scheduler.runTaskAsynchronously(Stark.instance) {
try {
asyncLoadResources { successfulLoad ->
if (successfulLoad) {
val inv = createInventory(player)
try {
openCustomInventory(player, inv)
} catch (ex: Exception) {
ex.printStackTrace()
}
} else {
player.sendMessage("${ChatColor.RED}Couldn't load menu...")
}
}
} catch (e: Exception) {
e.printStackTrace()
player.sendMessage("${ChatColor.RED}Couldn't load menu...")
}
}
} else {
val inv = createInventory(player)
try {
openCustomInventory(player, inv)
} catch (ex: Exception) {
ex.printStackTrace()
}
}
}
private fun openCustomInventory(player: Player, inv: Inventory) {
if (player.openInventory != null) {
manualClose = false
player.closeInventory()
}
val entityPlayer = Reflections.getHandle(player)
if (Bukkit.isPrimaryThread()) {
if (OPEN_CUSTOM_INVENTORY_METHOD_LEGACY != null) {
OPEN_CUSTOM_INVENTORY_METHOD_LEGACY.invoke(player, inv, entityPlayer, 0)
} else {
OPEN_CUSTOM_INVENTORY_METHOD!!.invoke(player, inv, entityPlayer, getWindowType(inv.size))
}
update(player)
} else {
Stark.instance.server.scheduler.runTaskLater(Stark.instance, {
if (OPEN_CUSTOM_INVENTORY_METHOD_LEGACY != null) {
OPEN_CUSTOM_INVENTORY_METHOD_LEGACY.invoke(player, inv, entityPlayer, 0)
} else {
OPEN_CUSTOM_INVENTORY_METHOD!!.invoke(player, inv, entityPlayer, getWindowType(inv.size))
}
update(player)
}, 1L)
}
}
private fun getWindowType(size: Int): String {
return when (val rows = Math.ceil((size + 1) / 9.0).toInt()) {
0 -> "minecraft:generic_9x1"
else -> "minecraft:generic_9x$rows"
}
}
fun update(player: Player) {
// cancel check
cancelCheck(player)
// set open menu reference to this menu
currentlyOpenedMenus[player.name] = this
// call abstract onOpen
onOpen(player)
val runnable = object : BukkitRunnable() {
override fun run() {
if (!player.isOnline) {
cancelCheck(player)
currentlyOpenedMenus.remove(player.name)
}
if (this@Menu.autoUpdate) {
player.openInventory.topInventory.contents = this@Menu.createInventory(player).contents
}
}
}
runnable.runTaskTimer(Stark.instance, 6L, 6L)
checkTasks[player.name] = runnable
}
open fun size(buttons: Map<Int, Button>): Int {
var highest = 0
for (buttonValue in buttons.keys) {
if (buttonValue > highest) {
highest = buttonValue
}
}
return (Math.ceil((highest + 1) / 9.0) * 9.0).toInt()
}
fun getSlot(x: Int, y: Int): Int {
return 9 * y + x
}
open fun asyncLoadResources(callback: (Boolean) -> Unit) {}
open fun acceptsShiftClickedItem(player: Player, itemStack: ItemStack): Boolean {
return true
}
companion object {
private val OPEN_CUSTOM_INVENTORY_METHOD_LEGACY: Method? = Reflections.getDeclaredMethod(true, Reflections.CRAFT_HUMAN_ENTITY_CLASS, "openCustomInventory", Inventory::class.java, Reflections.ENTITY_PLAYER_CLASS, Integer.TYPE)
private val OPEN_CUSTOM_INVENTORY_METHOD: Method? = Reflections.getDeclaredMethod(true, Reflections.CRAFT_HUMAN_ENTITY_CLASS, "openCustomInventory", Inventory::class.java, Reflections.ENTITY_PLAYER_CLASS, String::class.java)
@JvmStatic var currentlyOpenedMenus: HashMap<String, Menu> = hashMapOf()
@JvmStatic var checkTasks: HashMap<String, BukkitRunnable> = hashMapOf()
fun cancelCheck(player: Player) {
if (checkTasks.containsKey(player.name)) {
checkTasks.remove(player.name)!!.cancel()
}
}
val BAR = "&7&m${StringUtils.repeat("-", 32)}"
}
}

View File

@ -0,0 +1,31 @@
package net.evilblock.stark.engine.menu.buttons
import net.evilblock.stark.engine.menu.Button
import net.evilblock.stark.util.Callback
import org.bukkit.Material
import org.bukkit.event.inventory.ClickType
import org.bukkit.entity.Player
import java.util.ArrayList
class BackButton(private val callback: Callback<Player>) : Button() {
override fun getMaterial(player: Player): Material? {
return Material.BED
}
override fun getName(player: Player): String? {
return "§cGo back"
}
override fun getDescription(player: Player): List<String>? {
return ArrayList()
}
override fun clicked(player: Player, i: Int, clickType: ClickType) {
playNeutral(player)
player.closeInventory()
callback.callback(player)
}
}

View File

@ -0,0 +1,40 @@
package net.evilblock.stark.engine.menu.buttons
import net.evilblock.stark.engine.menu.Button
import net.evilblock.stark.util.Callback
import org.bukkit.Material
import org.bukkit.entity.Player
import java.util.ArrayList
import org.bukkit.Sound
import org.bukkit.event.inventory.ClickType
class BooleanButton(private val confirm: Boolean, private val callback: Callback<Boolean>) : Button() {
override fun getName(player: Player): String? {
return if (confirm) "§aConfirm" else "§cCancel"
}
override fun getDescription(player: Player): List<String>? {
return ArrayList()
}
override fun getDamageValue(player: Player): Byte {
return (if (this.confirm) 5 else 14).toByte()
}
override fun getMaterial(player: Player): Material? {
return Material.WOOL
}
override fun clicked(player: Player, i: Int, clickType: ClickType) {
if (confirm) {
playSuccess(player)
} else {
playFail(player)
}
player.closeInventory()
callback.callback(confirm)
}
}

View File

@ -0,0 +1,31 @@
package net.evilblock.stark.engine.menu.menus
import net.evilblock.stark.engine.menu.Button
import net.evilblock.stark.engine.menu.Menu
import net.evilblock.stark.util.Callback
import org.bukkit.entity.Player
import net.evilblock.stark.engine.menu.buttons.BooleanButton
import org.bukkit.Material
import java.util.HashMap
class ConfirmMenu(private val title: String, private val callback: Callback<Boolean>) : Menu() {
override fun getButtons(player: Player): Map<Int, Button> {
val buttons = HashMap<Int, Button>()
for (i in 0..8) {
when (i) {
3 -> buttons[i] = BooleanButton(true, callback)
5 -> buttons[i] = BooleanButton(false, callback)
else -> buttons[i] = Button.placeholder(Material.STAINED_GLASS_PANE, 14.toByte())
}
}
return buttons
}
override fun getTitle(player: Player): String {
return title
}
}

View File

@ -0,0 +1,31 @@
package net.evilblock.stark.engine.menu.pagination
import net.evilblock.stark.engine.menu.Button
import org.bukkit.Material
import org.bukkit.event.inventory.ClickType
import org.bukkit.entity.Player
class JumpToPageButton(private val page: Int, private val menu: PaginatedMenu) : Button() {
override fun getName(player: Player): String {
return "§ePage " + this.page
}
override fun getDescription(player: Player): List<String>? {
return null
}
override fun getMaterial(player: Player): Material {
return Material.BOOK
}
override fun getAmount(player: Player): Int {
return this.page
}
override fun clicked(player: Player, i: Int, clickType: ClickType) {
menu.modPage(player, page - menu.page)
playNeutral(player)
}
}

View File

@ -0,0 +1,51 @@
package net.evilblock.stark.engine.menu.pagination
import net.evilblock.stark.engine.menu.Button
import org.bukkit.Material
import org.bukkit.entity.Player
import java.util.ArrayList
import org.bukkit.event.inventory.ClickType
class PageButton(private val mod: Int, private val menu: PaginatedMenu) : Button() {
override fun clicked(player: Player, i: Int, clickType: ClickType) {
when {
clickType == ClickType.RIGHT -> {
ViewAllPagesMenu(menu).openMenu(player)
playNeutral(player)
}
hasNext(player) -> {
menu.modPage(player, mod)
playNeutral(player)
}
else -> playFail(player)
}
}
private fun hasNext(player: Player): Boolean {
val pg = menu.page + mod
return pg > 0 && menu.getPages(player) >= pg
}
override fun getName(player: Player): String? {
if (!this.hasNext(player)) {
return if (this.mod > 0) "§7Last page" else "§7First page"
}
val str = "(§e" + (menu.page + mod) + "/§e" + menu.getPages(player) + "§a)"
return (if (this.mod > 0) "§a\u27f6" else "§c\u27f5") + str
}
override fun getDescription(player: Player): List<String>? {
return ArrayList()
}
override fun getDamageValue(player: Player): Byte {
return (if (this.hasNext(player)) 11 else 7).toByte()
}
override fun getMaterial(player: Player): Material {
return Material.CARPET
}
}

View File

@ -0,0 +1,66 @@
package net.evilblock.stark.engine.menu.pagination
import net.evilblock.stark.engine.menu.Button
import net.evilblock.stark.engine.menu.Menu
import org.bukkit.entity.Player
import java.util.HashMap
abstract class PaginatedMenu : Menu() {
internal var page: Int = 1
override fun getTitle(player: Player): String {
return getPrePaginatedTitle(player) + " - " + page + "/" + getPages(player)
}
fun modPage(player: Player, mod: Int) {
page += mod
buttons.clear()
openMenu(player)
}
internal fun getPages(player: Player): Int {
val buttonAmount = getAllPagesButtons(player).size
return if (buttonAmount == 0) {
1
} else Math.ceil(buttonAmount / getMaxItemsPerPage(player).toDouble()).toInt()
}
override fun getButtons(player: Player): MutableMap<Int, Button> {
val minIndex = ((page - 1) * getMaxItemsPerPage(player).toDouble()).toInt()
val maxIndex = (page * getMaxItemsPerPage(player).toDouble()).toInt()
val buttons = HashMap<Int, Button>()
buttons[0] = PageButton(-1, this)
buttons[8] = PageButton(1, this)
for (entry in getAllPagesButtons(player).entries) {
var ind = entry.key
if (ind in minIndex until maxIndex) {
ind -= (getMaxItemsPerPage(player) * (page - 1).toDouble()).toInt() - 9
buttons[ind] = entry.value
}
}
val global = getGlobalButtons(player)
if (global != null) {
for ((key, value) in global) {
buttons[key] = value
}
}
return buttons
}
open fun getMaxItemsPerPage(player: Player): Int {
return 18
}
open fun getGlobalButtons(player: Player): Map<Int, Button>? {
return null
}
abstract fun getPrePaginatedTitle(player: Player): String
abstract fun getAllPagesButtons(player: Player): Map<Int, Button>
}

View File

@ -0,0 +1,40 @@
package net.evilblock.stark.engine.menu.pagination
import net.evilblock.stark.engine.menu.Button
import net.evilblock.stark.engine.menu.Menu
import net.evilblock.stark.engine.menu.buttons.BackButton
import net.evilblock.stark.util.Callback
import java.util.HashMap
import org.bukkit.entity.Player
class ViewAllPagesMenu(private val menu: PaginatedMenu) : Menu() {
init {
autoUpdate = true
}
override fun getTitle(player: Player): String {
return "Jump to page"
}
override fun getButtons(player: Player): Map<Int, Button> {
val buttons = HashMap<Int, Button>()
buttons[0] = BackButton(object : Callback<Player> {
override fun callback(value: Player) {
menu.openMenu(player)
}
})
var index = 10
for (i in 1..menu.getPages(player)) {
buttons[index++] = JumpToPageButton(i, menu)
if ((index - 8) % 9 == 0) {
index += 2
}
}
return buttons
}
}

View File

@ -0,0 +1,37 @@
package net.evilblock.stark.engine.protocol
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.protocol.event.PlayerCloseInventoryEvent
import net.evilblock.stark.engine.protocol.event.PlayerOpenInventoryEvent
import java.util.UUID
import java.util.HashSet
import org.bukkit.Bukkit
import com.comphenix.protocol.PacketType
import com.comphenix.protocol.wrappers.EnumWrappers
import com.comphenix.protocol.events.PacketEvent
import com.comphenix.protocol.events.PacketAdapter
class InventoryAdapter : PacketAdapter(Stark.instance, PacketType.Play.Client.CLIENT_COMMAND, PacketType.Play.Client.CLOSE_WINDOW) {
override fun onPacketReceiving(event: PacketEvent?) {
val player = event!!.player
val packet = event.packet
if (packet.type === PacketType.Play.Client.CLIENT_COMMAND && packet.clientCommands.size() != 0 && packet.clientCommands.read(0) == EnumWrappers.ClientCommand.OPEN_INVENTORY_ACHIEVEMENT) {
if (!currentlyOpen.contains(player.uniqueId)) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Stark.instance) { Bukkit.getPluginManager().callEvent(PlayerOpenInventoryEvent(player)) }
}
currentlyOpen.add(player.uniqueId)
} else if (packet.type === PacketType.Play.Client.CLOSE_WINDOW) {
if (currentlyOpen.contains(player.uniqueId)) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Stark.instance) { Bukkit.getPluginManager().callEvent(PlayerCloseInventoryEvent(player)) }
}
currentlyOpen.remove(player.uniqueId)
}
}
companion object {
var currentlyOpen: HashSet<UUID> = HashSet()
}
}

View File

@ -0,0 +1,27 @@
package net.evilblock.stark.engine.protocol
import net.evilblock.stark.engine.protocol.event.ServerLaggedOutEvent
import net.evilblock.stark.util.PlayerUtils
import org.bukkit.Bukkit
import org.bukkit.scheduler.BukkitRunnable
class LagCheck : BukkitRunnable() {
override fun run() {
val players = Bukkit.getOnlinePlayers()
if (players.size >= 100) {
var playersLagging = 0
for (player in players) {
if (PlayerUtils.isLagging(player)) {
++playersLagging
}
}
val percentage = playersLagging * 100 / players.size
if (Math.abs(percentage) >= 30.0) {
Bukkit.getPluginManager().callEvent(ServerLaggedOutEvent(PingAdapter.averagePing()))
}
}
}
}

View File

@ -0,0 +1,82 @@
package net.evilblock.stark.engine.protocol
import net.evilblock.stark.Stark
import net.evilblock.stark.util.Reflections
import com.comphenix.protocol.PacketType
import com.comphenix.protocol.events.PacketAdapter
import com.comphenix.protocol.events.PacketEvent
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerQuitEvent
import java.lang.Exception
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class PingAdapter : PacketAdapter(Stark.instance, PacketType.Play.Server.KEEP_ALIVE, PacketType.Play.Client.KEEP_ALIVE), Listener {
override fun onPacketSending(event: PacketEvent) {
val id = try {
event.packet.integers.read(0) as Int
} catch (e: Exception) {
(event.packet.longs.read(0) as Long).toInt()
}
callbacks[event.player.uniqueId] = object : PingCallback(id) {
override fun call() {
val ping = (System.currentTimeMillis() - this.sendTime).toInt()
Companion.ping[event.player.uniqueId] = ping
lastReply[event.player.uniqueId] = Reflections.getFieldValue(Reflections.getMinecraftServer()!!, "currentTick") as Int
}
}
}
override fun onPacketReceiving(event: PacketEvent) {
val iterator = callbacks.entries.iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
val id = try {
event.packet.integers.read(0) as Int
} catch (e: Exception) {
(event.packet.longs.read(0) as Long).toInt()
}
if (entry.value.id == id) {
entry.value.call()
iterator.remove()
break
}
}
}
@EventHandler
fun onQuit(event: PlayerQuitEvent) {
ping.remove(event.player.uniqueId)
lastReply.remove(event.player.uniqueId)
callbacks.remove(event.player.uniqueId)
}
private abstract class PingCallback
constructor(val id: Int) {
val sendTime: Long = System.currentTimeMillis()
abstract fun call()
}
companion object {
private val callbacks: ConcurrentHashMap<UUID, PingCallback> = ConcurrentHashMap()
val ping: ConcurrentHashMap<UUID, Int> = ConcurrentHashMap()
val lastReply: ConcurrentHashMap<UUID, Int> = ConcurrentHashMap()
fun averagePing(): Int {
if (ping.isEmpty()) {
return 0
}
var x = 0
for (p in ping.values) {
x += p
}
return x / ping.size
}
}
}

View File

@ -0,0 +1,19 @@
package net.evilblock.stark.engine.protocol.event
import org.bukkit.event.HandlerList
import org.bukkit.entity.Player
import org.bukkit.event.player.PlayerEvent
class PlayerCloseInventoryEvent(player: Player) : PlayerEvent(player) {
private val instanceHandlers: HandlerList = ServerLaggedOutEvent.handlerList
override fun getHandlers(): HandlerList {
return instanceHandlers
}
companion object {
var handlerList: HandlerList = HandlerList()
}
}

View File

@ -0,0 +1,19 @@
package net.evilblock.stark.engine.protocol.event
import org.bukkit.event.HandlerList
import org.bukkit.entity.Player
import org.bukkit.event.player.PlayerEvent
class PlayerOpenInventoryEvent(player: Player) : PlayerEvent(player) {
private val instanceHandlers: HandlerList = ServerLaggedOutEvent.handlerList
override fun getHandlers(): HandlerList {
return instanceHandlers
}
companion object {
var handlerList: HandlerList = HandlerList()
}
}

View File

@ -0,0 +1,18 @@
package net.evilblock.stark.engine.protocol.event
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
class ServerLaggedOutEvent(private val averagePing: Int) : Event(true) {
private val instanceHandlers: HandlerList = handlerList
override fun getHandlers(): HandlerList {
return instanceHandlers
}
companion object {
val handlerList: HandlerList = HandlerList()
}
}

View File

@ -0,0 +1,18 @@
package net.evilblock.stark.hook
import net.evilblock.stark.Stark
import net.milkbowl.vault.permission.Permission
import org.bukkit.Bukkit
import org.bukkit.plugin.ServicePriority
object VaultHook {
fun hook() {
if (Bukkit.getServer().pluginManager.getPlugin("Vault") == null) {
return
}
Bukkit.getServer().servicesManager.register(Permission::class.java, VaultPermissionImpl(), Stark.instance, ServicePriority.Highest)
}
}

View File

@ -0,0 +1,220 @@
package net.evilblock.stark.hook
import net.evilblock.stark.Stark
import net.evilblock.stark.core.profile.grant.ProfileGrant
import net.milkbowl.vault.permission.Permission
import org.bukkit.OfflinePlayer
import org.bukkit.World
import org.bukkit.entity.Player
class VaultPermissionImpl : Permission() {
override fun hasSuperPermsCompat(): Boolean {
return true
}
override fun getPlayerGroups(player: Player): Array<String> {
val groups = arrayListOf<String>()
val profile = Stark.instance.core.getProfileHandler().getByUUID(player.uniqueId)
profile?.rankGrants?.filter { grant -> grant.isActive() }?.forEach {
groups.add(it.rank.id)
}
return groups.toTypedArray()
}
// TODO: ASYNC OFFLINE SUPPORT
override fun getPlayerGroups(world: String, player: OfflinePlayer): Array<String> {
return emptyArray()
}
override fun getPrimaryGroup(player: Player): String {
val profile = Stark.instance.core.getProfileHandler().getByUUID(player.uniqueId)
return profile?.getRank()?.id ?: Stark.instance.core.rankHandler.getDefaultRank().id
}
// TODO: ASYNC OFFLINE SUPPORT
override fun getPrimaryGroup(world: String, player: OfflinePlayer): String {
return Stark.instance.core.rankHandler.getDefaultRank().id
}
override fun groupAdd(world: World, group: String, permission: String): Boolean {
val rank = Stark.instance.core.rankHandler.getById(group)
return if (rank != null) {
val success = rank.permissions.add(permission)
if (success) {
Stark.instance.server.scheduler.runTaskAsynchronously(Stark.instance) {
Stark.instance.core.rankHandler.saveRank(rank)
}
}
return success
} else {
false
}
}
override fun groupHas(world: World, group: String, permission: String): Boolean {
val rank = Stark.instance.core.rankHandler.getById(group)
return rank?.permissions?.contains(permission) ?: false
}
override fun groupRemove(world: World, group: String, permission: String): Boolean {
val rank = Stark.instance.core.rankHandler.getById(group)
return if (rank != null) {
val success = rank.permissions.remove(permission)
if (success) {
Stark.instance.server.scheduler.runTaskAsynchronously(Stark.instance) {
Stark.instance.core.rankHandler.saveRank(rank)
}
}
return success
} else {
false
}
}
override fun playerAddGroup(player: Player, group: String): Boolean {
val rank = Stark.instance.core.rankHandler.getById(group) ?: return false
val profile = Stark.instance.core.getProfileHandler().getByUUID(player.uniqueId)
if (profile != null) {
profile.rankGrants.filter { it.isActive() }.forEach { grant ->
if (grant.rank.id.equals(group, ignoreCase = true)) {
return@forEach
}
}
// TODO: MAKE VAULT GRANT'S DEFAULT DURATION CONFIGURABLE
val grant = ProfileGrant()
grant.rank = rank
grant.reason = "VaultAPI Hook"
grant.issuedAt = System.currentTimeMillis()
profile.rankGrants.add(grant)
Stark.instance.server.scheduler.runTaskAsynchronously(Stark.instance) {
Stark.instance.core.getProfileHandler().saveProfile(profile)
}
return true
}
return false
}
// TODO: ASYNC OFFLINE SUPPORT
override fun playerAddGroup(world: String, player: OfflinePlayer, group: String): Boolean {
return false
}
override fun playerInGroup(player: Player, group: String): Boolean {
val profile = Stark.instance.core.getProfileHandler().getByUUID(player.uniqueId)
profile?.rankGrants?.filter { it.isActive() }?.forEach { grant ->
if (grant.rank.id.equals(group, ignoreCase = true)) {
return true
}
}
return false
}
// TODO: ASYNC OFFLINE SUPPORT
override fun playerInGroup(world: String, player: OfflinePlayer, group: String): Boolean {
return super.playerInGroup(world, player, group)
}
override fun playerRemoveGroup(player: Player, group: String): Boolean {
val profile = Stark.instance.core.getProfileHandler().getByUUID(player.uniqueId)
if (profile != null) {
profile.rankGrants.filter { it.isActive() }.forEach { grant ->
if (grant.rank.id.equals(group, ignoreCase = true)) {
grant.removedAt = System.currentTimeMillis()
grant.removalReason = "VaultAPI Hook"
return true
}
}
Stark.instance.server.scheduler.runTaskAsynchronously(Stark.instance) {
Stark.instance.core.getProfileHandler().saveProfile(profile)
}
}
return false
}
// TODO: ASYNC OFFLINE SUPPORT
override fun playerRemoveGroup(world: String, player: OfflinePlayer, group: String): Boolean {
return super.playerRemoveGroup(world, player, group)
}
override fun playerHas(world: String, player: String, permission: String): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun playerAdd(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun playerRemove(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun getPlayerGroups(p0: String?, p1: String?): Array<String> {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun getPrimaryGroup(p0: String?, p1: String?): String {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun playerAddGroup(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun playerInGroup(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun playerRemoveGroup(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun getGroups(): Array<String> {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun getName(): String {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun groupAdd(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun groupHas(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun groupRemove(p0: String?, p1: String?, p2: String?): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun hasGroupSupport(): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
override fun isEnabled(): Boolean {
throw UnsupportedOperationException("Stark does not support deprecated VaultAPI methods")
}
}

View File

@ -0,0 +1,231 @@
package net.evilblock.stark.messaging
import net.evilblock.stark.Stark
import net.evilblock.stark.messaging.event.PlayerMessageEvent
import net.evilblock.stark.util.SoundCompat
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.entity.Player
import java.util.*
class MessagingManager {
private val key = "stark:messageSettings"
val globalSpy: MutableSet<UUID> = hashSetOf()
/**
* Gets the last messaged player for a player.
*
* @param player the player
*
* @return the last player's uuid that [player] has messaged
*/
fun getLastMessaged(player: UUID): UUID? {
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hget("$key:$player", "lastMessaged")
}?.run { UUID.fromString(this) }
}
/**
* Sets the last messaged player for a player.
*
* @param player the player
*/
fun setLastMessaged(player: UUID, lastMessaged: UUID) {
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hset("$key:$player", hashMapOf("lastMessaged" to "$lastMessaged"))
}
}
/**
* Gets if a player's messages are disabled.
*
* @param player the player
*/
fun isMessagesDisabled(player: UUID): Boolean {
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hget("$key:$player", "messagesDisabled")
}?.toBoolean() ?: false
}
/**
* Toggles if a player's messages are disabled.
*
* @param player the player
*
* @return if the [player]'s messages are disabled after toggle
*/
fun toggleMessages(player: UUID): Boolean {
val value = !isMessagesDisabled(player)
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hmset("$key:$player", hashMapOf("messagesDisabled" to value.toString()))
}
return value
}
/**
* Gets if a player's message sounds are disabled.
*
* @param player the player
*/
fun isSoundsDisabled(player: UUID): Boolean {
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hget("$key:$player", "soundsDisabled")
}?.toBoolean() ?: false
}
/**
* Toggles if a player's message sounds are disabled.
*
* @param player the player
*
* @return if the [player]'s message sounds are disabled after toggle
*/
fun toggleSounds(player: UUID): Boolean {
val value = !isSoundsDisabled(player)
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hmset("$key:$player", hashMapOf("soundsDisabled" to value.toString()))
}
return value
}
/**
* Gets whether or not the [player] is ignored by the [target].
*
* @param player the player
* @param target the target
*
* @return if the [player] is ignored by the [target]
*/
fun isIgnored(player: UUID, target: UUID): Boolean {
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hget("$key:ignoreList:$target", "$player")
}?.toBoolean() ?: false
}
/**
* Adds a target to a player's ignore list.
*/
fun addToIgnoreList(player: UUID, target: UUID) {
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hmset("$key:ignoreList:$player", hashMapOf(target.toString() to "true"))
}
}
/**
* Removes a target from a player's ignore list.
*
* @param player the player's UUID
* @param target the target's UUID
*/
fun removeFromIgnoreList(player: UUID, target: UUID) {
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hdel("$key:ignoreList:$player", target.toString())
}
}
/**
* Clears a player's ignore list.
*
* @param player the player's UUID
*/
fun clearIgnoreList(player: UUID) {
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.del("$key:ignoreList:$player")
}
}
/**
* Retrieves a player's ignore list.
*
* @param player the player's UUID
*
* @return the player's ignore list as {@link List<UUID>}
*/
fun getIgnoreList(player: UUID): List<UUID> {
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.hgetAll("$key:ignoreList:$player").map { entry -> UUID.fromString(entry.key) }
}
}
/**
* Determines whether a sender player can message a target.
*
* @param sender the player trying to send the message
* @param target the player the [sender] is trying to send a message to
*
* @return true if the sender can message the target.
*/
fun canMessage(sender: Player, target: Player): Boolean {
if (sender.hasPermission("stark.staff")) {
return true
}
if (isIgnored(sender.uniqueId, target.uniqueId)) {
sender.sendMessage(ChatColor.RED.toString() + "That player is ignoring you.")
return false
}
if (isIgnored(target.uniqueId, sender.uniqueId)) {
sender.sendMessage(ChatColor.RED.toString() + "You are ignoring that player.")
return false
}
if (isMessagesDisabled(sender.uniqueId)) {
sender.sendMessage(ChatColor.RED.toString() + "You have messages turned off.")
}
if (isMessagesDisabled(target.uniqueId)) {
sender.sendMessage(target.displayName + ChatColor.RED + " has messages turned off.")
return false
}
return true
}
/**
* Sends a [message] from the [sender] to the [target].
*
* @param sender the player sending the [message]
* @param target the player the [sender] is sending the [message] to
* @param message the message the [sender] is trying to send to the [target]
*/
fun sendMessage(sender: Player, target: Player, message: String) {
val event = PlayerMessageEvent(sender, target, message)
Stark.instance.server.pluginManager.callEvent(event)
if (event.isCancelled) {
return
}
setLastMessaged(sender.uniqueId, target.uniqueId)
setLastMessaged(target.uniqueId, sender.uniqueId)
val senderProfile = Stark.instance.core.getProfileHandler().getByUUID(sender.uniqueId)!!
val targetProfile = Stark.instance.core.getProfileHandler().getByUUID(target.uniqueId)!!
target.sendMessage(ChatColor.RED.toString() + "(From " + ChatColor.WHITE + senderProfile.getPlayerListName() + ChatColor.RED + ") " + message)
sender.sendMessage(ChatColor.RED.toString() + "(To " + ChatColor.WHITE + targetProfile.getPlayerListName() + ChatColor.RED + ") " + message)
if (!isSoundsDisabled(target.uniqueId)) {
SoundCompat.MESSAGE_RECEIVED.playSound(target)
}
for (player in Bukkit.getOnlinePlayers()) {
if (player !== sender) {
if (player === target) {
continue
}
if (globalSpy.contains(player.uniqueId)) {
player.sendMessage(ChatColor.GRAY.toString() + "(" + ChatColor.WHITE + sender.displayName + ChatColor.GRAY + " to " + ChatColor.WHITE + target.displayName + ChatColor.GRAY + ") " + message)
}
}
}
}
}

View File

@ -0,0 +1,28 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.core.util.mojanguser.MojangUser
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object IgnoreCommand {
@Command(["ignore"], description = "Start ignoring a player. You won't receive private messages from them or see their public chat messages", async = true)
@JvmStatic
fun execute(player: Player, @Param("player") target: MojangUser) {
if (player.uniqueId == target.uuid) {
player.sendMessage("${ChatColor.RED}You can't ignore yourself.")
return
}
if (Stark.instance.messagingManager.isIgnored(player.uniqueId, target.uuid)) {
player.sendMessage("${ChatColor.RED}You are already ignoring ${ChatColor.WHITE}${target.username}${ChatColor.RED}.")
return
}
Stark.instance.messagingManager.addToIgnoreList(player.uniqueId, target.uuid)
player.sendMessage("${ChatColor.YELLOW}Now ignoring ${ChatColor.WHITE}${target.username}${ChatColor.YELLOW}.")
}
}

View File

@ -0,0 +1,15 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object IgnoreListClearCommand {
@Command(["ignore clear"], description = "Clear your ignore list", async = true)
@JvmStatic
fun execute(player: Player) {
Stark.instance.messagingManager.clearIgnoreList(player.uniqueId)
player.sendMessage("${ChatColor.YELLOW}You've cleared your ignore list.")
}
}

View File

@ -0,0 +1,27 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object IgnoreListCommand {
@Command(["ignore list"], description = "See a list of people you're currently ignoring", async = true)
@JvmStatic
fun execute(player: Player) {
val ignoreList = Stark.instance.messagingManager.getIgnoreList(player.uniqueId)
if (ignoreList.isEmpty()) {
player.sendMessage("${ChatColor.RED}You aren't ignoring anyone.")
return
}
val names = arrayListOf<String>()
for (uuid in ignoreList) {
names.add(Stark.instance.core.uuidCache.name(uuid))
}
player.sendMessage("${ChatColor.YELLOW}You are currently ignoring ${ChatColor.RED}${names.size} ${ChatColor.YELLOW}player${if (names.size == 1) "" else "s"}:")
player.sendMessage(ChatColor.translateAlternateColorCodes('&', names.joinToString("&e, ", "&c")))
}
}

View File

@ -0,0 +1,23 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.core.util.mojanguser.MojangUser
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object IgnoreRemoveCommand {
@Command(["ignore remove"], description = "Stop ignoring a player", async = true)
@JvmStatic
fun execute(player: Player, @Param("player") target: MojangUser) {
if (!Stark.instance.messagingManager.isIgnored(player.uniqueId, target.uuid)) {
player.sendMessage("${ChatColor.RED}You aren't ignoring ${ChatColor.WHITE}${target.username}${ChatColor.RED}.")
return
}
Stark.instance.messagingManager.removeFromIgnoreList(player.uniqueId, target.uuid)
player.sendMessage("${ChatColor.YELLOW}You are no longer ignoring ${ChatColor.WHITE}${target.username}${ChatColor.YELLOW}.")
}
}

View File

@ -0,0 +1,24 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object MessageCommand {
@Command(["message", "msg", "m", "whisper", "w", "tell", "t"], description = "Send a player a private message", async = true)
@JvmStatic
fun message(sender: Player, @Param(name = "player") target: Player, @Param(name = "message", wildcard = true) message: String) {
if (sender.uniqueId == target.uniqueId) {
sender.sendMessage("${ChatColor.RED}You can't message yourself.")
return
}
if (!Stark.instance.messagingManager.canMessage(sender, target)) {
return
}
Stark.instance.messagingManager.sendMessage(sender, target, message)
}
}

View File

@ -0,0 +1,44 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import net.evilblock.stark.engine.command.data.parameter.Param
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object ReplyCommand {
@Command(["reply", "r"], description = "Reply to the player you're in a conversation with", async = true)
@JvmStatic
fun reply(sender: Player, @Param(name = "message", defaultValue = " ", wildcard = true) message: String) {
val lastMessaged = Stark.instance.messagingManager.getLastMessaged(sender.uniqueId)
if (message == " ") {
if (lastMessaged == null) {
sender.sendMessage("${ChatColor.RED}You aren't in a conversation.")
} else {
sender.sendMessage("${ChatColor.GOLD}You are in a conversation with ${ChatColor.WHITE}${Stark.instance.core.uuidCache.name(lastMessaged)}${ChatColor.GOLD}.")
}
return
}
if (lastMessaged == null) {
sender.sendMessage("${ChatColor.RED}You have no one to reply to.")
return
}
val target = Bukkit.getPlayer(lastMessaged)
if (target == null) {
sender.sendMessage("${ChatColor.RED}That player has logged out.")
return
}
if (!Stark.instance.messagingManager.canMessage(sender, target)) {
return
}
Stark.instance.messagingManager.sendMessage(sender, target, message)
}
}

View File

@ -0,0 +1,22 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object SpyCommand {
@Command(["spy"], permission = "stark.message.spy", description = "Toggle global private message spying")
@JvmStatic
fun spy(sender: Player) {
val contains = Stark.instance.messagingManager.globalSpy.contains(sender.uniqueId)
if (contains) {
Stark.instance.messagingManager.globalSpy.remove(sender.uniqueId)
} else {
Stark.instance.messagingManager.globalSpy.add(sender.uniqueId)
}
sender.sendMessage("${ChatColor.GOLD}Global chat spy has been set to ${ChatColor.WHITE}$contains${ChatColor.GOLD}.")
}
}

View File

@ -0,0 +1,20 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object ToggleMessagesCommand {
@Command(["togglepm", "tpm"], description = "Toggle private messaging", async = true)
@JvmStatic
fun execute(player: Player) {
val toggle = Stark.instance.messagingManager.toggleMessages(player.uniqueId)
if (toggle) {
player.sendMessage("${ChatColor.RED}Private messages have been disabled.")
} else {
player.sendMessage("${ChatColor.GREEN}Private messages have been enabled.")
}
}
}

View File

@ -0,0 +1,20 @@
package net.evilblock.stark.messaging.command
import net.evilblock.stark.Stark
import net.evilblock.stark.engine.command.Command
import org.bukkit.ChatColor
import org.bukkit.entity.Player
object ToggleSoundsCommand {
@Command(["sounds", "togglesounds"], description = "Toggle messaging sounds", async = true)
@JvmStatic
fun execute(player: Player) {
val toggle = Stark.instance.messagingManager.toggleSounds(player.uniqueId)
if (toggle) {
player.sendMessage(ChatColor.YELLOW.toString() + "Messaging sounds have been disabled.")
} else {
player.sendMessage(ChatColor.YELLOW.toString() + "Messaging sounds have been enabled.")
}
}
}

View File

@ -0,0 +1,28 @@
package net.evilblock.stark.messaging.event
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
class PlayerMessageEvent(val sender: Player, val target: Player, val message: String) : Event(), Cancellable {
private var cancelled: Boolean = false
companion object {
@JvmStatic val handlerList = HandlerList()
}
override fun getHandlers(): HandlerList {
return handlerList
}
override fun isCancelled(): Boolean {
return cancelled
}
override fun setCancelled(cancelled: Boolean) {
this.cancelled = cancelled
}
}

View File

@ -0,0 +1,46 @@
package net.evilblock.stark.modsuite
import net.evilblock.stark.Stark
import java.util.concurrent.TimeUnit
import org.bukkit.entity.Player
import redis.clients.jedis.Jedis
import java.util.*
object ModRequestHandler {
fun hasRequestCooldown(player: Player): Boolean {
val key = "stark:request:" + player.uniqueId + ":cooldown"
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.exists(key)
}
}
fun addRequestCooldown(player: Player, time: Long, unit: TimeUnit) {
val key = "stark:request:" + player.uniqueId + ":cooldown"
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.setex(key, unit.toSeconds(time).toInt(), "")
}
}
fun getReportCount(target: UUID): Int {
val key = "stark:request:$target:reports"
val time = System.currentTimeMillis()
return Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.zcount(key, (time - TimeUnit.MINUTES.toMillis(15L)).toDouble(), time.toDouble())!!.toInt()
}
}
fun incrementReportCount(target: Player) {
val key = "stark:request:" + target.uniqueId + ":reports"
val time = System.currentTimeMillis()
Stark.instance.core.redis.runBackboneRedisCommand { redis ->
redis.zadd(key, time.toDouble(), time.toString())
redis.expire(key, TimeUnit.MINUTES.toMillis(15L).toInt())
}
}
}

View File

@ -0,0 +1,66 @@
package net.evilblock.stark.modsuite
import nig.cock.nigger.message.handler.IncomingMessageHandler
import nig.cock.nigger.message.listener.MessageListener
import com.google.gson.JsonObject
import net.evilblock.stark.modsuite.options.ModOptionsHandler
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import java.util.*
class ModSuiteMessageListeners : MessageListener {
@IncomingMessageHandler("STAFF_CHAT")
fun onIncomingStaffChatMessage(data: JsonObject) {
val serverName = data.get("serverName").asString
val senderName = data.get("senderName").asString
val message = data.get("message").asString
Bukkit.getOnlinePlayers().forEach {
if (it.hasPermission("stark.staff")) {
val options = ModOptionsHandler.get(it)
if (options.receivingStaffChat) {
it.sendMessage("${ChatColor.RED}[SC] [$serverName]${ChatColor.DARK_PURPLE}$senderName${ChatColor.LIGHT_PURPLE}: $message")
}
}
}
}
@IncomingMessageHandler("REQUEST")
fun onIncomingRequestMessage(data: JsonObject) {
val serverName = data.get("serverName").asString
val senderName = data.get("senderName").asString
val reason = data.get("reason").asString
Bukkit.getOnlinePlayers().forEach {
if (it.hasPermission("stark.staff")) {
val options = ModOptionsHandler.get(it)
if (options.receivingRequests) {
it.sendMessage("${ChatColor.BLUE}${ChatColor.BOLD}[Request] ${ChatColor.GRAY}[$serverName] ${ChatColor.AQUA}$senderName ${ChatColor.GRAY}requested assistance")
it.sendMessage("${ChatColor.BLUE}${ChatColor.BOLD} Reason: ${ChatColor.GRAY}$reason")
}
}
}
}
@IncomingMessageHandler("REPORT")
fun onIncomingReportMessage(data: JsonObject) {
val serverName = data.get("serverName").asString
val senderName = data.get("senderName").asString
val reportedUuid = data.get("reportedUuid").asString
val reportedName = data.get("reportedName").asString
val reason = data.get("reason").asString
val reportCount = ModRequestHandler.getReportCount(UUID.fromString(reportedUuid))
Bukkit.getOnlinePlayers().forEach {
if (it.hasPermission("stark.staff")) {
val options = ModOptionsHandler.get(it)
if (options.receivingRequests) {
it.sendMessage("${ChatColor.BLUE}${ChatColor.BOLD}[Report] ${ChatColor.GRAY}[$serverName] ${ChatColor.AQUA}$reportedName ${ChatColor.GRAY}($reportCount) reported by ${ChatColor.AQUA}$senderName")
it.sendMessage("${ChatColor.BLUE}${ChatColor.BOLD} Reason: ${ChatColor.GRAY}$reason")
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More