Semi Latest Perm core

This commit is contained in:
disclearing 2022-09-05 21:54:43 +01:00
parent 6ea4e9c056
commit b4595b0fac
519 changed files with 9869 additions and 25275 deletions

9
Venom/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/.idea/
/build/
/gradle/
/.gradle/
/api/build/
/proxy/build/
/bukkit/build/
/gradlew.bat
/gradlew

62
Venom/api/build.gradle Normal file
View File

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

BIN
Venom/api/libs/Symbiote.jar Normal file

Binary file not shown.

6
Venom/api/plugin.yml Normal file
View File

@ -0,0 +1,6 @@
name: VenomAPI
main: cc.fyre.venom.Venom
author: Fyre Services
version: 1.0-SNAPSHOT
depend: [Kotlin,Proton]
softdepend: [LuckPerms,PlaceholderAPI]

View File

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

View File

@ -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 <T> runRedisCommand(command: RedisCommand<T>): 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
}
}
}

View File

@ -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<Any>() {
init {
testWhileIdle = true
numTestsPerEvictionRun = -1
minEvictableIdleTimeMillis = 60000L
timeBetweenEvictionRunsMillis = 30000L
}
}

View File

@ -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<T> {
fun execute(jedis: Jedis):T
}

View File

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

View File

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

View File

@ -0,0 +1,13 @@
package cc.fyre.venom.database.mongo
interface Repository<K,V> {
fun pull():Map<K,V>
fun update(value: V):Boolean
fun delete(value: V):Boolean
fun findById(id: K):V?
}

View File

@ -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<UUID,Rank>()
val scoped = HashMap<UUID,Rank>()
val subscription = HashMap<UUID,Rank>()
val active = HashMap<UUID,ArrayList<Grant>>()
val repository = GrantRepository(this.instance)
val expiryService = GrantExpiryService(this.instance)
private var adapter: Optional<GrantAdapter> = 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<Group>):Boolean {
return this.grant(rank,target,sender,reason,scopes,0L)
}
fun grant(rank: Rank,target: UUID,sender: UUID,reason: String,scopes: Set<Group>,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<Grant>):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<Grant>):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<Grant>,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>):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>):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>):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<Grant>) {
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<Grant>) {
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<Grant>) {
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<GrantAdapter> {
return this.adapter
}
fun setProvider(adapter: GrantAdapter?) {
this.adapter = Optional.ofNullable(adapter)
}
}

View File

@ -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<String> = 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"
}
}

View File

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

View File

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

View File

@ -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<UUID,Grant> {
/*
*
* 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<Document> = this.instance.databaseHandler.mongoDB.getCollection("grants")
@Deprecated(message = "empty()",level = DeprecationLevel.HIDDEN)
override fun pull(): Map<UUID,Grant> {
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<Grant> {
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<Grant> {
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<Grant> {
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()
}
}

View File

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

View File

@ -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<Group>()
val proxies = HashSet<Proxy>()
val servers = HashSet<Server>()
var server: Server? = null
/* TODO: All in one collection? */
private val groupsCollection: MongoCollection<Document> = this.api.databaseHandler.mongoDB.getCollection("groups")
private val proxiesCollection: MongoCollection<Document> = this.api.databaseHandler.mongoDB.getCollection("proxies")
private val serversCollection: MongoCollection<Document> = 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"
}
}

View File

@ -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<ArrayList<String>>()
fun hasServer(server: Server):Boolean {
return this.findServers().any{it.id.equals(server.id,true) && it.port == server.port}
}
fun findServers():MutableSet<Server> {
return VenomAPI.instance.networkHandler.servers.filter{it.group.equals(this.id,true)}.toMutableSet()
}
companion object {
const val UPDATE_ID = "SERVER_GROUP_UPDATE"
}
}

View File

@ -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<String> = arrayOf("","")
var update: Long = 0L
var status: Status = Status.OFFLINE
val created: Long = System.currentTimeMillis()
var onlinePlayers = HashSet<UUID>()
var bungeeServers = HashSet<String>()
fun findServers():List<Server> {
return this.bungeeServers.mapNotNull{VenomAPI.instance.networkHandler.findServerById(it)}.toList()
}
companion object {
const val UPDATE_ID = "PROXY_UPDATE"
}
}

