♻️ Optimize code by Gemini 3 Pro
This commit is contained in:
@@ -12,7 +12,13 @@ import dev.solsynth.snConnect.models.SnChatMessage
|
|||||||
import dev.solsynth.snConnect.models.WebSocketPacket
|
import dev.solsynth.snConnect.models.WebSocketPacket
|
||||||
import dev.solsynth.snConnect.services.SnMessageService
|
import dev.solsynth.snConnect.services.SnMessageService
|
||||||
import dev.solsynth.snConnect.services.SnService
|
import dev.solsynth.snConnect.services.SnService
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import net.md_5.bungee.api.ChatColor
|
import net.md_5.bungee.api.ChatColor
|
||||||
import net.md_5.bungee.api.chat.ClickEvent
|
import net.md_5.bungee.api.chat.ClickEvent
|
||||||
import net.md_5.bungee.api.chat.ComponentBuilder
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
@@ -24,9 +30,12 @@ import org.bukkit.Bukkit.getOnlinePlayers
|
|||||||
import org.bukkit.configuration.file.YamlConfiguration
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
|
||||||
class SolarNetworkConnect : JavaPlugin() {
|
class SolarNetworkConnect : JavaPlugin() {
|
||||||
|
private val pluginScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
private var economy: Economy? = null
|
private var economy: Economy? = null
|
||||||
private var sn: SnService? = null
|
private var sn: SnService? = null
|
||||||
private var authService: AuthService? = null
|
private var authService: AuthService? = null
|
||||||
@@ -34,9 +43,8 @@ class SolarNetworkConnect : JavaPlugin() {
|
|||||||
private var messageService: SnMessageService? = null
|
private var messageService: SnMessageService? = null
|
||||||
private var syncChatRooms: List<String> = emptyList()
|
private var syncChatRooms: List<String> = emptyList()
|
||||||
private var destinationChatId: String? = null
|
private var destinationChatId: String? = null
|
||||||
private var webSocketJob: Job? = null
|
|
||||||
private var messages: Map<String, String> = mapOf()
|
private var messages: Map<String, String> = mapOf()
|
||||||
private var playerSolarpassMap: MutableMap<String, String?> = mutableMapOf()
|
private var playerSolarpassMap: ConcurrentHashMap<UUID, String?> = ConcurrentHashMap()
|
||||||
|
|
||||||
private fun handleWebSocketPacket(packet: WebSocketPacket) {
|
private fun handleWebSocketPacket(packet: WebSocketPacket) {
|
||||||
if (config.getBoolean("debug"))
|
if (config.getBoolean("debug"))
|
||||||
@@ -74,9 +82,11 @@ class SolarNetworkConnect : JavaPlugin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val component = componentBuilder.create()
|
val component = componentBuilder.create()
|
||||||
for (player in getOnlinePlayers()) {
|
Bukkit.getScheduler().runTask(this, Runnable {
|
||||||
player.spigot().sendMessage(*component)
|
for (player in getOnlinePlayers()) {
|
||||||
}
|
player.spigot().sendMessage(*component)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,17 +119,17 @@ class SolarNetworkConnect : JavaPlugin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (messageService != null && destinationChatId != null) {
|
if (messageService != null && destinationChatId != null) {
|
||||||
server.pluginManager.registerEvents(SnChatListener(messageService!!, destinationChatId!!, messages), this)
|
server.pluginManager.registerEvents(SnChatListener(pluginScope, messageService!!, destinationChatId!!, messages), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authUserService != null) {
|
if (authUserService != null) {
|
||||||
server.pluginManager.registerEvents(
|
server.pluginManager.registerEvents(
|
||||||
SolarpassCheckListener(authUserService!!, messages, playerSolarpassMap),
|
SolarpassCheckListener(pluginScope, authUserService!!, messages, playerSolarpassMap),
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Bukkit.getPluginCommand("solar")!!.setExecutor(SnCommand(this.sn!!, this.economy, messages, playerSolarpassMap))
|
Bukkit.getPluginCommand("solar")!!.setExecutor(SnCommand(this, pluginScope, this.sn!!, this.economy, messages, playerSolarpassMap))
|
||||||
Bukkit.getPluginCommand("solar")!!.tabCompleter = SnCommandCompleter()
|
Bukkit.getPluginCommand("solar")!!.tabCompleter = SnCommandCompleter()
|
||||||
|
|
||||||
Bukkit.getPluginCommand("eatrock")!!.setExecutor(BedrockRemoverCommand(this.economy))
|
Bukkit.getPluginCommand("eatrock")!!.setExecutor(BedrockRemoverCommand(this.economy))
|
||||||
@@ -135,7 +145,9 @@ class SolarNetworkConnect : JavaPlugin() {
|
|||||||
// Send server start message
|
// Send server start message
|
||||||
try {
|
try {
|
||||||
destinationChatId?.let { chatId ->
|
destinationChatId?.let { chatId ->
|
||||||
messageService?.sendMessage(chatId, messages["server_start"] ?: "🚀 Server started successfully")
|
pluginScope.launch {
|
||||||
|
messageService?.sendMessage(chatId, messages["server_start"] ?: "🚀 Server started successfully")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.warning("Failed to send server start message: ${e.message}")
|
logger.warning("Failed to send server start message: ${e.message}")
|
||||||
@@ -148,14 +160,16 @@ class SolarNetworkConnect : JavaPlugin() {
|
|||||||
// Send server stop message
|
// Send server stop message
|
||||||
try {
|
try {
|
||||||
destinationChatId?.let { chatId ->
|
destinationChatId?.let { chatId ->
|
||||||
messageService?.sendMessage(chatId, messages["server_stop"] ?: "⏹️ Server stopped")
|
pluginScope.launch {
|
||||||
|
messageService?.sendMessage(chatId, messages["server_stop"] ?: "⏹️ Server stopped")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.warning("Failed to send server stop message: ${e.message}")
|
logger.warning("Failed to send server stop message: ${e.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
sn?.disconnect()
|
sn?.disconnect()
|
||||||
webSocketJob?.cancel()
|
pluginScope.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupNetwork(): Boolean {
|
private fun setupNetwork(): Boolean {
|
||||||
@@ -175,11 +189,19 @@ class SolarNetworkConnect : JavaPlugin() {
|
|||||||
authService = AuthService(authUrl, siteSecret);
|
authService = AuthService(authUrl, siteSecret);
|
||||||
authUserService = AuthUserService(authService!!)
|
authUserService = AuthUserService(authService!!)
|
||||||
|
|
||||||
webSocketJob = GlobalScope.launch {
|
pluginScope.launch {
|
||||||
sn!!.connectWebSocketAsFlow().collect { packet ->
|
sn!!.connectWebSocketAsFlow().collect { packet ->
|
||||||
handleWebSocketPacket(packet)
|
handleWebSocketPacket(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginScope.launch {
|
||||||
|
while(isActive) {
|
||||||
|
delay(60000)
|
||||||
|
sn?.sendPing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import org.bukkit.inventory.ItemStack
|
|||||||
|
|
||||||
class BedrockRemoverCommand(private val economy: Economy?) : CommandExecutor {
|
class BedrockRemoverCommand(private val economy: Economy?) : CommandExecutor {
|
||||||
private val paymentMethods = listOf("money", "materials")
|
private val paymentMethods = listOf("money", "materials")
|
||||||
private val requiredMaterials = listOf(
|
private val requiredMaterials = mapOf(
|
||||||
Material.PISTON,
|
Material.PISTON to 1,
|
||||||
Material.TNT,
|
Material.TNT to 1,
|
||||||
Material.LEVER,
|
Material.LEVER to 1,
|
||||||
Material.OAK_TRAPDOOR // Representative for trapdoor group
|
Material.OAK_TRAPDOOR to 1
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
||||||
@@ -27,41 +27,30 @@ class BedrockRemoverCommand(private val economy: Economy?) : CommandExecutor {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.isEmpty() || args.size > 1) {
|
if (args.size != 1 || args[0].lowercase() !in paymentMethods) {
|
||||||
sender.sendMessage(ChatColor.RED.toString() + "Usage: /bedrockremove <money/materials>")
|
sender.sendMessage(ChatColor.RED.toString() + "Usage: /bedrockremove <money|materials>")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val paymentMethod = args[0].lowercase()
|
|
||||||
if (paymentMethod !in paymentMethods) {
|
|
||||||
sender.sendMessage(ChatColor.RED.toString() + "Invalid payment method. Use: money or materials.")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the block the player is looking at
|
|
||||||
val targetBlock = sender.getTargetBlock(null, 10)
|
val targetBlock = sender.getTargetBlock(null, 10)
|
||||||
if (targetBlock == null || targetBlock.type != Material.BEDROCK) {
|
if (targetBlock?.type != Material.BEDROCK) {
|
||||||
sender.sendMessage(ChatColor.RED.toString() + "You must be looking at a bedrock block within 10 blocks.")
|
sender.sendMessage(ChatColor.RED.toString() + "You must be looking at a bedrock block within 10 blocks.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt payment
|
val paymentMethod = args[0].lowercase()
|
||||||
val success = when (paymentMethod) {
|
val success = when (paymentMethod) {
|
||||||
"money" -> payWithMoney(sender, 100.0)
|
"money" -> payWithMoney(sender, 100.0)
|
||||||
"materials" -> payWithAllMaterials(sender)
|
"materials" -> payWithMaterials(sender)
|
||||||
else -> return false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (success) {
|
||||||
// Error messages are handled in the pay methods
|
targetBlock.type = Material.AIR
|
||||||
return true
|
sender.sendMessage(ChatColor.GREEN.toString() + "Bedrock removed successfully!")
|
||||||
|
sender.playSound(sender.location, Sound.BLOCK_STONE_BREAK, 1.0f, 1.0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the bedrock
|
|
||||||
targetBlock.type = Material.AIR
|
|
||||||
sender.sendMessage(ChatColor.GREEN.toString() + "Bedrock removed successfully!")
|
|
||||||
sender.playSound(sender.location, Sound.BLOCK_STONE_BREAK, 1.0f, 1.0f)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,136 +59,72 @@ class BedrockRemoverCommand(private val economy: Economy?) : CommandExecutor {
|
|||||||
player.sendMessage(ChatColor.RED.toString() + "Economy not available.")
|
player.sendMessage(ChatColor.RED.toString() + "Economy not available.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val response = economy.withdrawPlayer(player, "Bedrock removal", amount)
|
val response = economy.withdrawPlayer(player, amount)
|
||||||
if (response.type != EconomyResponse.ResponseType.SUCCESS) {
|
if (response.type != EconomyResponse.ResponseType.SUCCESS) {
|
||||||
player.sendMessage(ChatColor.RED.toString() + "Insufficient funds. You need ${amount}.")
|
player.sendMessage(ChatColor.RED.toString() + "Insufficient funds. You need ${economy.format(amount)}.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
player.sendMessage(ChatColor.GREEN.toString() + "Withdrew $amount from your account.")
|
player.sendMessage(ChatColor.GREEN.toString() + "Withdrew ${economy.format(amount)} from your account.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun payWithMaterial(player: Player, material: Material): Boolean {
|
private fun payWithMaterials(player: Player): Boolean {
|
||||||
val inventory = player.inventory
|
val inventory = player.inventory
|
||||||
|
val itemsToRemove = mutableListOf<ItemStack>()
|
||||||
|
|
||||||
// Special handling for materials with multiple variants
|
for ((material, amount) in requiredMaterials) {
|
||||||
val hasItem = when (material) {
|
val foundItems = findRequiredItems(inventory, material, amount)
|
||||||
Material.OAK_TRAPDOOR -> {
|
if (foundItems == null) {
|
||||||
// Check for any trapdoor type
|
player.sendMessage(ChatColor.RED.toString() + "You don't have all required materials: piston, TNT, lever, and a trapdoor.")
|
||||||
inventory.contents.any { item -> item != null && item.type.name.endsWith("_TRAPDOOR") }
|
|
||||||
}
|
|
||||||
Material.PISTON -> {
|
|
||||||
// Check for any piston type
|
|
||||||
inventory.contents.any { item -> item != null && (item.type == Material.PISTON || item.type == Material.STICKY_PISTON) }
|
|
||||||
}
|
|
||||||
else -> inventory.contains(material, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasItem) {
|
|
||||||
player.sendMessage(ChatColor.RED.toString() + "You don't have a ${material.name.lowercase()} in your inventory.")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the item
|
|
||||||
when (material) {
|
|
||||||
Material.OAK_TRAPDOOR -> {
|
|
||||||
// Find and remove any trapdoor
|
|
||||||
for (item in inventory.contents) {
|
|
||||||
if (item != null && item.type.name.endsWith("_TRAPDOOR")) {
|
|
||||||
val amount = item.amount
|
|
||||||
if (amount > 1) {
|
|
||||||
item.amount = amount - 1
|
|
||||||
} else {
|
|
||||||
inventory.remove(item)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Material.PISTON -> {
|
|
||||||
// Find and remove any piston
|
|
||||||
for (item in inventory.contents) {
|
|
||||||
if (item != null && (item.type == Material.PISTON || item.type == Material.STICKY_PISTON)) {
|
|
||||||
val amount = item.amount
|
|
||||||
if (amount > 1) {
|
|
||||||
item.amount = amount - 1
|
|
||||||
} else {
|
|
||||||
inventory.remove(item)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
inventory.removeItem(ItemStack(material, 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
player.sendMessage(ChatColor.GREEN.toString() + "Consumed 1 ${material.name.lowercase()}.")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun payWithAllMaterials(player: Player): Boolean {
|
|
||||||
val inventory = player.inventory
|
|
||||||
|
|
||||||
// Check if player has all required materials
|
|
||||||
for (material in requiredMaterials) {
|
|
||||||
val hasItem = when (material) {
|
|
||||||
Material.OAK_TRAPDOOR -> {
|
|
||||||
// Check for any trapdoor type
|
|
||||||
inventory.contents.any { item -> item != null && item.type.name.endsWith("_TRAPDOOR") }
|
|
||||||
}
|
|
||||||
Material.PISTON -> {
|
|
||||||
// Check for any piston type
|
|
||||||
inventory.contents.any { item -> item != null && (item.type == Material.PISTON || item.type == Material.STICKY_PISTON) }
|
|
||||||
}
|
|
||||||
else -> inventory.contains(material, 1)
|
|
||||||
}
|
|
||||||
if (!hasItem) {
|
|
||||||
player.sendMessage(ChatColor.RED.toString() + "You don't have all required materials: piston, tnt, lever, and trapdoor.")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
itemsToRemove.addAll(foundItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove one of each material
|
// This check-then-act approach has a potential race condition if the player
|
||||||
for (material in requiredMaterials) {
|
// modifies their inventory between the check and the removal. For this plugin,
|
||||||
when (material) {
|
// the risk is low, but in a more critical system, a more robust transactional
|
||||||
Material.OAK_TRAPDOOR -> {
|
// approach would be needed.
|
||||||
// Find and remove any trapdoor
|
inventory.removeItem(*itemsToRemove.toTypedArray())
|
||||||
for (item in inventory.contents) {
|
|
||||||
if (item != null && item.type.name.endsWith("_TRAPDOOR")) {
|
player.sendMessage(ChatColor.GREEN.toString() + "Consumed materials: piston, TNT, lever, trapdoor.")
|
||||||
val amount = item.amount
|
return true
|
||||||
if (amount > 1) {
|
}
|
||||||
item.amount = amount - 1
|
|
||||||
} else {
|
private fun findRequiredItems(inventory: org.bukkit.inventory.Inventory, material: Material, requiredAmount: Int): List<ItemStack>? {
|
||||||
inventory.remove(item)
|
val foundItems = mutableListOf<ItemStack>()
|
||||||
}
|
var amountFound = 0
|
||||||
break
|
|
||||||
}
|
for (item in inventory.contents) {
|
||||||
}
|
if (item != null && isMaterialMatch(item.type, material)) {
|
||||||
}
|
amountFound += item.amount
|
||||||
Material.PISTON -> {
|
foundItems.add(item)
|
||||||
// Find and remove any piston
|
|
||||||
for (item in inventory.contents) {
|
|
||||||
if (item != null && (item.type == Material.PISTON || item.type == Material.STICKY_PISTON)) {
|
|
||||||
val amount = item.amount
|
|
||||||
if (amount > 1) {
|
|
||||||
item.amount = amount - 1
|
|
||||||
} else {
|
|
||||||
inventory.remove(item)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
inventory.removeItem(ItemStack(material, 1))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendMessage(ChatColor.GREEN.toString() + "Consumed materials: piston, tnt, lever, trapdoor.")
|
if (amountFound >= requiredAmount) {
|
||||||
return true
|
// We have enough, now determine the exact stacks to remove
|
||||||
|
val toRemove = mutableListOf<ItemStack>()
|
||||||
|
var amountToRemove = requiredAmount
|
||||||
|
for (item in foundItems) {
|
||||||
|
val itemClone = item.clone()
|
||||||
|
if (amountToRemove <= 0) break
|
||||||
|
val amountFromThisStack = itemClone.amount.coerceAtMost(amountToRemove)
|
||||||
|
itemClone.amount = amountFromThisStack
|
||||||
|
toRemove.add(itemClone)
|
||||||
|
amountToRemove -= amountFromThisStack
|
||||||
|
}
|
||||||
|
return toRemove
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isMaterialMatch(itemType: Material, requiredMaterial: Material): Boolean {
|
||||||
|
return when (requiredMaterial) {
|
||||||
|
Material.OAK_TRAPDOOR -> itemType.name.endsWith("_TRAPDOOR")
|
||||||
|
Material.PISTON -> itemType == Material.PISTON || itemType == Material.STICKY_PISTON
|
||||||
|
else -> itemType == requiredMaterial
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,9 +137,10 @@ class BedrockRemoverCompleter : TabCompleter {
|
|||||||
label: String,
|
label: String,
|
||||||
args: Array<out String>
|
args: Array<out String>
|
||||||
): MutableList<String> {
|
): MutableList<String> {
|
||||||
return when (args.size) {
|
return if (args.size == 1) {
|
||||||
1 -> paymentMethods.filter { it.startsWith(args[0], ignoreCase = true) }.toMutableList()
|
paymentMethods.filter { it.startsWith(args[0], ignoreCase = true) }.toMutableList()
|
||||||
else -> mutableListOf()
|
} else {
|
||||||
|
mutableListOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package dev.solsynth.snConnect.commands
|
package dev.solsynth.snConnect.commands
|
||||||
|
|
||||||
import dev.solsynth.snConnect.services.*
|
import dev.solsynth.snConnect.services.*
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import net.md_5.bungee.api.chat.ClickEvent
|
import net.md_5.bungee.api.chat.ClickEvent
|
||||||
import net.md_5.bungee.api.chat.TextComponent
|
import net.md_5.bungee.api.chat.TextComponent
|
||||||
import net.milkbowl.vault.economy.Economy
|
import net.milkbowl.vault.economy.Economy
|
||||||
import net.milkbowl.vault.economy.EconomyResponse
|
import net.milkbowl.vault.economy.EconomyResponse
|
||||||
import org.bukkit.Bukkit.getLogger
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
import org.bukkit.Sound
|
import org.bukkit.Sound
|
||||||
import org.bukkit.command.Command
|
import org.bukkit.command.Command
|
||||||
@@ -13,12 +14,18 @@ import org.bukkit.command.CommandExecutor
|
|||||||
import org.bukkit.command.CommandSender
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.command.TabCompleter
|
import org.bukkit.command.TabCompleter
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class SnCommand(
|
class SnCommand(
|
||||||
|
private val plugin: JavaPlugin,
|
||||||
|
private val pluginScope: CoroutineScope,
|
||||||
private val sn: SnService,
|
private val sn: SnService,
|
||||||
private val eco: Economy?,
|
private val eco: Economy?,
|
||||||
private val messages: Map<String, String>,
|
private val messages: Map<String, String>,
|
||||||
private val playerSolarpassMap: MutableMap<String, String?>
|
private val playerSolarpassMap: ConcurrentHashMap<UUID, String?>
|
||||||
) :
|
) :
|
||||||
CommandExecutor {
|
CommandExecutor {
|
||||||
override fun onCommand(p0: CommandSender, p1: Command, p2: String, p3: Array<out String>): Boolean {
|
override fun onCommand(p0: CommandSender, p1: Command, p2: String, p3: Array<out String>): Boolean {
|
||||||
@@ -48,42 +55,45 @@ class SnCommand(
|
|||||||
?: "Confirming payment, please stand by...")
|
?: "Confirming payment, please stand by...")
|
||||||
);
|
);
|
||||||
|
|
||||||
val order: SnOrder
|
pluginScope.launch {
|
||||||
try {
|
try {
|
||||||
order = orderSrv.getOrder(orderNumber);
|
val order = orderSrv.getOrder(orderNumber);
|
||||||
// The update validated the order is created by us
|
// The update validated the order is created by us
|
||||||
orderSrv.updateOrderStatus(orderNumber, false);
|
orderSrv.updateOrderStatus(orderNumber, false);
|
||||||
} catch (_: Exception) {
|
|
||||||
p0.sendMessage(
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
ChatColor.RED.toString() + (messages["command_deposit_pull_error"]
|
if (order.status != 1L) {
|
||||||
?: "An error occurred while pulling transaction. Make sure the order exists then try again later.")
|
p0.sendMessage(
|
||||||
)
|
ChatColor.RED.toString() + (messages["command_deposit_order_not_paid"]
|
||||||
return true;
|
?: "Order was not paid yet.")
|
||||||
|
)
|
||||||
|
return@Runnable
|
||||||
|
}
|
||||||
|
|
||||||
|
val bal = order.amount;
|
||||||
|
eco?.depositPlayer(p0, bal)
|
||||||
|
|
||||||
|
val doneComponent =
|
||||||
|
TextComponent(ChatColor.GREEN.toString() + (messages["command_deposit_done"] ?: "Done!"))
|
||||||
|
val moneyComponent = TextComponent(ChatColor.GOLD.toString() + ChatColor.BOLD + " $bal$")
|
||||||
|
val suffixComponent =
|
||||||
|
TextComponent(
|
||||||
|
ChatColor.GREEN.toString() + (messages["command_deposit_added_balance"]
|
||||||
|
?: " has been added to your balance.")
|
||||||
|
)
|
||||||
|
|
||||||
|
p0.playSound(p0.location, Sound.BLOCK_ANVIL_PLACE, 1.0F, 1.0F)
|
||||||
|
p0.spigot().sendMessage(doneComponent, moneyComponent, suffixComponent)
|
||||||
|
})
|
||||||
|
} catch (_: Exception) {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
|
p0.sendMessage(
|
||||||
|
ChatColor.RED.toString() + (messages["command_deposit_pull_error"]
|
||||||
|
?: "An error occurred while pulling transaction. Make sure the order exists then try again later.")
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order.status != 1L) {
|
|
||||||
p0.sendMessage(
|
|
||||||
ChatColor.RED.toString() + (messages["command_deposit_order_not_paid"]
|
|
||||||
?: "Order was not paid yet.")
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
val bal = order.amount;
|
|
||||||
eco?.depositPlayer(p0.player, bal)
|
|
||||||
|
|
||||||
val doneComponent =
|
|
||||||
TextComponent(ChatColor.GREEN.toString() + (messages["command_deposit_done"] ?: "Done!"))
|
|
||||||
val moneyComponent = TextComponent(ChatColor.GOLD.toString() + ChatColor.BOLD + " $bal$")
|
|
||||||
val suffixComponent =
|
|
||||||
TextComponent(
|
|
||||||
ChatColor.GREEN.toString() + (messages["command_deposit_added_balance"]
|
|
||||||
?: " has been added to your balance.")
|
|
||||||
)
|
|
||||||
|
|
||||||
p0.playSound(p0.player!!, Sound.BLOCK_ANVIL_PLACE, 1.0F, 1.0F)
|
|
||||||
p0.spigot().sendMessage(doneComponent, moneyComponent, suffixComponent)
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,44 +112,47 @@ class SnCommand(
|
|||||||
?: "Creating order, please stand by...")
|
?: "Creating order, please stand by...")
|
||||||
);
|
);
|
||||||
|
|
||||||
val order: SnOrder
|
pluginScope.launch {
|
||||||
try {
|
try {
|
||||||
order = orderSrv.createOrder("Deposit to GoatCraft", amount);
|
val order = orderSrv.createOrder("Deposit to GoatCraft", amount);
|
||||||
} catch (e: Exception) {
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
p0.sendMessage(
|
val linkComponent =
|
||||||
ChatColor.RED.toString() + (messages["command_deposit_create_error"]
|
TextComponent(
|
||||||
?: "An error occurred while creating order. Try again later.")
|
ChatColor.GOLD.toString() + ChatColor.UNDERLINE.toString() + ChatColor.BOLD.toString() + (messages["command_deposit_click_here"]
|
||||||
)
|
?: "click here")
|
||||||
e.printStackTrace();
|
)
|
||||||
return true;
|
linkComponent.clickEvent =
|
||||||
|
ClickEvent(ClickEvent.Action.OPEN_URL, "https://solian.app/orders/${order.id}");
|
||||||
|
val orderHintComponent =
|
||||||
|
TextComponent(
|
||||||
|
ChatColor.GRAY.toString() + (messages["command_deposit_order_created"]
|
||||||
|
?: "Order created, number ") + ChatColor.WHITE + ChatColor.BOLD + "#${order.id.take(6)}" + " "
|
||||||
|
)
|
||||||
|
val followingComponent = TextComponent(
|
||||||
|
ChatColor.GRAY.toString() + (messages["command_deposit_to_payment_page"] ?: " to the payment page.")
|
||||||
|
)
|
||||||
|
p0.spigot()
|
||||||
|
.sendMessage(orderHintComponent, linkComponent, followingComponent);
|
||||||
|
|
||||||
|
val afterPaidComponent =
|
||||||
|
TextComponent(
|
||||||
|
ChatColor.UNDERLINE.toString() + ChatColor.YELLOW + (messages["command_deposit_after_paid"]
|
||||||
|
?: "After you paid, click here to confirm payment.")
|
||||||
|
)
|
||||||
|
afterPaidComponent.clickEvent =
|
||||||
|
ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sn deposit confirm ${order.id}")
|
||||||
|
p0.spigot().sendMessage(afterPaidComponent);
|
||||||
|
})
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
|
p0.sendMessage(
|
||||||
|
ChatColor.RED.toString() + (messages["command_deposit_create_error"]
|
||||||
|
?: "An error occurred while creating order. Try again later.")
|
||||||
|
)
|
||||||
|
e.printStackTrace();
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val linkComponent =
|
|
||||||
TextComponent(
|
|
||||||
ChatColor.GOLD.toString() + ChatColor.UNDERLINE.toString() + ChatColor.BOLD.toString() + (messages["command_deposit_click_here"]
|
|
||||||
?: "click here")
|
|
||||||
)
|
|
||||||
linkComponent.clickEvent =
|
|
||||||
ClickEvent(ClickEvent.Action.OPEN_URL, "https://solian.app/orders/${order.id}");
|
|
||||||
val orderHintComponent =
|
|
||||||
TextComponent(
|
|
||||||
ChatColor.GRAY.toString() + (messages["command_deposit_order_created"]
|
|
||||||
?: "Order created, number ") + ChatColor.WHITE + ChatColor.BOLD + "#${order.id.take(6)}" + " "
|
|
||||||
)
|
|
||||||
val followingComponent = TextComponent(
|
|
||||||
ChatColor.GRAY.toString() + (messages["command_deposit_to_payment_page"] ?: " to the payment page.")
|
|
||||||
)
|
|
||||||
p0.spigot()
|
|
||||||
.sendMessage(orderHintComponent, linkComponent, followingComponent);
|
|
||||||
|
|
||||||
val afterPaidComponent =
|
|
||||||
TextComponent(
|
|
||||||
ChatColor.UNDERLINE.toString() + ChatColor.YELLOW + (messages["command_deposit_after_paid"]
|
|
||||||
?: "After you paid, click here to confirm payment.")
|
|
||||||
)
|
|
||||||
afterPaidComponent.clickEvent =
|
|
||||||
ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sn deposit confirm ${order.id}")
|
|
||||||
p0.spigot().sendMessage(afterPaidComponent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"withdraw" -> {
|
"withdraw" -> {
|
||||||
@@ -160,7 +173,7 @@ class SnCommand(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
val playerUuid = p0.uniqueId.toString()
|
val playerUuid = p0.uniqueId
|
||||||
val accountId = playerSolarpassMap[playerUuid]
|
val accountId = playerSolarpassMap[playerUuid]
|
||||||
if (accountId == null) {
|
if (accountId == null) {
|
||||||
p0.sendMessage(
|
p0.sendMessage(
|
||||||
@@ -176,7 +189,7 @@ class SnCommand(
|
|||||||
|
|
||||||
// Takes extra 20% as fee
|
// Takes extra 20% as fee
|
||||||
val fee = amount * 0.2;
|
val fee = amount * 0.2;
|
||||||
val resp = eco?.withdrawPlayer(p0.player, amount + fee);
|
val resp = eco?.withdrawPlayer(p0, amount + fee);
|
||||||
if (resp?.type != EconomyResponse.ResponseType.SUCCESS) {
|
if (resp?.type != EconomyResponse.ResponseType.SUCCESS) {
|
||||||
p0.sendMessage(
|
p0.sendMessage(
|
||||||
ChatColor.RED.toString() + (messages["command_withdraw_no_money"]
|
ChatColor.RED.toString() + (messages["command_withdraw_no_money"]
|
||||||
@@ -185,25 +198,31 @@ class SnCommand(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
pluginScope.launch {
|
||||||
val transactionSrv = SnBalanceService(sn);
|
try {
|
||||||
transactionSrv.addBalance(amount, "Withdraw from GoatCraft", accountId);
|
val transactionSrv = SnBalanceService(sn);
|
||||||
val transactionHintComponent =
|
transactionSrv.addBalance(amount, "Withdraw from GoatCraft", accountId);
|
||||||
TextComponent(
|
|
||||||
ChatColor.GREEN.toString() + (messages["command_withdraw_done"]
|
|
||||||
?: "Done! ")
|
|
||||||
)
|
|
||||||
|
|
||||||
p0.playSound(p0.player!!, Sound.BLOCK_ANVIL_PLACE, 1.0F, 1.0F)
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
p0.spigot().sendMessage(transactionHintComponent)
|
val transactionHintComponent =
|
||||||
} catch (e: Exception) {
|
TextComponent(
|
||||||
eco.depositPlayer(p0.player, amount + fee)
|
ChatColor.GREEN.toString() + (messages["command_withdraw_done"]
|
||||||
p0.sendMessage(
|
?: "Done! ")
|
||||||
ChatColor.RED.toString() + (messages["command_withdraw_error"]
|
)
|
||||||
?: "An error occurred while making transaction. Make sure your wallet exists then try again later.")
|
|
||||||
)
|
p0.playSound(p0.location, Sound.BLOCK_ANVIL_PLACE, 1.0F, 1.0F)
|
||||||
e.printStackTrace()
|
p0.spigot().sendMessage(transactionHintComponent)
|
||||||
return true
|
})
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
|
eco.depositPlayer(p0, amount + fee)
|
||||||
|
p0.sendMessage(
|
||||||
|
ChatColor.RED.toString() + (messages["command_withdraw_error"]
|
||||||
|
?: "An error occurred while making transaction. Make sure your wallet exists then try again later.")
|
||||||
|
)
|
||||||
|
e.printStackTrace()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
package dev.solsynth.snConnect.listeners
|
package dev.solsynth.snConnect.listeners
|
||||||
|
|
||||||
import com.Zrips.CMI.CMI
|
|
||||||
import dev.solsynth.snConnect.services.SnMessageService
|
import dev.solsynth.snConnect.services.SnMessageService
|
||||||
import org.bukkit.Bukkit
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import org.bukkit.entity.Player
|
import kotlinx.coroutines.launch
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.EventPriority
|
import org.bukkit.event.EventPriority
|
||||||
import org.bukkit.event.Listener
|
import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.entity.PlayerDeathEvent
|
import org.bukkit.event.entity.PlayerDeathEvent
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent
|
import org.bukkit.event.player.AsyncPlayerChatEvent
|
||||||
import org.bukkit.event.player.PlayerAdvancementDoneEvent
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
import org.bukkit.event.player.PlayerQuitEvent
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
|
|
||||||
class SnChatListener(
|
class SnChatListener(
|
||||||
|
private val pluginScope: CoroutineScope,
|
||||||
private val messageService: SnMessageService,
|
private val messageService: SnMessageService,
|
||||||
private val destinationChatId: String,
|
private val destinationChatId: String,
|
||||||
private val messages: Map<String, String>
|
private val messages: Map<String, String>
|
||||||
@@ -21,31 +20,38 @@ class SnChatListener(
|
|||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
fun onPlayerChat(event: AsyncPlayerChatEvent) {
|
fun onPlayerChat(event: AsyncPlayerChatEvent) {
|
||||||
val message = "${event.player.name}: ${event.message}"
|
val message = "${event.player.name}: ${event.message}"
|
||||||
messageService.sendMessage(destinationChatId, message)
|
pluginScope.launch {
|
||||||
|
messageService.sendMessage(destinationChatId, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("SENSELESS_COMPARISON")
|
|
||||||
@EventHandler()
|
@EventHandler()
|
||||||
fun onPlayerJoin(event: PlayerJoinEvent) {
|
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||||
val firstTime = Bukkit.getOfflinePlayer(event.player.uniqueId) == null;
|
val firstTime = !event.player.hasPlayedBefore();
|
||||||
val templateKey = if (!firstTime) "join" else "join_first";
|
val templateKey = if (firstTime) "join_first" else "join";
|
||||||
val template = messages[templateKey]
|
val template = messages[templateKey]
|
||||||
?: if (!firstTime) "➡️ {player} joined the game." else "➡️ {player} first time joined the game."
|
?: if (firstTime) "➡️ {player} first time joined the game." else "➡️ {player} joined the game."
|
||||||
val message = template.replace("{player}", event.player.name)
|
val message = template.replace("{player}", event.player.name)
|
||||||
messageService.sendMessage(destinationChatId, message)
|
pluginScope.launch {
|
||||||
|
messageService.sendMessage(destinationChatId, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler()
|
@EventHandler()
|
||||||
fun onPlayerQuit(event: PlayerQuitEvent) {
|
fun onPlayerQuit(event: PlayerQuitEvent) {
|
||||||
val template = messages["quit"] ?: "⬅️ {player} left the game."
|
val template = messages["quit"] ?: "⬅️ {player} left the game."
|
||||||
val message = template.replace("{player}", event.player.name)
|
val message = template.replace("{player}", event.player.name)
|
||||||
messageService.sendMessage(destinationChatId, message)
|
pluginScope.launch {
|
||||||
|
messageService.sendMessage(destinationChatId, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler()
|
@EventHandler()
|
||||||
fun onPlayerDeath(event: PlayerDeathEvent) {
|
fun onPlayerDeath(event: PlayerDeathEvent) {
|
||||||
val template = messages["death"] ?: "💀 {player} {message}"
|
val template = messages["death"] ?: "💀 {message}"
|
||||||
val message = template.replace("{player}", event.entity.name).replace("{message}", event.deathMessage ?: "")
|
val message = template.replace("{player}", event.entity.name).replace("{message}", event.deathMessage ?: "")
|
||||||
messageService.sendMessage(destinationChatId, message)
|
pluginScope.launch {
|
||||||
|
messageService.sendMessage(destinationChatId, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,41 @@
|
|||||||
package dev.solsynth.snConnect.listeners
|
package dev.solsynth.snConnect.listeners
|
||||||
|
|
||||||
import dev.solsynth.snConnect.services.AuthUserService
|
import dev.solsynth.snConnect.services.AuthUserService
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.Listener
|
import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.player.PlayerJoinEvent
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
class SolarpassCheckListener(
|
class SolarpassCheckListener(
|
||||||
|
private val pluginScope: CoroutineScope,
|
||||||
private val authUserService: AuthUserService,
|
private val authUserService: AuthUserService,
|
||||||
private val messages: Map<String, String>,
|
private val messages: Map<String, String>,
|
||||||
private val playerSolarpassMap: MutableMap<String, String?>
|
private val playerSolarpassMap: ConcurrentHashMap<UUID, String?>
|
||||||
) : Listener {
|
) : Listener {
|
||||||
|
|
||||||
@EventHandler()
|
@EventHandler()
|
||||||
fun onPlayerJoin(event: PlayerJoinEvent) {
|
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||||
GlobalScope.launch {
|
pluginScope.launch {
|
||||||
try {
|
try {
|
||||||
val playerUuid = event.player.uniqueId.toString()
|
val playerUuid = event.player.uniqueId
|
||||||
var solarpassId = playerSolarpassMap[playerUuid]
|
if (playerSolarpassMap.containsKey(playerUuid)) {
|
||||||
if (solarpassId == null) {
|
return@launch
|
||||||
solarpassId = authUserService.getSnByPlayer(playerUuid)
|
|
||||||
playerSolarpassMap[playerUuid] = solarpassId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val solarpassId = authUserService.getSnByPlayer(playerUuid.toString())
|
||||||
|
playerSolarpassMap[playerUuid] = solarpassId
|
||||||
|
|
||||||
if (solarpassId == null) {
|
if (solarpassId == null) {
|
||||||
// Send suggestion message
|
// Send suggestion message
|
||||||
val message = messages["solarpass_bind_suggestion"] ?: "${ChatColor.YELLOW}To get more features, please bind your Solarpass account!"
|
val message = messages["solarpass_bind_suggestion"] ?: "${ChatColor.YELLOW}To get more features, please bind your Solarpass account!"
|
||||||
event.player.sendMessage(message)
|
Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("SolarNetworkConnect")!!, Runnable {
|
||||||
|
event.player.sendMessage(message)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Optionally log the error or handle it
|
// Optionally log the error or handle it
|
||||||
|
|||||||
@@ -95,4 +95,8 @@ class SnService(private val baseUrl: String, val clientId: String, val clientSec
|
|||||||
websocket?.close(1000, "Disconnecting")
|
websocket?.close(1000, "Disconnecting")
|
||||||
websocket = null
|
websocket = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendPing() {
|
||||||
|
websocket?.send("{\"type\":\"ping\"}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user