add new features:

- logout time check
- inspect command
This commit is contained in:
TONY_All 2022-02-05 22:08:50 +08:00
parent 420a2da064
commit 585761ae9c
6 changed files with 100 additions and 8 deletions

View File

@ -10,18 +10,41 @@ BiliInviteCode - 邀请制入服检测
子命令: 子命令:
- /inviteCode use <邀请码> 激活邀请码 - /inviteCode use <邀请码> 激活邀请码
- /inviteCode generate <数量> 生成指定数量的激活码 (后台) - /inviteCode generate <数量> 生成指定数量的激活码 (后台)
激活码会被保存在`服务器根目录/plugins/BiliInviteCode/InviteCode/generated/xx.txt` 激活码会被保存在`服务器根目录/plugins/BiliInviteCode/InviteCode/generated/xx.txt`
- /inviteCode edit <玩家ID> <新的QQ号> 修改激活码对应的值 (后台) - /inviteCode edit <玩家ID> <新的QQ号> 修改激活码对应的值 (后台)
- /inviteCode remove <激活码> 移除该激活码 - /inviteCode remove <激活码> 移除该激活码
- /inviteCode current 显示所有可用激活码 - /inviteCode current 显示所有可用激活码
- /inviteCode add <激活码> 手动创建激活码 (后台) - /inviteCode add <激活码> 手动创建激活码 (后台)
激活码的长度不能长于24位 激活码的长度不能长于24位
- /inviteCode inspect <玩家ID> 查询玩家绑定的QQ号
## 数据库结构
数据库分为两张表: `InviteCodes``TimeTable`
### InviteCodes
`InviteCodes` 负责存储玩家的邀请码数据, 格式如下:
| id(int) | inviteCode(varchar) | name(id) | uid(UUID) | qq(varchar) |
| ------------ | ------------------- | ------------------------ | ---------- | ------------ |
| 数据库索引ID | 玩家的邀请码 | 玩家ID(随正版ID自动变更) | 玩家的UUID | 玩家绑定QQ号 |
### TimeTable
`TimeTable` 负责存储玩家的最后退出游戏的日期, 以便能在超过3个月未进入过服务器时移除权限, 格式如下:
| id(UUID) | lastLogout(date) |
| ---------- | -------------------------------- |
| 玩家的UUID | 玩家最后推出游戏的日期(精确到日) |

View File

@ -34,6 +34,7 @@ dependencies {
implementation("org.jetbrains.exposed:exposed-core:$exposedVersion") implementation("org.jetbrains.exposed:exposed-core:$exposedVersion")
implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion") implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion")
implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion") implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")
implementation("org.jetbrains.exposed:exposed-java-time:$exposedVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
} }

View File

@ -19,6 +19,7 @@ import java.util.concurrent.Executor
RuntimeDependency("org.jetbrains.exposed:exposed-core:0.37.3"), RuntimeDependency("org.jetbrains.exposed:exposed-core:0.37.3"),
RuntimeDependency("org.jetbrains.exposed:exposed-dao:0.37.3"), RuntimeDependency("org.jetbrains.exposed:exposed-dao:0.37.3"),
RuntimeDependency("org.jetbrains.exposed:exposed-jdbc:0.37.3"), RuntimeDependency("org.jetbrains.exposed:exposed-jdbc:0.37.3"),
RuntimeDependency("org.jetbrains.exposed:exposed-java-time:0.37.3"),
RuntimeDependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0"), RuntimeDependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0"),
RuntimeDependency("com.h2database:h2:1.4.200") RuntimeDependency("com.h2database:h2:1.4.200")
) )

View File