View File

@ -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<UUID>()
var maximumPlayers: Int = 0
var whitelistedPlayers = HashSet<UUID>()
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"
}
}

View File

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

View File

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

View File

@ -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<UUID,Profile>()
val repository = ProfileRepository(this.instance)
private val uuidToName = ConcurrentHashMap<UUID,String>()
private val nameToUuid = ConcurrentHashMap<String,UUID>()
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<String>,defaultPermissions: Boolean):ConcurrentHashMap<String,Boolean> {
val toReturn = ConcurrentHashMap<String,Boolean>()
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"
}
}

View File

@ -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<UUID>()
var settings = Setting()
val created = System.currentTimeMillis()
val permissions = ArrayList<String>()
val identifiers: ArrayList<String> = 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"
}
}

View File

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

View File

@ -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<UUID,Profile> {
val collection: MongoCollection<Document> = this.instance.databaseHandler.mongoDB.getCollection("profiles")
@Deprecated("INVALID",level = DeprecationLevel.HIDDEN)
override fun pull(): HashMap<UUID,Profile> {
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<Profile> {
return this.findAlts(profile.id,profile.identifiers)
}
fun findAlts(uuid: UUID,addresses: Collection<String>):MutableSet<Profile> {
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()
}
}

View File

@ -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<UUID,HashSet<Punishment>>()
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<String>,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<String>,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
}
}

View File

@ -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<Evidence>()
var identifiers: ArrayList<String> = 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"
}
}

View File

@ -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<UUID,Punishment> {
/*
*
* 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<Document> = this.instance.databaseHandler.mongoDB.getCollection("punishments")
@Deprecated(message = "empty()",level = DeprecationLevel.HIDDEN)
override fun pull(): Map<UUID,Punishment> {
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<Punishment> {
return this.findByVictim(victim,arrayListOf(type))
}
fun findByVictim(victim: UUID,types: MutableList<Punishment.Type>):MutableSet<Punishment> {
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<String>):MutableSet<Punishment> {
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<Punishment> {
return this.findBySender(uuid,arrayListOf(type))
}
fun findBySender(uuid: UUID,types: MutableList<Punishment.Type>):MutableSet<Punishment> {
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<Punishment> {
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>):Punishment? {
return this.findMostRecentPunishment(punishments,punishments.first().type)
}
fun findMostRecentPunishment(punishments: MutableSet<Punishment>,type: Punishment.Type):Punishment? {
return this.findMostRecentPunishment(punishments,arrayListOf(type))
}
fun findMostRecentPunishment(punishments: MutableSet<Punishment>,types: MutableList<Punishment.Type>):Punishment? {
return punishments
.filter{types.contains(it.type)}
.filter{!it.isVoided() && !it.isPardoned()}
.sortedBy{it.type.ordinal}
.reversed()
.sortedBy{it.created}
.reversed()
.firstOrNull()
}
}

View File

@ -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<String,Rank>()
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"
}
}

View File

@ -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<String>()
var metadata = hashSetOf<Metadata>()
var permissions = hashSetOf<String>()
var evidenceRequired = hashSetOf<Punishment.Type>()
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"
}
}

View File

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

View File

@ -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<String,Rank> {
private val collection: MongoCollection<Document> = this.instance.databaseHandler.mongoDB.getCollection("ranks")
override fun pull(): MutableMap<String,Rank> {
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)
}
}

View File

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

View File

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

View File

@ -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<UUID,Session> {
private val collection: MongoCollection<Document> = this.instance.databaseHandler.mongoDB.getCollection("sessions")
@Deprecated(level = DeprecationLevel.HIDDEN,message = "empty()")
override fun pull(): Map<UUID,Session> {
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<Session> {
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)
}
}

View File

@ -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<String,Tag>()
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"
}
}

View File

@ -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 != ""
}
}

View File

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

View File

@ -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<String,Tag> {
private val collection: MongoCollection<Document> = this.instance.databaseHandler.mongoDB.getCollection("tags")
override fun pull():MutableMap<String,Tag> {
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)
}
}

View File

@ -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<String,String>? {
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<UUID,String>? {
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<String,Long>? {
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()
}
}

View File

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

21
Venom/build.gradle Normal file
View File

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

69
Venom/bukkit/build.gradle Normal file
View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Session>) : PaginatedMenu() {
override fun getPrePaginatedTitle(player: Player): String {
return "Sessions - ${this.displayName}"
}
override fun getAllPagesButtons(player: Player):MutableMap<Int, Button> {
return this.sessions.sortedByDescending{it.login}.withIndex().associate{it.index to SessionButton(it.value)}.toMutableMap()
}
}

View File

@ -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<String> {
val toReturn = ArrayList<String>()
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
}
}

View File

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

View File

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

View File

@ -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 <player>"
}
return "${ChatColor.RED}Usage: /grant <player> <rank> <duration> <scopes> <reason...>"
}
}

View File

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

View File

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

View File

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

View File

@ -1,18 +1,25 @@
package net.evilblock.stark.profile.grant.event package cc.fyre.venom.grant.event
import cc.fyre.venom.grant.data.Grant
import net.evilblock.stark.core.profile.grant.ProfileGrant
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.Event import org.bukkit.event.Event
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
class GrantRemovedEvent(val player: Player, val grant: ProfileGrant) : Event() { /**
* @project venom
companion object { *
@JvmStatic val handlerList = HandlerList() * @date 31/03/2020
} * @author xanderume@gmail.com
*/
class GrantApplyEvent(val player: Player,val grant: Grant) : Event() {
override fun getHandlers(): HandlerList { override fun getHandlers(): HandlerList {
return handlerList return handlerList
} }
companion object {
@JvmStatic val handlerList = HandlerList()
}
} }

