Добавление покупки по табличке.
This commit is contained in:
parent
79d21942bb
commit
5bd184ec2a
163
src/main/kotlin/main/VpcSpigotIntegration/SignHandler.kt
Normal file
163
src/main/kotlin/main/VpcSpigotIntegration/SignHandler.kt
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package main.VpcSpigotIntegration
|
||||||
|
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.INVOICE_CREATION_TIMES
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.LOGGER
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.PAY_BY_SIGN
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.PLUGIN
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.PREFIX
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.SIGN_PAYMENT_INFO
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.TO_PAY_SIGN_INVOICES
|
||||||
|
import main.VpcSpigotIntegration.VpcServerIntegration.Companion.USERNAME
|
||||||
|
import net.md_5.bungee.api.chat.ClickEvent
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.md_5.bungee.api.chat.HoverEvent
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Bukkit.getWorld
|
||||||
|
import org.bukkit.ChatColor
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.block.BlockEvent
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent
|
||||||
|
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.block.Chest
|
||||||
|
import org.bukkit.block.Container
|
||||||
|
import org.bukkit.block.Sign
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.Action
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent
|
||||||
|
import org.bukkit.event.block.SignChangeEvent
|
||||||
|
import org.bukkit.inventory.Inventory
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.Locale.getDefault
|
||||||
|
|
||||||
|
class SignPaymentInfo(
|
||||||
|
public val amount: Int,
|
||||||
|
public val type: Material,
|
||||||
|
public val container: Chest,
|
||||||
|
public val player: Player,
|
||||||
|
public val cost: Double,
|
||||||
|
public val dst_username: String
|
||||||
|
)
|
||||||
|
|
||||||
|
class SignHandler: Listener {
|
||||||
|
@EventHandler
|
||||||
|
fun onClick(event: PlayerInteractEvent) {
|
||||||
|
// Check if feature enabled
|
||||||
|
if (!PAY_BY_SIGN) return
|
||||||
|
|
||||||
|
// Check if clicked block is a sign
|
||||||
|
val block = event.clickedBlock!!
|
||||||
|
if (block.type != Material.SIGN_POST && block.type != Material.WALL_SIGN) return
|
||||||
|
// Verify it's actually a sign state
|
||||||
|
val state = block.state
|
||||||
|
if (state !is Sign) return
|
||||||
|
// Check if it is RIGHT CLICK
|
||||||
|
if (event.action != Action.RIGHT_CLICK_BLOCK) return
|
||||||
|
// Check if this is good formatted sign
|
||||||
|
val sign = block.state as Sign
|
||||||
|
val clearFirstLine = ChatColor.stripColor(sign.getLine(0)).trim()
|
||||||
|
val clearPrefix = ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', PREFIX)).trim()
|
||||||
|
if (clearFirstLine != clearPrefix) return
|
||||||
|
|
||||||
|
// Check if player already have open invoices
|
||||||
|
if (TO_PAY_SIGN_INVOICES.contains(event.player.name)) {
|
||||||
|
Utils.send(event.player, "&cУ вас уже есть открытый счёт, сначала оплатите его.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val blockFace = event.blockFace.toString()
|
||||||
|
LOGGER.info("Block face: $blockFace")
|
||||||
|
var cordX: Int = event.clickedBlock.location.x.toInt()
|
||||||
|
var cordY: Int = event.clickedBlock.location.y.toInt()
|
||||||
|
var cordZ: Int = event.clickedBlock.location.z.toInt()
|
||||||
|
LOGGER.info("Cords: $cordX $cordY $cordZ")
|
||||||
|
when {
|
||||||
|
blockFace == "EAST" -> {
|
||||||
|
cordX -= 1
|
||||||
|
}
|
||||||
|
blockFace == "NORTH" -> {
|
||||||
|
cordZ += 1
|
||||||
|
}
|
||||||
|
blockFace == "WEST" -> {
|
||||||
|
cordX += 1
|
||||||
|
}
|
||||||
|
blockFace == "SOUTH" -> {
|
||||||
|
cordZ -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val containerBlock = getWorld(event.clickedBlock.world.uid).getBlockAt(cordX, cordY, cordZ)
|
||||||
|
LOGGER.info("Container block: $cordX $cordY $cordZ")
|
||||||
|
|
||||||
|
val container: Chest = containerBlock.state as Chest
|
||||||
|
val firstItem = container.blockInventory.contents[0]
|
||||||
|
LOGGER.info("firstItem: ${firstItem.type} | amount: ${firstItem.amount}")
|
||||||
|
|
||||||
|
// Get info
|
||||||
|
val vpcUsername = sign.getLine(1)
|
||||||
|
val costPerItem: Double? = sign.getLine(2).toDoubleOrNull()
|
||||||
|
val amount: Int? = sign.getLine(3).toIntOrNull()
|
||||||
|
if (vpcUsername.isEmpty() || costPerItem == null || amount == null) return
|
||||||
|
LOGGER.info("vpcUsername: $vpcUsername")
|
||||||
|
LOGGER.info("costPerItem: $costPerItem")
|
||||||
|
LOGGER.info("amount: $amount")
|
||||||
|
|
||||||
|
// Fixed: Properly check if there are enough items of the required type
|
||||||
|
val availableAmount = container.inventory.all(firstItem.type).values.sumOf { it.amount }
|
||||||
|
if (availableAmount < amount) {
|
||||||
|
LOGGER.info("Not enough items: [type: ${firstItem.type}, requested: $amount, available: $availableAmount]")
|
||||||
|
Utils.send(event.player,"&cВ контейнере не хватает предметов для покупки.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate invoice etc.
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(PLUGIN, Runnable {
|
||||||
|
val cost = costPerItem*amount
|
||||||
|
val invoiceId = VpcApi.create_invoice(cost).toString()
|
||||||
|
LOGGER.info("Invoice id: $invoiceId")
|
||||||
|
if (invoiceId == "null") {
|
||||||
|
Utils.send(event.player,"&cПроизошла ошибка при генерации счёта. Обратитесь к администратору или повторите позже.")
|
||||||
|
return@Runnable
|
||||||
|
}
|
||||||
|
// Add data to map
|
||||||
|
TO_PAY_SIGN_INVOICES[event.player.name] = invoiceId
|
||||||
|
INVOICE_CREATION_TIMES[invoiceId] = System.currentTimeMillis()
|
||||||
|
SIGN_PAYMENT_INFO[invoiceId] = SignPaymentInfo(amount, firstItem.type, container, event.player, cost, vpcUsername)
|
||||||
|
|
||||||
|
val colored = ChatColor.translateAlternateColorCodes('&',
|
||||||
|
"${PREFIX}Нажмите здесь, оплатить &6$cost VPC")
|
||||||
|
val message = TextComponent(colored)
|
||||||
|
message.clickEvent = ClickEvent(ClickEvent.Action.RUN_COMMAND, "/vpc pay $USERNAME $cost $invoiceId")
|
||||||
|
message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||||
|
ComponentBuilder("/vpc pay $USERNAME $cost $invoiceId").create())
|
||||||
|
event.player.spigot().sendMessage(message)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onSignChange(event: SignChangeEvent) {
|
||||||
|
// Check if feature enabled
|
||||||
|
if (!PAY_BY_SIGN) return
|
||||||
|
if (event.getLine(0).contains("[VPC]")) {
|
||||||
|
val vpcUsername = event.getLine(1)
|
||||||
|
val cost: Double? = event.getLine(2).toDoubleOrNull()
|
||||||
|
val amount: Int? = event.getLine(3).toIntOrNull()
|
||||||
|
|
||||||
|
var coloredLine: String
|
||||||
|
// Check if some data is missing
|
||||||
|
if (vpcUsername.isEmpty() || cost == null || amount == null) {
|
||||||
|
coloredLine = ChatColor.translateAlternateColorCodes('&', "$PREFIX&cError")
|
||||||
|
event.setLine(0, coloredLine)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
coloredLine = ChatColor.translateAlternateColorCodes('&', PREFIX)
|
||||||
|
event.setLine(0, coloredLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ package main.VpcSpigotIntegration
|
|||||||
// Here you will see the main logic
|
// Here you will see the main logic
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
import com.sun.org.apache.xpath.internal.operations.Bool
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.command.Command
|
import org.bukkit.command.Command
|
||||||
@ -15,6 +16,8 @@ import net.md_5.bungee.api.chat.HoverEvent
|
|||||||
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 org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.scheduler.BukkitRunnable
|
import org.bukkit.scheduler.BukkitRunnable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
@ -40,6 +43,7 @@ class VpcServerIntegration() : JavaPlugin(), CommandExecutor {
|
|||||||
lateinit var COURSE_DYNAMIC_COMMAND: String
|
lateinit var COURSE_DYNAMIC_COMMAND: String
|
||||||
var COURSE_COMMISSION: Float = DEFAULT_COURSE_COMMISSION
|
var COURSE_COMMISSION: Float = DEFAULT_COURSE_COMMISSION
|
||||||
var INVOICE_TIMEOUT_SECONDS: Long = DEFAULT_INVOICE_TIMEOUT_SECONDS
|
var INVOICE_TIMEOUT_SECONDS: Long = DEFAULT_INVOICE_TIMEOUT_SECONDS
|
||||||
|
var PAY_BY_SIGN: Boolean = true
|
||||||
|
|
||||||
// Default configuration values
|
// Default configuration values
|
||||||
const val DEFAULT_USERNAME: String = "test"
|
const val DEFAULT_USERNAME: String = "test"
|
||||||
@ -55,6 +59,7 @@ class VpcServerIntegration() : JavaPlugin(), CommandExecutor {
|
|||||||
const val DEFAULT_COURSE_DYNAMIC_COMMAND: String = "baltop force"
|
const val DEFAULT_COURSE_DYNAMIC_COMMAND: String = "baltop force"
|
||||||
const val DEFAULT_COURSE_COMMISSION: Float = 5.0f
|
const val DEFAULT_COURSE_COMMISSION: Float = 5.0f
|
||||||
const val DEFAULT_INVOICE_TIMEOUT_SECONDS: Long = 300 // 5 minutes
|
const val DEFAULT_INVOICE_TIMEOUT_SECONDS: Long = 300 // 5 minutes
|
||||||
|
const val DEFAULT_PAY_BY_SIGN: Boolean = true
|
||||||
|
|
||||||
// Static configurations
|
// Static configurations
|
||||||
const val PREFIX = "&9[&bVPC&7-&6I&9] &3"
|
const val PREFIX = "&9[&bVPC&7-&6I&9] &3"
|
||||||
@ -70,11 +75,17 @@ class VpcServerIntegration() : JavaPlugin(), CommandExecutor {
|
|||||||
var TO_AUTH_PLAYERS: MutableMap<String, String> = mutableMapOf() // Pair: {player: vpc_username}
|
var TO_AUTH_PLAYERS: MutableMap<String, String> = mutableMapOf() // Pair: {player: vpc_username}
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
var TO_AUTH_PLAYERS_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id}
|
var TO_AUTH_PLAYERS_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
var TO_PAY_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id}
|
var TO_PAY_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id}
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
var INVOICES_AMOUNT: MutableMap<String, Double> = mutableMapOf() // How many should we pay to player after invoice?
|
var INVOICES_AMOUNT: MutableMap<String, Double> = mutableMapOf() // How many should we pay to player after invoice?
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
var TO_PAY_SIGN_INVOICES: MutableMap<String, String> = mutableMapOf() // Pair: {player: invoice_id}
|
||||||
|
@JvmStatic
|
||||||
|
var SIGN_PAYMENT_INFO: MutableMap<String, SignPaymentInfo> = mutableMapOf() // Information about amount, type and block
|
||||||
|
|
||||||
// Track invoice creation times for timeout handling
|
// Track invoice creation times for timeout handling
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
var INVOICE_CREATION_TIMES: MutableMap<String, Long> = mutableMapOf() // Pair: {invoice_id: creation_timestamp}
|
var INVOICE_CREATION_TIMES: MutableMap<String, Long> = mutableMapOf() // Pair: {invoice_id: creation_timestamp}
|
||||||
@ -115,6 +126,7 @@ class VpcServerIntegration() : JavaPlugin(), CommandExecutor {
|
|||||||
COURSE_DYNAMIC_COMMAND = properties.getProperty("course_dynamic_command", DEFAULT_COURSE_DYNAMIC_COMMAND).replace("'", "")
|
COURSE_DYNAMIC_COMMAND = properties.getProperty("course_dynamic_command", DEFAULT_COURSE_DYNAMIC_COMMAND).replace("'", "")
|
||||||
COURSE_COMMISSION = properties.getProperty("course_commission", DEFAULT_COURSE_COMMISSION.toString()).replace("'", "").toFloat()
|
COURSE_COMMISSION = properties.getProperty("course_commission", DEFAULT_COURSE_COMMISSION.toString()).replace("'", "").toFloat()
|
||||||
INVOICE_TIMEOUT_SECONDS = properties.getProperty("invoice_timeout_seconds", DEFAULT_INVOICE_TIMEOUT_SECONDS.toString()).replace("'", "").toLong()
|
INVOICE_TIMEOUT_SECONDS = properties.getProperty("invoice_timeout_seconds", DEFAULT_INVOICE_TIMEOUT_SECONDS.toString()).replace("'", "").toLong()
|
||||||
|
PAY_BY_SIGN = properties.getProperty("pay_by_sign", DEFAULT_PAY_BY_SIGN.toString()).replace("'", "").toBoolean()
|
||||||
|
|
||||||
logger.info("Configuration loaded successfully - Username: $USERNAME, API URL: $USER_API_URL")
|
logger.info("Configuration loaded successfully - Username: $USERNAME, API URL: $USER_API_URL")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -184,6 +196,11 @@ course_commission=$DEFAULT_COURSE_COMMISSION
|
|||||||
# After how many seconds unpaid invoices will be deleted (default: 300 seconds = 5 minutes)
|
# After how many seconds unpaid invoices will be deleted (default: 300 seconds = 5 minutes)
|
||||||
invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
|
invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
|
||||||
# -------------------- END ------------------------
|
# -------------------- END ------------------------
|
||||||
|
|
||||||
|
# ------------------ Features ---------------------
|
||||||
|
# Should we enable pay by signs from containers (chest/etc.)?
|
||||||
|
pay_by_sign=${DEFAULT_PAY_BY_SIGN}
|
||||||
|
# -------------------- END ------------------------
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -201,6 +218,8 @@ invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
|
|||||||
|
|
||||||
// Register command executor
|
// Register command executor
|
||||||
getCommand("vpi")?.setExecutor(this)
|
getCommand("vpi")?.setExecutor(this)
|
||||||
|
// Register clicking on sign
|
||||||
|
server.pluginManager.registerEvents(SignHandler(), this)
|
||||||
|
|
||||||
// Background checks such a auth, invoice check, ...
|
// Background checks such a auth, invoice check, ...
|
||||||
startBackgroundChecks()
|
startBackgroundChecks()
|
||||||
@ -563,6 +582,8 @@ invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
|
|||||||
override fun run() {
|
override fun run() {
|
||||||
processAuthenticationInvoices()
|
processAuthenticationInvoices()
|
||||||
processPaymentInvoices()
|
processPaymentInvoices()
|
||||||
|
processSignInvoices()
|
||||||
|
|
||||||
cleanupExpiredInvoices()
|
cleanupExpiredInvoices()
|
||||||
}
|
}
|
||||||
}.runTaskTimerAsynchronously(this, 0L, 20L)
|
}.runTaskTimerAsynchronously(this, 0L, 20L)
|
||||||
@ -661,6 +682,69 @@ invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun processSignInvoices() {
|
||||||
|
synchronized(TO_PAY_SIGN_INVOICES) {
|
||||||
|
if (TO_PAY_SIGN_INVOICES.isNotEmpty()) {
|
||||||
|
val iterator = TO_PAY_SIGN_INVOICES.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val entry = iterator.next()
|
||||||
|
try {
|
||||||
|
val result = VpcApi.get_invoice(entry.value) as Map<*, *>?
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
val status = result["status"]
|
||||||
|
LOGGER.info("Payment invoice ${entry.value} status: $status")
|
||||||
|
|
||||||
|
if (status != null && status.toString() == "true") {
|
||||||
|
LOGGER.info("Processing successful payment")
|
||||||
|
VpcApi.delete_invoice(entry.value)
|
||||||
|
|
||||||
|
// Check if we have payment info for this entry
|
||||||
|
val paymentInfo = SIGN_PAYMENT_INFO[entry.value]
|
||||||
|
if (paymentInfo == null) {
|
||||||
|
LOGGER.error("No payment info found for key: ${entry.value}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val itemStack = ItemStack(paymentInfo.type, paymentInfo.amount)
|
||||||
|
val type = paymentInfo.type
|
||||||
|
// Check if container have needed items
|
||||||
|
val availableAmount = paymentInfo.container.inventory.all(type).values.sumOf { it.amount }
|
||||||
|
if (availableAmount < paymentInfo.amount) {
|
||||||
|
LOGGER.error("Not enough items after pay invoice, try to return VPC...")
|
||||||
|
val vpcUsername = DataManager.getPlayerVPCUsername(paymentInfo.player.name).toString()
|
||||||
|
val transferResult = VpcApi.transfer_coins(vpcUsername, paymentInfo.cost).toString()
|
||||||
|
if (transferResult != "OK") {
|
||||||
|
LOGGER.error("Can't return VPC, result: $transferResult")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If we have needed items
|
||||||
|
paymentInfo.player.inventory.addItem(itemStack)
|
||||||
|
paymentInfo.container.inventory.removeItem(itemStack)
|
||||||
|
|
||||||
|
val transferResult = VpcApi.transfer_coins(paymentInfo.dst_username, paymentInfo.cost).toString()
|
||||||
|
if (transferResult != "OK") {
|
||||||
|
LOGGER.error("Can't transfer VPC, result: $transferResult")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up tracking maps
|
||||||
|
INVOICE_CREATION_TIMES.remove(entry.value)
|
||||||
|
SIGN_PAYMENT_INFO.remove(entry.value)
|
||||||
|
iterator.remove()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warning("Received null result for payment invoice ${entry.value}")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LOGGER.error("Error processing payment invoice ${entry.value}: ${e.message}")
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleanup expired invoices based on timeout configuration
|
* Cleanup expired invoices based on timeout configuration
|
||||||
*/
|
*/
|
||||||
@ -729,5 +813,36 @@ invoice_timeout_seconds=$DEFAULT_INVOICE_TIMEOUT_SECONDS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cleanup sign invoices
|
||||||
|
synchronized(TO_PAY_SIGN_INVOICES) {
|
||||||
|
val paymentIterator = TO_PAY_SIGN_INVOICES.iterator()
|
||||||
|
while (paymentIterator.hasNext()) {
|
||||||
|
val entry = paymentIterator.next()
|
||||||
|
val invoiceId = entry.value
|
||||||
|
val creationTime = INVOICE_CREATION_TIMES[invoiceId] ?: continue
|
||||||
|
LOGGER.info("invoice ( $invoiceId ) left to live: ${timeoutMillis - (currentTime - creationTime)}")
|
||||||
|
|
||||||
|
if (currentTime - creationTime > timeoutMillis) {
|
||||||
|
LOGGER.info("Deleting expired payment invoice: $invoiceId")
|
||||||
|
try {
|
||||||
|
VpcApi.delete_invoice(invoiceId)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LOGGER.error("Error deleting expired payment invoice $invoiceId: ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up tracking maps
|
||||||
|
SIGN_PAYMENT_INFO.remove(invoiceId)
|
||||||
|
INVOICE_CREATION_TIMES.remove(invoiceId)
|
||||||
|
paymentIterator.remove()
|
||||||
|
|
||||||
|
// Notify player if online
|
||||||
|
val player = Bukkit.getPlayer(entry.key)
|
||||||
|
if (player != null && player.isOnline) {
|
||||||
|
Utils.send(player, "&cВаша оплата истекла. Нажмите ещё раз на табличку.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user