@ -11,8 +11,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.command.ConsoleCommandSender import org.bukkit.command.ConsoleCommandSender
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import taboolib.common.platform.command.CommandBuilder import taboolib.common.platform.command.CommandBuilder
import taboolib.common.platform.command.command import taboolib.common.platform.command.command
@ -139,7 +141,7 @@ object InviteCodeCommands {
} }
} }
private fun CommandBuilder.CommandComponent.cmdEdit() = literal("edit", permission = "invitecode.edit") { private fun CommandBuilder.CommandComponent.cmdEdit() = literal("edit", permission = "inviteCode.edit".lowercase()) {
dynamic { dynamic {
restrict<ConsoleCommandSender> { _, _, arg -> restrict<ConsoleCommandSender> { _, _, arg ->
transaction { transaction {
@ -222,4 +224,22 @@ object InviteCodeCommands {
} }
} }
} }
private fun CommandBuilder.CommandComponent.cmdInspect() =
literal("inspect", permission = "inviteCode.inspect".lowercase()) {
dynamic {
suggestion<CommandSender>(uncheck = true) { _, _ ->
return@suggestion Bukkit.getOnlinePlayers().map { it.name }
}
execute<CommandSender> { sender, _, arg ->
PluginScope.launch {
newSuspendedTransaction {
val code = InviteCode.find { InviteCodes.name eq arg }.firstOrNull()
?: return@newSuspendedTransaction sender.sendMessage("§c| §7该玩家不存在")
sender.sendMessage("§a| §7该玩家绑定的QQ为: §a${code.qq}")
}
}
}
}
}
} }

View File

@ -3,12 +3,14 @@ package cc.maxmc.invite.data
import cc.maxmc.invite.PluginScope import cc.maxmc.invite.PluginScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.jetbrains.exposed.dao.IntEntity import org.jetbrains.exposed.dao.*
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IdTable
import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.javatime.date
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import taboolib.common.platform.function.getDataFolder import taboolib.common.platform.function.getDataFolder
import taboolib.common.platform.function.info import taboolib.common.platform.function.info
@ -47,11 +49,24 @@ class InviteCode(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<InviteCode>(InviteCodes) companion object : IntEntityClass<InviteCode>(InviteCodes)
var inviteCode by InviteCodes.inviteCode var inviteCode by InviteCodes.inviteCode
var name by InviteCodes.name
var uid by InviteCodes.uid var uid by InviteCodes.uid
var name by InviteCodes.name
var qq by InviteCodes.qq var qq by InviteCodes.qq
} }
object TimeTable : IdTable<UUID>() {
override val id = uuid("uid").entityId()
val lastLogout = date("last_login")
override val primaryKey = PrimaryKey(id)
}
class LastLogout(id: EntityID<UUID>): UUIDEntity(id) {
companion object : UUIDEntityClass<LastLogout>(TimeTable)
val uid by TimeTable.id
var last by TimeTable.lastLogout
}
val userTrials = HashMap<UUID, UserTrial>() val userTrials = HashMap<UUID, UserTrial>()
data class UserTrial(val uid: UUID, private var attempts: Int = 0) { data class UserTrial(val uid: UUID, private var attempts: Int = 0) {

View File

@ -4,6 +4,7 @@ import cc.maxmc.invite.PluginScope
import cc.maxmc.invite.concurrent.chatInput import cc.maxmc.invite.concurrent.chatInput
import cc.maxmc.invite.data.InviteCode import cc.maxmc.invite.data.InviteCode
import cc.maxmc.invite.data.InviteCodes import cc.maxmc.invite.data.InviteCodes
import cc.maxmc.invite.data.LastLogout
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.entity.Player import org.bukkit.entity.Player
@ -11,6 +12,7 @@ import org.bukkit.event.player.*
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import taboolib.common.platform.event.SubscribeEvent import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.console import taboolib.common.platform.function.console
import java.time.LocalDate
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@ -64,6 +66,13 @@ object InvitedListener {
return input return input
} }
suspend fun checkTime(uid: UUID): Boolean {
return newSuspendedTransaction {
val lastLogout = LastLogout.findById(uid) ?: return@newSuspendedTransaction true
lastLogout.last.plusMonths(3).isBefore(LocalDate.now())
}
}
cache[e.player.uniqueId] = e.player.location cache[e.player.uniqueId] = e.player.location
e.player.sendMessage("§e| §7正在检查您的邀请码...请稍等.") e.player.sendMessage("§e| §7正在检查您的邀请码...请稍等.")
PluginScope.launch { PluginScope.launch {
@ -71,6 +80,11 @@ object InvitedListener {
val playerInviteCode = InviteCode.find { InviteCodes.uid eq e.player.uniqueId } val playerInviteCode = InviteCode.find { InviteCodes.uid eq e.player.uniqueId }
.firstOrNull() .firstOrNull()
?: return@newSuspendedTransaction e.player.sendMessage("§c| §7您的账号未激活, 请输入 §c/ic use <激活码> §7来进行激活.") ?: return@newSuspendedTransaction e.player.sendMessage("§c| §7您的账号未激活, 请输入 §c/ic use <激活码> §7来进行激活.")
if (!checkTime(e.player.uniqueId)) {
e.player.kickPlayer("§c| §7由于超过3个月未登录游戏, 您的邀请码已失效.")
playerInviteCode.delete()
return@newSuspendedTransaction
}
if (playerInviteCode.qq == null) { if (playerInviteCode.qq == null) {
playerInviteCode.qq = requireQQNumber(e.player) playerInviteCode.qq = requireQQNumber(e.player)
} }
@ -84,4 +98,22 @@ object InvitedListener {
} }
} }
} }
@SubscribeEvent
fun onQuit(e: PlayerQuitEvent) {
PluginScope.launch {
newSuspendedTransaction {
val lastLogout = LastLogout.findById(e.player.uniqueId)
if (lastLogout == null) {
LastLogout.new(e.player.uniqueId) {
last = LocalDate.now()
}
} else {
lastLogout.run {
last = LocalDate.now()
}
}
}
}
}
} }