View File

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

View File

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

View File

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

View File

@ -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<String>()
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<Int,Button> {
var i = 5*9
val toReturn = HashMap<Int, Button>()
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
}
}

View File

@ -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<String>,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<String> {
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)}"}.")
}
}

View File

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

View File

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

View File

@ -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<Grant>,private val mojangProfile: MojangProfile) : PaginatedMenu() {
override fun getPrePaginatedTitle(player: Player): String {
return this.mojangProfile.displayName
}
override fun getAllPagesButtons(player: Player): MutableMap<Int, Button> {
return this.grants.filter{player.hasPermission("grant.rank.${it.rank}")}.sortedByDescending{it.created}.withIndex().associate{it.index to ViewButton(it.value)}.toMutableMap()
}
}

View File

@ -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<Grant>, private val mojangProfile: MojangProfile) : PaginatedMenu() {
override fun getPrePaginatedTitle(p0: Player?): String {
return this.mojangProfile.displayName
}
override fun getAllPagesButtons(player: Player): MutableMap<Int, Button> {
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()
}
}

View File

@ -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<String> {
val toReturn = ArrayList<String>()
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))
}
}

View File

@ -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<String> {
val toReturn = ArrayList<String>()
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))
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<String,Boolean>()
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<String,Boolean> {
val permissions = ArrayList<String>()
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<PermissionAttachmentInfo> {
return this.permissions.entries.map{PermissionAttachmentInfo(this,it.key,PermissionAttachment(Venom.instance,this),it.value)}.toMutableSet()
}
}

View File

@ -1,18 +1,24 @@
package net.evilblock.stark.profile.grant.event package cc.fyre.venom.permission.event
import net.evilblock.stark.core.profile.grant.ProfileGrant
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.Event import org.bukkit.event.Event
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
class GrantCreatedEvent(val player: Player, val grant: ProfileGrant) : Event() { /**
* @project venom
companion object { *
@JvmStatic val handlerList = HandlerList() * @date 15/04/2020
} * @author xanderume@gmail.com
*/
class PermissionUpdateEvent(val player: Player) : Event(){
override fun getHandlers(): HandlerList { override fun getHandlers(): HandlerList {
return handlerList return handlerList
} }
companion object {
@JvmStatic val handlerList = HandlerList()
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Int, Button> {
return ChatColor.values().filter{it.ordinal in 1..15}.sortedByDescending{it.ordinal}.withIndex().associate{it.index to ChatColorElement(it.value)}.toMutableMap()
}
}

View File

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

View File

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

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