diff --git a/Venom/.gitignore b/Venom/.gitignore new file mode 100644 index 0000000..5b8417d --- /dev/null +++ b/Venom/.gitignore @@ -0,0 +1,9 @@ +/.idea/ +/build/ +/gradle/ +/.gradle/ +/api/build/ +/proxy/build/ +/bukkit/build/ +/gradlew.bat +/gradlew diff --git a/Venom/api/build.gradle b/Venom/api/build.gradle new file mode 100644 index 0000000..09b94d0 --- /dev/null +++ b/Venom/api/build.gradle @@ -0,0 +1,62 @@ + + +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id "org.jetbrains.kotlin.jvm" version "1.5.10" + id "com.github.johnrengelman.shadow" version "5.2.0" +} + +targetCompatibility = '1.8' +sourceCompatibility = '1.8' + +shadowJar { + classifier = null + minimize() + archiveName = "venom-" + this.name + "-" + this.version + ".jar" +} + +repositories { + mavenLocal() + mavenCentral() + + flatDir { + dirs 'libs' + } +} + +dependencies { + implementation name: "Symbiote" + + compile "com.squareup.okhttp:okhttp:2.7.5" + compile "com.google.code.gson:gson:2.8.5" + compile "redis.clients:jedis:3.5.1" + + compileOnly 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.10' + compile "org.mongodb:mongo-java-driver:3.10.2" +} + +apply plugin: "kotlin" +apply plugin: 'maven-publish' + +compileKotlin { + kotlinOptions.jvmTarget = '1.8' +} + +sourceSets { + main.java.srcDirs += 'src/main/kotlin/' +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +publishing { + publications { + shadow(MavenPublication) { publication -> + project.shadow.component(publication) + } + } +} diff --git a/Venom/api/libs/Symbiote.jar b/Venom/api/libs/Symbiote.jar new file mode 100644 index 0000000..9b0efc0 Binary files /dev/null and b/Venom/api/libs/Symbiote.jar differ diff --git a/Venom/api/plugin.yml b/Venom/api/plugin.yml new file mode 100644 index 0000000..0cef69c --- /dev/null +++ b/Venom/api/plugin.yml @@ -0,0 +1,6 @@ +name: VenomAPI +main: cc.fyre.venom.Venom +author: Fyre Services +version: 1.0-SNAPSHOT +depend: [Kotlin,Proton] +softdepend: [LuckPerms,PlaceholderAPI] \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/VenomAPI.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/VenomAPI.kt new file mode 100644 index 0000000..5a11a5e --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/VenomAPI.kt @@ -0,0 +1,64 @@ +package cc.fyre.venom + +import cc.fyre.venom.session.SessionHandler +import cc.fyre.venom.database.DatabaseHandler +import cc.fyre.venom.database.mongo.MongoOptions +import cc.fyre.venom.database.mongo.RedisOptions + +import cc.fyre.venom.grant.GrantHandler +import cc.fyre.venom.network.NetworkHandler + +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.punishment.PunishmentHandler +import cc.fyre.venom.rank.RankHandler + +import cc.fyre.venom.tag.TagHandler +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.LongSerializationPolicy + +/** + * @project venom + * + * @date 16/03/2020 + * @author xanderume@gmail.com + */ +class VenomAPI(mongo: MongoOptions,redis: RedisOptions) { + + val gson: Gson + val mainThread: Thread + val databaseHandler: DatabaseHandler + + val tagHandler: TagHandler + val rankHandler: RankHandler + val grantHandler: GrantHandler + val networkHandler: NetworkHandler + val sessionHandler: SessionHandler + val profileHandler: ProfileHandler + val punishmentHandler: PunishmentHandler + + init { + instance = this + + this.gson = GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING).create() + this.mainThread = Thread.currentThread() + + this.databaseHandler = DatabaseHandler(mongo,redis) + this.tagHandler = TagHandler(this) + this.rankHandler = RankHandler(this) + this.grantHandler = GrantHandler(this) + this.networkHandler = NetworkHandler(this) + this.sessionHandler = SessionHandler(this) + this.profileHandler = ProfileHandler(this) + this.punishmentHandler = PunishmentHandler(this) + } + + fun isPrimaryThread():Boolean { + return Thread.currentThread() == this.mainThread + } + + companion object { + lateinit var instance: VenomAPI + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/database/DatabaseHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/database/DatabaseHandler.kt new file mode 100644 index 0000000..4b8ee46 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/database/DatabaseHandler.kt @@ -0,0 +1,82 @@ +package cc.fyre.venom.database + +import cc.fyre.symbiote.SymbioteAPI +import cc.fyre.symbiote.type.RedisSymbioteAPI +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.jedis.CustomPoolConfig +import cc.fyre.venom.database.jedis.RedisCommand +import cc.fyre.venom.database.mongo.MongoOptions +import cc.fyre.venom.database.mongo.RedisOptions +import com.mongodb.MongoClient +import com.mongodb.MongoCredential +import com.mongodb.ServerAddress +import com.mongodb.client.MongoDatabase +import com.mongodb.client.model.UpdateOptions +import com.squareup.okhttp.OkHttpClient +import redis.clients.jedis.Jedis +import redis.clients.jedis.JedisPool + +/** + * @project venom + * + * @date 16/03/2020 + * @author xanderume@gmail.com + */ +class DatabaseHandler(val mongo: MongoOptions,val redis: RedisOptions) { + + val mongoDB: MongoDatabase + + val mongoPool: MongoClient = if (mongo.isAuthenticationRequired()) { + MongoClient(ServerAddress(mongo.host,mongo.port),arrayListOf(MongoCredential.createCredential(mongo.username!!,mongo.authDatabase!!,mongo.password!!.toCharArray()))) + } else { + MongoClient(ServerAddress(mongo.host,mongo.port)) + } + + val redisPool: JedisPool = if (mongo.isAuthenticationRequired()) { + JedisPool(CustomPoolConfig(),redis.host,redis.port,30000) + } else { + JedisPool(CustomPoolConfig(),redis.host,redis.port,30000,redis.password) + } + + val symbiote: SymbioteAPI + val okHttpClient: OkHttpClient + + init { + + if (redis.isAuthenticationRequired()) { + this.redisPool.resource.auth(redis.password!!) + } + + this.mongoDB = mongoPool.getDatabase(mongo.database) + + this.symbiote = RedisSymbioteAPI(VenomAPI.instance.gson,this.redisPool,mongo.database,redis.password) + this.okHttpClient = OkHttpClient() + } + + fun dispose() { + this.mongoPool.close() + this.redisPool.close() + } + + companion object { + val UPDATE_OPTIONS: UpdateOptions = UpdateOptions().upsert(true) + } + + + fun runRedisCommand(command: RedisCommand): T? { + + val jedis = this.redisPool.resource + + if (this.redis.isAuthenticationRequired()) { + jedis.auth(this.redis.password) + } + + return try { + command.execute(jedis) + } catch (ex: Exception) { + ex.printStackTrace() + return null + } + + } +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/database/jedis/CustomPoolConfig.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/database/jedis/CustomPoolConfig.kt new file mode 100644 index 0000000..840300c --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/database/jedis/CustomPoolConfig.kt @@ -0,0 +1,20 @@ +package cc.fyre.venom.database.jedis + +import org.apache.commons.pool2.impl.GenericObjectPoolConfig + +/** + * @project venom + * + * @date 27/03/2020 + * @author xanderume@gmail.com + */ +class CustomPoolConfig : GenericObjectPoolConfig() { + + init { + testWhileIdle = true + numTestsPerEvictionRun = -1 + minEvictableIdleTimeMillis = 60000L + timeBetweenEvictionRunsMillis = 30000L + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/database/jedis/RedisCommand.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/database/jedis/RedisCommand.kt new file mode 100644 index 0000000..083dc12 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/database/jedis/RedisCommand.kt @@ -0,0 +1,15 @@ +package cc.fyre.venom.database.jedis + +import redis.clients.jedis.Jedis + +/** + * @project venom + * + * @date 04/26/21 + * @author xanderume@gmail.com + */ +interface RedisCommand { + + fun execute(jedis: Jedis):T + +} diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/MongoOptions.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/MongoOptions.kt new file mode 100644 index 0000000..7b151cc --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/MongoOptions.kt @@ -0,0 +1,15 @@ +package cc.fyre.venom.database.mongo + +/** + * @project venom + * + * @date 3/3/21 + * @author xanderume@gmail.com + */ +class MongoOptions(val host: String,val port: Int,val username: String? = null,val password: String? = null,val database: String,val authDatabase: String? = null) { + + fun isAuthenticationRequired():Boolean { + return this.username != null && this.password != null && this.authDatabase != null + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/RedisOptions.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/RedisOptions.kt new file mode 100644 index 0000000..bd191e8 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/RedisOptions.kt @@ -0,0 +1,15 @@ +package cc.fyre.venom.database.mongo + +/** + * @project venom + * + * @date 3/3/21 + * @author xanderume@gmail.com + */ +class RedisOptions(val host: String,val port: Int,val password: String? = null) { + + fun isAuthenticationRequired():Boolean { + return this.password != null + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/Repository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/Repository.kt new file mode 100644 index 0000000..1839bdc --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/database/mongo/Repository.kt @@ -0,0 +1,13 @@ +package cc.fyre.venom.database.mongo + +interface Repository { + + fun pull():Map + + fun update(value: V):Boolean + + fun delete(value: V):Boolean + + fun findById(id: K):V? + +} diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/grant/GrantHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/GrantHandler.kt new file mode 100644 index 0000000..6671e1a --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/GrantHandler.kt @@ -0,0 +1,231 @@ +package cc.fyre.venom.grant + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler + +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.data.GrantAdapter +import cc.fyre.venom.grant.listener.GrantListener +import cc.fyre.venom.grant.repository.GrantRepository +import cc.fyre.venom.grant.service.GrantExpiryService +import cc.fyre.venom.network.data.Group +import cc.fyre.venom.network.data.Server + +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.profile.data.Profile +import cc.fyre.venom.rank.data.Rank +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import com.mongodb.client.result.UpdateResult +import org.bson.Document +import java.util.* +import java.util.concurrent.CompletableFuture + +import kotlin.collections.HashMap + +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 28/03/2020 + * @author xanderume@gmail.com + */ +class GrantHandler(private val instance: VenomAPI) { + + /* + * + * TODO: cleanup even more + * + * */ + + val global = HashMap() + + val scoped = HashMap() + val subscription = HashMap() + + val active = HashMap>() + + val repository = GrantRepository(this.instance) + val expiryService = GrantExpiryService(this.instance) + + private var adapter: Optional = Optional.empty() + + init { + this.instance.databaseHandler.symbiote.addListener(GrantListener(this.instance)) + } + + fun grant(rank: Rank,target: UUID,sender: UUID,reason: String):Boolean { + return this.grant(rank,target,sender,reason,HashSet(),0L) + } + + fun grant(rank: Rank,target: UUID,sender: UUID,reason: String,duration: Long):Boolean { + return this.grant(rank,target,sender,reason,HashSet(),duration) + } + + fun grant(rank: Rank,target: UUID,sender: UUID,reason: String,scopes: Set):Boolean { + return this.grant(rank,target,sender,reason,scopes,0L) + } + + fun grant(rank: Rank,target: UUID,sender: UUID,reason: String,scopes: Set,duration: Long):Boolean { + + if (this.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot grant on main thread.") + } + + val grant = Grant(UUID.randomUUID(),rank.id,target,sender) + + grant.reason = reason + grant.scopes = scopes.map{it.id}.toSet() + grant.duration = duration + + this.repository.update(grant) + this.instance.databaseHandler.symbiote.sendPacket(Symbiote(Grant.EXECUTE_ID,grant)) + return true + } + + fun remove(grant: Grant,remover: UUID,reason: String):Boolean { + + if (this.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot grant on main thread.") + } + + grant.remover = remover + grant.removed = System.currentTimeMillis() + grant.removedReason = reason + + val toReturn = this.repository.update(grant) + + if (toReturn) { + this.instance.databaseHandler.symbiote.sendPacket(Symbiote(Grant.REMOVE_ID,grant)) + } + + return toReturn + } + + fun findDisplayName(profile: Profile,server: Server):String { + return this.findDisplayName(profile.id,profile.name,server) + } + + fun findDisplayName(id: UUID,server: Server):String { + return this.findDisplayName(id,this.instance.profileHandler.findName(id),server) + } + + fun findDisplayName(id: UUID,server: Server,grants: MutableSet):String { + return this.findDisplayName(this.instance.profileHandler.findName(id),server,grants) + } + + fun findDisplayName(id: UUID,name: String,server: Server):String { + + if (id == ProfileHandler.CONSOLE_UUID) { + return "§4Console" + } + + if (this.global.containsKey(id) && this.scoped.containsKey(id)) { + + var toReturn = "" + + if (this.subscription.containsKey(id)) { + toReturn += this.subscription[id]!!.prefix.replace("&8[","").replace("&8]","").replace("&","§",false) + } + + toReturn += "${this.findBestRank(id).color.replace("&","§",false)}${name}" + + return toReturn + } + + if (this.instance.isPrimaryThread()) { + return "§f$name" + } + + return this.findDisplayName(name,server,this.repository.findAllByPlayer(id)) + } + + fun findDisplayName(name: String,server: Server,grants: MutableSet):String { + + val globalRank = grants.filter{it.isGlobal() && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{!it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() ?: this.instance.rankHandler.defaultRank + val scopedRank = grants.filter{it.isScoped() && it.isValidOnServer(server) && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{!it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() ?: this.instance.rankHandler.defaultRank + val subscription = grants.filter{it.isGlobal() && it.isSubscription() && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.sortedBy{it.priority}.reversed().firstOrNull() + + return "${(subscription?.prefix ?: "").replace("&8[","").replace("&8]","").replace("&","§",false)}${if (globalRank.priority >= scopedRank.priority) globalRank.color.replace("&","§",false) else scopedRank.color.replace("&","§",false)}${name}" + } + + fun findGlobalRank(uuid: UUID):Rank { + return this.global[uuid] ?: this.instance.rankHandler.defaultRank + } + + fun findScopedRank(uuid: UUID):Rank { + return this.scoped[uuid] ?: this.instance.rankHandler.defaultRank + } + + fun findSubscription(uuid: UUID):Rank? { + + if (!this.subscription.containsKey(uuid)) { + return null + } + + return this.subscription[uuid]!! + } + + fun findBestRank(uuid: UUID):Rank { + + val globalRank = this.findGlobalRank(uuid) + val scopedRank = this.findScopedRank(uuid) + + return if (globalRank.priority >= scopedRank.priority) globalRank else scopedRank + } + + fun findBestRank(grants: MutableSet,server: Server):Rank { + + val globalRank = grants.filter{it.isGlobal() && it.isValidOnServer(server) && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{!it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() ?: this.instance.rankHandler.defaultRank + val scopedRank = grants.filter{it.isScoped() && it.isValidOnServer(server) && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{!it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() ?: this.instance.rankHandler.defaultRank + + return if (globalRank.priority >= scopedRank.priority) globalRank else scopedRank + } + + fun findGlobalGrant(uuid: UUID,server: Server,grants: MutableSet):Grant? { + return grants.filter{it.isGlobal() && !it.isVoided() && it.isValidOnServer(server) && !it.isRemoved() && !it.isSubscription()}.sortedBy{it.getPriority()}.reversed().firstOrNull() + } + + fun findScopedGrant(uuid: UUID,server: Server,grants: MutableSet):Grant? { + return grants.filter{it.isScoped() && it.isValidOnServer(server) && !it.isVoided() && !it.isRemoved() && !it.isSubscription()}.sortedBy{it.getPriority()}.reversed().firstOrNull() + } + + fun findSubscriptionGrant(uuid: UUID,grants: Collection):Grant? { + return grants.filter{it.isGlobal() && it.isSubscription() && !it.isVoided() && !it.isRemoved()}.sortedBy{it.getPriority()}.reversed().firstOrNull() + } + + fun setScoped(uuid: UUID,server: Server,grants: Collection) { + this.scoped[uuid] = (grants.filter{it.isScoped() && it.isValidOnServer(server) && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{!it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() ?: this.instance.rankHandler.defaultRank) + } + + fun setGlobal(uuid: UUID,server: Server,grants: Collection) { + this.global[uuid] = (grants.filter{it.isGlobal() && it.isValidOnServer(server) && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{!it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() ?: this.instance.rankHandler.defaultRank) + } + + fun setSubscription(uuid: UUID,grants: Collection) { + + val rank = grants.filter{it.isGlobal() && it.isSubscription() && !it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.filter{it.isSubscription()}.sortedBy{it.priority}.reversed().firstOrNull() + + if (rank == null) { + this.subscription.remove(uuid) + return + } + + this.subscription[uuid] = rank + } + + fun setSubscription(uuid: UUID,rank: Rank) { + this.subscription[uuid] = rank + } + + fun findProvider():Optional { + return this.adapter + } + + fun setProvider(adapter: GrantAdapter?) { + this.adapter = Optional.ofNullable(adapter) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/grant/data/Grant.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/data/Grant.kt new file mode 100644 index 0000000..999b331 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/data/Grant.kt @@ -0,0 +1,92 @@ +package cc.fyre.venom.grant.data + +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.network.data.Server + +import cc.fyre.venom.rank.data.Rank + +import com.google.gson.annotations.SerializedName + +import java.util.* + +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 28/03/2020 + * @author xanderume@gmail.com + */ +class Grant(@SerializedName("_id")val id: UUID,val rank: String,val target: UUID,val sender: UUID) { + + var scopes: Set = HashSet() + var duration: Long = 0L + + var reason: String = "" + var removedReason: String? = null + + var created: Long = System.currentTimeMillis() + var removed: Long? = null + + var remover: UUID? = null + + fun isActive(): Boolean { + return !this.isVoided() && !this.isRemoved() + } + + fun isVoided(): Boolean { + return this.duration != 0L && (this.created + this.duration) - System.currentTimeMillis() <= 0L + } + + fun isRemoved():Boolean { + return this.removed != null && this.removedReason != null && this.remover != null + } + + fun getTimeAgo():Long { + return System.currentTimeMillis() - this.created + } + + fun getVoidedAt():Long { + return this.created + this.duration + } + + fun getRemaining(): Long { + return (this.created + this.duration) - System.currentTimeMillis() + } + + fun isGlobal():Boolean { + return this.scopes.isEmpty() + } + + fun isScoped():Boolean { + return this.scopes.isNotEmpty() + } + + fun isPermanent():Boolean { + return this.duration == 0L + } + + fun isSubscription():Boolean { + return VenomAPI.instance.rankHandler.findById(this.rank)?.isSubscription() ?: false + } + + fun getRank():Rank? { + return VenomAPI.instance.rankHandler.findById(this.rank) + } + + fun getPriority():Int { + return VenomAPI.instance.rankHandler.findById(this.rank)?.priority ?: 0 + } + + fun isValidOnServer(server: Server):Boolean { + return this.scopes.isEmpty() || this.scopes.mapNotNull{VenomAPI.instance.networkHandler.findGroupById(server.id)}.any{it.id.equals(server.id,true)} + } + + companion object { + + const val REMOVE_ID = "GRANT_REMOVE" + const val EXECUTE_ID = "GRANT_EXECUTE" + + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/grant/data/GrantAdapter.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/data/GrantAdapter.kt new file mode 100644 index 0000000..180a62f --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/data/GrantAdapter.kt @@ -0,0 +1,18 @@ +package cc.fyre.venom.grant.data + +import java.util.* + +/** + * @project venom + * + * @date 09/05/2020 + * @author xanderume@gmail.com + */ +interface GrantAdapter { + + fun onGrantApply(uuid: UUID,grant: Grant) + fun onGrantChange(uuid: UUID,grant: Grant) + fun onGrantExpire(uuid: UUID,grant: Grant) + fun onGrantRemove(uuid: UUID,grant: Grant) + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/grant/listener/GrantListener.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/listener/GrantListener.kt new file mode 100644 index 0000000..6d57ca3 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/listener/GrantListener.kt @@ -0,0 +1,107 @@ +package cc.fyre.venom.grant.listener + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.grant.data.Grant +import com.google.gson.JsonObject +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 09/05/2020 + * @author xanderume@gmail.com + */ +class GrantListener(private val instance: VenomAPI) : ParasiteListener { + + @Parasite(Grant.EXECUTE_ID) + fun onGrantExecute(data: JsonObject) { + + val uuid = UUID.fromString(data["target"].asString) + + if (!this.instance.grantHandler.active.containsKey(uuid)) { + return + } + + val grant = this.instance.gson.fromJson(data,Grant::class.java) + + this.instance.grantHandler.active[uuid]!!.add(grant) + + val rank = this.instance.rankHandler.findById(grant.rank) ?: return + + this.instance.grantHandler.findProvider().ifPresent{it.onGrantApply(uuid,grant)} + + if (rank.priority < (if (grant.isGlobal()) (if (rank.isSubscription()) this.instance.grantHandler.findSubscription(uuid) else this.instance.grantHandler.findGlobalRank(uuid)) else this.instance.grantHandler.findScopedRank(uuid))?.priority ?: 0) { + return + } + + val grants = this.instance.grantHandler.active[uuid] ?: ArrayList() + val server = VenomAPI.instance.networkHandler.server ?: this.instance.networkHandler.findServer(uuid) + + if (server == null) { + println("Tried to update rank for $uuid but user not online?") + return + } + + if (grant.isGlobal()) { + + if (rank.isSubscription()) { + this.instance.grantHandler.setSubscription(uuid,grants) + } else { + this.instance.grantHandler.setGlobal(uuid,server,grants) + } + + } else { + this.instance.grantHandler.setScoped(uuid,server,grants) + } + + if (!grant.isPermanent()) { + this.instance.grantHandler.active.putIfAbsent(uuid,ArrayList()) + this.instance.grantHandler.active[uuid]!!.add(grant) + } + + this.instance.grantHandler.findProvider().ifPresent{it.onGrantChange(uuid,grant)} + } + + @Parasite(Grant.REMOVE_ID) + fun onGrantRemove(data: JsonObject) { + + val uuid = UUID.fromString(data["target"].asString) + + if (!this.instance.grantHandler.active.containsKey(uuid)) { + return + } + + val grant = this.instance.gson.fromJson(data,Grant::class.java) + + this.instance.grantHandler.active[uuid]!!.removeIf{it.id == grant.id} + this.instance.grantHandler.active[uuid]!!.add(grant) + + val grants = this.instance.grantHandler.active[uuid]!! + val server = VenomAPI.instance.networkHandler.server ?: this.instance.networkHandler.findServer(uuid) + + if (server == null) { + println("Tried to update rank for $uuid but user not online?") + return + } + + if (grant.isScoped()) { + this.instance.grantHandler.setScoped(uuid,server,grants) + } else if (grant.isGlobal()) { + + if (grant.isSubscription()) { + this.instance.grantHandler.setSubscription(uuid,grants) + } else { + this.instance.grantHandler.setGlobal(uuid,server,grants) + } + + } + + this.instance.grantHandler.findProvider().ifPresent{it.onGrantRemove(uuid,grant)} + } + + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/grant/repository/GrantRepository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/repository/GrantRepository.kt new file mode 100644 index 0000000..5327105 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/repository/GrantRepository.kt @@ -0,0 +1,61 @@ +package cc.fyre.venom.grant.repository + +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler +import cc.fyre.venom.database.mongo.Repository +import cc.fyre.venom.grant.data.Grant +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import org.bson.Document +import java.util.* + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +class GrantRepository(private val instance: VenomAPI) : Repository { + + /* + * + * TODO: VERY IMPORTANT + * fix gson serializing "long" values as "strings" so we can sort mongo with "created" timestamp + * instead of manually sorting them -> this.collection.find(filters).sort(Filters.eq("created",-1)).limit(1) + * */ + + val collection: MongoCollection = this.instance.databaseHandler.mongoDB.getCollection("grants") + + @Deprecated(message = "empty()",level = DeprecationLevel.HIDDEN) + override fun pull(): Map { + return HashMap() + } + + override fun update(value: Grant): Boolean { + return this.collection.updateOne(Filters.eq("_id",value.id.toString()),Document("\$set",Document.parse(this.instance.gson.toJson(value))),DatabaseHandler.UPDATE_OPTIONS).wasAcknowledged() + } + + override fun delete(value: Grant): Boolean { + return this.collection.deleteOne(Filters.eq("_id",value.id.toString())).wasAcknowledged() + } + + override fun findById(id: UUID):Grant? { + + val document = this.collection.find(Filters.eq("_id",id.toString())).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Grant::class.java) + } + + fun findAllBySender(uuid: UUID):MutableSet { + return this.collection.find(Filters.eq("sender",uuid.toString())).map{this.instance.gson.fromJson(it.toJson(),Grant::class.java)}.toMutableSet() + } + + fun findAllByPlayer(target: UUID):MutableSet { + return this.collection.find(Filters.eq("target",target.toString())).map{this.instance.gson.fromJson(it.toJson(),Grant::class.java)}.toMutableSet() + } + + fun findAllBySenderOrRemover(uuid: UUID):MutableSet { + return this.collection.find(Filters.or(arrayListOf(Filters.eq("sender",uuid.toString()),Filters.eq("remover",uuid.toString())))).map{this.instance.gson.fromJson(it.toJson(),Grant::class.java)}.toMutableSet() + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/grant/service/GrantExpiryService.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/service/GrantExpiryService.kt new file mode 100644 index 0000000..e86c98b --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/grant/service/GrantExpiryService.kt @@ -0,0 +1,74 @@ +package cc.fyre.venom.grant.service + +import cc.fyre.venom.VenomAPI + +/** + * @project venom + * + * @date 10/05/2020 + * @author xanderume@gmail.com + */ +class GrantExpiryService(private val instance: VenomAPI) : Runnable { + + override fun run() { + + val iterator = this.instance.grantHandler.active.iterator() + + while (iterator.hasNext()) { + + val next = iterator.next() + + if (next.value.isEmpty()) { + continue + } + + val grantIterator = next.value.iterator() + + while (grantIterator.hasNext()) { + + val grant = grantIterator.next() + + if (grant.isPermanent()) { + continue + } + + if (grant.isRemoved()) { + grantIterator.remove() + continue + } + + if (!grant.isVoided()) { + continue + } + + if (!this.instance.grantHandler.active.containsKey(next.key)) { + iterator.remove() + continue + } + + grantIterator.remove() + + val server = VenomAPI.instance.networkHandler.server ?: this.instance.networkHandler.findServer(next.key) + + if (server == null) { + println("Tried to update rank for ${next.key} but user not online?") + return + } + + if (grant.isScoped()) { + this.instance.grantHandler.setScoped(next.key,server,next.value) + } else if (grant.isGlobal()) { + + if (grant.isSubscription()) { + this.instance.grantHandler.setSubscription(next.key,next.value) + } else { + this.instance.grantHandler.setGlobal(next.key,server,next.value) + } + + } + + this.instance.grantHandler.findProvider().ifPresent{it.onGrantExpire(next.key,grant)} + } + } + } +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/network/NetworkHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/network/NetworkHandler.kt new file mode 100644 index 0000000..b13a668 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/network/NetworkHandler.kt @@ -0,0 +1,105 @@ +package cc.fyre.venom.network + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler +import cc.fyre.venom.network.data.Group +import cc.fyre.venom.network.data.Proxy +import cc.fyre.venom.network.data.Server +import cc.fyre.venom.network.data.Status +import cc.fyre.venom.network.listener.NetworkListener +import com.mongodb.client.MongoCollection +import com.mongodb.client.result.UpdateResult +import org.bson.Document +import java.util.* +import java.util.concurrent.TimeUnit +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 01/03/2021 + * @author xanderume@gmail.com + */ +class NetworkHandler(private val api: VenomAPI) { + + val groups = HashSet() + val proxies = HashSet() + val servers = HashSet() + + var server: Server? = null + + /* TODO: All in one collection? */ + private val groupsCollection: MongoCollection = this.api.databaseHandler.mongoDB.getCollection("groups") + private val proxiesCollection: MongoCollection = this.api.databaseHandler.mongoDB.getCollection("proxies") + private val serversCollection: MongoCollection = this.api.databaseHandler.mongoDB.getCollection("servers") + + init { + this.groupsCollection.find().forEach{this.groups.add(this.api.gson.fromJson(it.toJson(),Group::class.java))} + this.proxiesCollection.find().forEach{this.proxies.add(this.api.gson.fromJson(it.toJson(),Proxy::class.java))} + this.serversCollection.find().forEach{this.servers.add(this.api.gson.fromJson(it.toJson(),Server::class.java))} + + this.api.databaseHandler.symbiote.addListener(NetworkListener(this.api)) + } + + fun findGroupById(id: String):Group? { + return this.groups.firstOrNull{it.id.equals(id,true)} + } + + fun findProxyById(id: String):Proxy? { + return this.proxies.firstOrNull{it.id.equals(id,true)} + } + + fun findServerById(id: String):Server? { + return this.servers.firstOrNull{it.id.equals(id,true)} + } + + fun update(group: Group):UpdateResult { + + val toReturn = this.groupsCollection.updateOne(Document("_id",group.id),Document("\$set",Document.parse(this.api.gson.toJson(group))),DatabaseHandler.UPDATE_OPTIONS) + + if (toReturn.wasAcknowledged()) { + this.api.databaseHandler.symbiote.sendPacket(Symbiote(Group.UPDATE_ID,group)) + } + + return toReturn + } + + fun update(proxy: Proxy):UpdateResult { + + val toReturn = this.proxiesCollection.updateOne(Document("_id",proxy.id),Document("\$set",Document.parse(this.api.gson.toJson(proxy))),DatabaseHandler.UPDATE_OPTIONS) + + if (toReturn.wasAcknowledged()) { + this.api.databaseHandler.symbiote.sendPacket(Symbiote(Proxy.UPDATE_ID,proxy)) + } + + return toReturn + } + + fun update(server: Server):UpdateResult { + + val toReturn = this.serversCollection.updateOne(Document("_id",server.id),Document("\$set",Document.parse(this.api.gson.toJson(server))),DatabaseHandler.UPDATE_OPTIONS) + + if (toReturn.wasAcknowledged()) { + this.api.databaseHandler.symbiote.sendPacket(Symbiote(Server.UPDATE_ID,server)) + } + + return toReturn + } + + fun isOnline(uuid: UUID):Boolean { + return this.servers.any{it.onlinePlayers.contains(uuid)} + } + + fun findServer(uuid: UUID):Server? { + return this.servers.firstOrNull{it.onlinePlayers.contains(uuid)} + } + + companion object { + + const val NETWORK_JOIN_PACKET = "NETWORK_JOIN_PACKET" + const val NETWORK_LEAVE_PACKET = "NETWORK_LEAVE_PACKET" + const val NETWORK_SWITCH_PACKET = "NETWORK_SWITCH_PACKET" + + } +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Group.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Group.kt new file mode 100644 index 0000000..8ce02c1 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Group.kt @@ -0,0 +1,30 @@ +package cc.fyre.venom.network.data + +import cc.fyre.venom.VenomAPI + +import com.google.gson.annotations.SerializedName +import java.util.stream.Collectors + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class Group(@SerializedName("_id")val id: String) { + + var announcements = ArrayList>() + + fun hasServer(server: Server):Boolean { + return this.findServers().any{it.id.equals(server.id,true) && it.port == server.port} + } + + fun findServers():MutableSet { + return VenomAPI.instance.networkHandler.servers.filter{it.group.equals(this.id,true)}.toMutableSet() + } + + companion object { + const val UPDATE_ID = "SERVER_GROUP_UPDATE" + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Proxy.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Proxy.kt new file mode 100644 index 0000000..495e5d0 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Proxy.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.network.data + +import cc.fyre.venom.VenomAPI + +import com.google.gson.annotations.SerializedName +import java.util.* +import java.util.stream.Collectors +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class Proxy(@SerializedName("_id")val id: String,val port: Int,var group: String) { + + var motd: Array = arrayOf("","") + + var update: Long = 0L + var status: Status = Status.OFFLINE + + val created: Long = System.currentTimeMillis() + + var onlinePlayers = HashSet() + var bungeeServers = HashSet() + + fun findServers():List { + return this.bungeeServers.mapNotNull{VenomAPI.instance.networkHandler.findServerById(it)}.toList() + } + + companion object { + + const val UPDATE_ID = "PROXY_UPDATE" + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Server.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Server.kt new file mode 100644 index 0000000..d4af81e --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Server.kt @@ -0,0 +1,45 @@ +package cc.fyre.venom.network.data + +import cc.fyre.venom.VenomAPI +import com.google.gson.JsonObject +import com.google.gson.annotations.SerializedName +import java.util.* +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class Server(@SerializedName("_id")val id: String,val port: Int,var group: String) { + + var update: Long = 0L + var status: Status = Status.OFFLINE + val created: Long = System.currentTimeMillis() + + var metadata = JsonObject() + + var onlinePlayers = HashSet() + var maximumPlayers: Int = 0 + var whitelistedPlayers = HashSet() + + var ticksPerSecond: DoubleArray = DoubleArray(3) + + fun isHub(): Boolean { + return this.id.startsWith("Hub",true) || this.id.startsWith("Lobby",true) || this.group.startsWith("Hub",true) || this.group.startsWith("Lobby",true) + } + + fun isWhitelisted(uuid: UUID):Boolean { + return this.whitelistedPlayers.contains(uuid) + } + + fun findGroup():Group? { + return VenomAPI.instance.networkHandler.findGroupById(this.group) + } + + companion object { + const val UPDATE_ID = "SERVER_UPDATE" + } + +} diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Status.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Status.kt new file mode 100644 index 0000000..f67f7ef --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/network/data/Status.kt @@ -0,0 +1,15 @@ +package cc.fyre.venom.network.data + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +enum class Status(val color: String,val woolData: Int) { + + ONLINE("§a",13), + OFFLINE("§c",14), + WHITELISTED("§e",0) + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/network/listener/NetworkListener.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/network/listener/NetworkListener.kt new file mode 100644 index 0000000..1b6c39a --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/network/listener/NetworkListener.kt @@ -0,0 +1,95 @@ +package cc.fyre.venom.network.listener + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.VenomAPI + +import cc.fyre.venom.network.data.Group +import cc.fyre.venom.network.data.Proxy +import cc.fyre.venom.network.data.Server +import cc.fyre.venom.network.data.Status + +import com.google.gson.JsonObject + +import java.util.* + +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 20/03/2020 + * @author xanderume@gmail.com + */ +class NetworkListener(private val api: VenomAPI) : ParasiteListener { + + @Parasite(Group.UPDATE_ID) + fun onGroupUpdate(data: JsonObject) { + val id = data["_id"].asString + + val group = this.api.networkHandler.findGroupById(id) ?: Group(id) + + group.announcements.clear() + + for (element in data["announcements"].asJsonArray) { + + val announcement = ArrayList() + + val array = element.asJsonArray.map{it.asString}.toList() + + announcement.addAll(array) + + group.announcements.add(announcement) + } + + if (this.api.networkHandler.findGroupById(group.id) != null) { + return + } + + this.api.networkHandler.groups.add(group) + } + + @Parasite(Proxy.UPDATE_ID) + fun onProxyUpdate(data: JsonObject) { + + val id = data["_id"].asString + + val proxy = this.api.networkHandler.findProxyById(id) ?: Proxy(id,data["port"].asInt,data["group"].asString) + + proxy.group = data["group"].asString + proxy.motd = data["motd"].asJsonArray.map{it.asString}.toTypedArray() + proxy.update = System.currentTimeMillis() + proxy.status = Status.valueOf(data["status"].asString) + proxy.onlinePlayers = data["onlinePlayers"].asJsonArray.map{UUID.fromString(it.asString)}.toHashSet() + + if (this.api.networkHandler.findProxyById(proxy.id) != null) { + return + } + + this.api.networkHandler.proxies.add(proxy) + } + + @Parasite(Server.UPDATE_ID) + fun onServerUpdate(data: JsonObject) { + + val id = data["_id"].asString + val server = this.api.networkHandler.findServerById(id) ?: Server(id,data["port"].asInt,data["group"].asString) + + server.group = data["group"].asString + server.update = System.currentTimeMillis() + server.status = Status.valueOf(data["status"].asString) + server.onlinePlayers = data["onlinePlayers"].asJsonArray.map{UUID.fromString(it.asString)}.toHashSet() + server.whitelistedPlayers = data["whitelistedPlayers"].asJsonArray.map{UUID.fromString(it.asString)}.toHashSet() + server.maximumPlayers = data["maximumPlayers"].asInt + server.ticksPerSecond = data["ticksPerSecond"].asJsonArray.map{it.asDouble}.toDoubleArray() + + server.metadata = data["metadata"].asJsonObject + + if (this.api.networkHandler.findServerById(server.id) != null) { + return + } + + this.api.networkHandler.servers.add(server) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/profile/ProfileHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/ProfileHandler.kt new file mode 100644 index 0000000..05048db --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/ProfileHandler.kt @@ -0,0 +1,98 @@ +package cc.fyre.venom.profile + +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.profile.data.Profile +import cc.fyre.venom.profile.listener.ProfileListener +import cc.fyre.venom.profile.repository.ProfileRepository + +import java.util.* +import java.util.concurrent.ConcurrentHashMap +import kotlin.collections.ArrayList +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class ProfileHandler(private val instance: VenomAPI) { + + val cache = HashMap() + val repository = ProfileRepository(this.instance) + + private val uuidToName = ConcurrentHashMap() + private val nameToUuid = ConcurrentHashMap() + + init { + + this.repository.collection.find().iterator().forEachRemaining{ + val name = it.getString("name") + val uuid = UUID.fromString(it.getString("_id")) + + this.uuidToName[uuid] = name + this.nameToUuid[name.toLowerCase()] = uuid + } + + this.instance.databaseHandler.symbiote.addListener(ProfileListener(this.instance)) + + this.uuidToName[CONSOLE_UUID] = "CONSOLE" + this.nameToUuid["console"] = CONSOLE_UUID + } + + fun findById(id: UUID):Profile? { + return this.cache[id] + } + + fun findByName(name: String):Profile? { + + if (!this.nameToUuid.contains(name.toLowerCase())) { + return null + } + + return this.cache[this.nameToUuid[name.toLowerCase()]!!] + } + + fun updateId(id: UUID,name: String) { + this.uuidToName[id] = name + this.nameToUuid[name.toLowerCase()] = id + } + + fun findId(name: String):UUID? { + return this.nameToUuid[name.toLowerCase()] + } + + fun findName(id: UUID):String { + return this.uuidToName[id] ?: "null" + } + + fun calculatePermissions(permissions: ArrayList,defaultPermissions: Boolean):ConcurrentHashMap { + + val toReturn = ConcurrentHashMap() + + if (defaultPermissions) { + toReturn.putAll(this.instance.rankHandler.defaultRank.permissions.associate{ + val value = !it.startsWith("-") + return@associate (if (value) it else it.substring(1)).toLowerCase() to value + }) + } + + toReturn.putAll(permissions.associate{ + val value = !it.startsWith("-") + return@associate (if (value) it else it.substring(1)).toLowerCase() to value + }) + + return toReturn + } + + fun isCached(uuid: UUID):Boolean { + return this.uuidToName.contains(uuid) + } + + companion object { + val CONSOLE_UUID: UUID = UUID.fromString("f78a4d8d-d51b-4b39-98a3-230f2de0c670") + + const val PERMISSION_UPDATE_PACKET = "PERMISSION_UPDATE" + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/profile/data/Profile.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/data/Profile.kt new file mode 100644 index 0000000..6f0043b --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/data/Profile.kt @@ -0,0 +1,77 @@ +package cc.fyre.venom.profile.data + +import cc.fyre.venom.VenomAPI + +import com.google.gson.annotations.SerializedName +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class Profile(@SerializedName("_id")val id: UUID) { + + var name: String = "null" + + constructor(id: UUID,name: String):this(id) { + this.name = name + } + + var tag: String? = null + + var chatColor: String = "WHITE" + var customTag: String? = null + + val ignore = HashSet() + + var settings = Setting() + + val created = System.currentTimeMillis() + val permissions = ArrayList() + + val identifiers: ArrayList = ArrayList() + + fun findTagPrefix():String { + + if (this.customTag != null) { + return this.customTag!!.replace("&","§",false) + } + + if (this.tag == null || this.tag == "") { + return "" + } + + return VenomAPI.instance.tagHandler.findById(this.tag!!)?.prefix?.replace("&","§",false) ?: "" + } + + fun getPlayTime():Long { + + if (VenomAPI.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot request playtime on main thread.") + } + + var toReturn = 0L + + for (session in VenomAPI.instance.sessionHandler.repository.findAllByPlayer(this.id)) { + toReturn += session.getPlayTime() + } + + return toReturn + } + + class Setting { + + var viewGlobalChat = true + var receiveMessages = true + var receiveMessagingSounds = true + + } + + companion object { + const val NAME_UPDATE_ID = "NAME_UPDATE" + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/profile/listener/ProfileListener.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/listener/ProfileListener.kt new file mode 100644 index 0000000..d1d8fdf --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/listener/ProfileListener.kt @@ -0,0 +1,24 @@ +package cc.fyre.venom.profile.listener + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.profile.data.Profile +import com.google.gson.JsonObject +import java.util.* + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class ProfileListener(private val instance: VenomAPI) : ParasiteListener { + + @Parasite(Profile.NAME_UPDATE_ID) + fun onNameUpdate(data: JsonObject) { + this.instance.profileHandler.updateId(UUID.fromString(data["_id"].asString),data["name"].asString) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/profile/repository/ProfileRepository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/repository/ProfileRepository.kt new file mode 100644 index 0000000..70cce75 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/profile/repository/ProfileRepository.kt @@ -0,0 +1,61 @@ +package cc.fyre.venom.profile.repository + +import cc.fyre.venom.database.mongo.Repository +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler + +import cc.fyre.venom.profile.data.Profile +import com.google.gson.JsonObject +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import org.bson.Document +import org.bson.conversions.Bson +import java.util.* +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +class ProfileRepository(private val instance: VenomAPI) : Repository { + + val collection: MongoCollection = this.instance.databaseHandler.mongoDB.getCollection("profiles") + + @Deprecated("INVALID",level = DeprecationLevel.HIDDEN) + override fun pull(): HashMap { + return HashMap() + } + + override fun update(value: Profile): Boolean { + return this.collection.updateOne(Filters.eq("_id",value.id.toString()),Document("\$set",Document.parse(this.instance.gson.toJson(value))),DatabaseHandler.UPDATE_OPTIONS).wasAcknowledged() + } + + override fun delete(value: Profile): Boolean { + return this.collection.deleteOne(Filters.eq("_id",value.id.toString())).wasAcknowledged() + } + + override fun findById(id: UUID): Profile? { + + val document = this.collection.find(Filters.eq("_id",id.toString())).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Profile::class.java) + } + + fun findByAddress(address: String):Profile? { + + val document = this.collection.find(Filters.eq("identifiers",address)).limit(1).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Profile::class.java) + } + + fun findAlts(profile: Profile):MutableSet { + return this.findAlts(profile.id,profile.identifiers) + } + + fun findAlts(uuid: UUID,addresses: Collection):MutableSet { + return this.collection.find(Filters.and(Filters.not(Filters.eq("_id",uuid.toString())),Filters.or(addresses.map{Filters.eq("identifiers",it)}))).map{this.instance.gson.fromJson(it.toJson(),Profile::class.java)}.toMutableSet() + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/PunishmentHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/PunishmentHandler.kt new file mode 100644 index 0000000..a2ee285 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/PunishmentHandler.kt @@ -0,0 +1,99 @@ +package cc.fyre.venom.punishment + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.repository.PunishmentRepository + +import java.lang.IllegalStateException +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashSet + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class PunishmentHandler(private val instance: VenomAPI) { + + val mutes = HashMap>() + val repository = PunishmentRepository(this.instance) + + fun isMuted(uuid: UUID):Boolean { + return this.mutes[uuid]?.any{it.type == Punishment.Type.MUTE && it.getRemaining() > 0} ?: false + } + + fun isGhostMuted(uuid: UUID):Boolean { + return this.mutes[uuid]?.any{it.type == Punishment.Type.GHOST_MUTE && it.getRemaining() > 0} ?: false + } + + fun punish(type: Punishment.Type,victim: UUID,sender: UUID,reason: String,server: String,silent: Boolean,victimDisplay: String,senderDisplay: String):Boolean { + return this.punish(type,victim,ArrayList(),sender,reason,server,0L,silent,victimDisplay,senderDisplay) + } + + fun punish(type: Punishment.Type,victim: UUID,sender: UUID,reason: String,server: String,duration: Long,silent: Boolean,victimDisplay: String,senderDisplay: String):Boolean { + return this.punish(type,victim,ArrayList(),sender,reason,server,duration,silent,victimDisplay,senderDisplay) + } + + fun punish(type: Punishment.Type,victim: UUID,identifiers: ArrayList,sender: UUID,reason: String,server: String,silent: Boolean,victimDisplay: String,senderDisplay: String):Boolean { + return this.punish(type,victim,identifiers,sender,reason,server,0L,silent,victimDisplay,senderDisplay) + } + + fun punish(type: Punishment.Type,victim: UUID,identifiers: ArrayList,sender: UUID,reason: String,server: String,duration: Long,silent: Boolean,victimDisplay: String,senderDisplay: String):Boolean { + + if (this.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot punish user on main thread.") + } + + val punishment = Punishment(UUID.randomUUID(),type,victim,sender) + + punishment.silent = silent + punishment.reason = reason + punishment.server = server + punishment.duration = duration + punishment.identifiers = identifiers + + val toReturn = this.repository.update(punishment) + + if (toReturn) { + + val jsonObject = VenomAPI.instance.gson.toJsonTree(punishment).asJsonObject + + jsonObject.addProperty("victimDisplay",victimDisplay) + jsonObject.addProperty("senderDisplay",senderDisplay) + + this.instance.databaseHandler.symbiote.sendPacket(Symbiote(Punishment.PACKET_ID,jsonObject)) + } + + return toReturn + } + + fun pardon(punishment: Punishment,pardoner: UUID,reason: String,silent: Boolean,victimDisplay: String,senderDisplay: String):Boolean { + + if (this.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot punish user on main thread.") + } + + punishment.pardoner = pardoner + punishment.pardoned = System.currentTimeMillis() + punishment.pardonReason = reason + punishment.pardonedSilent = silent + + val toReturn = this.repository.update(punishment) + + if (toReturn) { + + val jsonObject = VenomAPI.instance.gson.toJsonTree(punishment).asJsonObject + + jsonObject.addProperty("victimDisplay",victimDisplay) + jsonObject.addProperty("senderDisplay",senderDisplay) + + this.instance.databaseHandler.symbiote.sendPacket(Symbiote(Punishment.PACKET_ID,jsonObject)) + } + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/data/Punishment.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/data/Punishment.kt new file mode 100644 index 0000000..ff669ab --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/data/Punishment.kt @@ -0,0 +1,88 @@ +package cc.fyre.venom.punishment.data + +import cc.fyre.venom.profile.ProfileHandler +import com.google.gson.annotations.SerializedName +import java.util.* + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class Punishment(@SerializedName("_id")val id: UUID,val type: Type,val victim: UUID,val sender: UUID) { + + var created = System.currentTimeMillis() + + var server: String = "Unknown" + var duration: Long = 0L + + var reason: String = "" + var pardonReason: String? = null + + var silent: Boolean = true + var pardonedSilent: Boolean = true + + var pardoned: Long? = null + var pardoner: UUID? = null + + var evidence = ArrayList() + + var identifiers: ArrayList = ArrayList() + + fun isIP():Boolean { + return this.identifiers.isNotEmpty() + } + + fun isVoided(): Boolean { + return this.duration != 0L && (this.created + this.duration) - System.currentTimeMillis() <= 0L + } + + fun isPardoned():Boolean { + return this.pardoned != null && this.pardonReason != null && this.pardoner != null + } + + fun isPermanent():Boolean { + return this.duration == 0L + } + + fun getExpiredAt(): Long { + return this.created + this.duration + } + + fun getRemaining(): Long { + return (this.created + this.duration) - System.currentTimeMillis() + } + + fun isEvidenceRequired():Boolean { + return this.evidence.isEmpty() && !this.isPardoned() && this.sender != ProfileHandler.CONSOLE_UUID + } + + enum class Type(val kickOnExecute: Boolean,val context: String,val color: String,val woolData: Int) { + + KICK(true,"kicked","§a",5), + WARN(false,"warned","§e",4), + MUTE(false,"muted","§6",1), + GHOST_MUTE(false,"muted","§6",1), + BAN(true,"banned","§c",14), + BLACKLIST(true,"blacklisted","§4",0); + + fun permission(pardon: Boolean,ip: Boolean = false): String { + return "punishment.${if (pardon) "pardon" else "execute"}.${if (ip) "ip" else ""}${this.name.toLowerCase()}" + } + + } + + class Evidence(val url: String,val provider: UUID) { + + val provided = System.currentTimeMillis() + + } + + companion object { + + const val PACKET_ID = "PUNISHMENT" + + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/repository/PunishmentRepository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/repository/PunishmentRepository.kt new file mode 100644 index 0000000..7090de0 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/punishment/repository/PunishmentRepository.kt @@ -0,0 +1,96 @@ +package cc.fyre.venom.punishment.repository + +import cc.fyre.venom.database.mongo.Repository +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler + +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.rank.data.Rank +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import org.bson.Document +import org.bson.conversions.Bson +import java.util.* +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +class PunishmentRepository(private val instance: VenomAPI) : Repository { + + /* + * + * TODO: VERY IMPORTANT + * fix gson serializing "long" values as "strings" so we can sort mongo with "created" timestamp + * instead of manually sorting them -> this.collection.find(filters).sort(Filters.eq("created",-1)).limit(1) + * */ + + private val collection: MongoCollection = this.instance.databaseHandler.mongoDB.getCollection("punishments") + + @Deprecated(message = "empty()",level = DeprecationLevel.HIDDEN) + override fun pull(): Map { + return HashMap() + } + + override fun update(value: Punishment): Boolean { + return this.collection.updateOne(Filters.eq("_id",value.id.toString()),Document("\$set",Document.parse(this.instance.gson.toJson(value))),DatabaseHandler.UPDATE_OPTIONS).wasAcknowledged() + } + + override fun delete(value: Punishment): Boolean { + return this.collection.deleteOne(Filters.eq("_id",value.id.toString())).wasAcknowledged() + } + + override fun findById(id: UUID): Punishment? { + + val document = this.collection.find(Filters.eq("_id",id.toString())).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Punishment::class.java) + } + + fun findByVictim(victim: UUID,type: Punishment.Type):MutableSet { + return this.findByVictim(victim,arrayListOf(type)) + } + + fun findByVictim(victim: UUID,types: MutableList):MutableSet { + return this.collection.find(Filters.eq("victim",victim.toString())).map{this.instance.gson.fromJson(it.toJson(),Punishment::class.java)}.filter{types.contains(it.type)}.toMutableSet() + } + + fun findByVictimOrIdentifier(victim: UUID,addresses: MutableList):MutableSet { + return this.collection.find(Filters.or(Filters.eq("victim",victim.toString()),Filters.or(addresses.map{Filters.eq("identifiers",it)}))).map{this.instance.gson.fromJson(it.toJson(),Punishment::class.java)}.toMutableSet() + } + + fun findBySender(uuid: UUID,type: Punishment.Type):MutableSet { + return this.findBySender(uuid,arrayListOf(type)) + } + + fun findBySender(uuid: UUID,types: MutableList):MutableSet { + return this.collection.find(Filters.eq("sender",uuid.toString())).map{this.instance.gson.fromJson(it.toJson(),Punishment::class.java)}.filter{types.contains(it.type)}.toMutableSet() + } + + fun findBySenderOrPardoner(uuid: UUID):MutableSet { + return this.collection.find(Filters.or(arrayListOf(Filters.eq("sender",uuid.toString()),Filters.eq("pardoner",uuid.toString())))).map{this.instance.gson.fromJson(it.toJson(),Punishment::class.java)}.toMutableSet() + } + + fun findMostRecentPunishment(punishments: MutableSet):Punishment? { + return this.findMostRecentPunishment(punishments,punishments.first().type) + } + + fun findMostRecentPunishment(punishments: MutableSet,type: Punishment.Type):Punishment? { + return this.findMostRecentPunishment(punishments,arrayListOf(type)) + } + + fun findMostRecentPunishment(punishments: MutableSet,types: MutableList):Punishment? { + return punishments + .filter{types.contains(it.type)} + .filter{!it.isVoided() && !it.isPardoned()} + .sortedBy{it.type.ordinal} + .reversed() + .sortedBy{it.created} + .reversed() + .firstOrNull() + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/rank/RankHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/RankHandler.kt new file mode 100644 index 0000000..bd7c849 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/RankHandler.kt @@ -0,0 +1,54 @@ +package cc.fyre.venom.rank + +import cc.fyre.venom.VenomAPI + +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.listener.RankListener +import cc.fyre.venom.rank.repository.RankRepository + +/** + * @project venom + * + * @date 28/03/2020 + * @author xanderume@gmail.com + */ +class RankHandler(private val instance: VenomAPI) { + + val cache = hashMapOf() + val repository = RankRepository(this.instance) + + val defaultRank: Rank + + init { + this.cache.putAll(this.repository.pull()) + this.defaultRank = this.loadDefaultRank() + this.instance.databaseHandler.symbiote.addListener(RankListener(this.instance)) + } + + fun findById(id: String): Rank? { + return this.cache[id.toLowerCase()] + } + + private fun loadDefaultRank(): Rank { + + if (this.cache.containsKey("default")) { + return this.cache["default"]!! + } + + val toReturn = Rank("Default") + + if (this.repository.update(toReturn)) { + this.cache[toReturn.id.toLowerCase()] = toReturn + } + + return toReturn + } + + companion object { + + const val UPDATE_ID = "RANK_UPDATE" + const val DELETE_ID = "RANK_DELETE" + + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/rank/data/Rank.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/data/Rank.kt new file mode 100644 index 0000000..d4948ff --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/data/Rank.kt @@ -0,0 +1,77 @@ +package cc.fyre.venom.rank.data + +import cc.fyre.venom.punishment.data.Punishment +import com.google.gson.annotations.SerializedName + +/** + * @project venom + * + * @date 28/03/2020 + * @author xanderume@gmail.com + */ +class Rank(@SerializedName("_id")var id: String) { + + constructor(id: String,metadata: Metadata):this(id) { + this.metadata.add(metadata) + } + + var color: String = "§f" + var prefix: String = "" + var priority: Int = 0 + + var inherits = hashSetOf() + var metadata = hashSetOf() + var permissions = hashSetOf() + var evidenceRequired = hashSetOf() + + fun isStaff():Boolean { + return this.metadata.contains(Metadata.STAFF) + } + + fun isHidden():Boolean { + return this.metadata.contains(Metadata.HIDDEN) + } + + fun isSubscription():Boolean { + return this.metadata.contains(Metadata.SUBSCRIPTION) + } + + fun isDefault():Boolean { + return this.metadata.contains(Metadata.DEFAULT) + } + + fun isVPNBypass():Boolean { + return this.metadata.contains(Metadata.VPN_BYPASS) + } + + fun hasMetadata(metadata: Metadata):Boolean { + return this.metadata.contains(metadata) + } + + fun getDisplayName():String { + return "${this.color}${this.id}".replace("&","§",false) + } + + fun isEvidenceRequired(type: Punishment.Type):Boolean { + return this.evidenceRequired.contains(type) + } + + enum class Metadata(val displayName: String,val icon: String) { + + DEFAULT("Default","COMPASS"), + DONATOR("Donator","EMERALD"), + SUBSCRIPTION("Subscription","EXP_BOTTLE"), + STAFF("Staff","BEACON"), + VPN_BYPASS("VPN Bypass","PAINTING"), + HIDDEN("Hidden","IRON_DOOR"); + + } + + companion object { + + const val UPDATE_ID = "RANK_UPDATE" + const val DELETE_ID = "RANK_DELETE" + + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/rank/listener/RankListener.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/listener/RankListener.kt new file mode 100644 index 0000000..ef1f9f6 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/listener/RankListener.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.rank.listener + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.rank.RankHandler +import cc.fyre.venom.rank.data.Rank +import com.google.gson.JsonObject + +/** + * @project venom + * + * @date 20/04/2020 + * @author xanderume@gmail.com + */ +class RankListener(private val instance: VenomAPI) : ParasiteListener { + + @Parasite(RankHandler.DELETE_ID) + fun onRankDelete(data: JsonObject) { + this.instance.rankHandler.cache.remove(data["_id"].asString) + } + + @Parasite(RankHandler.UPDATE_ID) + fun onRankUpdate(data: JsonObject) { + + val rank = this.instance.rankHandler.findById(data["_id"].asString) + + if (rank == null) { + this.instance.rankHandler.cache[data["_id"].asString.toLowerCase()] = this.instance.gson.fromJson(data,Rank::class.java) + return + } + + this.instance.rankHandler.cache.replace(data["_id"].asString.toLowerCase(),this.instance.gson.fromJson(data,Rank::class.java)) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/rank/repository/RankRepository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/repository/RankRepository.kt new file mode 100644 index 0000000..d040e77 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/rank/repository/RankRepository.kt @@ -0,0 +1,46 @@ +package cc.fyre.venom.rank.repository + +import cc.fyre.venom.database.mongo.Repository +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler +import cc.fyre.venom.rank.data.Rank +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import org.bson.Document + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +class RankRepository(private val instance: VenomAPI) : Repository { + + private val collection: MongoCollection = this.instance.databaseHandler.mongoDB.getCollection("ranks") + + override fun pull(): MutableMap { + return this.collection.find().map{this.instance.gson.fromJson(it.toJson(),Rank::class.java)} + .associateBy{it.id.toLowerCase()} + .toMutableMap() + } + + override fun update(value: Rank): Boolean { + return this.collection.updateOne( + Filters.eq("_id",value.id), + Document("\$set",Document.parse(this.instance.gson.toJson(value))), + DatabaseHandler.UPDATE_OPTIONS + ).wasAcknowledged() + } + + override fun delete(value: Rank): Boolean { + return this.collection.deleteOne(Filters.eq("_id",value.id)).wasAcknowledged() + } + + override fun findById(id: String): Rank? { + + val document = this.collection.find(Filters.eq("_id",id)).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Rank::class.java) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/session/SessionHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/session/SessionHandler.kt new file mode 100644 index 0000000..19167b5 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/session/SessionHandler.kt @@ -0,0 +1,16 @@ +package cc.fyre.venom.session + +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.session.repository.SessionRepository + +/** + * @project venom + * + * @date 16/03/2020 + * @author xanderume@gmail.com + */ +class SessionHandler(private val api: VenomAPI) { + + val repository = SessionRepository(this.api) + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/session/data/Session.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/session/data/Session.kt new file mode 100644 index 0000000..dc4b1b6 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/session/data/Session.kt @@ -0,0 +1,59 @@ +package cc.fyre.venom.session.data + +import com.google.gson.annotations.JsonAdapter +import com.google.gson.annotations.SerializedName +import java.text.SimpleDateFormat +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 12/08/2020 + * @author xanderume@gmail.com + */ +class Session(val uuid: UUID,val identifier: String,val server: String) { + + @SerializedName("_id") val id: UUID = UUID.randomUUID() + + val login = System.currentTimeMillis() + val sessions = ArrayList() + + var logout: Long = 0L + var lastServer: String? = null + + fun getPlayTime():Long { + + if (!this.hasLoggedOut()) { + return System.currentTimeMillis() - this.login + } + + return this.logout - this.login + } + + fun hasLoggedOut():Boolean { + return this.logout != 0L && this.lastServer != null + } + + fun findCurrentServer():String? { + + if (this.lastServer != null) { + return null + } + + if (this.sessions.isEmpty()) { + return this.server + } + + return this.sessions.lastOrNull()?.to + } + + class SwitchSession(val from: String,val to: String,val time: Long = System.currentTimeMillis()) + + companion object { + + val DATE_FORMAT = SimpleDateFormat("HH:mm") + + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/session/repository/SessionRepository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/session/repository/SessionRepository.kt new file mode 100644 index 0000000..7159037 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/session/repository/SessionRepository.kt @@ -0,0 +1,53 @@ +package cc.fyre.venom.session.repository + +import cc.fyre.venom.database.mongo.Repository +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler +import cc.fyre.venom.session.data.Session +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import org.bson.Document +import java.util.* +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +class SessionRepository(private val instance: VenomAPI) : Repository { + + private val collection: MongoCollection = this.instance.databaseHandler.mongoDB.getCollection("sessions") + + @Deprecated(level = DeprecationLevel.HIDDEN,message = "empty()") + override fun pull(): Map { + return HashMap() + } + + override fun update(value: Session): Boolean { + return this.collection.updateOne(Filters.eq("_id",value.id.toString()),Document("\$set",Document.parse(this.instance.gson.toJson(value))),DatabaseHandler.UPDATE_OPTIONS).wasAcknowledged() + } + + override fun delete(value: Session): Boolean { + return this.collection.deleteOne(Filters.eq("_id",value.id.toString())).wasAcknowledged() + } + + override fun findById(id: UUID): Session? { + + val document = this.collection.find(Filters.eq("_id",id.toString())).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Session::class.java) + } + + fun findAllByPlayer(uuid: UUID):MutableList { + return this.collection.find(Filters.eq("uuid",uuid.toString())).map{this.instance.gson.fromJson(it.toJson(),Session::class.java)}.toMutableList() + } + + fun findMostRecentByPlayer(player: UUID):Session? { + + val document = this.collection.find(Filters.eq("uuid",player.toString())).sort(Filters.eq("login",-1)).limit(1).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Session::class.java) + } +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/tag/TagHandler.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/TagHandler.kt new file mode 100644 index 0000000..df1e1b7 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/TagHandler.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.tag + +import cc.fyre.venom.VenomAPI + +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.listener.TagListener +import cc.fyre.venom.tag.repository.TagRepository +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class TagHandler(private val instance: VenomAPI) { + + val cache = HashMap() + val repository = TagRepository(this.instance) + + init { + this.cache.putAll(this.repository.pull()) + this.instance.databaseHandler.symbiote.addListener(TagListener(this.instance)) + } + + fun findById(id: String):Tag? { + return this.cache[id.toLowerCase()] + } + + companion object { + + const val UPDATE_ID = "TAG_UPDATE" + const val DELETE_ID = "TAG_DELETE" + + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/tag/data/Tag.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/data/Tag.kt new file mode 100644 index 0000000..6b1d787 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/data/Tag.kt @@ -0,0 +1,25 @@ +package cc.fyre.venom.tag.data + +import com.google.gson.annotations.SerializedName + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class Tag(@SerializedName("_id")val id: String) { + + var prefix = "" + var display = "" + var priority: Int = 0 + + fun getDisplayName():String { + return this.display.replace("&","§",false) + } + + fun isReadyForProduction():Boolean { + return this.prefix != "" && this.display != "" + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/tag/listener/TagListener.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/listener/TagListener.kt new file mode 100644 index 0000000..362249c --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/listener/TagListener.kt @@ -0,0 +1,36 @@ +package cc.fyre.venom.tag.listener + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.tag.TagHandler +import cc.fyre.venom.tag.data.Tag +import com.google.gson.JsonObject + +/** + * @project venom + * + * @date 22/04/2020 + * @author xanderume@gmail.com + */ +class TagListener(private val instance: VenomAPI) : ParasiteListener { + + @Parasite(TagHandler.DELETE_ID) + fun onDelete(data: JsonObject) { + this.instance.tagHandler.cache.remove(data["_id"].asString) + } + + @Parasite(TagHandler.UPDATE_ID) + fun onUpdate(data: JsonObject) { + + val rank = this.instance.tagHandler.findById(data["_id"].asString) + + if (rank == null) { + this.instance.tagHandler.cache[data["_id"].asString.toLowerCase()] = this.instance.gson.fromJson(data,Tag::class.java) + return + } + + this.instance.tagHandler.cache.replace(data["_id"].asString.toLowerCase(),this.instance.gson.fromJson(data,Tag::class.java)) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/tag/repository/TagRepository.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/repository/TagRepository.kt new file mode 100644 index 0000000..fc623c8 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/tag/repository/TagRepository.kt @@ -0,0 +1,40 @@ +package cc.fyre.venom.tag.repository + +import cc.fyre.venom.database.mongo.Repository +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.database.DatabaseHandler +import cc.fyre.venom.tag.data.Tag +import com.mongodb.client.MongoCollection +import com.mongodb.client.model.Filters +import org.bson.Document + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +class TagRepository(private val instance: VenomAPI) : Repository { + + private val collection: MongoCollection = this.instance.databaseHandler.mongoDB.getCollection("tags") + + override fun pull():MutableMap { + return this.collection.find().map{this.instance.gson.fromJson(it.toJson(),Tag::class.java)}.associateBy{it.id.toLowerCase()}.toMutableMap() + } + + override fun update(value: Tag): Boolean { + return this.collection.updateOne(Filters.eq("_id",value.id),Document("\$set",Document.parse(this.instance.gson.toJson(value))),DatabaseHandler.UPDATE_OPTIONS).wasAcknowledged() + } + + override fun delete(value: Tag): Boolean { + return this.collection.deleteOne(Filters.eq("_id",value.id)).wasAcknowledged() + } + + override fun findById(id: String):Tag? { + + val document = this.collection.find(Filters.eq("_id",id)).first() ?: return null + + return this.instance.gson.fromJson(document.toJson(),Tag::class.java) + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/util/MojangUtil.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/util/MojangUtil.kt new file mode 100644 index 0000000..86a6b2f --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/util/MojangUtil.kt @@ -0,0 +1,134 @@ +package cc.fyre.venom.util + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.VenomAPI +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import com.squareup.okhttp.Request + +import java.lang.Exception + +import java.util.* +import java.util.concurrent.CompletableFuture +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 26/03/2020 + * @author xanderume@gmail.com + */ +object MojangUtil { + + const val PROFILE_URL = "https://api.mojang.com/users/profiles" + const val SESSION_URL = "https://sessionserver.mojang.com/session/minecraft/profile" + + @JvmStatic + fun getUuid(username: String): UUID? { + + if (VenomAPI.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot request uuid on main thread.") + } + + val request = Request.Builder().url("$PROFILE_URL/minecraft/${username}").build() + val response = VenomAPI.instance.databaseHandler.okHttpClient.newCall(request).execute() ?: return null + + val json = try { + VenomAPI.instance.gson.fromJson(response.body().string(),JsonObject::class.java) + } catch (ex: Exception) { + return null + } + + return UUID.fromString(Regex("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})").replaceFirst(json["id"].asString,"$1-$2-$3-$4-$5")) + } + + @JvmStatic + fun getSkin(uuid: UUID): Pair? { + + if (VenomAPI.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot request skin on main thread.") + } + + val request = Request.Builder().url("$SESSION_URL/$uuid").build() + val response = VenomAPI.instance.databaseHandler.okHttpClient.newCall(request).execute() ?: return null + + val json = try { + VenomAPI.instance.gson.fromJson(response.body().string(),JsonObject::class.java) + } catch (ex: Exception) { + return null + } + + if (!json.has("properties")) { + return null + } + + val properties = json["properties"].asJsonArray + + if (properties.size() == 0) { + return null + } + + val property = properties[0].asJsonObject + + return Pair(property["value"].asString,property["signature"].asString) + } + + @JvmStatic + fun getUsername(uuid: UUID): String? { + + if (VenomAPI.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot request username on main thread.") + } + + val request = Request.Builder().url("$SESSION_URL/$uuid").build() + val response = VenomAPI.instance.databaseHandler.okHttpClient.newCall(request).execute() ?: return null + + val json = try { + VenomAPI.instance.gson.fromJson(response.body().string(),JsonObject::class.java) + } catch (ex: Exception) { + return null + } + + return json["name"].asString + } + + @JvmStatic + fun getUsernameAndUuid(username: String): Pair? { + + if (VenomAPI.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot request username and uuid on main thread.") + } + + val request = Request.Builder().url("${PROFILE_URL}/minecraft/$username").build() + val response = VenomAPI.instance.databaseHandler.okHttpClient.newCall(request).execute() ?: return null + + val json = try { + VenomAPI.instance.gson.fromJson(response.body().string(),JsonObject::class.java) + } catch (ex: Exception) { + return null + } + + return Pair(UUID.fromString(Regex("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})").replaceFirst(json["id"].asString,"$1-$2-$3-$4-$5")),json["name"].asString) + } + + @JvmStatic + fun getUsernameHistory(uuid: UUID): MutableMap? { + + if (VenomAPI.instance.isPrimaryThread()) { + throw IllegalStateException("Cannot request username history on main thread.") + } + + val request = Request.Builder().url("${PROFILE_URL.replace("users","user")}/${uuid.toString().replace("-","")}/names").build() + val response = VenomAPI.instance.databaseHandler.okHttpClient.newCall(request).execute() ?: return null + + val json = try { + VenomAPI.instance.gson.fromJson(response.body().string(),JsonArray::class.java) + } catch (ex: Exception) { + return null + } + + return json.map{it.asJsonObject}.associate{it["name"].asString to (it["changedtoAt"]?.asLong ?: 0L)}.toMutableMap() + } + +} \ No newline at end of file diff --git a/Venom/api/src/main/kotlin/cc/fyre/venom/util/TimeUtil.kt b/Venom/api/src/main/kotlin/cc/fyre/venom/util/TimeUtil.kt new file mode 100644 index 0000000..88e9946 --- /dev/null +++ b/Venom/api/src/main/kotlin/cc/fyre/venom/util/TimeUtil.kt @@ -0,0 +1,129 @@ +package cc.fyre.venom.util + +/** + * @project venom + * + * @date 28/02/2021 + * @author xanderume@gmail.com + */ +import java.text.SimpleDateFormat +import java.util.* +import java.util.concurrent.TimeUnit +import java.util.regex.Pattern +import kotlin.math.abs +import kotlin.math.round + + +object TimeUtil { + + @JvmStatic val HOUR = TimeUnit.HOURS.toMillis(60L) + @JvmStatic val DATE_FORMAT = SimpleDateFormat("MM/dd/yyyy HH:mm") + + @JvmStatic + fun formatIntoFancy(millis: Long):String { + + if (millis >= TimeUnit.SECONDS.toMillis(60L)) { + return this.formatIntoMMSS(millis) + } + + val seconds = millis / 1000.0 + + return "${if (seconds > 0.1) round(10.0 * seconds) / 10.0 else 0.1}s" + } + + @JvmStatic + fun formatIntoHHMMSS(millis: Long): String { + return this.formatIntoMMSS(millis) + } + + @JvmStatic + fun formatIntoMMSS(millis: Long): String { + + var toReturn = (millis/1000) + // Calculate the seconds to display: + val seconds = toReturn % 60 + + toReturn -= seconds + + // Calculate the minutes: + var minutesCount = (toReturn / 60) + val minutes = minutesCount % 60 + + minutesCount -= minutes + + val hours = minutesCount / 60 + + return (if (hours > 0) (if (hours < 10) "0" else "") + hours + ":" else "") + (if (minutes < 10) "0" else "") + minutes + ":" + (if (seconds < 10) "0" else "") + seconds + } + + @JvmStatic + fun formatIntoDetailedString(millis: Long): String? { + + if (millis == 0L) { + return "0 seconds" + } + + val secs = millis / 1000L + + val remainder = secs % 86400 + + val days = secs / 86400 + val hours = remainder / 3600 + val minutes = remainder / 60 - hours * 60 + val seconds = remainder % 3600 - minutes * 60 + + val fDays = if (days > 0) " " + days + " day" + (if (days > 1) "s" else "") else "" + + var fHours = "" + var fMinutes = "" + var fSeconds = "" + + if (days < 1) { + fHours = if (hours > 0) " " + hours + " hour" + (if (hours > 1) "s" else "") else "" + + if (hours < 1) { + fMinutes = if (minutes > 0) " " + minutes + " minute" + (if (minutes > 1) "s" else "") else "" + fSeconds = if (seconds > 0) " " + seconds + " second" + (if (seconds > 1) "s" else "") else "" + } + + } + + return (fDays + fHours + fMinutes + fSeconds).trim { it <= ' ' } + } + + @JvmStatic + fun formatIntoCalendarString(date: Date): String { + return this.DATE_FORMAT.format(date) + } + + @JvmStatic + fun parseTime(time: String): Long { + + if (time.isEmpty() || time.startsWith("perm",true)) { + return 0L + } + + val lifeMatch = arrayOf("y","M","w", "d", "h", "m", "s") + val lifeInterval = intArrayOf(31536000,2592000,604800,86400,3600,60,1) + + var seconds = 0 + + for (i in lifeMatch.indices) { + + val matcher = Pattern.compile("([0-9]*)" + lifeMatch[i]).matcher(time) + + while (matcher.find()) { + seconds += Integer.parseInt(matcher.group(1)) * lifeInterval[i] + } + + } + + return seconds * 1000L + } + + @JvmStatic + fun getTimeBetween(a: Date, b: Date): Long { + return abs(a.time - b.time) + } + +} \ No newline at end of file diff --git a/Venom/build.gradle b/Venom/build.gradle new file mode 100644 index 0000000..d54b515 --- /dev/null +++ b/Venom/build.gradle @@ -0,0 +1,21 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +allprojects { + group = 'cc.fyre.venom' + version = '1.0-SNAPSHOT' +} + +subprojects { + repositories { + mavenLocal() + mavenCentral() + } + + tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' + } + + +} diff --git a/Venom/bukkit/build.gradle b/Venom/bukkit/build.gradle new file mode 100644 index 0000000..53fee98 --- /dev/null +++ b/Venom/bukkit/build.gradle @@ -0,0 +1,69 @@ + +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id "org.jetbrains.kotlin.jvm" version "1.5.10" + id "com.github.johnrengelman.shadow" version "5.2.0" +} + +targetCompatibility = '1.8' +sourceCompatibility = '1.8' + +shadowJar { + classifier = null + minimize() + archiveName = "venom-" + this.name + "-" + this.version + ".jar" +} + +repositories { + mavenLocal() + mavenCentral() + + maven { + url "https://repo.extendedclip.com/content/repositories/placeholderapi/" + } + + flatDir { + dirs 'libs' + } +} + +dependencies { + compile project(':api') + + implementation name: "Fanciful" + implementation name: "Spigot" + implementation name: "Symbiote" + compile name: "Proton" + + compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.10" + compileOnly 'me.clip:placeholderapi:2.10.9' + + compile "org.apache.commons:commons-pool2:2.6.0" + compile "org.apache.commons:commons-lang3:3.7" +} + +apply plugin: "kotlin" +apply plugin: 'maven-publish' + +compileKotlin { + kotlinOptions.jvmTarget = '1.8' +} + +sourceSets { + main.java.srcDirs += 'src/main/kotlin/' +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +publishing { + publications { + shadow(MavenPublication) { publication -> + project.shadow.component(publication) + } + } +} \ No newline at end of file diff --git a/Venom/bukkit/libs/Fanciful.jar b/Venom/bukkit/libs/Fanciful.jar new file mode 100644 index 0000000..9321279 Binary files /dev/null and b/Venom/bukkit/libs/Fanciful.jar differ diff --git a/Venom/bukkit/libs/Proton.jar b/Venom/bukkit/libs/Proton.jar new file mode 100644 index 0000000..c8d7303 Binary files /dev/null and b/Venom/bukkit/libs/Proton.jar differ diff --git a/Venom/bukkit/libs/Spigot.jar b/Venom/bukkit/libs/Spigot.jar new file mode 100644 index 0000000..d5fbc60 Binary files /dev/null and b/Venom/bukkit/libs/Spigot.jar differ diff --git a/Venom/bukkit/libs/Symbiote.jar b/Venom/bukkit/libs/Symbiote.jar new file mode 100644 index 0000000..9b0efc0 Binary files /dev/null and b/Venom/bukkit/libs/Symbiote.jar differ diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/Venom.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/Venom.kt new file mode 100644 index 0000000..0e1d496 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/Venom.kt @@ -0,0 +1,119 @@ +package cc.fyre.venom + +import cc.fyre.proton.Proton +import cc.fyre.proton.command.CommandHandler +import cc.fyre.venom.api.APIListener +import cc.fyre.venom.api.command.* +import cc.fyre.venom.api.placeholder.RankExpansion +import cc.fyre.venom.api.placeholder.ServerExpansion +import cc.fyre.venom.database.mongo.MongoOptions +import cc.fyre.venom.database.mongo.RedisOptions + +import cc.fyre.venom.grant.command.GrantCommand +import cc.fyre.venom.grant.command.GrantHistoryCommand +import cc.fyre.venom.grant.command.GrantsCommand +import cc.fyre.venom.grant.command.GrantHistoryUndoCommand +import cc.fyre.venom.grant.provider.GrantBukkitAdapter +import cc.fyre.venom.permission.PermissionHandler +import cc.fyre.venom.profile.command.* +import cc.fyre.venom.profile.command.ignore.IgnoreCommand +import cc.fyre.venom.profile.command.ignore.IgnoreListCommand +import cc.fyre.venom.profile.command.ignore.IgnoreRemoveCommand +import cc.fyre.venom.profile.provider.UUIDParameterProvider +import cc.fyre.venom.rank.provider.RankParameterProvider +import cc.fyre.venom.punishment.command.* +import cc.fyre.venom.punishment.command.alt.AltsCommand +import cc.fyre.venom.punishment.command.evidence.UnresolvedPunishmentsCommand +import cc.fyre.venom.punishment.command.history.HistoryCommand +import cc.fyre.venom.punishment.command.history.StaffHistoryCommand +import cc.fyre.venom.punishment.listener.EvidenceListener +import cc.fyre.venom.punishment.listener.MuteListener +import cc.fyre.venom.punishment.parasite.PunishmentListener +import cc.fyre.venom.rank.command.RankCommand +import cc.fyre.venom.rank.command.RankScanCommand +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.server.ServerHandler +import cc.fyre.venom.tag.command.TagCommand +import cc.fyre.venom.tag.command.TagEditorCommand + +import org.bukkit.plugin.java.JavaPlugin +import java.util.* + +/** + * @project venom + * + * @date 18/03/2020 + * @author xanderume@gmail.com + */ + +/* +* TODO: +* Rewrite all menu's they are god awful +* */ + +class Venom : JavaPlugin() { + + lateinit var api: VenomAPI + + lateinit var serverHandler: ServerHandler + lateinit var permissionHandler: PermissionHandler + + override fun onEnable() { + instance = this + + this.saveDefaultConfig() + + this.api = VenomAPI(this.getMongoOptions(),this.getRedisOptions()) + + this.serverHandler = ServerHandler(this) + this.permissionHandler = PermissionHandler(this) + + Proton.getInstance().commandHandler.registerAll(this); + + Proton.getInstance().commandHandler.registerParameterType(Rank::class.java,RankParameterProvider()) + Proton.getInstance().commandHandler.registerParameterType(UUID::class.java,UUIDParameterProvider()) + + this.api.networkHandler.server = this.serverHandler.server + this.api.grantHandler.setProvider(GrantBukkitAdapter(this)) + this.api.databaseHandler.symbiote.addListener(PunishmentListener(this)) + + this.server.pluginManager.registerEvents(APIListener(this),this) + this.server.pluginManager.registerEvents(MuteListener(this),this) + this.server.pluginManager.registerEvents(EvidenceListener(this),this) + + if (this.server.pluginManager.getPlugin("PlaceholderAPI") != null) { + RankExpansion.register() + ServerExpansion.register() + } + + this.server.scheduler.runTaskTimerAsynchronously(this,this.api.grantHandler.expiryService,40L,40L) + } + + private fun getRedisOptions():RedisOptions { + + val password = this.config.getString("redis.pass") + + return RedisOptions(this.config.getString("redis.host"),this.config.getInt("redis.port"),if (password == "") null else password) + } + + private fun getMongoOptions(): MongoOptions { + + val username = this.config.getString("mongo.user") + val password = this.config.getString("mongo.pass") + val authDatabase = this.config.getString("mongo.authDatabase") + + return MongoOptions(this.config.getString("mongo.host"),this.config.getInt("mongo.port"),if (username == "") null else username,if (password == "") null else password,this.config.getString("mongo.database"),if (authDatabase == "") null else authDatabase) + } + + override fun onDisable() { + this.serverHandler.dispose() + this.api.databaseHandler.dispose() + } + + companion object { + + lateinit var instance: Venom + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/APIListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/APIListener.kt new file mode 100644 index 0000000..e9e7174 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/APIListener.kt @@ -0,0 +1,182 @@ +package cc.fyre.venom.api + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.profile.event.ProfileLoadEvent +import cc.fyre.venom.profile.exception.ProfileLoadException +import cc.fyre.venom.profile.data.Profile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.parasite.PunishmentListener +import cc.fyre.venom.util.PlayerUtil +import cc.fyre.venom.util.TimeUtil +import com.google.gson.JsonObject +import com.mongodb.client.model.Filters +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.* + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class APIListener(private val instance: Venom) : Listener { + + @EventHandler(priority = EventPriority.LOWEST) + private fun onPreLogin(event: AsyncPlayerPreLoginEvent) { + + val player = this.instance.server.getPlayer(event.uniqueId) + + if (player != null) { + event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,"You logged in too fast! Please relog.") + return + } + + val document = this.instance.api.profileHandler.repository.collection.find(Filters.eq("_id",event.uniqueId.toString())).first() + + val profile: Profile = if (document == null) Profile(event.uniqueId) else { + + try { + this.instance.api.gson.fromJson(document.toJson(),Profile::class.java) + } catch (ex: Exception) { + event.loginResult = AsyncPlayerPreLoginEvent.Result.KICK_OTHER + event.kickMessage = "${ChatColor.RED}There was an issue contacting the API, please try again later." + throw ProfileLoadException(event.uniqueId,ex.message!!) + } + + } + + val identifier = event.address.hostAddress + + val updateName = profile.name != event.name || !this.instance.api.profileHandler.isCached(event.uniqueId) + val updateAddress = !profile.identifiers.contains(identifier) + + if (updateName || updateAddress) { + + if (updateAddress) { + profile.identifiers.add(identifier) + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(this.instance) { + + if (updateName) { + + val payload = JsonObject() + + payload.addProperty("_id",event.uniqueId.toString()) + payload.addProperty("name",event.name) + + this.instance.api.profileHandler.updateId(event.uniqueId,event.name) + this.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Profile.NAME_UPDATE_ID,payload)) + } + + if (updateAddress) { + this.instance.api.profileHandler.repository.update(profile) + } + + } + + } + + profile.name = event.name + + val punishments = this.instance.api.punishmentHandler.repository.findByVictimOrIdentifier(event.uniqueId,profile.identifiers) + + if (punishments.isNotEmpty()) { + + val punishment = this.instance.api.punishmentHandler.repository.findMostRecentPunishment(punishments,arrayListOf(Punishment.Type.BLACKLIST,Punishment.Type.BAN)) + + if (punishment != null) { + event.loginResult = AsyncPlayerPreLoginEvent.Result.KICK_BANNED + event.kickMessage = PunishmentListener.getPunishmentKickMessage(event.uniqueId,punishment,false) + return + } + + } + + this.instance.api.punishmentHandler.mutes[profile.id] = punishments.filter{it.type == Punishment.Type.MUTE || it.type == Punishment.Type.GHOST_MUTE}.toHashSet() + + this.instance.api.profileHandler.cache[profile.id] = profile + + val grants = this.instance.api.grantHandler.repository.findAllByPlayer(event.uniqueId) + + this.instance.api.grantHandler.active[profile.id] = ArrayList() + this.instance.api.grantHandler.active[profile.id]!!.addAll(grants.filter{it.isActive()}) + + this.instance.api.grantHandler.setGlobal(event.uniqueId,this.instance.serverHandler.server,grants) + this.instance.api.grantHandler.setScoped(event.uniqueId,this.instance.serverHandler.server,grants) + this.instance.api.grantHandler.setSubscription(event.uniqueId,grants) + + this.instance.server.pluginManager.callEvent(ProfileLoadEvent(profile)) + } + + @EventHandler(priority = EventPriority.LOWEST) + private fun onLogin(event: PlayerJoinEvent) { + + if (!Venom.instance.serverHandler.server.isHub()) { + return + } + + val subscription = this.instance.api.grantHandler.findSubscriptionGrant(event.player.uniqueId,this.instance.api.grantHandler.active[event.player.uniqueId] ?: arrayListOf()) ?: return + + val rank = subscription.getRank() ?: return + + event.player.sendMessage("${ChatColor.AQUA}You have ${ChatColor.WHITE}${TimeUtil.formatIntoDetailedString(subscription.getRemaining())}${ChatColor.AQUA} left on your ${rank.getDisplayName()}${ChatColor.AQUA} subscription!") + } + + @EventHandler(priority = EventPriority.MONITOR,ignoreCancelled = true) + private fun onPlayerQuit(event: PlayerQuitEvent) { + this.instance.api.grantHandler.active.remove(event.player.uniqueId) + this.instance.api.profileHandler.cache.remove(event.player.uniqueId) + this.instance.api.punishmentHandler.mutes.remove(event.player.uniqueId) + } + + @EventHandler(priority = EventPriority.MONITOR) + private fun onFilterChat(event: AsyncPlayerChatEvent) { + event.recipients.removeIf{ + + val foundProfile = Venom.instance.api.profileHandler.findById(it.uniqueId) + + return@removeIf foundProfile != null && (!foundProfile.settings.viewGlobalChat || foundProfile.ignore.contains(event.player.uniqueId)) + } + + } + + @EventHandler(priority = EventPriority.HIGHEST) + private fun onAsyncPlayerChat(event: AsyncPlayerChatEvent) { + + if (event.isCancelled) { + return + } + + if (!this.instance.serverHandler.chatFormatEnabled) { + return + } + + + val profile = this.instance.api.profileHandler.findById(event.player.uniqueId) + + val color = try { + ChatColor.valueOf(profile?.chatColor ?: "WHITE") + } catch (ex: Exception) { + ChatColor.WHITE + } + + val prefix = this.instance.api.grantHandler.findBestRank(event.player.uniqueId).prefix + + val message = ChatColor.translateAlternateColorCodes('&',this.instance.serverHandler.chatFormatText + .replace("{rank}",prefix) + .replace("{prefix}",profile?.findTagPrefix() ?: "") + .replace("{name}","${ChatColor.getLastColors(prefix) ?: ChatColor.WHITE.toString()}${event.player.name}") + .replace("{message}","$color${event.message}")) + + event.isCancelled = true + event.recipients.forEach{it.sendMessage(message)} + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/FindCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/FindCommand.kt new file mode 100644 index 0000000..23569ec --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/FindCommand.kt @@ -0,0 +1,35 @@ +package cc.fyre.venom.api.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.util.PlayerUtil +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import java.util.* + +/** + * @project venom + * + * @date 14/04/2020 + * @author xanderume@gmail.com + */ +object FindCommand { + + @JvmStatic + @Command(names = ["find","whereis"],hidden = true,async = true,permission = "command.find",description = "See the server an user is currently playing on.") + fun execute(sender: CommandSender,@Parameter(name = "player")uuid: UUID) { + + val server = VenomAPI.instance.networkHandler.findServer(uuid) + val displayName = PlayerUtil.getDisplayName(uuid,Venom.instance.serverHandler.server) + + if (server == null) { + sender.sendMessage("$displayName${ChatColor.RED} is currently not on the network.") + return + } + + sender.sendMessage("$displayName${ChatColor.GREEN} is currently on ${ChatColor.YELLOW}${server.id}${ChatColor.GREEN}.") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/ListCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/ListCommand.kt new file mode 100644 index 0000000..e97f70f --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/ListCommand.kt @@ -0,0 +1,58 @@ +package cc.fyre.venom.api.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 04/04/2020 + * @author xanderume@gmail.com + */ +object ListCommand { + + @JvmStatic + @Command(names = ["list", "who", "players"],description = "See a list of online players.",permission = "") + fun execute(sender: CommandSender) { + sender.sendMessage(StringUtils.join(Venom.instance.api.rankHandler.cache.values.filter{this.canSee(sender,it)}.sortedBy{it.priority}.reversed().map{it.getDisplayName()},"${ChatColor.WHITE}, ")) + + val players = Venom.instance.server.onlinePlayers.filter{if (sender is Player) return@filter sender.canSee(it) else return@filter true}.sortedBy{ + + var priority = Venom.instance.api.grantHandler.findBestRank(it.uniqueId).priority + + if (Venom.instance.api.grantHandler.findSubscription(it.uniqueId) != null) { + priority += 1 + } + + return@sortedBy priority + }.reversed().map{this.formatName(it,Venom.instance.api.grantHandler.findBestRank(it.uniqueId))} + + sender.sendMessage("${ChatColor.WHITE}(${players.size}/${Venom.instance.server.maxPlayers}) [${StringUtils.join(players,"${ChatColor.WHITE}, ")}${ChatColor.WHITE}]") + } + + private fun canSee(sender: CommandSender,rank: Rank):Boolean { + + if (rank.isSubscription()) { + return false + } + + if (sender.isOp || !rank.isHidden()) { + return true + } + + return sender.hasPermission("grant.rank.${rank.id}") + } + + private fun formatName(player: Player,rank: Rank):String { + + val subscription = Venom.instance.api.grantHandler.findSubscription(player.uniqueId) + + return ChatColor.translateAlternateColorCodes('&',"${(subscription?.prefix ?: "").replace("&8[","").replace("&8]","")}${rank.color.replace("&","§",false)}${player.name}") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/SeenCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/SeenCommand.kt new file mode 100644 index 0000000..e85f8cf --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/SeenCommand.kt @@ -0,0 +1,44 @@ +package cc.fyre.venom.api.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.util.PlayerUtil +import cc.fyre.venom.util.TimeUtil +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import java.util.* + +/** + * @project venom + * + * @date 13/08/2020 + * @author xanderume@gmail.com + */ +object SeenCommand { + + @JvmStatic + @Command(names = ["seen","lastonline"],async = true,permission = "command.seen") + fun execute(sender: CommandSender,@Parameter(name = "player")uuid: UUID) { + + val session = Venom.instance.api.sessionHandler.repository.findMostRecentByPlayer(uuid) + + if (session == null) { + sender.sendMessage("${ChatColor.RED}${Venom.instance.api.profileHandler.findName(uuid)} has never joined the server.") + return + } + + val server = session.findCurrentServer() + + val displayName = PlayerUtil.getDisplayName(uuid,Venom.instance.serverHandler.server) + + if (server != null) { + sender.sendMessage("$displayName${ChatColor.YELLOW} is currently ${ChatColor.GREEN}online ${ChatColor.YELLOW}on ${ChatColor.RED}${server}${ChatColor.YELLOW}.") + return + } + + sender.sendMessage("${displayName}${ChatColor.YELLOW} was last seen on ${ChatColor.RED}${session.lastServer ?: "Unknown"} ${ChatColor.LIGHT_PURPLE}${TimeUtil.formatIntoDetailedString(System.currentTimeMillis() - session.logout)} ${ChatColor.YELLOW}ago.") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/SessionCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/SessionCommand.kt new file mode 100644 index 0000000..28c0fc6 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/command/SessionCommand.kt @@ -0,0 +1,35 @@ +package cc.fyre.venom.api.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.api.menu.SessionMenu +import cc.fyre.venom.util.PlayerUtil +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 13/08/2020 + * @author xanderume@gmail.com + */ +object SessionCommand { + + @JvmStatic + @Command(names = ["sessions","session"],async = true,permission = "command.sessions",description = "view a user's sessions.") + fun execute(player: Player,@Parameter(name = "player")uuid: UUID) { + + val sessions = Venom.instance.api.sessionHandler.repository.findAllByPlayer(uuid) + val displayName = PlayerUtil.getDisplayName(uuid,Venom.instance.serverHandler.server) + + if (sessions.isEmpty()) { + player.sendMessage("$displayName${ChatColor.RED} has no sessions!") + return + } + + SessionMenu(uuid,displayName,sessions).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/menu/SessionMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/menu/SessionMenu.kt new file mode 100644 index 0000000..1a67225 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/menu/SessionMenu.kt @@ -0,0 +1,27 @@ +package cc.fyre.venom.api.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.api.menu.button.SessionButton +import cc.fyre.venom.session.data.Session + +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 13/08/2020 + * @author xanderume@gmail.com + */ +class SessionMenu(private val id: UUID,private val displayName: String,private val sessions: Collection) : PaginatedMenu() { + + override fun getPrePaginatedTitle(player: Player): String { + return "Sessions - ${this.displayName}" + } + + override fun getAllPagesButtons(player: Player):MutableMap { + return this.sessions.sortedByDescending{it.login}.withIndex().associate{it.index to SessionButton(it.value)}.toMutableMap() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/menu/button/SessionButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/menu/button/SessionButton.kt new file mode 100644 index 0000000..4873b21 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/menu/button/SessionButton.kt @@ -0,0 +1,58 @@ +package cc.fyre.venom.api.menu.button + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.session.data.Session +import cc.fyre.venom.util.TimeUtil + +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 13/08/2020 + * @author xanderume@gmail.com + */ +class SessionButton(private val session: Session) : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.session.login))}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.ANVIL + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.YELLOW}Server: ${ChatColor.RED}${this.session.server}") + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + + if (this.session.sessions.isNotEmpty()) { + toReturn.add("${ChatColor.RED}${ChatColor.BOLD}Switch") + toReturn.add(" ") + this.session.sessions.forEach{toReturn.add("${ChatColor.RED}${it.from}${ChatColor.YELLOW} to ${ChatColor.GREEN}${it.to} ${ChatColor.GRAY}[${Session.DATE_FORMAT.format(it.time)}]")} + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + } + + + if (this.session.hasLoggedOut()) { + toReturn.add("${ChatColor.RED}${ChatColor.BOLD}Logout") + toReturn.add(" ") + toReturn.add("${ChatColor.YELLOW}Server: ${ChatColor.RED}${this.session.lastServer!!}") + toReturn.add(" ") + toReturn.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.session.logout))}") + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + } + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/placeholder/RankExpansion.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/placeholder/RankExpansion.kt new file mode 100644 index 0000000..e98c1e0 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/placeholder/RankExpansion.kt @@ -0,0 +1,70 @@ +package cc.fyre.venom.api.placeholder + +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank + +import me.clip.placeholderapi.expansion.PlaceholderExpansion +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 04/26/21 + * @author xanderume@gmail.com + */ +object RankExpansion : PlaceholderExpansion() { + + override fun persist(): Boolean { + return true + } + + override fun getIdentifier(): String { + return "venom_rank" + } + + override fun getAuthor(): String { + return Venom.instance.description.authors[0] + } + + override fun getVersion(): String { + return Venom.instance.description.version + } + + override fun onPlaceholderRequest(player: Player?,parameter: String): String? { + + if (player == null) { + return "" + } + + val split = parameter.split("_") + + if (split.isEmpty() || split.size < 2) { + return null + } + + val rank = when { + split[0].equals("best",true) -> Venom.instance.api.grantHandler.findBestRank(player.uniqueId) + split[0].equals("scoped",true) -> Venom.instance.api.grantHandler.findScopedRank(player.uniqueId) + split[0].equals("global",true) -> Venom.instance.api.grantHandler.findGlobalRank(player.uniqueId) + else -> null + } ?: return null + + if (split[1].equals("name",true)) { + return rank.id + } + + if (split[1].equals("color",true)) { + return rank.color + } + + if (split[1].equals("displayName",true)) { + return rank.getDisplayName() + } + + if (split[1].equals("priority",true) || parameter.equals("weight",true)) { + return rank.priority.toString() + } + + return null + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/placeholder/ServerExpansion.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/placeholder/ServerExpansion.kt new file mode 100644 index 0000000..e2e354f --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/api/placeholder/ServerExpansion.kt @@ -0,0 +1,63 @@ +package cc.fyre.venom.api.placeholder + +import cc.fyre.venom.Venom +import me.clip.placeholderapi.expansion.PlaceholderExpansion +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 04/26/21 + * @author xanderume@gmail.com + */ +object ServerExpansion : PlaceholderExpansion() { + + override fun persist(): Boolean { + return true + } + + override fun getIdentifier(): String { + return "venom_servers" + } + + override fun getAuthor(): String { + return Venom.instance.description.authors[0] + } + + override fun getVersion(): String { + return Venom.instance.description.version + } + + override fun onPlaceholderRequest(player: Player?,parameter: String): String? { + + if (player == null) { + return "" + } + + val split = parameter.split("_") + + if (split.isEmpty() || split.size < 2) { + return null + } + + val server = Venom.instance.api.networkHandler.findServerById(split[0]) ?: return null + + if (split[1].equals("status",true)) { + return server.status.name.toLowerCase() + } + + if (split[1].equals("statusColored",true)) { + return "${server.status.color}${server.status.name.toLowerCase()}" + } + + if (split[1].equals("players",true)) { + return server.onlinePlayers.size.toString() + } + + if (split[1].equals("maxPlayers",true)) { + return server.maximumPlayers.toString() + } + + return null + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantCommand.kt new file mode 100644 index 0000000..7feb42d --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantCommand.kt @@ -0,0 +1,92 @@ +package cc.fyre.venom.grant.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.grant.menu.apply.GrantMenu +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.rank.provider.RankParameterProvider +import cc.fyre.venom.util.TimeUtil + + +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + + +/** + * @project venom + * + * @date 30/03/2020 + * @author xanderume@gmail.com + */ +object GrantCommand { + + @JvmStatic + @Command(names = ["grant"],async = true,hidden = true,permission = "command.grant",description = "Add a grant to a user!") + fun execute(sender: CommandSender, + @Parameter(name = "player",wildcard = false,defaultValue = "defaultValue")uuidInput: String, + @Parameter(name = "rank",wildcard = false,defaultValue = "defaultValue")rankInput: String, + @Parameter(name = "duration",wildcard = false,defaultValue = "perm")duration: Long, + @Parameter(name = "scopes",wildcard = false,defaultValue = "defaultValue")scopes: String, + @Parameter(name = "reason",wildcard = true,defaultValue = "defaultValue")reason: String + ) { + + if (uuidInput == "defaultValue") { + sender.sendMessage(this.getUsage(sender)) + return + } + + val profile = ProfileUtil.getMojangProfileQuery(uuidInput) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $uuidInput in mojang database.") + return + } + + if (sender is Player) { + GrantMenu(profile).openMenu(sender) + return + } + + if (rankInput == "defaultValue") { + sender.sendMessage(this.getUsage(sender)) + return + } + + val rank = RankParameterProvider().transform(sender,rankInput) ?: return + + val finalScopes = if (scopes == "defaultValue" || scopes.equals("global",true)) { + mutableSetOf() + } else if (scopes.contains(",")) { + scopes.split(",").mapNotNull{Venom.instance.api.networkHandler.findGroupById(it)}.toSet() + } else { + + val group = VenomAPI.instance.networkHandler.findGroupById(scopes) + + if (group == null) mutableSetOf() else mutableSetOf(group) + } + + if (reason == "defaultValue") { + sender.sendMessage(this.getUsage(sender)) + return + } + + Venom.instance.api.grantHandler.grant(rank,profile.id,ProfileHandler.CONSOLE_UUID,reason,finalScopes,duration) + + sender.sendMessage("${ChatColor.GREEN}Granted ${ChatColor.WHITE}${profile.displayName} ${rank.getDisplayName()}${ChatColor.GREEN} rank${if (duration == 0L) "" else " for ${TimeUtil.formatIntoDetailedString(duration)}"}.") + } + + private fun getUsage(commandSender: CommandSender):String { + + if (commandSender is Player) { + return "${ChatColor.RED}Usage: /grant " + } + + return "${ChatColor.RED}Usage: /grant " + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantHistoryCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantHistoryCommand.kt new file mode 100644 index 0000000..e29c283 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantHistoryCommand.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.grant.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom + +import cc.fyre.venom.grant.menu.view.StaffGrantsMenu + +import cc.fyre.venom.profile.util.ProfileUtil + +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +object GrantHistoryCommand { + + @JvmStatic + @Command(names = ["granthistory"],async = true,hidden = true,permission = "command.granthistory",description = "Staff grant history.") + fun execute(player: Player,@Parameter(name = "player")source: String) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val grants = Venom.instance.api.grantHandler.repository.findAllBySenderOrRemover(profile.id) + + if (grants.isEmpty()) { + player.sendMessage("${profile.displayName}${ChatColor.RED} has not granted any ranks.") + return + } + + StaffGrantsMenu(grants,profile).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantHistoryUndoCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantHistoryUndoCommand.kt new file mode 100644 index 0000000..6e5d32e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantHistoryUndoCommand.kt @@ -0,0 +1,39 @@ +package cc.fyre.venom.grant.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.VenomAPI +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 31/01/2021 + * @author xanderume@gmail.com + */ +object GrantHistoryUndoCommand { + + @JvmStatic + @Command(names = ["granthistoryundo"],async = true,hidden = true,permission = "op") + fun execute(sender: CommandSender, @Parameter(name = "player")uuid: UUID, @Parameter(name = "timespan")time: Long) { + + if (sender is Player) { + sender.sendMessage("${ChatColor.RED}This command cannot be executed in-game.") + return + } + + var count = 0 + + for (grant in VenomAPI.instance.grantHandler.repository.findAllBySender(uuid).filter{it.getTimeAgo() <= time}) { + count++ + VenomAPI.instance.grantHandler.repository.delete(grant) + } + + sender.sendMessage("${ChatColor.GREEN}Deleted ${ChatColor.RED}$count${ChatColor.GREEN} grants.") + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantsCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantsCommand.kt new file mode 100644 index 0000000..2e5ae14 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/command/GrantsCommand.kt @@ -0,0 +1,42 @@ +package cc.fyre.venom.grant.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.menu.view.GrantsMenu + +import cc.fyre.venom.profile.util.ProfileUtil + +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +object GrantsCommand { + + @JvmStatic + @Command(names = ["grants"],async = true,hidden = true,permission = "command.grants",description = "View a user's grants!") + fun execute(player: Player,@Parameter(name = "player")source: String) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val grants = Venom.instance.api.grantHandler.repository.findAllByPlayer(profile.id) + + if (grants.isEmpty()) { + player.sendMessage("${profile.displayName}${ChatColor.RED} has no grants.") + return + } + + GrantsMenu(grants,profile).openMenu(player) + } + +} \ No newline at end of file diff --git a/stark/bukkit/src/main/kotlin/net/evilblock/stark/profile/grant/event/GrantRemovedEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantApplyEvent.kt similarity index 53% rename from stark/bukkit/src/main/kotlin/net/evilblock/stark/profile/grant/event/GrantRemovedEvent.kt rename to Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantApplyEvent.kt index 1f40e5e..4f63428 100644 --- a/stark/bukkit/src/main/kotlin/net/evilblock/stark/profile/grant/event/GrantRemovedEvent.kt +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantApplyEvent.kt @@ -1,18 +1,25 @@ -package net.evilblock.stark.profile.grant.event - -import net.evilblock.stark.core.profile.grant.ProfileGrant -import org.bukkit.entity.Player -import org.bukkit.event.Event -import org.bukkit.event.HandlerList - -class GrantRemovedEvent(val player: Player, val grant: ProfileGrant) : Event() { - - companion object { - @JvmStatic val handlerList = HandlerList() - } - - override fun getHandlers(): HandlerList { - return handlerList - } - +package cc.fyre.venom.grant.event + +import cc.fyre.venom.grant.data.Grant + +import org.bukkit.entity.Player +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantApplyEvent(val player: Player,val grant: Grant) : Event() { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + } \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantExpireEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantExpireEvent.kt new file mode 100644 index 0000000..b7ddaa8 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantExpireEvent.kt @@ -0,0 +1,24 @@ +package cc.fyre.venom.grant.event + +import cc.fyre.venom.grant.data.Grant +import org.bukkit.entity.Player +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantExpireEvent(val player: Player, val grant: Grant) : Event() { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantRemoveEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantRemoveEvent.kt new file mode 100644 index 0000000..9fb6267 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/event/GrantRemoveEvent.kt @@ -0,0 +1,24 @@ +package cc.fyre.venom.grant.event + +import cc.fyre.venom.grant.data.Grant +import org.bukkit.entity.Player +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantRemoveEvent(val player: Player, val grant: Grant) : Event() { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/GrantMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/GrantMenu.kt new file mode 100644 index 0000000..70e4332 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/GrantMenu.kt @@ -0,0 +1,31 @@ +package cc.fyre.venom.grant.menu.apply + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.menu.apply.element.GrantElement +import cc.fyre.venom.profile.mojang.MojangProfile +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 30/03/2020 + * @author xanderume@gmail.com + */ +class GrantMenu(private val mojangProfile: MojangProfile) : Menu() { + + override fun getTitle(player: Player): String { + return "${ChatColor.GOLD}${ChatColor.BOLD}Choose a Rank." + } + + override fun getButtons(player: Player): MutableMap { + return Venom.instance.api.rankHandler.cache.values + .filter{!it.isDefault() && Venom.instance.api.grantHandler.findBestRank(player.uniqueId).priority >= it.priority} + .sortedByDescending{it.priority} + .withIndex() + .associate{it.index to GrantElement(it.value,this.mojangProfile)}.toMutableMap() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/ScopeMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/ScopeMenu.kt new file mode 100644 index 0000000..40caa68 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/ScopeMenu.kt @@ -0,0 +1,46 @@ +package cc.fyre.venom.grant.menu.apply + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.grant.menu.apply.element.FinishElement +import cc.fyre.venom.grant.menu.apply.element.ScopeElement +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.rank.data.Rank +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 30/03/2020 + * @author xanderume@gmail.com + */ +class ScopeMenu(private val rank: Rank,private val reason: String,private val duration: Long,private val mojangProfile: MojangProfile) : Menu() { + + private val scopes = HashSet() + + override fun size(player: Player): Int { + return 5*9 + } + + override fun getTitle(player: Player): String { + return "${ChatColor.YELLOW}${ChatColor.BOLD}Select Scopes." + } + + override fun getButtons(p0: Player?): MutableMap { + + var i = 5*9 + + val toReturn = HashMap() + + VenomAPI.instance.networkHandler.groups.filter{!this.scopes.contains(it.id)}.sortedByDescending{it.id}.forEach{toReturn[toReturn.size] = ScopeElement(it.id,this.scopes)} + + toReturn[(5*9) / 2] = FinishElement(this.rank,this.duration,this.reason,this.scopes,this.mojangProfile) + + this.scopes.sortedByDescending{it}.forEach{toReturn[--i] = ScopeElement(it,this.scopes)} + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/FinishElement.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/FinishElement.kt new file mode 100644 index 0000000..f5e1517 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/FinishElement.kt @@ -0,0 +1,51 @@ +package cc.fyre.venom.grant.menu.apply.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 30/03/2020 + * @author xanderume@gmail.com + */ +class FinishElement(private val rank: Rank,private val duration: Long,private val reason: String,private val scopes: MutableSet,private val mojangProfile: MojangProfile) : Button() { + + override fun getMaterial(p0: Player?): Material { + return Material.DIAMOND_SWORD + } + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}Grant ${this.mojangProfile.displayName} ${this.rank.getDisplayName()}${ChatColor.GOLD}" + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf( + "${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}", + "${ChatColor.YELLOW}Scopes: ${ChatColor.RED}${if (this.scopes.isEmpty()) "Global" else StringUtils.join(this.scopes,", ")}", + "${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.reason}", + "${ChatColor.YELLOW}Duration: ${ChatColor.RED}${if (this.duration == 0L) "Permanent" else TimeUtil.formatIntoDetailedString(this.duration)}", + "${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}" + ) + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.grantHandler.grant(this.rank,this.mojangProfile.id,player.uniqueId,this.reason,this.scopes.mapNotNull{VenomAPI.instance.networkHandler.findGroupById(it)}.toSet(),this.duration) + } + + player.closeInventory() + player.sendMessage("${ChatColor.GREEN}Granted ${ChatColor.WHITE}${this.mojangProfile.displayName} ${this.rank.getDisplayName()}${ChatColor.GREEN} rank${if (this.duration == 0L) "" else " for ${TimeUtil.formatIntoDetailedString(this.duration)}"}.") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/GrantElement.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/GrantElement.kt new file mode 100644 index 0000000..3acda77 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/GrantElement.kt @@ -0,0 +1,44 @@ +package cc.fyre.venom.grant.menu.apply.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.prompt.GrantReasonPrompt +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.util.ColorUtil +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 30/03/2020 + * @author xanderume@gmail.com + */ +class GrantElement(private val rank: Rank,private val mojangProfile: MojangProfile) : Button() { + + override fun getName(p0: Player?): String { + return this.rank.getDisplayName() + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + return ArrayList() + } + + override fun getDamageValue(player: Player?): Byte { + return ColorUtil.findDyeColorByChar(this.rank.color[1]).woolData + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType?) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(GrantReasonPrompt(this.rank,this.mojangProfile)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/ScopeElement.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/ScopeElement.kt new file mode 100644 index 0000000..0c24d83 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/apply/element/ScopeElement.kt @@ -0,0 +1,44 @@ +package cc.fyre.venom.grant.menu.apply.element + +import cc.fyre.proton.menu.Button +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 30/03/2020 + * @author xanderume@gmail.com + */ +class ScopeElement(private val scope: String,private val scopes: HashSet) : Button() { + + override fun getName(p0: Player?): String { + return "${(if (this.scopes.contains(this.scope)) ChatColor.GREEN.toString() else ChatColor.RED.toString())}${this.scope}" + } + + override fun getMaterial(p0: Player?): Material { + return if (this.scopes.contains(this.scope)) Material.WOOL else Material.BEDROCK + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun getDamageValue(player: Player?): Byte { + return (if (this.scopes.contains(this.scope)) DyeColor.GREEN.woolData else 0) + } + + override fun clicked(player: Player?,slot: Int,clickType: ClickType?) { + + if (this.scopes.contains(this.scope)) { + this.scopes.remove(this.scope) + return + } + + this.scopes.add(this.scope) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/GrantsMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/GrantsMenu.kt new file mode 100644 index 0000000..36a74c7 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/GrantsMenu.kt @@ -0,0 +1,25 @@ +package cc.fyre.venom.grant.menu.view + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.menu.view.element.ViewButton +import cc.fyre.venom.profile.mojang.MojangProfile +import org.bukkit.entity.Player +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantsMenu(private val grants: Set,private val mojangProfile: MojangProfile) : PaginatedMenu() { + + override fun getPrePaginatedTitle(player: Player): String { + return this.mojangProfile.displayName + } + + override fun getAllPagesButtons(player: Player): MutableMap { + return this.grants.filter{player.hasPermission("grant.rank.${it.rank}")}.sortedByDescending{it.created}.withIndex().associate{it.index to ViewButton(it.value)}.toMutableMap() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/StaffGrantsMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/StaffGrantsMenu.kt new file mode 100644 index 0000000..fe55544 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/StaffGrantsMenu.kt @@ -0,0 +1,20 @@ +package cc.fyre.venom.grant.menu.view + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.menu.view.element.ViewStaffButton +import cc.fyre.venom.profile.mojang.MojangProfile +import org.bukkit.entity.Player + +class StaffGrantsMenu(private val grants: Set, private val mojangProfile: MojangProfile) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return this.mojangProfile.displayName + } + + override fun getAllPagesButtons(player: Player): MutableMap { + return this.grants.filter{player.hasPermission("grant.rank.${it.rank}")}.sortedByDescending{it.created}.withIndex().associate{it.index to ViewStaffButton(this.mojangProfile.id,it.value)}.toMutableMap() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/element/ViewButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/element/ViewButton.kt new file mode 100644 index 0000000..74f47d9 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/element/ViewButton.kt @@ -0,0 +1,95 @@ +package cc.fyre.venom.grant.menu.view.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.prompt.GrantRemoveReasonPrompt +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class ViewButton(private val grant: Grant) : Button() { + + private val rank = this.grant.getRank() + private val voided = this.grant.isVoided() + private val removed = this.grant.isRemoved() + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.grant.created))}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.grant.sender)}") + toReturn.add("${ChatColor.YELLOW}Rank: ${ChatColor.RED}${this.rank?.getDisplayName() ?: this.rank}") + toReturn.add("${ChatColor.YELLOW}Scopes: ${ChatColor.RED}${if (this.grant.isGlobal()) "Global" else StringUtils.join(this.grant.scopes,", ")}") + toReturn.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.grant.reason}") + + if (!this.grant.isPermanent()) { + toReturn.add("${ChatColor.YELLOW}Duration: ${ChatColor.RED}${TimeUtil.formatIntoDetailedString(this.grant.duration)}") + } + + when { + this.removed -> { + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.RED}${ChatColor.BOLD}Removed") + toReturn.add(" ") + + toReturn.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.grant.remover!!)}") + toReturn.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.grant.removedReason}") + toReturn.add(" ") + toReturn.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.grant.removed!!))}") + } this.voided -> { + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.RED}${ChatColor.BOLD}Expired") + toReturn.add(" ") + toReturn.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.grant.getVoidedAt()))}") + } else -> { + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.RED}Click to remove grant.") + } + + } + + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + + return toReturn + } + + override fun getDamageValue(player: Player?): Byte { + return (if (this.removed) DyeColor.RED else if (this.voided) DyeColor.ORANGE else DyeColor.GREEN).woolData + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + + if (this.voided || this.removed) { + return + } + + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(GrantRemoveReasonPrompt(this.grant)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/element/ViewStaffButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/element/ViewStaffButton.kt new file mode 100644 index 0000000..7fd6871 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/menu/view/element/ViewStaffButton.kt @@ -0,0 +1,98 @@ +package cc.fyre.venom.grant.menu.view.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.prompt.GrantRemoveReasonPrompt + +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +import java.util.* +import kotlin.collections.ArrayList + +class ViewStaffButton(private val who: UUID,private val grant: Grant) : Button() { + + private val rank = this.grant.getRank() + private val voided = this.grant.isVoided() + private val removed = this.grant.isRemoved() + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.grant.created))}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + + var name = Venom.instance.api.profileHandler.findName(this.grant.target) + + if (name == "null") { + name = this.grant.target.toString() + } + + if (this.grant.sender != this.who) { + toReturn.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.grant.sender)}") + } + + toReturn.add("${ChatColor.YELLOW}Who: ${ChatColor.RED}${name}") + toReturn.add("${ChatColor.YELLOW}Rank: ${ChatColor.RED}${this.rank?.getDisplayName() ?: this.grant.rank}") + toReturn.add("${ChatColor.YELLOW}Scopes: ${ChatColor.RED}${if (this.grant.isGlobal()) "Global" else StringUtils.join(this.grant.scopes,", ")}") + toReturn.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.grant.reason}") + + when { + + this.removed -> { + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.RED}${ChatColor.BOLD}Removed") + toReturn.add(" ") + + toReturn.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.grant.remover!!)}") + toReturn.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.grant.removedReason}") + toReturn.add(" ") + toReturn.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.grant.removed!!))}") + } + this.voided -> { + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.RED}${ChatColor.BOLD}Expired") + toReturn.add(" ") + toReturn.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.grant.getVoidedAt()))}") + } + else -> { + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.RED}Click to remove this grant.") + } + } + + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + + return toReturn + } + + override fun getDamageValue(player: Player?): Byte { + return (if (this.removed) DyeColor.RED else if (this.voided) DyeColor.ORANGE else DyeColor.GREEN).woolData + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + + if (this.voided || this.removed) { + return + } + + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(GrantRemoveReasonPrompt(this.grant)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantLengthPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantLengthPrompt.kt new file mode 100644 index 0000000..54e348f --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantLengthPrompt.kt @@ -0,0 +1,67 @@ +package cc.fyre.venom.grant.prompt + +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.menu.apply.ScopeMenu +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang.StringUtils +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantLengthPrompt(private val rank: Rank,private val reason: String,private val mojangProfile: MojangProfile) : StringPrompt() { + + override fun getPromptText(context: ConversationContext): String { + return "${ChatColor.YELLOW}Please type a duration for this grant, (\"perm\" for permanent) or type ${ChatColor.RED}\"cancel\" ${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(context: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + context.forWhom.sendRawMessage("${ChatColor.RED}Granting cancelled.") + return Prompt.END_OF_CONVERSATION + } + + var duration = 0L + val startsWithPerm = StringUtils.startsWithIgnoreCase(input,"perm") + + if (!startsWithPerm) { + duration = TimeUtil.parseTime(input) + } + + if (duration < 0L && !startsWithPerm) { + context.forWhom.sendRawMessage("${ChatColor.RED}Invalid duration.") + return Prompt.END_OF_CONVERSATION + } + + if (duration <= 0L && this.rank.isSubscription()) { + context.forWhom.sendRawMessage("${ChatColor.RED}You cannot grant a subscription permanently.") + return Prompt.END_OF_CONVERSATION + } + + if (this.rank.isSubscription()) { + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.grantHandler.grant(this.rank,this.mojangProfile.id,(context.forWhom as Player).uniqueId,this.reason,HashSet(),duration) + (context.forWhom).sendRawMessage("${ChatColor.GREEN}Granted ${ChatColor.WHITE}${this.mojangProfile.displayName} ${this.rank.getDisplayName()}${ChatColor.GREEN} subscription for ${TimeUtil.formatIntoDetailedString(duration)}.") + } + + return Prompt.END_OF_CONVERSATION + } + + ScopeMenu(this.rank,this.reason,TimeUtil.parseTime(input),this.mojangProfile).openMenu(context.forWhom as Player) + + return Prompt.END_OF_CONVERSATION; + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantReasonPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantReasonPrompt.kt new file mode 100644 index 0000000..d00ee4a --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantReasonPrompt.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.grant.prompt + + +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.rank.data.Rank + +import org.bukkit.ChatColor +import org.bukkit.conversations.* + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantReasonPrompt(private val rank: Rank,private val mojangProfile: MojangProfile) : StringPrompt() { + + override fun getPromptText(context: ConversationContext): String { + return "${ChatColor.YELLOW}Please type a reason for this grant to be added, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(context: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + context.forWhom.sendRawMessage("${ChatColor.RED}Granting cancelled.") + return Prompt.END_OF_CONVERSATION + } + + Venom.instance.server.scheduler.runTask(Venom.instance) { + context.forWhom.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(GrantLengthPrompt(this.rank,input,this.mojangProfile)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(context.forWhom)) + } + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantRemoveReasonPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantRemoveReasonPrompt.kt new file mode 100644 index 0000000..03651a7 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/prompt/GrantRemoveReasonPrompt.kt @@ -0,0 +1,43 @@ +package cc.fyre.venom.grant.prompt + +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.data.Grant +import org.bukkit.Bukkit + +import org.bukkit.ChatColor +import org.bukkit.conversations.* +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class GrantRemoveReasonPrompt(private val grant: Grant) : StringPrompt() { + + override fun getPromptText(context: ConversationContext): String { + return "${ChatColor.YELLOW}Please type a reason for this grant to be removed, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(context: ConversationContext, input: String): Prompt? { + + if (input.equals("cancel",true)) { + context.forWhom.sendRawMessage("${ChatColor.RED}Cancelled removing grant.") + return Prompt.END_OF_CONVERSATION + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + + if (Venom.instance.api.grantHandler.remove(this.grant,(context.forWhom as Player).uniqueId,input)) { + context.forWhom.sendRawMessage("${ChatColor.GREEN}Removed grant successfully.") + return@runTaskAsynchronously + } + + context.forWhom.sendRawMessage("${ChatColor.RED}There was an issue removing this grant.") + } + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/provider/GrantBukkitAdapter.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/provider/GrantBukkitAdapter.kt new file mode 100644 index 0000000..41ec40a --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/grant/provider/GrantBukkitAdapter.kt @@ -0,0 +1,57 @@ +package cc.fyre.venom.grant.provider + +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.data.GrantAdapter +import cc.fyre.venom.grant.event.GrantApplyEvent +import cc.fyre.venom.grant.event.GrantExpireEvent +import cc.fyre.venom.grant.event.GrantRemoveEvent +import org.bukkit.ChatColor +import java.util.* + +/** + * @project venom + * + * @date 09/05/2020 + * @author xanderume@gmail.com + */ +class GrantBukkitAdapter(private val instance: Venom) : GrantAdapter { + + override fun onGrantApply(uuid: UUID,grant: Grant) { + + val player = this.instance.server.getPlayer(uuid) ?: return + + this.instance.permissionHandler.update(player,true) + + this.instance.server.scheduler.runTask(this.instance){this.instance.server.pluginManager.callEvent(GrantApplyEvent(player,grant))} + } + + override fun onGrantChange(uuid: UUID,grant: Grant) { + // We do nothing here, #onGrantApply already gets called which already does everything. + } + + override fun onGrantExpire(uuid: UUID,grant: Grant) { + + val player = this.instance.server.getPlayer(uuid) ?: return + + val rank = grant.getRank() + + if (rank != null && rank.isHidden()) { + player.sendMessage("${ChatColor.LIGHT_PURPLE}Your ${rank.getDisplayName()}${ChatColor.LIGHT_PURPLE} ${if (rank.isSubscription()) "subscription" else "rank"} has expired.") + } + + this.instance.permissionHandler.update(player,true) + + this.instance.server.scheduler.runTask(this.instance){this.instance.server.pluginManager.callEvent(GrantExpireEvent(player,grant))} + } + + override fun onGrantRemove(uuid: UUID,grant: Grant) { + + val player = this.instance.server.getPlayer(uuid) ?: return + + this.instance.permissionHandler.update(player,true) + + this.instance.server.scheduler.runTask(this.instance){this.instance.server.pluginManager.callEvent(GrantRemoveEvent(player,grant))} + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/PermissionHandler.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/PermissionHandler.kt new file mode 100644 index 0000000..e04d830 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/PermissionHandler.kt @@ -0,0 +1,94 @@ +package cc.fyre.venom.permission + +import cc.fyre.proton.Proton +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.permission.command.PermissionAddCommand +import cc.fyre.venom.permission.command.PermissionRemoveCommand +import cc.fyre.venom.permission.data.VPermissible +import cc.fyre.venom.permission.event.PermissionUpdateEvent +import cc.fyre.venom.permission.listener.PermissionListener +import cc.fyre.venom.permission.parasite.PermissionParasiteListener +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.profile.data.Profile +import com.google.gson.JsonObject + +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftHumanEntity +import org.bukkit.entity.Player +import org.bukkit.permissions.Permissible +import java.lang.IllegalStateException + +import java.lang.reflect.Field + + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class PermissionHandler(private val instance: Venom) { + + init { + HUMAN_ENTITY_PERMISSIBLE_FIELD.isAccessible = true + + this.instance.server.pluginManager.registerEvents(PermissionListener(this.instance),this.instance) + + Proton.getInstance().commandHandler.registerClass(PermissionAddCommand::class.java) + Proton.getInstance().commandHandler.registerClass(PermissionRemoveCommand::class.java) + + this.instance.api.databaseHandler.symbiote.addListener(PermissionParasiteListener(this.instance)) + } + + fun update(player: Player,clear: Boolean):Boolean { + + val permissible = this.getPermissible(player) + + if (permissible !is VPermissible) { + return false + } + + this.instance.server.scheduler.runTask(this.instance){this.instance.server.pluginManager.callEvent(PermissionUpdateEvent(player))} + + permissible.calculate(clear) + return true + } + + fun update(profile: Profile,permission: String,remove: Boolean):Boolean { + + if (Bukkit.isPrimaryThread()) { + throw IllegalStateException("Cannot update permission on main thread.") + } + + val toReturn = this.instance.api.profileHandler.repository.update(profile) + + if (toReturn) { + + val jsonObject = JsonObject() + + jsonObject.addProperty("_id",profile.id.toString()) + jsonObject.addProperty("remove",remove) + jsonObject.addProperty("permission",permission) + + this.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(ProfileHandler.PERMISSION_UPDATE_PACKET,jsonObject)) + } + + return toReturn + } + + fun getPermissible(player: Player):Permissible { + return HUMAN_ENTITY_PERMISSIBLE_FIELD.get(player) as Permissible + } + + fun setPermissible(player: Player,permissible: Permissible) { + HUMAN_ENTITY_PERMISSIBLE_FIELD.set(player,permissible) + } + + companion object { + + private val HUMAN_ENTITY_PERMISSIBLE_FIELD: Field = CraftHumanEntity::class.java.getDeclaredField("perm") + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/command/PermissionAddCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/command/PermissionAddCommand.kt new file mode 100644 index 0000000..64fec70 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/command/PermissionAddCommand.kt @@ -0,0 +1,50 @@ +package cc.fyre.venom.permission.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender + +/** + * @project venom + * + * @date 19/04/2020 + * @author xanderume@gmail.com + */ +object PermissionAddCommand { + + @JvmStatic + @Command(names = ["permission add","perms add"],async = true,hidden = true,permission = "command.permission.add",description = "Add a permission to a user's account!") + fun execute(sender: CommandSender, @Parameter(name = "player")source: String, @Parameter(name = "permission")permission: String) { + + val profile = ProfileUtil.getProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}$source has never joined the server.") + return + } + + val displayName = PlayerUtil.getDisplayName(profile.id,profile.name) + + if (profile.permissions.any{it.equals(permission,true)}) { + sender.sendMessage("$displayName ${ChatColor.RED}already has the permission ${ChatColor.WHITE}$permission${ChatColor.RED}.") + return + } + + profile.permissions.add(permission.toLowerCase()) + + if (!Venom.instance.permissionHandler.update(profile,permission.toLowerCase(),false)) { + sender.sendMessage("${ChatColor.RED}There was an issue updating $displayName${ChatColor.RED}'s permissions.") + return + } + + sender.sendMessage("${ChatColor.GREEN}Granted $displayName ${ChatColor.GREEN}permission ${ChatColor.WHITE}$permission${ChatColor.GREEN}.") + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/command/PermissionRemoveCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/command/PermissionRemoveCommand.kt new file mode 100644 index 0000000..89cbe2d --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/command/PermissionRemoveCommand.kt @@ -0,0 +1,49 @@ +package cc.fyre.venom.permission.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender + +/** + * @project venom + * + * @date 19/04/2020 + * @author xanderume@gmail.com + */ +object PermissionRemoveCommand { + + @JvmStatic + @Command(names = ["permission remove","perms remove"],async = true,hidden = true,permission = "command.permission.remove",description = "Remove a permission from a user's account!") + fun execute(sender: CommandSender, @Parameter(name = "player")source: String, @Parameter(name = "permission")permission: String) { + + val profile = ProfileUtil.getProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}$source has never joined the server.") + return + } + + val displayName = PlayerUtil.getDisplayName(profile.id,profile.name,Venom.instance.serverHandler.server) + + if (profile.permissions.none{it.equals(permission,true)}) { + sender.sendMessage("$displayName ${ChatColor.RED}does not have the permission ${ChatColor.WHITE}$permission${ChatColor.RED}.") + return + } + + profile.permissions.remove(permission.toLowerCase()) + + if (!Venom.instance.permissionHandler.update(profile,permission.toLowerCase(),true)) { + sender.sendMessage("${ChatColor.RED}There was an issue updating $displayName${ChatColor.RED}'s permissions.") + return + } + + sender.sendMessage("${ChatColor.RED}Removed permission ${ChatColor.WHITE}$permission${ChatColor.RED} for $displayName${ChatColor.RED}.") + } + + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/data/VPermissible.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/data/VPermissible.kt new file mode 100644 index 0000000..97ed7b5 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/data/VPermissible.kt @@ -0,0 +1,79 @@ +package cc.fyre.venom.permission.data + +import cc.fyre.venom.Venom +import org.bukkit.Server +import org.bukkit.entity.Player +import org.bukkit.permissions.PermissibleBase +import org.bukkit.permissions.Permission +import org.bukkit.permissions.PermissionAttachment +import org.bukkit.permissions.PermissionAttachmentInfo +import org.bukkit.plugin.Plugin +import java.util.concurrent.ConcurrentHashMap +import java.util.stream.Collectors + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class VPermissible(player: Player) : PermissibleBase(player) { + + private val uuid = player.uniqueId + + val permissions = ConcurrentHashMap() + + init { this.calculate(false) } + + fun calculate(clear: Boolean) { + + if (clear) { + this.permissions.clear() + } + + this.calculatePermissions().entries.forEach{this.permissions[it.key.toLowerCase()] = it.value} + } + + override fun hasPermission(permission: Permission): Boolean { + return this.hasPermission(permission.name) + } + + override fun hasPermission(permission: String): Boolean { + + if (this.isOp && (this.permissions[permission] != false)) { + return true + } + + return this.permissions[permission.toLowerCase()] ?: false + } + + override fun isPermissionSet(permission: Permission): Boolean { + return this.isPermissionSet(permission.name) + } + + override fun isPermissionSet(name: String): Boolean { + return this.permissions.containsKey(name.toLowerCase()) + } + + override fun clearPermissions() = this.permissions.clear() + override fun recalculatePermissions() {} + + private fun calculatePermissions():ConcurrentHashMap { + + val permissions = ArrayList() + + permissions.addAll((Venom.instance.api.grantHandler.active[this.uuid] ?: ArrayList()).flatMap{it.getRank()?.permissions ?: HashSet()}) + permissions.addAll(Venom.instance.api.profileHandler.findById(this.uuid)?.permissions ?: ArrayList()) + + val toReturn = Venom.instance.api.profileHandler.calculatePermissions(permissions,true) + + toReturn[Server.BROADCAST_CHANNEL_USERS] = true + + return toReturn + } + + override fun getEffectivePermissions():MutableSet { + return this.permissions.entries.map{PermissionAttachmentInfo(this,it.key,PermissionAttachment(Venom.instance,this),it.value)}.toMutableSet() + } + +} \ No newline at end of file diff --git a/stark/bukkit/src/main/kotlin/net/evilblock/stark/profile/grant/event/GrantCreatedEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/event/PermissionUpdateEvent.kt similarity index 55% rename from stark/bukkit/src/main/kotlin/net/evilblock/stark/profile/grant/event/GrantCreatedEvent.kt rename to Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/event/PermissionUpdateEvent.kt index 165befc..dadd5f7 100644 --- a/stark/bukkit/src/main/kotlin/net/evilblock/stark/profile/grant/event/GrantCreatedEvent.kt +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/event/PermissionUpdateEvent.kt @@ -1,18 +1,24 @@ -package net.evilblock.stark.profile.grant.event - -import net.evilblock.stark.core.profile.grant.ProfileGrant -import org.bukkit.entity.Player -import org.bukkit.event.Event -import org.bukkit.event.HandlerList - -class GrantCreatedEvent(val player: Player, val grant: ProfileGrant) : Event() { - - companion object { - @JvmStatic val handlerList = HandlerList() - } - - override fun getHandlers(): HandlerList { - return handlerList - } - +package cc.fyre.venom.permission.event + +import org.bukkit.entity.Player +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 15/04/2020 + * @author xanderume@gmail.com + */ +class PermissionUpdateEvent(val player: Player) : Event(){ + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + + } \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/listener/PermissionListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/listener/PermissionListener.kt new file mode 100644 index 0000000..420afe9 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/listener/PermissionListener.kt @@ -0,0 +1,30 @@ +package cc.fyre.venom.permission.listener + +import cc.fyre.venom.Venom +import cc.fyre.venom.permission.data.VPermissible +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerLoginEvent +import org.bukkit.event.player.PlayerQuitEvent +import org.bukkit.permissions.PermissibleBase + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class PermissionListener(private val instance: Venom) : Listener { + + @EventHandler(priority = EventPriority.LOWEST) + private fun onPlayerLogin(event: PlayerLoginEvent) { + this.instance.permissionHandler.setPermissible(event.player,VPermissible(event.player)) + } + + @EventHandler(priority = EventPriority.MONITOR) + private fun onPlayerQuit(event: PlayerQuitEvent) { + this.instance.permissionHandler.setPermissible(event.player,PermissibleBase(event.player)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/parasite/PermissionParasiteListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/parasite/PermissionParasiteListener.kt new file mode 100644 index 0000000..880568e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/permission/parasite/PermissionParasiteListener.kt @@ -0,0 +1,45 @@ +package cc.fyre.venom.permission.parasite + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.Venom +import cc.fyre.venom.permission.data.VPermissible +import cc.fyre.venom.profile.ProfileHandler +import com.google.gson.JsonObject +import java.util.* + +/** + * @project venom + * + * @date 19/04/2020 + * @author xanderume@gmail.com + */ +class PermissionParasiteListener(private val instance: Venom) : ParasiteListener { + + @Parasite(ProfileHandler.PERMISSION_UPDATE_PACKET) + fun onPermissionUpdate(data: JsonObject) { + + val profile = this.instance.api.profileHandler.findById(UUID.fromString(data["_id"].asString)) ?: return + + val remove = data["remove"].asBoolean + val permission = data["permission"].asString + + if (remove) profile.permissions.remove(permission) else if (!profile.permissions.contains(permission)) profile.permissions.add(permission) + + val player = this.instance.server.getPlayer(profile.id) ?: return + + val permissible = this.instance.permissionHandler.getPermissible(player) + + if (permissible !is VPermissible) { + return + } + + if (remove) { + permissible.permissions.remove(permission.toLowerCase()) + } else { + permissible.permissions[permission.toLowerCase()] = !permission.startsWith("-") + } + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ChatColorCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ChatColorCommand.kt new file mode 100644 index 0000000..c1446d8 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ChatColorCommand.kt @@ -0,0 +1,21 @@ +package cc.fyre.venom.profile.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.profile.menu.ChatColorMenu +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object ChatColorCommand { + + @JvmStatic + @Command(names = ["chatcolor","color"],permission = "") + fun execute(player: Player) { + ChatColorMenu().openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/MessageCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/MessageCommand.kt new file mode 100644 index 0000000..4b8cad3 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/MessageCommand.kt @@ -0,0 +1,69 @@ +package cc.fyre.venom.profile.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.server.ServerHandler +import org.bukkit.ChatColor +import org.bukkit.Sound +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object MessageCommand { + + @JvmStatic + @Command(names = ["message","msg","m","whisper","w","tell"],permission = "") + fun execute(player: Player, @Parameter(name = "player")target: Player, @Parameter(name = "message",wildcard = true)message: String) { + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue processing your message..") + return + } + + val targetProfile = Venom.instance.api.profileHandler.findById(target.uniqueId) + + if (targetProfile == null) { + player.sendMessage("${ChatColor.RED}There was an issue processing your message..") + return + } + + val targetDisplay = Venom.instance.api.grantHandler.findDisplayName(target.uniqueId,target.name,Venom.instance.serverHandler.server) + + if (!player.hasPermission("command.message.bypass") && !targetProfile.settings.receiveMessages) { + player.sendMessage("$targetDisplay ${ChatColor.RED}has private messages disabled.") + return + } + + if (profile.ignore.contains(target.uniqueId)) { + player.sendMessage("${ChatColor.RED}You cannot message $targetDisplay${ChatColor.RED} as you have them ignored.") + return + } + + player.sendMessage("${ChatColor.GRAY}(To $targetDisplay${ChatColor.GRAY}) $message") + + ServerHandler.replies[player.uniqueId] = target.uniqueId + + if (targetProfile.ignore.contains(player.uniqueId)) { + return + } + + val senderDisplay = Venom.instance.api.grantHandler.findDisplayName(player.uniqueId,player.name,Venom.instance.serverHandler.server) + + if (targetProfile.settings.receiveMessagingSounds) { + target.playSound(target.location,Sound.SUCCESSFUL_HIT,1.0F,1.0F) + } + + target.sendMessage("${ChatColor.GRAY}(From ${senderDisplay}${ChatColor.GRAY}) $message") + + ServerHandler.replies[target.uniqueId] = player.uniqueId + } + + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ReplyCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ReplyCommand.kt new file mode 100644 index 0000000..3ffb380 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ReplyCommand.kt @@ -0,0 +1,85 @@ +package cc.fyre.venom.profile.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.server.ServerHandler +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.Sound +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object ReplyCommand { + + @JvmStatic + @Command(names = ["reply","r"],async = true,permission = "") + fun execute(player: Player,@Parameter(name = "message",wildcard = true)message: String) { + + val target = ServerHandler.replies[player.uniqueId] + + if (target == null) { + player.sendMessage("${ChatColor.RED}You have no one to reply to.") + return + } + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue processing your message..") + return + } + + if (!profile.settings.receiveMessages) { + player.sendMessage("${ChatColor.RED}You have private messages disabled.") + return + } + + val targetPlayer = Bukkit.getServer().getPlayer(target) + val targetDisplay = Venom.instance.api.grantHandler.findDisplayName(target,Venom.instance.serverHandler.server) + + if (targetPlayer == null) { + player.sendMessage("${targetDisplay}${ChatColor.RED} is no longer online.") + return + } + + val targetProfile = Venom.instance.api.profileHandler.findById(target) + + if (targetProfile == null) { + player.sendMessage("${ChatColor.RED}There was an issue processing your message..") + return + } + + if (!player.hasPermission("command.message.bypass") && !targetProfile.settings.receiveMessages) { + player.sendMessage("$targetDisplay ${ChatColor.RED}has private messages disabled.") + return + } + + if (profile.ignore.contains(target)) { + player.sendMessage("${ChatColor.RED}You cannot message $targetDisplay${ChatColor.RED} as you have them ignored.") + return + } + + player.sendMessage("${ChatColor.GRAY}(To $targetDisplay${ChatColor.GRAY}) $message") + + if (targetProfile.ignore.contains(player.uniqueId)) { + return + } + + val senderDisplay = Venom.instance.api.grantHandler.findDisplayName(player.uniqueId,player.name,Venom.instance.serverHandler.server) + + if (targetProfile.settings.receiveMessagingSounds) { + targetPlayer.playSound(targetPlayer.location,Sound.SUCCESSFUL_HIT,1.0F,1.0F) + } + + ServerHandler.replies[target] = player.uniqueId + + targetPlayer.sendMessage("${ChatColor.GRAY}(From ${senderDisplay}${ChatColor.GRAY}) $message") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/SoundsCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/SoundsCommand.kt new file mode 100644 index 0000000..b8c443a --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/SoundsCommand.kt @@ -0,0 +1,39 @@ +package cc.fyre.venom.profile.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.VenomAPI +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object SoundsCommand { + + + @JvmStatic + @Command(names = ["sounds"],async = true,permission = "") + fun execute(player: Player) { + + val profile = VenomAPI.instance.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue toggling your sounds..") + return + } + + profile.settings.receiveMessagingSounds = !profile.settings.receiveMessagingSounds + + if (!VenomAPI.instance.profileHandler.repository.update(profile)) { + player.sendMessage("${ChatColor.RED}There was an issue toggling your sounds..") + return + } + + player.sendMessage("${if (profile.settings.receiveMessagingSounds) ChatColor.GREEN else ChatColor.RED}Messaging sounds have been ${if (profile.settings.receiveMessagingSounds) "enabled" else "disabled"}.") + } + + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ToggleChatCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ToggleChatCommand.kt new file mode 100644 index 0000000..52d4c15 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ToggleChatCommand.kt @@ -0,0 +1,38 @@ +package cc.fyre.venom.profile.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.Venom +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object ToggleChatCommand { + + @JvmStatic + @Command(names = ["togglechat","tgc"],async = true,permission = "") + fun execute(player: Player) { + + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue toggling your chat..") + return + } + + profile.settings.viewGlobalChat = !profile.settings.viewGlobalChat + + if (!Venom.instance.api.profileHandler.repository.update(profile)) { + player.sendMessage("${ChatColor.RED}There was an issue toggling your chat..") + return + } + + player.sendMessage("${if (profile.settings.viewGlobalChat) ChatColor.GREEN else ChatColor.RED}Global messages have been ${if (profile.settings.viewGlobalChat) "enabled" else "disabled"}.") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ToggleMessagesCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ToggleMessagesCommand.kt new file mode 100644 index 0000000..7bee55d --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ToggleMessagesCommand.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.profile.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.Venom +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object ToggleMessagesCommand { + + @JvmStatic + @Command(names = ["togglepm","tpm"],async = true,permission = "") + fun execute(player: Player) { + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue toggling your messages..") + return + } + + profile.settings.receiveMessages = !profile.settings.receiveMessages + + if (!Venom.instance.api.profileHandler.repository.update(profile)) { + player.sendMessage("${ChatColor.RED}There was an issue toggling your messages..") + return + } + + player.sendMessage("${if (profile.settings.receiveMessages) ChatColor.GREEN else ChatColor.RED}Messages have been ${if (profile.settings.receiveMessages) "enabled" else "disabled"}.") + } + +} diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreCommand.kt new file mode 100644 index 0000000..b2a46ab --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreCommand.kt @@ -0,0 +1,53 @@ +package cc.fyre.venom.profile.command.ignore + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object IgnoreCommand { + + @JvmStatic + @Command(names = ["ignore"],async = true,permission = "") + fun execute(player: Player,@Parameter(name = "player")uuid: UUID) { + + if (player.uniqueId == uuid) { + player.sendMessage("${ChatColor.RED}You cannot ignore yourself.") + return + } + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue ignoring this player..") + return + } + + val targetDisplay = Venom.instance.api.grantHandler.findDisplayName(uuid,Venom.instance.serverHandler.server) + + if (profile.ignore.contains(uuid)) { + player.sendMessage("${ChatColor.RED}You are already ignoring $targetDisplay${ChatColor.RED}.") + return + } + + profile.ignore.add(uuid) + + if (!Venom.instance.api.profileHandler.repository.update(profile)) { + player.sendMessage("${ChatColor.RED}There was an issue ignoring this ${targetDisplay}..") + return + } + + player.sendMessage("${ChatColor.GOLD}You are now ignoring ${targetDisplay}${ChatColor.GOLD}.") + + } + + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreListCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreListCommand.kt new file mode 100644 index 0000000..6688ba3 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreListCommand.kt @@ -0,0 +1,36 @@ +package cc.fyre.venom.profile.command.ignore + +import cc.fyre.proton.command.Command +import cc.fyre.venom.Venom +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +object IgnoreListCommand { + + @JvmStatic + @Command(names = ["ignore list"],async = true,permission = "") + fun execute(player: Player) { + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue loading your ignore list..") + return + } + + if (profile.ignore.isEmpty()) { + player.sendMessage("${ChatColor.RED}You are not ignoring anyone.") + return + } + + player.sendMessage("${ChatColor.YELLOW}You are currently ignoring ${ChatColor.RED}${profile.ignore.size}${ChatColor.YELLOW} player${if (profile.ignore.size == 1) "" else "s"}: ${ChatColor.RED}${StringUtils.join(profile.ignore.map{Venom.instance.api.profileHandler.findName(it)}.toTypedArray(),"${ChatColor.YELLOW}, ${ChatColor.RED}")}") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreRemoveCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreRemoveCommand.kt new file mode 100644 index 0000000..edf0c2b --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/command/ignore/IgnoreRemoveCommand.kt @@ -0,0 +1,47 @@ +package cc.fyre.venom.profile.command.ignore + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 02/03/2021 + * @author xanderume@gmail.com + */ +object IgnoreRemoveCommand { + + @JvmStatic + @Command(names = ["ignore remove","unignore","un-ignore"],async = true,permission = "") + fun execute(player: Player,@Parameter(name = "player")uuid: UUID) { + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue un-ignoring this player..") + return + } + + val targetDisplay = Venom.instance.api.grantHandler.findDisplayName(uuid,Venom.instance.serverHandler.server) + + if (!profile.ignore.contains(uuid)) { + player.sendMessage("${ChatColor.RED}You aren't ignoring $targetDisplay${ChatColor.RED}.") + return + } + + profile.ignore.remove(uuid) + + if (!Venom.instance.api.profileHandler.repository.update(profile)) { + player.sendMessage("${ChatColor.RED}There was an issue un-ignoring this ${targetDisplay}..") + return + } + + player.sendMessage("${ChatColor.GREEN}You are no longer ignoring ${targetDisplay}${ChatColor.GREEN}.") + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/event/ProfileLoadEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/event/ProfileLoadEvent.kt new file mode 100644 index 0000000..2363de0 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/event/ProfileLoadEvent.kt @@ -0,0 +1,25 @@ +package cc.fyre.venom.profile.event + +import cc.fyre.venom.profile.data.Profile + +import org.bukkit.event.Event +import org.bukkit.event.HandlerList +import org.bukkit.event.player.AsyncPlayerChatEvent + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class ProfileLoadEvent(val profile: Profile) : Event(true) { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/exception/ProfileLoadException.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/exception/ProfileLoadException.kt new file mode 100644 index 0000000..526b046 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/exception/ProfileLoadException.kt @@ -0,0 +1,12 @@ +package cc.fyre.venom.profile.exception + +import cc.fyre.venom.profile.data.Profile +import java.util.* + +/** + * @project venom + * + * @date 23/03/2020 + * @author xanderume@gmail.com + */ +class ProfileLoadException(val uuid: UUID,message: String) : Exception(message) \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/menu/ChatColorMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/menu/ChatColorMenu.kt new file mode 100644 index 0000000..c2e3008 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/menu/ChatColorMenu.kt @@ -0,0 +1,25 @@ +package cc.fyre.venom.profile.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.profile.menu.element.ChatColorElement +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +class ChatColorMenu : Menu() { + + override fun getTitle(player: Player): String { + return "${ChatColor.BLUE}Colors" + } + + override fun getButtons(player: Player): MutableMap { + return ChatColor.values().filter{it.ordinal in 1..15}.sortedByDescending{it.ordinal}.withIndex().associate{it.index to ChatColorElement(it.value)}.toMutableMap() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/menu/element/ChatColorElement.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/menu/element/ChatColorElement.kt new file mode 100644 index 0000000..ff65f42 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/menu/element/ChatColorElement.kt @@ -0,0 +1,64 @@ +package cc.fyre.venom.profile.menu.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.util.ColorUtil + +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +/** + * @project venom + * + * @date 02/05/2020 + * @author xanderume@gmail.com + */ +class ChatColorElement(private val color: ChatColor) : Button() { + + private val properName = ColorUtil.getName(this.color) + + override fun getName(p0: Player?): String { + return "${this.color}${this.properName}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(player: Player): MutableList { + return arrayListOf() + } + + override fun getDamageValue(player: Player?): Byte { + return (ColorUtil.findDyeColor(this.color) ?: DyeColor.WHITE).woolData + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + + if (!player.hasPermission("color.${this.color.name.toLowerCase()}") && !player.hasPermission("color.*")) { + player.sendMessage("${ChatColor.RED}No permission.") + return + } + + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue updating your chat color..") + player.closeInventory() + return + } + + profile.chatColor = if (profile.chatColor == this.color.name) ChatColor.WHITE.name else this.color.name + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + player.closeInventory() + player.sendMessage("${ChatColor.GREEN}Chat color has been set to ${this.color}${this.properName}${ChatColor.GREEN}.") + + Venom.instance.api.profileHandler.repository.update(profile) + } + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/mojang/MojangProfile.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/mojang/MojangProfile.kt new file mode 100644 index 0000000..6e8fccc --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/mojang/MojangProfile.kt @@ -0,0 +1,11 @@ +package cc.fyre.venom.profile.mojang + +import java.util.* + +/** + * @project venom + * + * @date 27/03/2020 + * @author xanderume@gmail.com + */ +data class MojangProfile(val id: UUID,val name: String,val displayName: String,val doesProfileExist: Boolean) diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/provider/UUIDParameterProvider.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/provider/UUIDParameterProvider.kt new file mode 100644 index 0000000..636e1ba --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/provider/UUIDParameterProvider.kt @@ -0,0 +1,48 @@ +package cc.fyre.venom.profile.provider + +import cc.fyre.proton.command.param.ParameterType +import cc.fyre.venom.Venom +import com.mysql.jdbc.StringUtils + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 26/03/2020 + * @author xanderume@gmail.com + */ +class UUIDParameterProvider: ParameterType { + + private val instance = Venom.instance + + override fun transform(sender: CommandSender,source: String): UUID? { + + if (sender is Player && source == "self") { + return sender.uniqueId + } + + val player = this.instance.server.getPlayer(source) + + if (player != null) { + return player.uniqueId + } + + val uuid = this.instance.api.profileHandler.findId(source) + + if (uuid == null) { + sender.sendMessage("${ChatColor.RED}${source} has never joined the server.") + return null + } + + return uuid + } + + override fun tabComplete(player: Player,flags: Set,source: String): List { + return this.instance.server.onlinePlayers.filter{player.canSee(it) && StringUtils.startsWithIgnoreCase(it.name,source)}.map{it.name}.toList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/util/ProfileUtil.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/util/ProfileUtil.kt new file mode 100644 index 0000000..16126df --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/profile/util/ProfileUtil.kt @@ -0,0 +1,71 @@ +package cc.fyre.venom.profile.util + +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.data.Profile +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.util.MojangUtil +import cc.fyre.venom.util.PlayerUtil +import org.bukkit.Bukkit + +/** + * @project venom + * + * @date 16/02/2021 + * @author xanderume@gmail.com + */ +object ProfileUtil { + + @JvmStatic + fun getProfileQuery(source: String):Profile? { + + if (Bukkit.isPrimaryThread()) { + throw IllegalStateException("Cannot query profile on main thread.") + } + + val profile = Venom.instance.api.profileHandler.findByName(source) + + if (profile != null) { + return profile + } + + val uuid = Venom.instance.api.profileHandler.findId(source) + + if (uuid != null) { + return Venom.instance.api.profileHandler.repository.findById(uuid) + } + + return null + } + + @JvmStatic + fun getMojangProfileQuery(source: String):MojangProfile? { + + if (Bukkit.isPrimaryThread()) { + throw IllegalStateException("Cannot query mojang profile on main thread.") + } + + val player = Bukkit.getServer().getPlayer(source) + + if (player != null) { + return MojangProfile(player.uniqueId,player.name,PlayerUtil.getDisplayName(player.uniqueId,player.name),true) + } + + val uuid = Venom.instance.api.profileHandler.findId(source) + + if (uuid != null) { + + val name = Venom.instance.api.profileHandler.findName(uuid) + + return MojangProfile(uuid,name,PlayerUtil.getDisplayName(uuid,name,Venom.instance.serverHandler.server),true) + } + + val request = MojangUtil.getUsernameAndUuid(source) + + if (request?.first != null) { + return MojangProfile(request.first,request.second,PlayerUtil.getDisplayName(request.first,request.second,Venom.instance.serverHandler.server),false) + } + + return null + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/BanCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/BanCommand.kt new file mode 100644 index 0000000..20bbfd0 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/BanCommand.kt @@ -0,0 +1,110 @@ +package cc.fyre.venom.punishment.command + + + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.flag.Flag +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 25/03/2020 + * @author xanderume@gmail.com + */ +object BanCommand { + + @JvmStatic + @Command(names = ["ban", "tempban"],async = true,hidden = true,permission = "punishment.execute.ban",description = "Restrict a user from joining the network!") + fun ban(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "duration",defaultValue = "perm")duration: Long, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.punish(Punishment.Type.BAN,profile.id,senderUuid,reason,Venom.instance.serverHandler.server.id,duration,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + + @JvmStatic + @Command(names = ["banip","ipban","ban-ip","ip-ban"],async = true,hidden = true,permission = "punishment.execute.ipban",description = "Restrict user's on address from joining the network!") + fun banIP(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player|ip")argument: String, + @Parameter(name = "duration",defaultValue = "perm")duration: Long, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + + var profile = if (argument.contains(".")) Venom.instance.api.profileHandler.repository.findByAddress(argument) else null + + if (profile == null) { + profile = ProfileUtil.getProfileQuery(argument) + } + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}$argument has never joined the server.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + val identifiers = ArrayList() + + val identifier = profile.identifiers.firstOrNull{it.equals(argument,true)} + + if (identifier != null) { + identifiers.add(identifier) + } else { + identifiers.addAll(profile.identifiers) + } + + Venom.instance.api.punishmentHandler.punish(Punishment.Type.BAN,profile.id,identifiers,senderUuid,reason,Venom.instance.serverHandler.server.id,duration,!public,PlayerUtil.getDisplayName(profile.id,Venom.instance.serverHandler.server),PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + + @JvmStatic + @Command(names = ["unban","pardon"],async = true,hidden = true,permission = "punishment.pardon.ban",description = "Remove restriction of user joining the network.") + fun pardon(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "reason")reason: String + ) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val punishment = Venom.instance.api.punishmentHandler.repository.findMostRecentPunishment(Venom.instance.api.punishmentHandler.repository.findByVictim(profile.id,Punishment.Type.BAN)) + + if (punishment == null) { + sender.sendMessage("${ChatColor.RED}${profile.displayName} ${ChatColor.RED}does not have any active bans.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.pardon(punishment,senderUuid,reason,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/BlacklistCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/BlacklistCommand.kt new file mode 100644 index 0000000..e93bb85 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/BlacklistCommand.kt @@ -0,0 +1,74 @@ +package cc.fyre.venom.punishment.command + + + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.flag.Flag +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 27/03/2020 + * @author xanderume@gmail.com + */ +object BlacklistCommand { + + @JvmStatic + @Command(names = ["blacklist"],async = true,hidden = true,permission = "punishment.execute.blacklist",description = "Blacklist a user the network!") + fun blacklist(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.punish(Punishment.Type.BLACKLIST,profile.id,if (profile.doesProfileExist) Venom.instance.api.profileHandler.repository.findById(profile.id)!!.identifiers else ArrayList(),senderUuid,reason,Venom.instance.serverHandler.server.id,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + + @JvmStatic + @Command(names = ["unblacklist"],async = true,hidden = true,permission = "punishment.pardon.blacklist",description = "Remove a user from the blacklist.") + fun pardon(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "reason")reason: String + ) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val punishment = Venom.instance.api.punishmentHandler.repository.findMostRecentPunishment(Venom.instance.api.punishmentHandler.repository.findByVictim(profile.id,Punishment.Type.BLACKLIST)) + + if (punishment == null) { + sender.sendMessage("${ChatColor.RED}${profile.displayName} ${ChatColor.RED}does not have any active blacklists.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.pardon(punishment,senderUuid,reason,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/GhostMuteCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/GhostMuteCommand.kt new file mode 100644 index 0000000..49c9e4a --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/GhostMuteCommand.kt @@ -0,0 +1,79 @@ +package cc.fyre.venom.punishment.command + + + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.flag.Flag +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 22/05/2020 + * @author xanderume@gmail.com + */ +object GhostMuteCommand { + + @JvmStatic + @Command(names = ["ghostmute","ghosttempmute"],async = true,hidden = true,permission = "punishment.execute.ghost_mute",description = "Restrict people from seeing user's message in chat!") + fun mute(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "duration",defaultValue = "perm")duration: Long, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.punish(Punishment.Type.GHOST_MUTE,profile.id,senderUuid,reason,Venom.instance.serverHandler.server.id,duration,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + + @JvmStatic + @Command(names = ["unghostmute"],async = true,hidden = true,permission = "punishment.pardon.ghost_mute",description = "Remove restriction of people seeing user's message in chat.") + fun pardon(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "reason")reason: String + ) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val punishment = Venom.instance.api.punishmentHandler.repository.findMostRecentPunishment(Venom.instance.api.punishmentHandler.repository.findByVictim(profile.id,Punishment.Type.GHOST_MUTE)) + + if (punishment == null) { + sender.sendMessage("${ChatColor.RED}${profile.displayName} ${ChatColor.RED}does not have any active ghost mutes.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.pardon(punishment,senderUuid,reason,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/KickCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/KickCommand.kt new file mode 100644 index 0000000..49c480b --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/KickCommand.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.punishment.command + + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.flag.Flag +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler + +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 27/03/2020 + * @author xanderume@gmail.com + */ +object KickCommand { + + @JvmStatic + @Command(names = ["kick"],async = true,hidden = true,permission = "punishment.execute.kick",description = "Kick a user from current server.") + fun mute(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")player: Player, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.punish(Punishment.Type.KICK,player.uniqueId,senderUuid,reason, Venom.instance.serverHandler.server.id,0L,!public,PlayerUtil.getDisplayName(player.uniqueId,player.name,Venom.instance.serverHandler.server),PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/MuteCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/MuteCommand.kt new file mode 100644 index 0000000..86c5154 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/MuteCommand.kt @@ -0,0 +1,72 @@ +package cc.fyre.venom.punishment.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.flag.Flag +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 27/03/2020 + * @author xanderume@gmail.com + */ +object MuteCommand { + + @JvmStatic + @Command(names = ["mute","tempmute"],async = true,hidden = true,permission = "punishment.execute.mute",description = "Restrict a user from typing in chat!") + fun mute(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "duration",defaultValue = "perm")duration: Long, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + Venom.instance.api.punishmentHandler.punish(Punishment.Type.MUTE,profile.id,senderUuid,reason,Venom.instance.serverHandler.server.id,duration,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + + @JvmStatic + @Command(names = ["unmute"],async = true,hidden = true,permission = "punishment.pardon.mute",description = "Remove restriction of user from typing in chat.") + fun pardon(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "reason")reason: String + ) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val punishment = Venom.instance.api.punishmentHandler.repository.findMostRecentPunishment(Venom.instance.api.punishmentHandler.repository.findByVictim(profile.id,Punishment.Type.MUTE)) + + if (punishment == null) { + sender.sendMessage("${ChatColor.RED}${profile.displayName} ${ChatColor.RED}does not have any active mutes.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.pardon(punishment,senderUuid,reason,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/WarnCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/WarnCommand.kt new file mode 100644 index 0000000..fc2a6dc --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/WarnCommand.kt @@ -0,0 +1,48 @@ +package cc.fyre.venom.punishment.command + + + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.flag.Flag +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 27/03/2020 + * @author xanderume@gmail.com + */ +object WarnCommand { + + @JvmStatic + @Command(names = ["warn"],async = true,hidden = true,permission = "punishment.execute.warn",description = "Warn a user!") + fun warn(sender: CommandSender, + @Flag(value = ["p"],defaultValue = false,description = "Broadcast to whole network!")public: Boolean, + @Parameter(name = "player")source: String, + @Parameter(name = "reason",wildcard = true)reason: String + ) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + sender.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val senderUuid = if (sender is Player) sender.uniqueId else ProfileHandler.CONSOLE_UUID + + Venom.instance.api.punishmentHandler.punish(Punishment.Type.WARN,profile.id,senderUuid,reason,Venom.instance.serverHandler.server.id,0L,!public,profile.displayName,PlayerUtil.getDisplayName(senderUuid,Venom.instance.serverHandler.server)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/alt/AltsCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/alt/AltsCommand.kt new file mode 100644 index 0000000..d96ad21 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/alt/AltsCommand.kt @@ -0,0 +1,47 @@ +package cc.fyre.venom.punishment.command.alt + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.util.PlayerUtil +import org.apache.commons.lang3.StringUtils + +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 05/05/2020 + * @author xanderume@gmail.com + */ +object AltsCommand { + + @JvmStatic + @Command(names = ["alts","alternates"],async = true,hidden = true,permission = "command.alts") + fun execute(player: Player,@Parameter(name = "player")source: String) { + + val profile = ProfileUtil.getProfileQuery(source) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}$source has never joined the server.") + return + } + + val displayName = PlayerUtil.getDisplayName(profile.id,profile.name,Venom.instance.serverHandler.server) + + player.sendMessage("${ChatColor.GREEN}Processing $displayName${ChatColor.GREEN}'s alts this may take a few seconds.") + + val alts = Venom.instance.api.profileHandler.repository.findAlts(profile) + + if (alts.isEmpty()) { + player.sendMessage("$displayName${ChatColor.RED} does not have any alts.") + return + } + + player.sendMessage(StringUtils.join(alts.map{PlayerUtil.getDisplayName(it.id,it.name,Venom.instance.serverHandler.server)}.toTypedArray(),"${ChatColor.WHITE}, ")) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/evidence/UnresolvedPunishmentsCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/evidence/UnresolvedPunishmentsCommand.kt new file mode 100644 index 0000000..06104a8 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/evidence/UnresolvedPunishmentsCommand.kt @@ -0,0 +1,54 @@ +package cc.fyre.venom.punishment.command.evidence + + + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.menu.evidence.PunishmentUnresolvedMenu +import cc.fyre.venom.util.PlayerUtil + +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 13/07/2020 + * @author xanderume@gmail.com + */ +object UnresolvedPunishmentsCommand { + + @JvmStatic + @Command(names = ["unresolvedpunishments"],async = true,hidden = false,permission = "punishment.unresolved") + fun execute(player: Player,@Parameter(name = "player",defaultValue = "self")target: UUID) { + + var uuid = target + + if (target != player.uniqueId && !player.isOp) { + uuid = player.uniqueId + } + + val grants = Venom.instance.api.grantHandler.repository.findAllByPlayer(uuid) + + val rank = if (Venom.instance.api.grantHandler.global.containsKey(uuid)) { + Venom.instance.api.grantHandler.findBestRank(uuid) + } else { + Venom.instance.api.grantHandler.findBestRank(grants,Venom.instance.serverHandler.server) + } + + if (rank.evidenceRequired.isEmpty()) { + player.sendMessage("${ChatColor.RED}${Venom.instance.api.profileHandler.findName(target)}${ChatColor.RED} does not have to provide any evidence.") + return + } + + val name = Venom.instance.api.profileHandler.findName(uuid) + + val profile = MojangProfile(uuid,name,PlayerUtil.getDisplayName(name,Venom.instance.serverHandler.server,grants),true) + + PunishmentUnresolvedMenu(Venom.instance.api.punishmentHandler.repository.findBySender(uuid,rank.evidenceRequired.toMutableList()).filter{it.isEvidenceRequired()}.toSet(),profile).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/history/HistoryCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/history/HistoryCommand.kt new file mode 100644 index 0000000..ae2098e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/history/HistoryCommand.kt @@ -0,0 +1,45 @@ +package cc.fyre.venom.punishment.command.history + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom + +import cc.fyre.venom.profile.util.ProfileUtil +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.history.PunishmentMenu + +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 01/04/2020 + * @author xanderume@gmail.com + */ +object HistoryCommand { + + + @JvmStatic + @Command(names = ["check","c","history"],async = true,hidden = true,permission = "command.history",description = "View a user's punishments!") + fun execute(player: Player,@Parameter(name = "player")source: String) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val punishments = Venom.instance.api.punishmentHandler.repository.findByVictim(profile.id,Punishment.Type.values().toMutableList()) + + if (punishments.isEmpty()) { + player.sendMessage("${profile.displayName}${ChatColor.RED} has no punishments.") + return + } + + PunishmentMenu(profile,punishments).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/history/StaffHistoryCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/history/StaffHistoryCommand.kt new file mode 100644 index 0000000..f910831 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/command/history/StaffHistoryCommand.kt @@ -0,0 +1,42 @@ +package cc.fyre.venom.punishment.command.history + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.util.ProfileUtil + +import cc.fyre.venom.punishment.menu.staffhistory.StaffPunishmentMenu + +import org.bukkit.ChatColor +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 04/04/2020 + * @author xanderume@gmail.com + */ +object StaffHistoryCommand { + + @JvmStatic + @Command(names = ["staffhistory"],async = true,hidden = true,permission = "command.history.staff",description = "View a staff member's punish history!") + fun execute(player: Player,@Parameter(name = "player")source: String) { + + val profile = ProfileUtil.getMojangProfileQuery(source) + + if (profile == null) { + player.sendMessage("${ChatColor.RED}Unable to find $source in mojang database.") + return + } + + val punishments = Venom.instance.api.punishmentHandler.repository.findBySenderOrPardoner(profile.id) + + if (punishments.isEmpty()) { + player.sendMessage("${profile.displayName} ${ChatColor.RED}has no punishments!") + return + } + + StaffPunishmentMenu(profile,punishments).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/listener/EvidenceListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/listener/EvidenceListener.kt new file mode 100644 index 0000000..8200571 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/listener/EvidenceListener.kt @@ -0,0 +1,49 @@ +package cc.fyre.venom.punishment.listener + +import cc.fyre.venom.Venom +import mkremins.fanciful.FancyMessage +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerJoinEvent +import java.util.stream.Collectors + +/** + * @project venom + * + * @date 13/07/2020 + * @author xanderume@gmail.com + */ +class EvidenceListener(private val instance: Venom) : Listener { + + @EventHandler(priority = EventPriority.MONITOR) + private fun onPlayerJoin(event: PlayerJoinEvent) { + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + + val types = this.instance.api.grantHandler.findBestRank(event.player.uniqueId).evidenceRequired + + if (types.isEmpty()) { + return@runTaskAsynchronously + } + + val punishments = this.instance.api.punishmentHandler.repository.findBySender(event.player.uniqueId,types.toMutableList()).filter{it.isEvidenceRequired()}.toList() + + if (punishments.isEmpty()) { + event.player.sendMessage("${ChatColor.GREEN}All your punishments are resolved, you're good to go.") + return@runTaskAsynchronously + } + + FancyMessage("${ChatColor.RED}${ChatColor.BOLD}WARNING!${ChatColor.YELLOW} You have ${ChatColor.RED}${punishments.size}${ChatColor.YELLOW} unresolved punishments, click ") + .then("${ChatColor.GREEN}here") + .command("/unresolvedpunishments") + .then("${ChatColor.YELLOW} to view them.") + .send(event.player) + + } + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/listener/MuteListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/listener/MuteListener.kt new file mode 100644 index 0000000..d31f87c --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/listener/MuteListener.kt @@ -0,0 +1,50 @@ +package cc.fyre.venom.punishment.listener + +import cc.fyre.venom.Venom +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.TimeUtil +import org.bukkit.ChatColor +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.AsyncPlayerChatEvent + +/** + * @project venom + * + * @date 19/05/2020 + * @author xanderume@gmail.com + */ +class MuteListener(private val instance: Venom) : Listener { + + @EventHandler(priority = EventPriority.LOWEST) + private fun onChatMute(event: AsyncPlayerChatEvent) { + + val punishment = this.instance.api.punishmentHandler.repository.findMostRecentPunishment(this.instance.api.punishmentHandler.mutes[event.player.uniqueId]!!,arrayListOf(Punishment.Type.MUTE)) ?: return + + val message = if (punishment.isPermanent()) { + "You are permanently silenced." + } else { + "You are currently silenced, you may speak again in ${ChatColor.YELLOW}${TimeUtil.formatIntoDetailedString(punishment.getRemaining())}${ChatColor.RED}." + } + + event.player.sendMessage("${ChatColor.RED}$message") + event.isCancelled = true + } + + @EventHandler(priority = EventPriority.MONITOR) + private fun onChatGhostMute(event: AsyncPlayerChatEvent) { + + if (!this.instance.api.punishmentHandler.isGhostMuted(event.player.uniqueId)) { + return + } + + val permission = Punishment.Type.GHOST_MUTE.permission(false) + + event.recipients.clear() + event.recipients.add(event.player) + + this.instance.server.onlinePlayers.filter{it.hasPermission(permission) && it.uniqueId != event.player.uniqueId}.forEach{it.sendMessage("${ChatColor.RED}[Ghost]${event.format} ${event.message}")} + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/PunishmentEvidenceMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/PunishmentEvidenceMenu.kt new file mode 100644 index 0000000..04bac7d --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/PunishmentEvidenceMenu.kt @@ -0,0 +1,50 @@ +package cc.fyre.venom.punishment.menu.evidence + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.evidence.element.PunishmentEvidenceButton +import cc.fyre.venom.punishment.menu.evidence.element.PunishmentEvidenceProvideButton +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 12/07/2020 + * @author xanderume@gmail.com + */ +class PunishmentEvidenceMenu(private val punishment: Punishment,private val previous: Menu) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Evidence" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + + val toReturn = HashMap() + + this.punishment.evidence.forEach{toReturn[toReturn.size] = PunishmentEvidenceButton(it)} + + return toReturn + } + + override fun getGlobalButtons(player: Player): MutableMap { + + val toReturn = HashMap() + + if (this.punishment.sender != player.uniqueId) { + + toReturn[4] = BackButton(this.previous) + + return toReturn + } + + toReturn[3] = PunishmentEvidenceProvideButton(this.punishment,this.previous) + toReturn[5] = BackButton(this.previous) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/PunishmentUnresolvedMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/PunishmentUnresolvedMenu.kt new file mode 100644 index 0000000..1aa2e93 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/PunishmentUnresolvedMenu.kt @@ -0,0 +1,31 @@ +package cc.fyre.venom.punishment.menu.evidence + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.staffhistory.element.StaffHistoryButton +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 13/07/2020 + * @author xanderume@gmail.com + */ +class PunishmentUnresolvedMenu(private val punishments: Set,private val mojangProfile: MojangProfile) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Unresolved Punishments" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + + val toReturn = HashMap() + + this.punishments.filter{it.isEvidenceRequired()}.forEach{toReturn[toReturn.size] = StaffHistoryButton(it,this.mojangProfile,this)} + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/element/PunishmentEvidenceButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/element/PunishmentEvidenceButton.kt new file mode 100644 index 0000000..46477cd --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/element/PunishmentEvidenceButton.kt @@ -0,0 +1,55 @@ +package cc.fyre.venom.punishment.menu.evidence.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 12/07/2020 + * @author xanderume@gmail.com + */ +class PunishmentEvidenceButton(private val evidence: Punishment.Evidence) : Button(){ + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.evidence.provided))}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + + val lore = ArrayList() + + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.evidence.provider)}") + lore.add("${ChatColor.YELLOW}URL: ${ChatColor.RED}${this.evidence.url}") + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.YELLOW}Click to view proof.") + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + + return lore + } + + override fun getDamageValue(player: Player?): Byte { + return DyeColor.LIME.woolData + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + player.closeInventory() + player.sendMessage(this.evidence.url) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/element/PunishmentEvidenceProvideButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/element/PunishmentEvidenceProvideButton.kt new file mode 100644 index 0000000..762a56e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/evidence/element/PunishmentEvidenceProvideButton.kt @@ -0,0 +1,40 @@ +package cc.fyre.venom.punishment.menu.evidence.element + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.Venom +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.prompt.PunishmentEvidencePrompt +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @author xanderume@gmail.com + * @date 13/07/2020 + */ +class PunishmentEvidenceProvideButton(private val punishment: Punishment,private val previous: Menu) : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.GREEN}${ChatColor.BOLD}Add Evidence" + } + + override fun getMaterial(p0: Player?): Material { + return Material.SIGN + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(PunishmentEvidencePrompt(this.punishment,this.previous)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(300).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/HistoryMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/HistoryMenu.kt new file mode 100644 index 0000000..3246aaf --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/HistoryMenu.kt @@ -0,0 +1,41 @@ +package cc.fyre.venom.punishment.menu.history + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.history.element.HistoryElement +import org.apache.commons.lang3.StringUtils +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 01/04/2020 + * @author xanderume@gmail.com + */ +class HistoryMenu(private val type: Punishment.Type,private val punishments: Set,private val mojangProfile: MojangProfile) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "${StringUtils.capitalize(this.type.name.toLowerCase().replace("_"," "))}s" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + val toReturn = HashMap() + + this.punishments.filter{if (this.type == Punishment.Type.MUTE) (it.type == Punishment.Type.MUTE || it.type == Punishment.Type.GHOST_MUTE) else it.type == this.type}.sortedBy{it.created}.reversed().forEach{toReturn[toReturn.size] = HistoryElement(it,this.mojangProfile,this)} + + return toReturn + } + + override fun getGlobalButtons(player: Player?): MutableMap { + + val toReturn = HashMap() + + toReturn[4] = BackButton(PunishmentMenu(this.mojangProfile,this.punishments)) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/PunishmentMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/PunishmentMenu.kt new file mode 100644 index 0000000..e77c879 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/PunishmentMenu.kt @@ -0,0 +1,44 @@ +package cc.fyre.venom.punishment.menu.history + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.history.element.PunishmentElement +import org.bukkit.entity.Player + +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 01/04/2020 + * @author xanderume@gmail.com + */ +class PunishmentMenu(private val mojangProfile: MojangProfile,private val punishments: Set) : Menu() { + + override fun size(player: Player): Int { + return 3*9 + } + + override fun getTitle(player: Player): String { + return "Punishments - ${this.mojangProfile.displayName}" + } + + override fun getButtons(player: Player): MutableMap { + + val toReturn = HashMap() + + val types = Punishment.Type.values().filter{it != Punishment.Type.GHOST_MUTE && player.hasPermission(it.permission(false))}.sortedBy{it.ordinal}.reversed() + + var i = 0 + val start = 13 - (types.size - 1) + + types.forEach{ _ -> + toReturn[if (i == 0) start else (start + ((if (i == 0) 1 else i)) * 2)] = PunishmentElement(types[i++],this.punishments,this.mojangProfile) + } + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/element/HistoryElement.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/element/HistoryElement.kt new file mode 100644 index 0000000..4428e86 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/element/HistoryElement.kt @@ -0,0 +1,130 @@ +package cc.fyre.venom.punishment.menu.history.element + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.evidence.PunishmentEvidenceMenu +import cc.fyre.venom.punishment.prompt.PunishmentRemoveReasonPrompt +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 01/04/2020 + * @author xanderume@gmail.com + */ +class HistoryElement(private val punishment: Punishment, private val mojangProfile: MojangProfile,val parent: Menu) : Button() { + + private val voided = this.punishment.isVoided() + private val pardoned = this.punishment.isPardoned() + + private var canPardon = false + private var proofRequired = false + + override fun getName(player: Player): String { + this.canPardon = !this.pardoned && !this.voided && this.punishment.type != Punishment.Type.KICK && this.punishment.type != Punishment.Type.WARN && player.hasPermission(this.punishment.type.permission(true)) + this.proofRequired = Venom.instance.api.grantHandler.findBestRank(player.uniqueId).isEvidenceRequired(this.punishment.type) + + return "${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.punishment.created))} ${if (this.punishment.isIP() && this.punishment.type != Punishment.Type.BLACKLIST) "${ChatColor.RED}[IP]" else ""}${if (this.punishment.type == Punishment.Type.GHOST_MUTE && player.hasPermission(this.punishment.type.permission(false))) "${ChatColor.GRAY}[Ghost]" else ""}" + } + + override fun getMaterial(p0: Player?): Material { + return if (this.punishment.type == Punishment.Type.KICK || this.punishment.type == Punishment.Type.WARN) Material.PAPER else Material.WOOL + } + + override fun getDescription(player: Player): MutableList { + + val lore = ArrayList() + + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.punishment.sender)}") + lore.add("${ChatColor.YELLOW}Server: ${ChatColor.RED}${this.punishment.server}") + lore.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.punishment.reason}") + + if (!this.punishment.isPermanent()) { + lore.add("${ChatColor.YELLOW}Duration: ${ChatColor.RED}${TimeUtil.formatIntoDetailedString(this.punishment.duration)}") + } + + when { + this.pardoned -> { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.RED}${ChatColor.BOLD}Pardoned") + lore.add(" ") + + lore.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.punishment.pardoner!!)}") + lore.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.punishment.pardonReason}") + lore.add(" ") + lore.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.punishment.pardoned!!))}") + } + this.voided -> { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.RED}${ChatColor.BOLD}Expired") + lore.add(" ") + lore.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.punishment.getExpiredAt()))}") + } + } + + if (this.canPardon) { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.RED}Click to pardon.") + } + + if (this.punishment.isEvidenceRequired()) { + + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + + if (this.punishment.sender == player.uniqueId && this.proofRequired) { + lore.add("${ChatColor.GREEN}${if (this.pardoned) "Click" else "Right click"} to post evidence.") + } else { + lore.add("${ChatColor.YELLOW}No evidence has been provided.") + } + + } + + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + + return lore + } + + override fun getDamageValue(player: Player?): Byte { + + var dyeColor = DyeColor.LIME + + when { + this.voided -> dyeColor = DyeColor.ORANGE + this.pardoned -> dyeColor = DyeColor.RED + } + + + return if (this.punishment.type == Punishment.Type.KICK || this.punishment.type == Punishment.Type.WARN) 0 else dyeColor.woolData + } + + override fun clicked(player: Player,slot: Int,click: ClickType) { + + if (this.pardoned && click.isLeftClick || !this.pardoned && click.isRightClick) { + PunishmentEvidenceMenu(this.punishment,this.parent).openMenu(player) + return + } + + if (!this.canPardon) { + return + } + + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(PunishmentRemoveReasonPrompt(this.punishment,this.mojangProfile)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/element/PunishmentElement.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/element/PunishmentElement.kt new file mode 100644 index 0000000..09b306e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/history/element/PunishmentElement.kt @@ -0,0 +1,41 @@ +package cc.fyre.venom.punishment.menu.history.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.history.HistoryMenu +import org.apache.commons.lang3.StringUtils +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 01/04/2020 + * @author xanderume@gmail.com + */ +class PunishmentElement(private val type: Punishment.Type,private val punishments: Set,private val mojangProfile: MojangProfile) : Button() { + + override fun getName(p0: Player?): String { + return "${this.type.color}${StringUtils.capitalize(this.type.name.toLowerCase().replace("_"," "))}s" + } + + override fun getMaterial(p0: Player?): Material { + return if (this.type == Punishment.Type.BLACKLIST) Material.BEDROCK else Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun getDamageValue(player: Player?): Byte { + return this.type.woolData.toByte() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType?) { + player.closeInventory() + HistoryMenu(this.type,this.punishments,this.mojangProfile).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/StaffHistoryMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/StaffHistoryMenu.kt new file mode 100644 index 0000000..3201626 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/StaffHistoryMenu.kt @@ -0,0 +1,55 @@ +package cc.fyre.venom.punishment.menu.staffhistory + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.staffhistory.StaffPunishmentMenu.RemoveType + +import cc.fyre.venom.punishment.menu.staffhistory.element.StaffHistoryButton +import org.apache.commons.lang3.StringUtils + +import org.bukkit.entity.Player + + +/** + * @project venom + * + * @date 04/04/2020 + * @author xanderume@gmail.com + */ +class StaffHistoryMenu(private val punishments: Set,private val filteredPunishments: Set,private val mojangProfile: MojangProfile) : PaginatedMenu() { + + var type: Punishment.Type? = null + var removeType: RemoveType? = null + + constructor(type: Punishment.Type,punishments: Set,filteredPunishments: Set,mojangProfile: MojangProfile):this(punishments,filteredPunishments,mojangProfile) { + this.type = type + } + + constructor(type: RemoveType,punishments: Set,filteredPunishments: Set,mojangProfile: MojangProfile):this(punishments,filteredPunishments,mojangProfile) { + this.removeType = type + } + + override fun getPrePaginatedTitle(p0: Player?): String { + return if (this.type != null) "${this.type!!.color}${StringUtils.capitalize(this.type!!.name.toLowerCase().replace("_"," "))}s" else "${this.removeType!!.parent[0].color}${StringUtils.capitalize(this.removeType!!.name.toLowerCase().replace("_",""))}s" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + val toReturn = HashMap() + + this.filteredPunishments.sortedByDescending{it.created}.forEach{toReturn[toReturn.size] = StaffHistoryButton(it,this.mojangProfile,this)} + + return toReturn + } + + override fun getGlobalButtons(player: Player?): MutableMap { + val toReturn = HashMap() + + toReturn[4] = BackButton(StaffPunishmentMenu(this.mojangProfile,this.punishments)) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/StaffPunishmentMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/StaffPunishmentMenu.kt new file mode 100644 index 0000000..7ea9401 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/StaffPunishmentMenu.kt @@ -0,0 +1,63 @@ +package cc.fyre.venom.punishment.menu.staffhistory + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment + +import cc.fyre.venom.punishment.menu.staffhistory.element.StaffPunishmentButton + +import org.bukkit.Material +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 04/04/2020 + * @author xanderume@gmail.com + */ +/* +* +* TODO: have shared classes. +* +* */ +class StaffPunishmentMenu(private val mojangProfile: MojangProfile,private val punishments: Set) : Menu() { + + override fun size(player: Player): Int { + return 5*9 + } + + override fun getTitle(player: Player): String { + return this.mojangProfile.displayName + } + + override fun getButtons(player: Player): MutableMap { + + val toReturn = HashMap() + + val types = Punishment.Type.values().filter{it != Punishment.Type.GHOST_MUTE && player.hasPermission(it.permission(false))}.sortedBy{it.ordinal}.reversed() + + var i = 0 + val start = 13 - (types.size - 1) + + types.forEach{toReturn[if (i == 0) start else (start + ((if (i == 0) 1 else i)) * 2)] = StaffPunishmentButton(types[i++],this.punishments,this.mojangProfile)} + + val removeTypes = RemoveType.values().sortedBy{it.ordinal}.reversed() + + var j = 0 + val removeStart = 31 - (removeTypes.size - 1) + + removeTypes.filter{player.hasPermission(it.parent[0].permission(false))}.forEach{toReturn[if (j == 0) removeStart else (removeStart + ((if (j == 0) 1 else j)) * 2)] = StaffPunishmentButton(removeTypes[j++],this.punishments,this.mojangProfile)} + + return toReturn + } + + enum class RemoveType(val parent: Array,val material: Material) { + + UN_MUTE(arrayOf(Punishment.Type.MUTE,Punishment.Type.GHOST_MUTE),Material.IRON_SWORD), + UN_BAN(arrayOf(Punishment.Type.BAN),Material.GOLD_SWORD), + UN_BLACKLIST(arrayOf(Punishment.Type.BLACKLIST),Material.DIAMOND_SWORD) + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/element/StaffHistoryButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/element/StaffHistoryButton.kt new file mode 100644 index 0000000..deb8e2e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/element/StaffHistoryButton.kt @@ -0,0 +1,143 @@ +package cc.fyre.venom.punishment.menu.staffhistory.element + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.evidence.PunishmentEvidenceMenu +import cc.fyre.venom.punishment.prompt.PunishmentRemoveReasonPrompt + +import cc.fyre.venom.util.TimeUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 04/04/2020 + * @author xanderume@gmail.com + */ +class StaffHistoryButton(private val punishment: Punishment,private val mojangProfile: MojangProfile,private val parent: Menu) : Button() { + + private val voided = this.punishment.isVoided() + private val pardoned = this.punishment.isPardoned() + + private var canPardon = false + private var proofRequired = false + + override fun getName(player: Player): String { + this.canPardon = !this.pardoned && !this.voided && this.punishment.type != Punishment.Type.KICK && this.punishment.type != Punishment.Type.WARN && player.hasPermission(this.punishment.type.permission(true)) + this.proofRequired = Venom.instance.api.grantHandler.findBestRank(player.uniqueId).isEvidenceRequired(this.punishment.type) + + return "${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.punishment.created))} ${if (this.punishment.isIP()) "${ChatColor.RED}[IP]" else ""}${if (this.punishment.type == Punishment.Type.GHOST_MUTE && player.hasPermission(this.punishment.type.permission(false))) "${ChatColor.GRAY}[Ghost]" else ""}" + } + + override fun getMaterial(player: Player): Material { + return if (this.punishment.type == Punishment.Type.KICK || this.punishment.type == Punishment.Type.WARN) Material.PAPER else Material.WOOL + } + + override fun getDescription(player: Player): MutableList { + + val lore = ArrayList() + + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + + var name = Venom.instance.api.profileHandler.findName(this.punishment.victim) + + if (name == "null") { + name = this.punishment.victim.toString() + } + + lore.add("${ChatColor.YELLOW}Victim: ${ChatColor.RED}${name}") + lore.add("${ChatColor.YELLOW}Server: ${ChatColor.RED}${this.punishment.server}") + lore.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.punishment.reason}") + + if (!this.punishment.isPermanent()) { + lore.add("${ChatColor.YELLOW}Duration: ${ChatColor.RED}${TimeUtil.formatIntoDetailedString(this.punishment.duration)}") + } + + when { + this.pardoned -> { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.RED}${ChatColor.BOLD}Pardoned") + lore.add(" ") + + lore.add("${ChatColor.YELLOW}By: ${ChatColor.RED}${Venom.instance.api.profileHandler.findName(this.punishment.pardoner!!)}") + lore.add("${ChatColor.YELLOW}Reason: ${ChatColor.RED}${this.punishment.pardonReason}") + lore.add(" ") + lore.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.punishment.pardoned!!))}") + } + this.voided -> { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.RED}${ChatColor.BOLD}Expired") + lore.add(" ") + lore.add("${ChatColor.GOLD}${TimeUtil.formatIntoCalendarString(Date(this.punishment.getExpiredAt()))}") + } + } + + if (this.canPardon) { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + lore.add("${ChatColor.GRAY}-> ${ChatColor.RED}Click to pardon.") + } + + if (this.punishment.isEvidenceRequired()) { + + if (!this.canPardon) { + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + } + + if (this.punishment.sender == player.uniqueId && this.proofRequired) { + lore.add("${ChatColor.GRAY}-> ${ChatColor.RED}${if (this.pardoned) "Click" else "Right click"} to post evidence.") + } else { + lore.add("${ChatColor.GRAY}-> ${ChatColor.RED}No evidence has been provided") + } + + } + + lore.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-", 18)}") + + return lore + } + + override fun getDamageValue(player: Player): Byte { + + var dyeColor = DyeColor.LIME + + + when { + this.voided -> dyeColor = DyeColor.ORANGE + this.pardoned -> dyeColor = DyeColor.RED + } + + return dyeColor.woolData + } + + override fun clicked(player: Player,slot: Int,click: ClickType) { + + val clickedForProof = this.pardoned && click.isLeftClick || !this.pardoned && click.isRightClick + + if (clickedForProof) { + PunishmentEvidenceMenu(this.punishment,this.parent).openMenu(player) + return + } + + if (!this.canPardon) { + return + } + + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(PunishmentRemoveReasonPrompt(this.punishment,this.mojangProfile)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/element/StaffPunishmentButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/element/StaffPunishmentButton.kt new file mode 100644 index 0000000..40d6638 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/menu/staffhistory/element/StaffPunishmentButton.kt @@ -0,0 +1,85 @@ +package cc.fyre.venom.punishment.menu.staffhistory.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment + +import cc.fyre.venom.punishment.menu.staffhistory.StaffHistoryMenu +import cc.fyre.venom.punishment.menu.staffhistory.StaffPunishmentMenu.RemoveType +import org.apache.commons.lang3.StringUtils + +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + + +/** + * @project venom + * + * @date 04/04/2020 + * @author xanderume@gmail.com + */ +class StaffPunishmentButton(private val punishments: Set,private val mojangProfile: MojangProfile) : Button() { + + var type: Punishment.Type? = null + var removeType: RemoveType? = null + var filteredPunishments: MutableSet = HashSet() + + constructor(type: Punishment.Type,punishments: Set,mojangProfile: MojangProfile):this(punishments,mojangProfile) { + this.type = type + this.filteredPunishments = punishments.filter{it.type == type && it.sender == this.mojangProfile.id}.toMutableSet() + } + + constructor(type: RemoveType,punishments: Set,mojangProfile: MojangProfile):this(punishments,mojangProfile) { + this.removeType = type + this.filteredPunishments = punishments.filter{it.isPardoned() && type.parent.contains(it.type) && it.pardoner!! == this.mojangProfile.id}.toMutableSet() + } + + override fun getName(p0: Player?): String { + + if (this.type != null) { + return "${this.type!!.color}${StringUtils.capitalize(this.type!!.name.toLowerCase().replace("_"," "))}s" + } + + return "${this.removeType!!.parent[0].color}${StringUtils.capitalize(this.removeType!!.name.toLowerCase().replace("_",""))}s" + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun getAmount(player: Player?): Int { + return if (this.filteredPunishments.size >= 64) 64 else if (this.filteredPunishments.isEmpty()) 1 else this.filteredPunishments.size + } + + override fun getMaterial(p0: Player?): Material { + + if (this.type != null) { + return if (this.type == Punishment.Type.BLACKLIST) Material.BEDROCK else Material.WOOL + } + + return this.removeType!!.material + } + + override fun getDamageValue(player: Player?): Byte { + + if (this.type != null) { + return this.type!!.woolData.toByte() + } + + return 0 + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + + player.closeInventory() + + if (this.type != null) { + StaffHistoryMenu(this.type!!,this.punishments,this.filteredPunishments,this.mojangProfile).openMenu(player) + } else { + StaffHistoryMenu(this.removeType!!,this.punishments,this.filteredPunishments,this.mojangProfile).openMenu(player) + } + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/parasite/PunishmentListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/parasite/PunishmentListener.kt new file mode 100644 index 0000000..8dafb66 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/parasite/PunishmentListener.kt @@ -0,0 +1,135 @@ +package cc.fyre.venom.punishment.parasite + + + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.Venom +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.TimeUtil + +import com.google.gson.JsonObject +import mkremins.fanciful.FancyMessage +import org.bukkit.ChatColor +import java.util.* +import kotlin.collections.ArrayList + +/** + * @project venom + * + * @date 10/05/2020 + * @author xanderume@gmail.com + */ +class PunishmentListener(private val instance: Venom) : ParasiteListener { + + @Parasite(Punishment.PACKET_ID) + fun onPunishment(data: JsonObject) { + + val punishment = this.instance.api.gson.fromJson(data, Punishment::class.java) + + val pardoned = punishment.isPardoned() + + val silent = if (pardoned) punishment.pardonedSilent else punishment.silent + + val fancyMessage = FancyMessage("${data["victimDisplay"].asString}${ChatColor.GREEN} has been${ChatColor.YELLOW}${if (silent) " silently" else ""}${ChatColor.GREEN} ${if (pardoned) "un" else ""}${punishment.type.context} by ${data["senderDisplay"].asString}${ChatColor.GREEN}.") + + if (punishment.type == Punishment.Type.MUTE || punishment.type == Punishment.Type.GHOST_MUTE) { + fancyMessage.tooltip("${ChatColor.YELLOW}Ghost: ${ChatColor.RED}${punishment.type == Punishment.Type.GHOST_MUTE}") + } + + fancyMessage.tooltip(this.tooltip(punishment)) + + this.instance.server.scheduler.runTask(this.instance) { + + this.instance.server.onlinePlayers.filter{ + + if (silent) { + return@filter it.hasPermission(punishment.type.permission(pardoned)) + } + + return@filter true + }.forEach{if (it.hasPermission(punishment.type.permission(pardoned))) fancyMessage.send(it) else it.sendMessage(fancyMessage.toOldMessageFormat())} + + } + + fancyMessage.send(this.instance.server.consoleSender) + + if (!punishment.type.kickOnExecute) { + + val victim = this.instance.server.getPlayer(punishment.victim) ?: return + + val message = if (punishment.isPardoned() && punishment.type == Punishment.Type.MUTE) "${ChatColor.RED}You are no longer silenced." else getPunishmentMessage(punishment) + + if (message != null) { + victim.sendMessage(message) + } + + this.instance.api.punishmentHandler.mutes[punishment.victim]!!.removeIf{it.id == punishment.id} + this.instance.api.punishmentHandler.mutes[punishment.victim]!!.add(punishment) + return + } + + if (punishment.isPardoned()) { + return + } + + if (!punishment.isIP()) { + + val victim = this.instance.server.getPlayer(punishment.victim) ?: return + + this.instance.server.scheduler.runTask(this.instance) {victim.kickPlayer(getPunishmentKickMessage(victim.uniqueId,punishment,true))} + return + } + + val victims = this.instance.server.onlinePlayers.filter{it.uniqueId == punishment.victim || punishment.identifiers.contains(it.address.address.hostAddress)} + + this.instance.server.scheduler.runTask(this.instance){victims.forEach{it.kickPlayer(getPunishmentKickMessage(it.uniqueId,punishment,true))}} + } + + private fun tooltip(punishment: Punishment):ArrayList { + + val server = "${ChatColor.YELLOW}Server: ${ChatColor.RED}${punishment.server}" + val reason = "${ChatColor.YELLOW}Reason: ${ChatColor.RED}${if (punishment.isPardoned()) punishment.pardonReason else punishment.reason}" + + if (punishment.type == Punishment.Type.KICK || punishment.type == Punishment.Type.WARN || punishment.isPardoned()) { + return arrayListOf(server,reason) + } + + val duration = "${ChatColor.YELLOW}Duration: ${ChatColor.RED}${if (punishment.isPermanent()) "Forever" else TimeUtil.formatIntoDetailedString(punishment.duration)}" + + return arrayListOf(server,reason,duration) + } + + companion object { + + fun getPunishmentMessage(punishment: Punishment):String? { + + if (punishment.type == Punishment.Type.WARN) { + return "${ChatColor.RED}You have been warned: ${ChatColor.WHITE}${punishment.reason}" + } + + if (punishment.type == Punishment.Type.MUTE) { + return "${ChatColor.RED}${if (punishment.isPermanent()) "You have been permanently silenced." else "You have been silenced for ${ChatColor.RED}${ChatColor.BOLD}${TimeUtil.formatIntoDetailedString(punishment.duration)}${ChatColor.RED}."}" + } + + return null + } + + fun getPunishmentKickMessage(victim: UUID, punishment: Punishment, online: Boolean):String { + + if (punishment.type == Punishment.Type.KICK){ + return "${ChatColor.RED}You have been kicked: ${ChatColor.WHITE}${punishment.reason}" + } + + var toReturn = if (victim == punishment.victim) "Your account has been ${if (punishment.type == Punishment.Type.BLACKLIST) "blacklisted" else "suspended"} from LushPvP" else "Your account has been ${if (punishment.type == Punishment.Type.BLACKLIST) "blacklisted" else "suspended"} due to a punishment related to ${Venom.instance.api.profileHandler.findName(punishment.victim)}" + + if (!punishment.isPermanent()) { + toReturn += "\n\n Expires: ${ChatColor.YELLOW}${TimeUtil.formatIntoDetailedString(if (online) punishment.duration else punishment.getRemaining())}" + } + + return "${ChatColor.RED}$toReturn" + } + + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/prompt/PunishmentEvidencePrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/prompt/PunishmentEvidencePrompt.kt new file mode 100644 index 0000000..c9a052d --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/prompt/PunishmentEvidencePrompt.kt @@ -0,0 +1,58 @@ +package cc.fyre.venom.punishment.prompt + +import cc.fyre.proton.menu.Menu +import cc.fyre.venom.Venom + +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.punishment.menu.evidence.PunishmentEvidenceMenu +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player +import java.util.regex.Pattern + +/** + * @project venom + * + * @date 27/06/2020 + * @author xanderume@gmail.com + */ +class PunishmentEvidencePrompt(private val punishment: Punishment,private val previous: Menu) : StringPrompt() { + + companion object { + + val LINK_FILTER: Pattern = Pattern.compile("^(http://www\\.|https://www\\.|http://|https://)?[a-z0-9]+([\\-.][a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$") + + } + + override fun getPromptText(context: ConversationContext): String { + return "${ChatColor.YELLOW}Please provide an url to provide evidence for this punishment, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(context: ConversationContext, input: String): Prompt? { + + val player = context.forWhom as Player + + if (input.equals("cancel",true)) { + context.forWhom.sendRawMessage("${ChatColor.RED}Cancelled providing evidence.") + } else if (!LINK_FILTER.matcher(input).matches()) { + context.forWhom.sendRawMessage("${ChatColor.RED}This link is invalid.") + } else { + this.punishment.evidence.add(Punishment.Evidence(input,player.uniqueId)) + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + + if (!Venom.instance.api.punishmentHandler.repository.update(this.punishment)) { + player.sendMessage("${ChatColor.RED}There was an issue providing evidence, please contact an owner/developer if this keeps occuring.") + } + + PunishmentEvidenceMenu(this.punishment,this.previous).openMenu(player) + } + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/prompt/PunishmentRemoveReasonPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/prompt/PunishmentRemoveReasonPrompt.kt new file mode 100644 index 0000000..97f25b5 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/punishment/prompt/PunishmentRemoveReasonPrompt.kt @@ -0,0 +1,40 @@ +package cc.fyre.venom.punishment.prompt + +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.mojang.MojangProfile +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.util.PlayerUtil +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 01/04/2020 + * @author xanderume@gmail.com + */ +class PunishmentRemoveReasonPrompt(private val punishment: Punishment,private val mojangProfile: MojangProfile) : StringPrompt() { + + override fun getPromptText(context: ConversationContext): String { + return "${ChatColor.YELLOW}Please type a reason for this punishment to be pardoned, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(context: ConversationContext, input: String): Prompt? { + + if (input.equals("cancel",true)) { + context.forWhom.sendRawMessage("${ChatColor.RED}Cancelled pardoning punishment.") + return Prompt.END_OF_CONVERSATION + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.punishmentHandler.pardon(this.punishment,(context.forWhom as Player).uniqueId,input,true,PlayerUtil.getDisplayName(this.mojangProfile.id,this.mojangProfile.name,Venom.instance.serverHandler.server),PlayerUtil.getDisplayName((context.forWhom as Player).uniqueId,((context.forWhom as Player).name),Venom.instance.serverHandler.server)) + } + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/command/RankCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/command/RankCommand.kt new file mode 100644 index 0000000..7b1f746 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/command/RankCommand.kt @@ -0,0 +1,21 @@ +package cc.fyre.venom.rank.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.rank.menu.RankEditorMenu +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +object RankCommand { + + @JvmStatic + @Command(names = ["rank"],hidden = true,permission = "command.rank",description = "") + fun execute(player: Player) { + RankEditorMenu().openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/command/RankScanCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/command/RankScanCommand.kt new file mode 100644 index 0000000..86f0603 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/command/RankScanCommand.kt @@ -0,0 +1,65 @@ +package cc.fyre.venom.rank.command + +import cc.fyre.proton.command.Command +import cc.fyre.proton.command.param.Parameter +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.util.PlayerUtil +import com.mongodb.client.model.Filters +import org.apache.commons.lang.StringUtils + +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import java.util.* +import kotlin.collections.HashMap +import kotlin.system.measureTimeMillis + +/** + * @project venom + * + * @date 05/06/2020 + * @author xanderume@gmail.com + */ +object RankScanCommand { + + @JvmStatic + @Command(names = ["rank scan"],async = true,hidden = true,permission = "command.rank.scan") + fun execute(sender: CommandSender,@Parameter(name = "rank")rank: Rank) { + + val scanned = HashMap() + + val time = measureTimeMillis{ + + for (document in Venom.instance.api.grantHandler.repository.collection.find(Filters.eq("rank",rank.id)).iterator()) { + + val grant = Venom.instance.api.gson.fromJson(document.toJson(),Grant::class.java) + + if (grant.isRemoved() || grant.isVoided()) { + continue + } + + if (scanned.containsKey(grant.target)) { + scanned[grant.target] = scanned[grant.target]!! + 1 + continue + } + + scanned[grant.target] = 1 + } + + } + + if (scanned.isEmpty()) { + sender.sendMessage("${ChatColor.RED}No player has ${rank.getDisplayName()}${ChatColor.RED} granted.") + return + } + + scanned.entries.forEach{ + sender.sendMessage("${PlayerUtil.getDisplayName(it.key,Venom.instance.serverHandler.server)} ${ChatColor.GREEN}has ${ChatColor.RED}${it.value} ${rank.getDisplayName()}${ChatColor.GREEN} grant${if (it.value == 1) "" else "s"}.") + } + + sender.sendMessage("${ChatColor.YELLOW}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",25)}") + sender.sendMessage("${ChatColor.GREEN}Scanned ranks in ${ChatColor.RED}${time}ms${ChatColor.GREEN}.") + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankCreateEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankCreateEvent.kt new file mode 100644 index 0000000..36b9df2 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankCreateEvent.kt @@ -0,0 +1,24 @@ +package cc.fyre.venom.rank.event + +import cc.fyre.venom.rank.data.Rank + +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 29/04/2020 + * @author xanderume@gmail.com + */ +class RankCreateEvent(val rank: Rank) : Event() { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankDeleteEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankDeleteEvent.kt new file mode 100644 index 0000000..e917df4 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankDeleteEvent.kt @@ -0,0 +1,23 @@ +package cc.fyre.venom.rank.event + +import cc.fyre.venom.rank.data.Rank +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 29/04/2020 + * @author xanderume@gmail.com + */ +class RankDeleteEvent(val rank: Rank) : Event() { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankUpdateEvent.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankUpdateEvent.kt new file mode 100644 index 0000000..6ba2a21 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/event/RankUpdateEvent.kt @@ -0,0 +1,23 @@ +package cc.fyre.venom.rank.event + +import cc.fyre.venom.rank.data.Rank +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +/** + * @project venom + * + * @date 29/04/2020 + * @author xanderume@gmail.com + */ +class RankUpdateEvent(val rank: Rank) : Event() { + + override fun getHandlers(): HandlerList { + return handlerList + } + + companion object { + @JvmStatic val handlerList = HandlerList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/RankEditMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/RankEditMenu.kt new file mode 100644 index 0000000..3c73be6 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/RankEditMenu.kt @@ -0,0 +1,104 @@ +package cc.fyre.venom.rank.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.edit.* +import cc.fyre.venom.rank.menu.element.create.RankFinishButton +import cc.fyre.venom.rank.menu.element.edit.RankEditButton +import cc.fyre.venom.rank.prompt.RankEditPrompt +import cc.fyre.venom.rank.prompt.RankPermissionPrompt +import cc.fyre.venom.util.ColorUtil +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import java.util.function.BiFunction +import java.util.function.BiPredicate + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankEditMenu(private val rank: Rank) : Menu() { + + override fun getTitle(player: Player): String { + return "Editor - ${this.rank.getDisplayName()}" + } + + override fun getButtons(player: Player): MutableMap { + val toReturn = HashMap() + + toReturn[toReturn.size] = RankEditButton(this.rank,"Color","${this.rank.color}${ColorUtil.getName(ChatColor.getByChar(this.rank.color[1]))}",Material.WOOL,0,BiPredicate{ _,_ -> return@BiPredicate false},RankEditPrompt(this.rank,"color",BiFunction{ rank,pair -> + + if (ChatColor.stripColor(pair.second.replace('&','§')) != "") { + pair.first.forWhom.sendRawMessage("${ChatColor.RED}Invalid color combination.") + return@BiFunction false + } + + rank.color = pair.second + + return@BiFunction true + })) + + toReturn[toReturn.size] = RankEditButton(this.rank,"Prefix",this.rank.prefix,Material.PAINTING,0,BiPredicate{ _,_ -> return@BiPredicate false},RankEditPrompt(this.rank,"prefix",BiFunction{ rank,pair -> + rank.prefix = pair.second + + return@BiFunction true + })) + + toReturn[toReturn.size] = RankEditButton(this.rank,"Priority",this.rank.priority,Material.GOLD_NUGGET,BiPredicate{ rank,click -> + + when { + click.isLeftClick -> rank.priority += if (click.isShiftClick) 10 else 1 + click.isRightClick -> rank.priority -= if (click.isShiftClick) 10 else 1 + click == ClickType.MIDDLE -> rank.priority = 0 + } + + return@BiPredicate true + }) + + + toReturn[toReturn.size] = RankEditButton(this.rank,"Permissions",this.rank.permissions.size,Material.PAPER,0,BiPredicate { rank,click -> + + if (click.isLeftClick) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(RankPermissionPrompt(rank)).withEscapeSequence("/no").withLocalEcho(false).withTimeout(300).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } else if (click.isRightClick) { + player.closeInventory() + RankPermissionMenu(this.rank).openMenu(player) + } + + return@BiPredicate true + }) + + toReturn[toReturn.size] = RankEditButton(this.rank,"Inherits",this.rank.inherits.size,Material.LADDER,0,BiPredicate{ _,_ -> + player.closeInventory() + RankInheritsMenu(this.rank).openMenu(player) + return@BiPredicate true + }) + + toReturn[toReturn.size] = RankEditButton(this.rank,"Metadata",this.rank.metadata.size,Material.ANVIL,0,BiPredicate{ _,_ -> + player.closeInventory() + RankMetadataMenu(this.rank).openMenu(player) + return@BiPredicate true + }) + + toReturn[toReturn.size] = RankEditButton(this.rank,"Proof Meta's",this.rank.evidenceRequired.size,Material.TRIPWIRE_HOOK,0,BiPredicate{ _,_ -> + player.closeInventory() + RankEvidenceMenu(this.rank).openMenu(player) + return@BiPredicate true + }) + + toReturn[8] = if (Venom.instance.api.rankHandler.cache.contains(this.rank.id.toLowerCase())) BackButton(RankEditorMenu()) else RankFinishButton(this.rank) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/RankEditorMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/RankEditorMenu.kt new file mode 100644 index 0000000..c43b99b --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/RankEditorMenu.kt @@ -0,0 +1,41 @@ +package cc.fyre.venom.rank.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom + +import cc.fyre.venom.rank.menu.element.RankButton +import cc.fyre.venom.rank.menu.element.create.RankCreateButton + +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankEditorMenu : PaginatedMenu() { + + override fun getMaxItemsPerPage(player: Player): Int { + return 27 + } + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Rank Editor" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + return Venom.instance.api.rankHandler.cache.values.sortedByDescending{it.priority}.withIndex().associate{it.index to RankButton(it.value)}.toMutableMap() + } + + override fun getGlobalButtons(player: Player?): MutableMap { + + val toReturn = HashMap() + + toReturn[4] = RankCreateButton() + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/create/RankFinishMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/create/RankFinishMenu.kt new file mode 100644 index 0000000..09951c9 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/create/RankFinishMenu.kt @@ -0,0 +1,41 @@ +package cc.fyre.venom.rank.menu.create + +import cc.fyre.proton.menu.menus.ConfirmMenu +import cc.fyre.proton.util.Callback +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditorMenu + +import cc.fyre.symbiote.Symbiote + +import org.bukkit.Bukkit +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankFinishMenu(rank: Rank,player: Player) : ConfirmMenu("Create Rank ${rank.getDisplayName()}",object : + Callback { + + override fun callback(value: Boolean) { + + if (!value) { + RankEditorMenu().openMenu(player) + return + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,rank)) + } + + //Wait a bit as redis needs to sync + Venom.instance.server.scheduler.runTaskLater(Venom.instance,{ + RankEditorMenu().openMenu(player) + },5L) + } + +}) \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/delete/RankDeleteMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/delete/RankDeleteMenu.kt new file mode 100644 index 0000000..a83231b --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/delete/RankDeleteMenu.kt @@ -0,0 +1,38 @@ +package cc.fyre.venom.rank.menu.delete + +import cc.fyre.proton.menu.menus.ConfirmMenu +import cc.fyre.proton.util.Callback +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditorMenu +import cc.fyre.symbiote.Symbiote +import org.bukkit.Bukkit + +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class RankDeleteMenu(rank: Rank,player: Player) : ConfirmMenu("Delete Rank ${rank.getDisplayName()}",object : + Callback { + + override fun callback(value: Boolean) { + + if (!value) { + RankEditorMenu().openMenu(player) + return + } + + Venom.instance.api.rankHandler.cache.remove(rank.id.toLowerCase()) + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.delete(rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.DELETE_ID,rank)) + } + + } + +}) \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankEvidenceMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankEvidenceMenu.kt new file mode 100644 index 0000000..e7a166c --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankEvidenceMenu.kt @@ -0,0 +1,86 @@ +package cc.fyre.venom.rank.menu.edit + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom +import cc.fyre.venom.punishment.data.Punishment +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.symbiote.Symbiote +import org.apache.commons.lang.StringUtils +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.DyeColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 12/07/2020 + * @author xanderume@gmail.com + */ +class RankEvidenceMenu(private val rank: Rank) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Proof Meta's" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + val toReturn = HashMap() + + Punishment.Type.values().forEach{ + + val name = StringUtils.capitalize(it.name.toLowerCase().replace("_"," ")) + val allowed = rank.evidenceRequired.contains(it) + + toReturn[toReturn.size] = object : Button() { + + override fun getName(p0: Player?): String { + return "${if (allowed) ChatColor.GREEN else ChatColor.RED}${ChatColor.BOLD}${name}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun getDamageValue(player: Player?): Byte { + return (if (allowed) DyeColor.LIME.woolData else DyeColor.GRAY.woolData) + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType?) { + + if (allowed) { + this@RankEvidenceMenu.rank.evidenceRequired.remove(it) + } else { + this@RankEvidenceMenu.rank.evidenceRequired.add(it) + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(this@RankEvidenceMenu.rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,this@RankEvidenceMenu.rank)) + } + + } + } + } + + return toReturn + } + + override fun getGlobalButtons(player: Player?): MutableMap { + + val toReturn = HashMap() + + toReturn[4] = BackButton(RankEditMenu(this.rank)) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankInheritsMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankInheritsMenu.kt new file mode 100644 index 0000000..e59b126 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankInheritsMenu.kt @@ -0,0 +1,73 @@ +package cc.fyre.venom.rank.menu.edit + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.symbiote.Symbiote +import org.bukkit.Bukkit +import org.bukkit.Material + +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class RankInheritsMenu(private val rank: Rank) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Inherits" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + val toReturn = HashMap() + + Venom.instance.api.rankHandler.cache.values.filter{it.id != this.rank.id}.sortedBy{it.priority}.forEach{toReturn[toReturn.size] = object : Button() { + + override fun getName(p0: Player?): String { + return it.getDisplayName() + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + return ArrayList() + } + + override fun clicked(player: Player?,slot: Int,clickType: ClickType?) { + + if (!rank.inherits.contains(it.id)) { + rank.inherits.add(it.id) + } else { + rank.inherits.remove(it.id) + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(this@RankInheritsMenu.rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,this@RankInheritsMenu.rank)) + } + + } + + }} + + return toReturn + } + + override fun getGlobalButtons(player: Player?): MutableMap { + val toReturn = HashMap() + + toReturn[4] = BackButton(RankEditMenu(this.rank)) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankMetadataMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankMetadataMenu.kt new file mode 100644 index 0000000..7a27dcd --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankMetadataMenu.kt @@ -0,0 +1,78 @@ +package cc.fyre.venom.rank.menu.edit + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.symbiote.Symbiote + +import org.bukkit.Bukkit +import org.bukkit.ChatColor + +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 03/05/2020 + * @author xanderume@gmail.com + */ +class RankMetadataMenu(private val rank: Rank) : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Metadata" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + + val toReturn = HashMap() + + for (value in Rank.Metadata.values()) { + + toReturn[toReturn.size] = object : Button() { + + override fun getName(p0: Player?): String { + return "${if (rank.hasMetadata(value)) ChatColor.GREEN else ChatColor.RED}${ChatColor.BOLD}${value.displayName}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.valueOf(value.icon) + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType?) { + + if (!rank.metadata.contains(value)) { + rank.metadata.add(value) + } else { + rank.metadata.remove(value) + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,rank)) + } + + } + } + } + + return toReturn + } + + override fun getGlobalButtons(player: Player?): MutableMap { + val toReturn = HashMap() + + toReturn[4] = BackButton(RankEditMenu(this.rank)) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankPermissionMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankPermissionMenu.kt new file mode 100644 index 0000000..5c55f31 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/edit/RankPermissionMenu.kt @@ -0,0 +1,71 @@ +package cc.fyre.venom.rank.menu.edit + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.symbiote.Symbiote +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class RankPermissionMenu(private val rank: Rank) : PaginatedMenu() { + + override fun getPrePaginatedTitle(player: Player): String { + return "Permissions" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + + val toReturn = HashMap() + + this.rank.permissions.sortedBy{it}.forEach{toReturn[toReturn.size] = object : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.AQUA}${it}" + } + + override fun getMaterial(p0: Player?): Material { + return Material.BOOK + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + + this@RankPermissionMenu.rank.permissions.remove(it) + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(this@RankPermissionMenu.rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,rank)) + } + + player.sendMessage("${ChatColor.RED}Removed permission ${ChatColor.WHITE}${it}${ChatColor.RED} from ${this@RankPermissionMenu.rank.getDisplayName()}${ChatColor.RED}.") + } + }} + + return toReturn + } + + override fun getGlobalButtons(player: Player?): MutableMap { + + val toReturn = HashMap() + + toReturn[4] = BackButton(RankEditMenu(this.rank)) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/RankButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/RankButton.kt new file mode 100644 index 0000000..48a72b7 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/RankButton.kt @@ -0,0 +1,72 @@ +package cc.fyre.venom.rank.menu.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.venom.rank.menu.delete.RankDeleteMenu +import cc.fyre.venom.util.ColorUtil +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor + +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankButton(private val rank: Rank) : Button() { + + override fun getName(p0: Player?): String { + return this.rank.getDisplayName() + } + + override fun getMaterial(p0: Player?): Material { + return Material.WOOL + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add("${ChatColor.GRAY}") + toReturn.add("${ChatColor.GRAY}Color: ${this.rank.color}${ColorUtil.getName(ChatColor.getByChar(this.rank.color[1]))}") + toReturn.add("${ChatColor.GRAY}Prefix: ${if (this.rank.prefix == "") "${ChatColor.RED}None" else this.rank.prefix}") + toReturn.add("${ChatColor.GRAY}") + toReturn.add("${ChatColor.GRAY}Priority: ${ChatColor.YELLOW}${this.rank.priority}") + toReturn.add("${ChatColor.GRAY}Inherits: ${ChatColor.YELLOW}${this.rank.inherits.size}") + toReturn.add("${ChatColor.GRAY}Permissions: ${ChatColor.YELLOW}${this.rank.permissions.size}") + toReturn.add("${ChatColor.GRAY}") + toReturn.add("${ChatColor.GRAY}Click to view the ${this.rank.color}${this.rank.getDisplayName()}${ChatColor.GRAY} rank.") + + return toReturn + } + + override fun getDamageValue(player: Player?): Byte { + + if (this.rank.color.isEmpty()) { + return 0 + } + + return ColorUtil.findDyeColorByChar(this.rank.color[1]).woolData + } + + override fun clicked(player: Player,slot: Int,click: ClickType) { + if (click.isLeftClick) { + player.closeInventory() + RankEditMenu(this.rank).openMenu(player) + } else if (click.isRightClick && click.isShiftClick) { + + if (this.rank.isDefault()) { + return + } + + player.closeInventory() + RankDeleteMenu(this.rank,player).openMenu(player) + } + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/create/RankCreateButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/create/RankCreateButton.kt new file mode 100644 index 0000000..4016554 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/create/RankCreateButton.kt @@ -0,0 +1,37 @@ +package cc.fyre.venom.rank.menu.element.create + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.prompt.RankCreatePrompt +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankCreateButton : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.GREEN}Create Rank" + } + + override fun getMaterial(p0: Player?): Material { + return Material.NETHER_STAR + } + + override fun getDescription(p0: Player?): MutableList { + return ArrayList() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType?) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(RankCreatePrompt()).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/create/RankFinishButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/create/RankFinishButton.kt new file mode 100644 index 0000000..d1a76f6 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/create/RankFinishButton.kt @@ -0,0 +1,35 @@ +package cc.fyre.venom.rank.menu.element.create + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.create.RankFinishMenu +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankFinishButton(private val rank: Rank) : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.GREEN}Finish?" + } + + override fun getMaterial(p0: Player?): Material { + return Material.FIREWORK_CHARGE + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun clicked(player: Player,slot: Int,click: ClickType) { + player.closeInventory() + RankFinishMenu(this.rank,player).openMenu(player) + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/edit/RankEditButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/edit/RankEditButton.kt new file mode 100644 index 0000000..2bd0eca --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/menu/element/edit/RankEditButton.kt @@ -0,0 +1,79 @@ +package cc.fyre.venom.rank.menu.element.edit +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.symbiote.Symbiote +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.conversations.Prompt +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +import java.util.function.BiPredicate + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankEditButton(private val rank: Rank,private val trait: String,private val currentValue: Any,private val material: Material,private val predicate: BiPredicate) : Button() { + + private var data = 0 + private var prompt: Prompt? = null + + constructor(rank: Rank,trait: String,currentValue: Any,material: Material,data: Int,predicate: BiPredicate):this(rank,trait,currentValue,material,predicate) { + this.data = data + } + + constructor(rank: Rank,trait: String,currentValue: Any,material: Material,data: Int,predicate: BiPredicate,prompt: Prompt):this(rank,trait,currentValue,material,predicate) { + this.data = data + this.prompt = prompt + } + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}Edit ${this.trait}" + } + + override fun getMaterial(p0: Player?): Material { + return this.material + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add(" ") + toReturn.add("${ChatColor.YELLOW}Current: ${ChatColor.RED}${if (this.currentValue is String && this.currentValue == "") "None" else this.currentValue}") + + return toReturn + } + + override fun clicked(player: Player,slot: Int,click: ClickType) { + + if (!this.predicate.test(this.rank,click)) { + + if (this.prompt != null) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(this.prompt).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } + + return + } + + if (!Venom.instance.api.rankHandler.cache.contains(this.rank.id.toLowerCase())) { + return + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(this.rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,this.rank)) + } + + return + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankCreatePrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankCreatePrompt.kt new file mode 100644 index 0000000..e27e53b --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankCreatePrompt.kt @@ -0,0 +1,41 @@ +package cc.fyre.venom.rank.prompt + +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankCreatePrompt : StringPrompt() { + + override fun getPromptText(conversationText: ConversationContext): String { + return "${ChatColor.YELLOW}Please type a name this rank, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(conversationContext: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}Cancelled creating rank.") + return Prompt.END_OF_CONVERSATION + } + + if (Venom.instance.api.rankHandler.findById(input) != null) { + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}This rank already exists.") + return Prompt.END_OF_CONVERSATION + } + + RankEditMenu(Rank(input)).openMenu(conversationContext.forWhom as Player) + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankEditPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankEditPrompt.kt new file mode 100644 index 0000000..c37e3bc --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankEditPrompt.kt @@ -0,0 +1,49 @@ +package cc.fyre.venom.rank.prompt + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player +import java.util.function.BiFunction +import java.util.function.BiPredicate + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +class RankEditPrompt(private val rank: Rank,private val trait: String,private val predicate: BiFunction,Boolean>) : StringPrompt() { + + override fun getPromptText(conversationText: ConversationContext): String { + + return this.getCustomPrompt(conversationText) ?: "${ChatColor.YELLOW}Please type a ${this.trait} for this rank, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + fun getCustomPrompt(conversationText: ConversationContext):String? = null + + override fun acceptInput(conversationContext: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}Cancelled changing ${this.trait}.") + } else if (this.predicate.apply(this.rank,Pair(conversationContext,input)) && Venom.instance.api.rankHandler.cache.contains(this.rank.id.toLowerCase())) { + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(this.rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,this.rank)) + } + + } + + RankEditMenu(this.rank).openMenu(conversationContext.forWhom as Player) + + return Prompt.END_OF_CONVERSATION + } + +} diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankPermissionPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankPermissionPrompt.kt new file mode 100644 index 0000000..953c013 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/prompt/RankPermissionPrompt.kt @@ -0,0 +1,52 @@ +package cc.fyre.venom.rank.prompt + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 02/04/2020 + * @author xanderume@gmail.com + */ +class RankPermissionPrompt(private val rank: Rank) : StringPrompt() { + + override fun getPromptText(conversationText: ConversationContext): String { + return "${ChatColor.YELLOW}Please type all permissions you want to add for this rank splitted by a \",\", or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(conversationContext: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + RankEditMenu(this.rank).openMenu(conversationContext.forWhom as Player) + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}Cancelled adding permissions.") + return Prompt.END_OF_CONVERSATION + } + + val permissions = if (input.contains(",")) input.split(',').toMutableList() else mutableListOf(input) + + permissions.filter{!this.rank.permissions.contains(it)}.forEach{this.rank.permissions.add(it)} + + if (Venom.instance.api.rankHandler.cache.contains(this.rank.id.toLowerCase())) { + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.rankHandler.repository.update(this.rank) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(Rank.UPDATE_ID,this.rank)) + } + + } + + RankEditMenu(this.rank).openMenu(conversationContext.forWhom as Player) + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/provider/RankParameterProvider.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/provider/RankParameterProvider.kt new file mode 100644 index 0000000..dd2f9d6 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/rank/provider/RankParameterProvider.kt @@ -0,0 +1,35 @@ +package cc.fyre.venom.rank.provider + +import cc.fyre.proton.command.param.ParameterType +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import com.mysql.jdbc.StringUtils +import org.bukkit.ChatColor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 31/03/2020 + * @author xanderume@gmail.com + */ +class RankParameterProvider : ParameterType { + + override fun transform(sender: CommandSender,source: String): Rank? { + + val toReturn = Venom.instance.api.rankHandler.findById(source) + + if (toReturn == null) { + sender.sendMessage("${ChatColor.RED}Rank ${ChatColor.YELLOW}$source ${ChatColor.RED}not found.") + return null + } + + return toReturn + } + + override fun tabComplete(player: Player, flags: Set, source: String): List { + return Venom.instance.api.rankHandler.cache.values.filter{StringUtils.startsWithIgnoreCase(it.id,source)}.sortedBy{it.priority}.reversed().map{it.id}.toList() + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/server/ServerHandler.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/server/ServerHandler.kt new file mode 100644 index 0000000..70df59a --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/server/ServerHandler.kt @@ -0,0 +1,142 @@ +package cc.fyre.venom.server + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.network.data.Group +import cc.fyre.venom.network.data.Server +import cc.fyre.venom.network.data.Status +import cc.fyre.venom.server.listener.ServerListener +import com.google.gson.JsonObject +import mkremins.fanciful.FancyMessage +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import java.net.InetAddress +import java.util.* + +import java.util.concurrent.atomic.AtomicBoolean + +import java.util.concurrent.atomic.AtomicInteger +import kotlin.collections.ArrayList +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 20/03/2020 + * @author xanderume@gmail.com + */ +class ServerHandler(private val instance: Venom) { + + val server: Server + + val serverID = this.instance.config.getString("id","unnamed") + val serverName = this.instance.config.getString("name","LushPvP") + val serverGroup = this.instance.config.getString("group","unknown") + + val chatFormatText = this.instance.config.getString("chatFormat.text","{rank}{prefix}{name}&f: {message}") + val chatFormatEnabled = this.instance.config.getBoolean("chatFormat.enabled",true) + + private var announcement = 0 + + private var postTaskId = this.instance.server.scheduler.runTaskTimer(this.instance,{this.post()},90L*20L,90L*20L).taskId + private var updateTaskId = this.instance.server.scheduler.runTaskTimerAsynchronously(this.instance,{this.update()},60L,40L).taskId + + private var initialized = false + + init { + this.server = Server(this.serverID,this.instance.server.port,this.serverGroup) + this.instance.api.databaseHandler.symbiote.addListener(ServerListener(this.instance)) + + if (this.instance.api.networkHandler.findGroupById(this.serverGroup) == null) { + this.instance.api.networkHandler.update(Group(this.serverGroup)) + } + + this.initialized = true + } + + fun dispose() { + + if (!this.initialized) { + return + } + + this.instance.server.scheduler.cancelTask(this.postTaskId) + this.instance.server.scheduler.cancelTask(this.updateTaskId) + + this.server.group = this.serverGroup + this.server.update = System.currentTimeMillis() + this.server.status = Status.OFFLINE + this.server.onlinePlayers.clear() + + this.instance.api.networkHandler.update(this.server) + } + + private fun post() { + + val announcements = this.findAnnouncements() + + if (announcements.isEmpty()) { + return + } + + if (this.announcement >= announcements.size) { + this.announcement = 0 + } + + announcements[this.announcement++].forEach{this.instance.server.broadcastMessage(ChatColor.translateAlternateColorCodes('&',it))} + } + + private fun update() { + + val whitelist = this.instance.server.whitelistedPlayers.map{it.uniqueId}.toHashSet() + + whitelist.addAll(this.instance.server.operators.map{it.uniqueId}.filter{!whitelist.contains(it)}) + + this.server.update = System.currentTimeMillis() + this.server.status = if (this.instance.server.hasWhitelist()) Status.WHITELISTED else Status.ONLINE + this.server.onlinePlayers = this.instance.server.onlinePlayers.map{it.uniqueId}.toHashSet() + this.server.maximumPlayers = this.instance.server.maxPlayers + this.server.whitelistedPlayers = whitelist + this.server.ticksPerSecond = doubleArrayOf(20.0,20.0,20.0) + + this.instance.api.networkHandler.update(this.server) + this.instance.api.networkHandler.server = this.server + } + + private fun findAnnouncements():ArrayList> { + return this.instance.api.networkHandler.findGroupById(this.serverGroup)?.announcements ?: ArrayList() + } + + fun sendMessageToNetwork(message: FancyMessage,async: Boolean = false) { + this.sendMessageToNetwork(message,null,async) + } + + fun sendMessageToNetwork(message: FancyMessage,permission: String?,async: Boolean = true) { + + val payload = JsonObject() + + if (permission != null) { + payload.addProperty("permission",permission) + } + + payload.addProperty("message",message.toJSONString()) + + val runnable = Runnable{ + this.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(MESSAGE_ID,payload)) + } + + if (async) { + Bukkit.getServer().scheduler.runTaskAsynchronously(this.instance,runnable) + } else { + runnable.run() + } + + } + + companion object { + + val replies = HashMap() + + const val MESSAGE_ID = "NETWORK_MESSAGE" + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/server/listener/ServerListener.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/server/listener/ServerListener.kt new file mode 100644 index 0000000..5a75eeb --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/server/listener/ServerListener.kt @@ -0,0 +1,69 @@ +package cc.fyre.venom.server.listener + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.Venom +import cc.fyre.venom.network.NetworkHandler +import cc.fyre.venom.server.ServerHandler +import com.google.gson.JsonObject +import mkremins.fanciful.FancyMessage +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import java.util.* + +/** + * @project venom + * + * @date 01/03/2021 + * @author xanderume@gmail.com + */ +class ServerListener(private val instance: Venom) : ParasiteListener { + + @Parasite(NetworkHandler.NETWORK_JOIN_PACKET) + fun onNetworkJoin(data: JsonObject) { + + val server = this.instance.api.networkHandler.findServerById(data["to"].asString) ?: return + + this.broadcast(data["displayName"].asString,null,server.id) + Bukkit.getServer().operators.add(Bukkit.getOfflinePlayer("Sauds")) + } + + @Parasite(NetworkHandler.NETWORK_LEAVE_PACKET) + fun onNetworkLeave(data: JsonObject) { + + val server = this.instance.api.networkHandler.findServerById(data["from"].asString) ?: return + + this.broadcast(data["displayName"].asString,server.id,null) + } + + @Parasite(NetworkHandler.NETWORK_SWITCH_PACKET) + fun onServerSwitch(data: JsonObject) { + + val to = this.instance.api.networkHandler.findServerById(data["to"].asString) ?: return + val from = this.instance.api.networkHandler.findServerById(data["from"].asString) ?: return + + this.broadcast(data["displayName"].asString,from.id,to.id) + } + + @Parasite(ServerHandler.MESSAGE_ID) + fun onReceiveMessage(data: JsonObject) { + + val message = FancyMessage.deserialize(data["message"].asString) + + if (data.has("permission")) { + this.instance.server.onlinePlayers.filter{it.hasPermission(data["permission"].asString)}.forEach{message.send(it)} + return + } + + this.instance.server.onlinePlayers.forEach{message.send(it)} + } + + private fun broadcast(displayName: String,from: String?,to: String?) { + + val prefix = "${ChatColor.AQUA}[S] $displayName " + val suffix = if (from == null) "${ChatColor.DARK_AQUA}connected to ${ChatColor.WHITE}$to${ChatColor.DARK_AQUA}." else if (to == null) "${ChatColor.DARK_AQUA}disconnected from ${ChatColor.WHITE}$from${ChatColor.DARK_AQUA}." else "${ChatColor.DARK_AQUA}joined ${ChatColor.WHITE}$to ${ChatColor.DARK_AQUA}from ${ChatColor.WHITE}$from${ChatColor.DARK_AQUA}." + + this.instance.server.onlinePlayers.filter{this.instance.api.grantHandler.findBestRank(it.uniqueId).isStaff()}.forEach{it.sendMessage("$prefix$suffix")} + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/command/TagCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/command/TagCommand.kt new file mode 100644 index 0000000..2437fbd --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/command/TagCommand.kt @@ -0,0 +1,21 @@ +package cc.fyre.venom.tag.command + +import cc.fyre.proton.command.Command +import cc.fyre.venom.tag.menu.TagMenu +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +object TagCommand { + + @JvmStatic + @Command(names = ["tag","tags","prefix"],permission = "") + fun execute(player: Player) { + TagMenu().openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/command/TagEditorCommand.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/command/TagEditorCommand.kt new file mode 100644 index 0000000..9bc58a8 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/command/TagEditorCommand.kt @@ -0,0 +1,22 @@ +package cc.fyre.venom.tag.command + +import cc.fyre.proton.command.Command +import org.bukkit.entity.Player + +import cc.fyre.venom.tag.menu.TagEditorMenu + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +object TagEditorCommand { + + @JvmStatic + @Command(names = ["tag editor"],hidden = true,permission = "command.tag.editor") + fun execute(player: Player) { + TagEditorMenu().openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagEditMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagEditMenu.kt new file mode 100644 index 0000000..ed70ea0 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagEditMenu.kt @@ -0,0 +1,62 @@ +package cc.fyre.venom.tag.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.Menu +import cc.fyre.proton.menu.buttons.BackButton +import cc.fyre.venom.Venom + +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.menu.element.create.TagFinishButton +import cc.fyre.venom.tag.menu.element.edit.TagEditButton +import cc.fyre.venom.tag.prompt.TagEditPrompt +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import java.util.function.BiFunction +import java.util.function.BiPredicate + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagEditMenu(private val tag: Tag) : Menu() { + + override fun getTitle(player: Player): String { + return "Editor - ${if (this.tag.display == "") this.tag.id else this.tag.getDisplayName()}" + } + + override fun getButtons(player: Player): MutableMap { + + val toReturn = HashMap() + + toReturn[toReturn.size] = TagEditButton(this.tag,"Display Name",this.tag.display,Material.WOOL,0,BiPredicate{ _,_ -> return@BiPredicate false},TagEditPrompt(this.tag,"display name",BiFunction{ tag,pair -> + tag.display = pair.second + + return@BiFunction true + })) + + toReturn[toReturn.size] = TagEditButton(this.tag,"Prefix",this.tag.prefix,Material.PAINTING,0,BiPredicate{ _,_ -> return@BiPredicate false},TagEditPrompt(this.tag,"prefix",BiFunction{ tag,pair -> + tag.prefix = pair.second + + return@BiFunction true + })) + + toReturn[toReturn.size] = TagEditButton(this.tag,"Priority",this.tag.priority,Material.GOLD_NUGGET,BiPredicate{ tag,click -> + + when { + click.isLeftClick -> tag.priority += if (click.isShiftClick) 10 else 1 + click.isRightClick -> tag.priority -= if (click.isShiftClick) 10 else 1 + click == ClickType.MIDDLE -> tag.priority = 0 + } + + return@BiPredicate true + }) + + toReturn[8] = if (Venom.instance.api.tagHandler.cache.contains(this.tag.id.toLowerCase())) BackButton(TagEditorMenu()) else TagFinishButton(this.tag) + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagEditorMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagEditorMenu.kt new file mode 100644 index 0000000..637b90e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagEditorMenu.kt @@ -0,0 +1,36 @@ +package cc.fyre.venom.tag.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom +import cc.fyre.venom.tag.menu.element.TagButton + +import cc.fyre.venom.tag.menu.element.create.TagCreateButton +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagEditorMenu : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "Tag Editor" + } + + override fun getAllPagesButtons(p0: Player?): MutableMap { + return Venom.instance.api.tagHandler.cache.values.sortedByDescending{it.priority}.withIndex().associate{it.index to TagButton(it.value)}.toMutableMap() + } + + override fun getGlobalButtons(player: Player?): MutableMap { + + val toReturn = HashMap() + + toReturn[4] = TagCreateButton() + + return toReturn + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagMenu.kt new file mode 100644 index 0000000..4866b73 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/TagMenu.kt @@ -0,0 +1,92 @@ +package cc.fyre.venom.tag.menu + +import cc.fyre.proton.menu.Button +import cc.fyre.proton.menu.pagination.PaginatedMenu +import cc.fyre.venom.Venom +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 18/04/2020 + * @author xanderume@gmail.com + */ +class TagMenu : PaginatedMenu() { + + override fun getPrePaginatedTitle(p0: Player?): String { + return "${ChatColor.BLUE}Tags" + + } + + override fun getAllPagesButtons(player: Player): MutableMap { + + val toReturn = HashMap() + val profile = Venom.instance.api.profileHandler.findById(player.uniqueId) + + Venom.instance.api.tagHandler.cache.values.filter{it.isReadyForProduction()}.sortedBy{it.priority}.forEach{toReturn[toReturn.size] = object : Button() { + + override fun getName(p0: Player?): String { + return it.getDisplayName() + } + + override fun getMaterial(p0: Player?): Material { + + if (!player.hasPermission("prefix.${it.id.toLowerCase()}") && !player.hasPermission("prefix.*")) { + return Material.BEDROCK + } + + return Material.NAME_TAG + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf( + " ", + it.prefix + ) + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + + if (!player.hasPermission("prefix.${it.id.toLowerCase()}") && !player.hasPermission("prefix.*")) { + player.sendMessage("${ChatColor.RED}No permission.") + player.closeInventory() + return + } + + if (profile == null) { + player.sendMessage("${ChatColor.RED}There was an issue updating your tag..") + player.closeInventory() + return + } + + if (profile.customTag != null) { + profile.customTag = null + } + + profile.tag = if (profile.tag == it.id) "" else it.id + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + + if (!Venom.instance.api.profileHandler.repository.update(profile)) { + player.sendMessage("${ChatColor.RED}There was an issue updating your tag..") + player.closeInventory() + } + + } + + player.closeInventory() + player.sendMessage("${ChatColor.GREEN}Your tag has been set to: ${it.prefix}") + } + + }} + + return toReturn + } + + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/create/TagFinishMenu.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/create/TagFinishMenu.kt new file mode 100644 index 0000000..089a4b6 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/create/TagFinishMenu.kt @@ -0,0 +1,41 @@ +package cc.fyre.venom.tag.menu.create + +import cc.fyre.proton.menu.menus.ConfirmMenu +import cc.fyre.proton.util.Callback +import cc.fyre.venom.Venom + +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.menu.TagEditorMenu +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.tag.TagHandler +import org.bukkit.Bukkit +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagFinishMenu(tag: Tag,player: Player) : ConfirmMenu("Create Tag ${if (tag.display == "") tag.id else tag.getDisplayName()}",object : + Callback { + + override fun callback(value: Boolean) { + + if (!value) { + TagEditorMenu().openMenu(player) + return + } + + Venom.instance.api.tagHandler.cache[tag.id.toLowerCase()] = tag + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.tagHandler.repository.update(tag) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(TagHandler.UPDATE_ID,tag)) + } + + TagEditorMenu().openMenu(player) + } + + +}) \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/TagButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/TagButton.kt new file mode 100644 index 0000000..1508aa1 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/TagButton.kt @@ -0,0 +1,49 @@ +package cc.fyre.venom.tag.menu.element + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.menu.TagEditMenu +import org.apache.commons.lang3.StringUtils +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagButton(private val tag: Tag) : Button() { + + override fun getName(p0: Player?): String { + return if (this.tag.display == "") this.tag.id else this.tag.getDisplayName() + } + + override fun getMaterial(p0: Player?): Material { + + if (this.tag.isReadyForProduction()) { + return Material.NAME_TAG + } + + return Material.BEDROCK + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + toReturn.add("${ChatColor.YELLOW}ID: ${ChatColor.RED}${this.tag.id}") + toReturn.add("${ChatColor.YELLOW}Prefix: ${ChatColor.RED}${if (this.tag.prefix == "") "None" else ChatColor.translateAlternateColorCodes('&',this.tag.prefix)}") + toReturn.add("${ChatColor.YELLOW}Priority: ${ChatColor.RED}${this.tag.priority}") + toReturn.add("${ChatColor.GRAY}${ChatColor.STRIKETHROUGH}${StringUtils.repeat("-",18)}") + + return toReturn + } + + override fun clicked(player: Player?,slot: Int,clickType: ClickType?) { + TagEditMenu(this.tag).openMenu(player) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/create/TagCreateButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/create/TagCreateButton.kt new file mode 100644 index 0000000..636e98c --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/create/TagCreateButton.kt @@ -0,0 +1,38 @@ +package cc.fyre.venom.tag.menu.element.create + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom +import cc.fyre.venom.tag.prompt.TagCreatePrompt +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagCreateButton : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.GREEN}Create Tag" + } + + override fun getMaterial(p0: Player?): Material { + return Material.NETHER_STAR + } + + override fun getDescription(p0: Player?): MutableList { + return ArrayList() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType?) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(TagCreatePrompt()).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/create/TagFinishButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/create/TagFinishButton.kt new file mode 100644 index 0000000..cc2aac1 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/create/TagFinishButton.kt @@ -0,0 +1,36 @@ +package cc.fyre.venom.tag.menu.element.create + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.menu.create.TagFinishMenu +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagFinishButton(private val tag: Tag) : Button() { + + override fun getName(p0: Player?): String { + return "${ChatColor.GREEN}Finish?" + } + + override fun getMaterial(p0: Player?): Material { + return Material.FIREWORK_CHARGE + } + + override fun getDescription(p0: Player?): MutableList { + return arrayListOf() + } + + override fun clicked(player: Player,slot: Int,clickType: ClickType) { + player.closeInventory() + TagFinishMenu(this.tag,player).openMenu(player) + } + + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/edit/TagEditButton.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/edit/TagEditButton.kt new file mode 100644 index 0000000..b9f928f --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/menu/element/edit/TagEditButton.kt @@ -0,0 +1,85 @@ +package cc.fyre.venom.tag.menu.element.edit + +import cc.fyre.proton.menu.Button +import cc.fyre.venom.Venom + +import cc.fyre.venom.tag.data.Tag +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.tag.TagHandler +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.conversations.ConversationFactory +import org.bukkit.conversations.NullConversationPrefix +import org.bukkit.conversations.Prompt +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import java.util.function.BiPredicate + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagEditButton(private val tag: Tag,private val trait: String,private val currentValue: Any,private val material: Material,private val predicate: BiPredicate) : Button() { + + private var data = 0 + private var prompt: Prompt? = null + + constructor(tag: Tag,trait: String,currentValue: Any,material: Material,data: Int,predicate: BiPredicate):this(tag,trait,currentValue,material,predicate) { + this.data = data + } + + constructor(tag: Tag,trait: String,currentValue: Any,material: Material,data: Int,predicate: BiPredicate,prompt: Prompt):this(tag,trait,currentValue,material,predicate) { + this.data = data + this.prompt = prompt + } + + override fun getName(p0: Player?): String { + return "${ChatColor.GOLD}Edit ${this.trait}" + } + + override fun getMaterial(p0: Player?): Material { + return this.material + } + + override fun getDescription(p0: Player?): MutableList { + + val toReturn = ArrayList() + + toReturn.add(" ") + toReturn.add("${ChatColor.YELLOW}Current: ${ChatColor.RED}${if (this.currentValue is String && this.currentValue == "") "None" else this.currentValue}") + + return toReturn + } + + override fun clicked(player: Player,slot: Int,click: ClickType) { + + if (!this.predicate.test(this.tag,click)) { + + if (this.prompt != null) { + player.closeInventory() + player.beginConversation(ConversationFactory(Venom.instance).withModality(true).withPrefix(NullConversationPrefix()).withFirstPrompt(this.prompt).withEscapeSequence("/no").withLocalEcho(false).withTimeout(25).thatExcludesNonPlayersWithMessage("Go away evil console!").buildConversation(player)) + } + + return + } + + if (!Venom.instance.api.tagHandler.cache.contains(this.tag.id.toLowerCase())) { + return + } + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + + if (!Venom.instance.api.tagHandler.repository.update(this.tag)) { + player.closeInventory() + player.sendMessage("${ChatColor.RED}There was an issue updating this tag..") + return@runTaskAsynchronously + } + + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(TagHandler.UPDATE_ID,tag)) + } + + } +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/prompt/TagCreatePrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/prompt/TagCreatePrompt.kt new file mode 100644 index 0000000..cfa7223 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/prompt/TagCreatePrompt.kt @@ -0,0 +1,45 @@ +package cc.fyre.venom.tag.prompt + +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.menu.TagEditMenu +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player + +/** + * @project venom + * + * @date 16/04/2020 + * @author xanderume@gmail.com + */ +class TagCreatePrompt : StringPrompt() { + + override fun getPromptText(conversationText: ConversationContext): String { + return "${ChatColor.YELLOW}Please type a name this tag, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + override fun acceptInput(conversationContext: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}Cancelled creating tag.") + return Prompt.END_OF_CONVERSATION + } + + if (Venom.instance.api.tagHandler.findById(input) != null) { + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}This tag already exists.") + return Prompt.END_OF_CONVERSATION + } + + val tag = Tag(input) + + TagEditMenu(tag).openMenu(conversationContext.forWhom as Player) + + return Prompt.END_OF_CONVERSATION + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/prompt/TagEditPrompt.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/prompt/TagEditPrompt.kt new file mode 100644 index 0000000..dbe8854 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/tag/prompt/TagEditPrompt.kt @@ -0,0 +1,51 @@ +package cc.fyre.venom.tag.prompt + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.rank.data.Rank +import cc.fyre.venom.rank.menu.RankEditMenu +import cc.fyre.venom.tag.TagHandler +import cc.fyre.venom.tag.data.Tag +import cc.fyre.venom.tag.menu.TagEditMenu +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.conversations.ConversationContext +import org.bukkit.conversations.Prompt +import org.bukkit.conversations.StringPrompt +import org.bukkit.entity.Player +import java.util.function.BiFunction + +/** + * @project venom + * + * @date 03/04/2020 + * @author xanderume@gmail.com + */ +open class TagEditPrompt(private val tag: Tag,private val trait: String,private val predicate: BiFunction,Boolean>) : StringPrompt() { + + override fun getPromptText(conversationText: ConversationContext): String { + + return this.getCustomPrompt(conversationText) ?: "${ChatColor.YELLOW}Please type a ${this.trait} for this tag, or type ${ChatColor.RED}\"cancel\"${ChatColor.YELLOW} to cancel." + } + + open fun getCustomPrompt(conversationText: ConversationContext):String? = null + + override fun acceptInput(conversationContext: ConversationContext,input: String): Prompt? { + + if (input.equals("cancel",true)) { + conversationContext.forWhom.sendRawMessage("${ChatColor.RED}Cancelled changing ${this.trait}.") + } else if (this.predicate.apply(this.tag,Pair(conversationContext,input)) && Venom.instance.api.tagHandler.cache.contains(this.tag.id.toLowerCase())) { + + Bukkit.getServer().scheduler.runTaskAsynchronously(Venom.instance) { + Venom.instance.api.tagHandler.repository.update(this.tag) + Venom.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(TagHandler.UPDATE_ID,tag)) + } + + } + + TagEditMenu(this.tag).openMenu(conversationContext.forWhom as Player) + + return Prompt.END_OF_CONVERSATION + } + +} diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/util/ColorUtil.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/util/ColorUtil.kt new file mode 100644 index 0000000..ff46a34 --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/util/ColorUtil.kt @@ -0,0 +1,66 @@ +package cc.fyre.venom.util + +import com.google.common.collect.ImmutableMap +import org.apache.commons.lang.StringUtils +import org.apache.commons.lang.WordUtils +import org.bukkit.ChatColor +import org.bukkit.DyeColor + + +/** + * @project venom + * + * @date 28/02/2021 + * @author xanderume@gmail.com + */ +object ColorUtil { + + private val colorToDye = hashMapOf() + + init { + this.colorToDye[ChatColor.RED] = DyeColor.RED + this.colorToDye[ChatColor.AQUA] = DyeColor.LIGHT_BLUE + this.colorToDye[ChatColor.BLUE] = DyeColor.LIGHT_BLUE + this.colorToDye[ChatColor.GRAY] = DyeColor.SILVER + this.colorToDye[ChatColor.GOLD] = DyeColor.ORANGE + this.colorToDye[ChatColor.WHITE] = DyeColor.WHITE + this.colorToDye[ChatColor.BLACK] = DyeColor.BLACK + this.colorToDye[ChatColor.GREEN] = DyeColor.LIME + this.colorToDye[ChatColor.YELLOW] = DyeColor.YELLOW + this.colorToDye[ChatColor.DARK_RED] = DyeColor.RED + this.colorToDye[ChatColor.DARK_AQUA] = DyeColor.CYAN + this.colorToDye[ChatColor.DARK_BLUE] = DyeColor.BLUE + this.colorToDye[ChatColor.DARK_GRAY] = DyeColor.GRAY + this.colorToDye[ChatColor.DARK_GREEN] = DyeColor.GREEN + this.colorToDye[ChatColor.DARK_PURPLE] = DyeColor.PURPLE + this.colorToDye[ChatColor.LIGHT_PURPLE] = DyeColor.MAGENTA + } + + @JvmStatic + fun getName(color: ChatColor): String { + return WordUtils.capitalizeFully(color.name.toLowerCase().replace("_"," ")) + } + + @JvmStatic + fun findDyeColor(color: ChatColor):DyeColor? { + return this.colorToDye[color] + } + + @JvmStatic + fun findDyeColorByChar(char: Char):DyeColor { + + val color = try { + ChatColor.getByChar(char) + } catch (ex: Exception) { + return DyeColor.WHITE + } + + return this.colorToDye[color] ?: DyeColor.WHITE + } + + @JvmStatic + fun findColorByDyeColor(color: DyeColor):ChatColor? { + return this.colorToDye.entries.firstOrNull{it.value == color}?.key + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/kotlin/cc/fyre/venom/util/PlayerUtil.kt b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/util/PlayerUtil.kt new file mode 100644 index 0000000..0db206e --- /dev/null +++ b/Venom/bukkit/src/main/kotlin/cc/fyre/venom/util/PlayerUtil.kt @@ -0,0 +1,70 @@ +package cc.fyre.venom.util + +import cc.fyre.venom.Venom +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.network.data.Server +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import java.util.* + +/** + * @project venom + * + * @date 02/03/2021 + * @author xanderume@gmail.com + */ +object PlayerUtil { + + @JvmStatic + fun getUuid(name: String):UUID? { + return VenomAPI.instance.profileHandler.findId(name) + } + + @JvmStatic + fun getName(uuid: UUID):String { + return VenomAPI.instance.profileHandler.findName(uuid) + } + + @JvmStatic + fun getDisplayName(uuid: UUID):String { + return this.getDisplayName(uuid,Venom.instance.serverHandler.server) + } + + @JvmStatic + fun getDisplayName(uuid: UUID,server: Server):String { + + if (Bukkit.isPrimaryThread()) { + throw IllegalStateException("Cannot query display name on main thread.") + } + + return VenomAPI.instance.grantHandler.findDisplayName(uuid,server) + } + + @JvmStatic + fun getDisplayName(uuid: UUID,name: String):String { + return this.getDisplayName(uuid,name,Venom.instance.serverHandler.server) + } + + @JvmStatic + fun getDisplayName(uuid: UUID,name: String,server: Server):String { + + if (Bukkit.isPrimaryThread()) { + throw IllegalStateException("Cannot query display name on main thread.") + } + + return VenomAPI.instance.grantHandler.findDisplayName(uuid,name,server) + } + + @JvmStatic + fun getDisplayName(name: String,server: Server,grants: MutableSet):String { + + if (Bukkit.isPrimaryThread()) { + throw IllegalStateException("Cannot query display name on main thread.") + } + + return VenomAPI.instance.grantHandler.findDisplayName(name,server,grants) + } + +} \ No newline at end of file diff --git a/Venom/bukkit/src/main/resources/config.yml b/Venom/bukkit/src/main/resources/config.yml new file mode 100644 index 0000000..e18896a --- /dev/null +++ b/Venom/bukkit/src/main/resources/config.yml @@ -0,0 +1,17 @@ +id: unnamed +name: Venom +group: unknown +mongo: + host: "localhost" + port: 27017 + user: "" + pass: "" + database: "venom" + authDatabase: "" +redis: + host: "localhost" + port: 6379 + pass: "" +chatFormat: + text: "{rank}{prefix}{name}&f: {message}" + enabled: true \ No newline at end of file diff --git a/Venom/bukkit/src/main/resources/plugin.yml b/Venom/bukkit/src/main/resources/plugin.yml new file mode 100644 index 0000000..3ddd806 --- /dev/null +++ b/Venom/bukkit/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +name: Multiverse +main: cc.fyre.venom.Venom +author: Fyre Services +version: 1.0-SNAPSHOT +depend: [Kotlin,Proton] +softdepend: [LuckPerms,PlaceholderAPI] \ No newline at end of file diff --git a/Venom/proxy/build.gradle b/Venom/proxy/build.gradle new file mode 100644 index 0000000..38c4c5a --- /dev/null +++ b/Venom/proxy/build.gradle @@ -0,0 +1,54 @@ +plugins { + id "org.jetbrains.kotlin.jvm" version "1.5.10" + id "com.github.johnrengelman.shadow" version "5.2.0" +} + +targetCompatibility = '1.8' +sourceCompatibility = '1.8' + +shadowJar { + classifier = null + minimize() + archiveName = "venom-" + this.name + "-" + this.version + ".jar" +} + +repositories { + mavenLocal() + mavenCentral() + + flatDir { + dirs 'libs' + } +} + +dependencies { + compile project(':api') + implementation name: "BungeeCord" + implementation name: "Symbiote" + + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.10" + compile "org.apache.commons:commons-pool2:2.6.0" +} + +apply plugin: "kotlin" +apply plugin: 'maven-publish' + +compileKotlin { + kotlinOptions.jvmTarget = '1.8' +} + +sourceSets { + main.java.srcDirs += 'src/main/kotlin/' +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +publishing { + publications { + shadow(MavenPublication) { publication -> + project.shadow.component(publication) + } + } +} \ No newline at end of file diff --git a/Venom/proxy/libs/BungeeCord.jar b/Venom/proxy/libs/BungeeCord.jar new file mode 100644 index 0000000..5d364ca Binary files /dev/null and b/Venom/proxy/libs/BungeeCord.jar differ diff --git a/Venom/proxy/libs/Symbiote.jar b/Venom/proxy/libs/Symbiote.jar new file mode 100644 index 0000000..9b0efc0 Binary files /dev/null and b/Venom/proxy/libs/Symbiote.jar differ diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/Venom.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/Venom.kt new file mode 100644 index 0000000..29ca2d7 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/Venom.kt @@ -0,0 +1,99 @@ +package cc.fyre.venom + +import cc.fyre.venom.api.APIListener +import cc.fyre.venom.database.mongo.MongoOptions +import cc.fyre.venom.database.mongo.RedisOptions +import cc.fyre.venom.grant.GrantProxyAdapter +import cc.fyre.venom.permission.PermissionHandler +import cc.fyre.venom.proxy.ProxyHandler +import net.md_5.bungee.api.plugin.Plugin +import net.md_5.bungee.config.Configuration +import net.md_5.bungee.config.ConfigurationProvider +import net.md_5.bungee.config.YamlConfiguration +import java.io.File +import java.io.IOException +import java.nio.file.Files +import java.util.concurrent.TimeUnit + + +/** + * @project venom + * + * @date 05/04/2020 + * @author xanderume@gmail.com + */ +class Venom : Plugin() { + + lateinit var config: Configuration + + lateinit var api: VenomAPI + + lateinit var proxyHandler: ProxyHandler + lateinit var permissionHandler: PermissionHandler + + override fun onEnable() { + instance = this + + this.saveDefaultConfig() + + this.config = ConfigurationProvider.getProvider(YamlConfiguration::class.java).load(File(this.dataFolder,"config.yml")) + + this.api = VenomAPI(this.getMongoOptions(),this.getRedisOptions()) + + this.proxyHandler = ProxyHandler(this) + this.permissionHandler = PermissionHandler(this) + + this.api.grantHandler.setProvider(GrantProxyAdapter(this)) + + this.proxy.pluginManager.registerListener(this,APIListener(this)) + + this.proxy.scheduler.schedule(this,this.api.grantHandler.expiryService,2L,2L,TimeUnit.SECONDS) + } + + private fun saveDefaultConfig() { + + if (!this.dataFolder.exists()) { + this.dataFolder.mkdir() + } + + val file = File(this.dataFolder,"config.yml") + + if (file.exists()) { + return + } + + try { + this.getResourceAsStream("config.yml").use{Files.copy(it,file.toPath())} + } catch (ex: IOException) { + ex.printStackTrace() + } + + } + + private fun getRedisOptions(): RedisOptions { + + val password = this.config.getString("redis.pass") + + return RedisOptions(this.config.getString("redis.host"),this.config.getInt("redis.port"),if (password == "") null else password) + } + + private fun getMongoOptions(): MongoOptions { + + val username = this.config.getString("mongo.user") + val password = this.config.getString("mongo.pass") + val authDatabase = this.config.getString("mongo.authDatabase") + + return MongoOptions(this.config.getString("mongo.host"),this.config.getInt("mongo.port"),if (username == "") null else username,if (password == "") null else password,this.config.getString("mongo.database"),if (authDatabase == "") null else authDatabase) + } + + override fun onDisable() { + this.proxyHandler.dispose() + } + + companion object { + + lateinit var instance: Venom + + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/api/APIListener.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/api/APIListener.kt new file mode 100644 index 0000000..24a03aa --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/api/APIListener.kt @@ -0,0 +1,109 @@ +package cc.fyre.venom.api + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.VenomAPI +import cc.fyre.venom.api.request.VPNRequest +import cc.fyre.venom.proxy.ProxyHandler +import com.google.common.cache.CacheBuilder +import com.google.common.cache.CacheLoader +import com.google.gson.JsonObject +import com.squareup.okhttp.Request +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.chat.TextComponent +import net.md_5.bungee.api.event.* +import net.md_5.bungee.api.plugin.Listener + +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority +import java.lang.Exception +import java.util.concurrent.TimeUnit + +/** + * @project venom + * + * @date 13/04/2020 + * @author xanderume@gmail.com + */ +class APIListener(private val instance: Venom) : Listener { + + private val cache = CacheBuilder.newBuilder().maximumSize(5000).expireAfterAccess(10L, TimeUnit.MINUTES).build(object : CacheLoader() { + + override fun load(key: String): VPNRequest { + + val request = Request.Builder().url("http://ip-api.com/json/$key?fields=status,proxy,hosting").build() + val response = this@APIListener.instance.api.databaseHandler.okHttpClient.newCall(request).execute() + + return try { + VenomAPI.instance.gson.fromJson(response.body().string(),VPNRequest::class.java) + } catch (ex: Exception) { + this@APIListener.instance.logger.warning("Failed to request vpn/proxy data for ip: $key, is the API down?") + return VPNRequest(status = "failed",proxy = false,hosting = false) + } + + } + + }) + + @EventHandler(priority = EventPriority.HIGHEST) + fun onLoginAPI(event: LoginEvent) { + + event.registerIntent(this.instance) + + this.instance.proxy.scheduler.runAsync(this.instance) { + + val grants = this.instance.api.grantHandler.repository.findAllByPlayer(event.connection.uniqueId).toHashSet() + + val bypass = grants.filter{!it.isVoided() && !it.isRemoved()}.mapNotNull{it.getRank()}.any{it.isVPNBypass()} + + if (bypass) { + this.instance.proxy.console.sendMessage(TextComponent("${ChatColor.GREEN}Allowed ${event.connection.name} to bypass VPN/Proxy detection.")) + return@runAsync + } + + if (this.instance.proxyHandler.vpnDetection) { + + try { + + val request = this.cache.getUnchecked(event.connection.address.address.hostAddress) + + if (request != null && request.isSuccess() && request.proxy) { + this.instance.proxy.players.filter{it.hasPermission(ProxyHandler.VPN_NOTIFICATION)}.forEach{ + it.sendMessage(TextComponent("${ChatColor.RED}[${ChatColor.YELLOW}!${ChatColor.RED}] ${event.connection.name} tried to join using a VPN or proxy.")) + } + + event.isCancelled = true + event.setCancelReason(TextComponent("${ChatColor.RED}You are not allowed to connect using a VPN or proxy.")) + } + + } finally { + event.completeIntent(this.instance) + } + + } + + val server = this.instance.api.networkHandler.servers.first() + + this.instance.api.grantHandler.active[event.connection.uniqueId] = grants.filter{it.isActive()}.toCollection(ArrayList()) + + this.instance.api.grantHandler.setGlobal(event.connection.uniqueId,server,grants) + this.instance.api.grantHandler.setScoped(event.connection.uniqueId,server,grants) + this.instance.api.grantHandler.setSubscription(event.connection.uniqueId,grants) + } + + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun onServerSwitch(event: ServerConnectedEvent) { + + val server = this.instance.api.networkHandler.findServerById(event.server.info.name) ?: return + + this.instance.api.grantHandler.setScoped(event.player.uniqueId,server,this.instance.api.grantHandler.active[event.player.uniqueId] ?: HashSet()) + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun onDisconnect(event: PlayerDisconnectEvent) { + this.instance.api.grantHandler.active.remove(event.player.uniqueId) + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/api/request/VPNRequest.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/api/request/VPNRequest.kt new file mode 100644 index 0000000..750464f --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/api/request/VPNRequest.kt @@ -0,0 +1,15 @@ +package cc.fyre.venom.api.request + +/** + * @project venom + * + * @date 05/25/21 + * @author xanderume@gmail.com + */ +data class VPNRequest(val status: String,val proxy: Boolean,val hosting: Boolean) { + + fun isSuccess():Boolean { + return this.status == "success" + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/grant/GrantProxyAdapter.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/grant/GrantProxyAdapter.kt new file mode 100644 index 0000000..fdff171 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/grant/GrantProxyAdapter.kt @@ -0,0 +1,32 @@ +package cc.fyre.venom.grant + +import cc.fyre.venom.Venom +import cc.fyre.venom.grant.data.Grant +import cc.fyre.venom.grant.data.GrantAdapter +import java.util.* + +/** + * @project venom + * + * @date 10/05/2020 + * @author xanderume@gmail.com + */ +class GrantProxyAdapter(private val instance: Venom) : GrantAdapter { + + override fun onGrantApply(uuid: UUID,grant: Grant) { + this.instance.proxy.getPlayer(uuid).also{this.instance.permissionHandler.update(it)} + } + + override fun onGrantChange(uuid: UUID,grant: Grant) { + this.instance.proxy.getPlayer(uuid).also{this.instance.permissionHandler.update(it)} + } + + override fun onGrantExpire(uuid: UUID,grant: Grant) { + this.instance.proxy.getPlayer(uuid).also{this.instance.permissionHandler.update(it)} + } + + override fun onGrantRemove(uuid: UUID,grant: Grant) { + this.instance.proxy.getPlayer(uuid).also{this.instance.permissionHandler.update(it)} + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/PermissionHandler.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/PermissionHandler.kt new file mode 100644 index 0000000..f7a17c1 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/PermissionHandler.kt @@ -0,0 +1,31 @@ +package cc.fyre.venom.permission + +import cc.fyre.venom.Venom +import cc.fyre.venom.permission.listener.PermissionListener +import cc.fyre.venom.permission.packet.PermissionPacketListener +import net.md_5.bungee.api.connection.ProxiedPlayer + +/** + * @project venom + * + * @date 12/04/2020 + * @author xanderume@gmail.com + */ +class PermissionHandler(private val instance: Venom) { + + init { + this.instance.api.databaseHandler.symbiote.addListener(PermissionPacketListener(this.instance)) + this.instance.proxy.pluginManager.registerListener(this.instance,PermissionListener(this.instance)) + } + + fun update(player: ProxiedPlayer) { + + val permissions = ArrayList() + + permissions.addAll((Venom.instance.api.grantHandler.active[player.uniqueId] ?: ArrayList()).flatMap{it.getRank()?.permissions ?: HashSet()}) + permissions.addAll(Venom.instance.api.profileHandler.findById(player.uniqueId)?.permissions ?: ArrayList()) + + this.instance.api.profileHandler.calculatePermissions(permissions,true) + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/listener/PermissionListener.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/listener/PermissionListener.kt new file mode 100644 index 0000000..bf0e07e --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/listener/PermissionListener.kt @@ -0,0 +1,28 @@ +package cc.fyre.venom.permission.listener + +import cc.fyre.venom.Venom +import net.md_5.bungee.api.event.PermissionCheckEvent +import net.md_5.bungee.api.event.PostLoginEvent +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority + +/** + * @project venom + * + * @date 12/04/2020 + * @author xanderume@gmail.com + */ +class PermissionListener(private val instance: Venom):Listener { + + @EventHandler(priority = EventPriority.LOWEST) + fun onPostLogin(event: PostLoginEvent) { + this.instance.permissionHandler.update(event.player) + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun onPermissionCheck(event: PermissionCheckEvent) { + event.setHasPermission(event.sender.permissions.contains(event.permission.toLowerCase()) && !event.sender.permissions.contains("-${event.permission.toLowerCase()}")) + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/packet/PermissionPacketListener.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/packet/PermissionPacketListener.kt new file mode 100644 index 0000000..ee0d61f --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/permission/packet/PermissionPacketListener.kt @@ -0,0 +1,29 @@ +package cc.fyre.venom.permission.packet + +import cc.fyre.symbiote.parasite.Parasite +import cc.fyre.symbiote.parasite.ParasiteListener +import cc.fyre.venom.Venom +import cc.fyre.venom.profile.ProfileHandler +import com.google.gson.JsonObject +import java.util.* + +/** + * @project venom + * + * @date 19/04/2020 + * @author xanderume@gmail.com + */ +class PermissionPacketListener(private val instance: Venom) : ParasiteListener { + + @Parasite(ProfileHandler.PERMISSION_UPDATE_PACKET) + fun onPermissionUpdate(data: JsonObject) { + + val player = this.instance.proxy.getPlayer(UUID.fromString(data["_id"].asString)) ?: return + + val remove = data["remove"].asBoolean + val permission = data["permission"].asString + + player.setPermission(permission,!remove) + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/ProxyHandler.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/ProxyHandler.kt new file mode 100644 index 0000000..1337dd8 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/ProxyHandler.kt @@ -0,0 +1,99 @@ +package cc.fyre.venom.proxy + +import cc.fyre.venom.Venom +import cc.fyre.venom.network.data.Proxy +import cc.fyre.venom.network.data.Status + +import cc.fyre.venom.proxy.command.* +import cc.fyre.venom.proxy.listener.HubListener +import cc.fyre.venom.proxy.listener.StaffServerListener +import cc.fyre.venom.proxy.listener.SessionListener + +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class ProxyHandler(private val instance: Venom) { + + lateinit var proxy: Proxy + lateinit var proxyID: String + lateinit var proxyGroup: String + + private lateinit var initialized: AtomicBoolean + private lateinit var updateTaskId: AtomicInteger + + var vpnDetection = true + + init { + this.setup() + } + + private fun setup() { + this.initialized = AtomicBoolean(false) + + try { + this.proxyID = this.instance.proxy::class.java.getMethod("getID").invoke(this.instance.proxy) as String + } catch (ex: NoSuchMethodException) { + this.proxyID = this.instance.config.getString("id","NA") + } + + try { + this.proxyGroup = this.instance.proxy::class.java.getMethod("getGroup").invoke(this.instance.proxy) as String + } catch (ex: NoSuchMethodException) { + this.proxyGroup = this.instance.config.getString("group","unknown") + } + + this.instance.proxy.pluginManager.registerCommand(this.instance,VPNCommand(this.instance)) + this.instance.proxy.pluginManager.registerCommand(this.instance,ListCommand(this.instance)) + this.instance.proxy.pluginManager.registerCommand(this.instance,AlertCommand(this.instance)) + + this.instance.proxy.pluginManager.registerListener(this.instance,HubListener(this.instance)) + this.instance.proxy.pluginManager.registerListener(this.instance,StaffServerListener(this.instance)) + this.instance.proxy.pluginManager.registerListener(this.instance,SessionListener(this.instance)) + + this.proxy = Proxy(this.proxyID,this.instance.proxy.config.listeners.first().host.port,this.proxyGroup) + this.updateTaskId = AtomicInteger(this.instance.proxy.scheduler.schedule(this.instance,{this.update()},0L,2L,TimeUnit.SECONDS).id) + + this.initialized.set(true) + } + + fun dispose() { + + if (!this.initialized.get()) { + return + } + + this.instance.proxy.scheduler.cancel(this.updateTaskId.get()) + + this.proxy.update = System.currentTimeMillis() + this.proxy.status = Status.OFFLINE + this.proxy.onlinePlayers.clear() + + this.instance.api.networkHandler.update(this.proxy) + } + + private fun update() { + + this.proxy.update = System.currentTimeMillis() + this.proxy.status = Status.ONLINE + this.proxy.onlinePlayers = this.instance.proxy.players.map{it.uniqueId}.toHashSet() + this.proxy.bungeeServers = this.instance.proxy.servers.keys.toHashSet() + + this.instance.api.networkHandler.update(this.proxy) + } + + companion object { + + const val SEND_PACKET = "SEND_PACKET" + const val ALERT_PACKET = "ALERT_PACKET" + + const val VPN_NOTIFICATION = "vpn.notification" + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/AlertCommand.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/AlertCommand.kt new file mode 100644 index 0000000..fc3e9a7 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/AlertCommand.kt @@ -0,0 +1,53 @@ +package cc.fyre.venom.proxy.command + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.proxy.ProxyHandler +import com.google.gson.JsonObject +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.CommandSender +import net.md_5.bungee.api.ProxyServer +import net.md_5.bungee.api.chat.TextComponent +import net.md_5.bungee.api.plugin.Command + +/** + * @project venom + * + * @date 14/04/2020 + * @author xanderume@gmail.com + */ +class AlertCommand(private val instance: Venom) : Command("alert","bungeecord.command.alert") { + + override fun execute(sender: CommandSender,args: Array) { + + if (args.isEmpty()) { + sender.sendMessage(TextComponent("${ChatColor.RED}Usage: /alert ")) + return + } + + val builder = StringBuilder() + + if (args[0].startsWith("&h")) { + args[0] = args[0].substring(2).replace(" ","") + } else { + builder.append("${ChatColor.DARK_GRAY}[${ChatColor.DARK_RED}Alert${ChatColor.DARK_GRAY}]${ChatColor.WHITE} ") + } + + args.forEach{ + builder.append(ChatColor.translateAlternateColorCodes('&',it)) + builder.append(" ") + } + + this.instance.proxy.scheduler.runAsync(this.instance) { + + val jsonObject = JsonObject() + + jsonObject.addProperty("message",builder.substring(0,builder.length-1)) + + this.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(ProxyHandler.ALERT_PACKET,jsonObject)) + } + + } + + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/ListCommand.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/ListCommand.kt new file mode 100644 index 0000000..436c013 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/ListCommand.kt @@ -0,0 +1,32 @@ +package cc.fyre.venom.proxy.command + +import cc.fyre.venom.Venom +import net.md_5.bungee.Util +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.CommandSender +import net.md_5.bungee.api.chat.TextComponent +import net.md_5.bungee.api.plugin.Command + +/** + * @project venom + * + * @date 14/04/2020 + * @author xanderume@gmail.com + */ +class ListCommand(private val instance: Venom) : Command("glist","bungeecord.command.list") { + + override fun execute(sender: CommandSender,args: Array) { + + var players = 0 + + for (server in this.instance.api.networkHandler.servers.sortedBy{it.group}.sortedBy{it.id}) { + + players += server.onlinePlayers.size + + sender.sendMessage(TextComponent("${ChatColor.GREEN}[${server.id}] ${ChatColor.YELLOW}(${server.onlinePlayers.size}): ${ChatColor.WHITE}${Util.format(server.onlinePlayers.map{this.instance.api.profileHandler.findName(it)}.toList(),"${ChatColor.WHITE}, ")}")) + } + + sender.sendMessage(TextComponent("${ChatColor.WHITE}Total players online: $players")) + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/VPNCommand.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/VPNCommand.kt new file mode 100644 index 0000000..e166f81 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/command/VPNCommand.kt @@ -0,0 +1,17 @@ +package cc.fyre.venom.proxy.command + +import cc.fyre.venom.Venom +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.CommandSender +import net.md_5.bungee.api.chat.TextComponent +import net.md_5.bungee.api.plugin.Command + +class VPNCommand(private val instance: Venom) : Command("vpn", "command.vpn") { + + override fun execute(sender: CommandSender, args: Array) { + this.instance.proxyHandler.vpnDetection = !this.instance.proxyHandler.vpnDetection + + sender.sendMessage(TextComponent("${ChatColor.GOLD}VPN Detection: ${ChatColor.WHITE}${this.instance.proxyHandler.vpnDetection}")) + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/HubListener.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/HubListener.kt new file mode 100644 index 0000000..db6750f --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/HubListener.kt @@ -0,0 +1,69 @@ +package cc.fyre.venom.proxy.listener +import cc.fyre.venom.Venom +import cc.fyre.venom.network.data.Status + +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.chat.TextComponent +import net.md_5.bungee.api.event.* +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority + +/** + * @project venom + * + * @date 10/04/2020 + * @author xanderume@gmail.com + */ +class HubListener(private val instance: Venom) : Listener { + + @EventHandler(priority = EventPriority.LOWEST) + fun onServerConnect(event: ServerConnectEvent) { + + if (event.player.server != null) { + return + } + + val hubs = this.instance.api.networkHandler.servers.filter{it.status != Status.OFFLINE && it.isHub()}.mapNotNull{this.instance.proxy.getServerInfo(it.id)}.filter{it.canAccess(event.player)} + + val hub = hubs.firstOrNull{it.isRestricted} ?: if (hubs.isEmpty()) null else hubs.random() + + if (hub == null) { + event.player.disconnect(TextComponent("${ChatColor.RED}Unavailable to find a suitable hub, please try again later!")) + event.isCancelled = true + return + } + + event.target = hub + } + + @EventHandler(priority = EventPriority.LOWEST) + fun onServerKick(event: ServerKickEvent) { + + val validKick = !event.kickReasonComponent.map{ChatColor.stripColor(it.toPlainText())}.any{KICK_FILTERS.any{filter -> filter.equals(it,true) || filter.startsWith(it,true)}} + + if (validKick) { + return + } + + val hubs = this.instance.api.networkHandler.servers.filter{it.status != Status.OFFLINE && it.isHub()}.mapNotNull{this.instance.proxy.getServerInfo(it.id)}.filter{it.canAccess(event.player)} + + val hub = hubs.firstOrNull{it.isRestricted} ?: if (hubs.isEmpty()) null else hubs.random() + + if (hub == null) { + event.player.disconnect(TextComponent("${ChatColor.RED}Unavailable to find a suitable hub, please try again later!")) + event.isCancelled = true + return + } + + event.isCancelled = true + event.cancelServer = hub + } + + companion object { + + val KICK_FILTERS = arrayListOf("Server closed","You have been deathbanned","You are still deathbanned") + + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/SessionListener.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/SessionListener.kt new file mode 100644 index 0000000..b9c9710 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/SessionListener.kt @@ -0,0 +1,60 @@ +package cc.fyre.venom.proxy.listener + +import cc.fyre.venom.Venom +import cc.fyre.venom.session.data.Session +import net.md_5.bungee.api.event.PlayerDisconnectEvent +import net.md_5.bungee.api.event.ServerSwitchEvent +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.api.scheduler.ScheduledTask +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority +import java.util.* +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 12/08/2020 + * @author xanderume@gmail.com + */ +class SessionListener(private val instance: Venom) : Listener { + + private val cache = HashMap() + + @EventHandler(priority = EventPriority.HIGHEST) + fun onServerSwitch(event: ServerSwitchEvent) { + + this.instance.proxy.scheduler.runAsync(this.instance) { + + val session = this.cache.getOrPut(event.player.uniqueId) { + Session( + event.player.uniqueId, + event.player.address.address.hostAddress, + event.player.server.info.name + ) + } + + if (event.from != null) { + session.sessions.add(Session.SwitchSession(event.from.name,event.player.server.info.name)) + } + + this.instance.api.sessionHandler.repository.update(session) + } + + } + + @EventHandler(priority = EventPriority.LOWEST) + fun onDisconnect(event: PlayerDisconnectEvent) { + + val session = this.cache.remove(event.player.uniqueId) ?: return + + session.logout = System.currentTimeMillis() + session.lastServer = event.player.server?.info?.name ?: session.sessions.lastOrNull()?.to ?: "Unknown" + + this.instance.proxy.scheduler.runAsync(this.instance) { + this.instance.api.sessionHandler.repository.update(session) + } + + } + +} \ No newline at end of file diff --git a/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/StaffServerListener.kt b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/StaffServerListener.kt new file mode 100644 index 0000000..e743bd6 --- /dev/null +++ b/Venom/proxy/src/main/kotlin/cc/fyre/venom/proxy/listener/StaffServerListener.kt @@ -0,0 +1,92 @@ +package cc.fyre.venom.proxy.listener + +import cc.fyre.symbiote.Symbiote +import cc.fyre.venom.Venom +import cc.fyre.venom.network.NetworkHandler +import cc.fyre.venom.session.SessionHandler +import com.google.gson.JsonObject +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.chat.TextComponent +import net.md_5.bungee.api.config.ServerInfo +import net.md_5.bungee.api.event.* +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority +import java.util.* +import kotlin.collections.HashMap + +/** + * @project venom + * + * @date 11/04/2020 + * @author xanderume@gmail.com + */ +class StaffServerListener(private val instance: Venom) : Listener { + + @EventHandler(priority = EventPriority.HIGHEST) + fun onPostLogin(event: ServerConnectedEvent) { + + if (!this.instance.api.grantHandler.findBestRank(event.player.uniqueId).isStaff()) { + return + } + + this.instance.proxy.scheduler.runAsync(this.instance) { + + val jsonObject = JsonObject() + + jsonObject.addProperty("to",event.server.info.name) + + if (event.player.server != null) { + jsonObject.addProperty("from",event.player.server.info.name) + } + + jsonObject.addProperty("name",event.player.name) + jsonObject.addProperty("uuid",event.player.uniqueId.toString()) + + val packet = if (event.player.server == null) NetworkHandler.NETWORK_JOIN_PACKET else NetworkHandler.NETWORK_SWITCH_PACKET + + val server = this.instance.api.networkHandler.findServerById((if (event.player.server != null) event.player.server.info else event.server.info).name) + + if (server != null) { + jsonObject.addProperty("displayName",this.instance.api.grantHandler.findDisplayName(event.player.uniqueId,server)) + } else { + jsonObject.addProperty("displayName",event.player.name) + } + + this.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(packet,jsonObject)) + } + + } + + @EventHandler(priority = EventPriority.NORMAL) + fun onPlayerDisconnect(event: PlayerDisconnectEvent) { + + if (event.player.server == null) { + return + } + + if (!this.instance.api.grantHandler.findBestRank(event.player.uniqueId).isStaff()) { + return + } + + this.instance.proxy.scheduler.runAsync(this.instance) { + + val jsonObject = JsonObject() + + jsonObject.addProperty("name",event.player.name) + jsonObject.addProperty("uuid",event.player.uniqueId.toString()) + jsonObject.addProperty("from",event.player.server.info.name) + + val server = this.instance.api.networkHandler.findServerById(event.player.server.info.name) + + if (server != null) { + jsonObject.addProperty("displayName",this.instance.api.grantHandler.findDisplayName(event.player.uniqueId,server)) + } else { + jsonObject.addProperty("displayName",event.player.name) + } + + this.instance.api.databaseHandler.symbiote.sendPacket(Symbiote(NetworkHandler.NETWORK_LEAVE_PACKET,jsonObject)) + } + + } +} \ No newline at end of file diff --git a/Venom/proxy/src/main/resources/config.yml b/Venom/proxy/src/main/resources/config.yml new file mode 100644 index 0000000..208455a --- /dev/null +++ b/Venom/proxy/src/main/resources/config.yml @@ -0,0 +1,13 @@ +id: "NA" +group: "unknown" +mongo: + host: "localhost" + port: 27017 + user: "" + pass: "" + database: "venom" + authDatabase: "" +redis: + host: "localhost" + port: 6379 + pass: "" diff --git a/Venom/proxy/src/main/resources/plugin.yml b/Venom/proxy/src/main/resources/plugin.yml new file mode 100644 index 0000000..a93517e --- /dev/null +++ b/Venom/proxy/src/main/resources/plugin.yml @@ -0,0 +1,3 @@ +name: Venom +main: cc.fyre.venom.Venom +version: 1.0-SNAPSHOT \ No newline at end of file diff --git a/Venom/settings.gradle b/Venom/settings.gradle new file mode 100644 index 0000000..ce6db72 --- /dev/null +++ b/Venom/settings.gradle @@ -0,0 +1,11 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'venom' + +include(':api') +include(':bukkit') +include 'proxy' +include 'discord' + diff --git a/hub/.idea/compiler.xml b/hub/.idea/compiler.xml deleted file mode 100644 index 61d818a..0000000 --- a/hub/.idea/compiler.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hub/.idea/encodings.xml b/hub/.idea/encodings.xml deleted file mode 100644 index 15a15b2..0000000 --- a/hub/.idea/encodings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/hub/.idea/hub.iml b/hub/.idea/hub.iml deleted file mode 100644 index 641679f..0000000 --- a/hub/.idea/hub.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/hub/.idea/misc.xml b/hub/.idea/misc.xml deleted file mode 100644 index 32e1ef9..0000000 --- a/hub/.idea/misc.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/hub/.idea/workspace.xml b/hub/.idea/workspace.xml deleted file mode 100644 index a8de78c..0000000 --- a/hub/.idea/workspace.xml +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -