1.1 Миллиард хотфиксов, но теперь без ошибок и всё работает. У меня детокс, голова болит пздц
This commit is contained in:
parent
2b5a19c41b
commit
4d6cf540ef
9 changed files with 266 additions and 57 deletions
|
|
@ -14,8 +14,8 @@ plugins {
|
||||||
val javaVersion = 24
|
val javaVersion = 24
|
||||||
|
|
||||||
group = "dev.marrow"
|
group = "dev.marrow"
|
||||||
version = "1.0"
|
version = "1.1"
|
||||||
description = "paper plugin template"
|
description = "listener of labels and maps"
|
||||||
|
|
||||||
// paper-plugin.yml
|
// paper-plugin.yml
|
||||||
paper {
|
paper {
|
||||||
|
|
@ -25,10 +25,10 @@ paper {
|
||||||
// version is version value
|
// version is version value
|
||||||
|
|
||||||
foliaSupported = true
|
foliaSupported = true
|
||||||
author = "You"
|
author = "Lonewoss"
|
||||||
main = "$group.${project.name.lowercase()}.Core"
|
main = "$group.${project.name.lowercase()}.Core"
|
||||||
apiVersion = "1.21"
|
apiVersion = "1.21"
|
||||||
prefix = "example"
|
prefix = "ZSign"
|
||||||
|
|
||||||
load = BukkitPluginDescription.PluginLoadOrder.STARTUP
|
load = BukkitPluginDescription.PluginLoadOrder.STARTUP
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ publishing {
|
||||||
tasks {
|
tasks {
|
||||||
|
|
||||||
runServer {
|
runServer {
|
||||||
//dependsOn(build)
|
serverJar(file("run/prismatic-bundler-1.21.8-R0.1-SNAPSHOT-mojmap.jar"))
|
||||||
version("1.21.7")
|
version("1.21.7")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
rootProject.name = "plugin"
|
rootProject.name = "ZSign"
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package dev.marrow.plugin.commands
|
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType
|
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import net.kyori.adventure.text.Component
|
|
||||||
import com.github.shynixn.mccoroutine.bukkit.launch
|
|
||||||
import com.mojang.brigadier.Command
|
|
||||||
import dev.marrow.plugin.Core
|
|
||||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
|
||||||
import io.papermc.paper.command.brigadier.Commands
|
|
||||||
import io.papermc.paper.command.brigadier.Commands.argument
|
|
||||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
|
||||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
|
||||||
|
|
||||||
class Example private constructor() {
|
|
||||||
companion object {
|
|
||||||
operator fun invoke(command: String): LiteralCommandNode<CommandSourceStack> {
|
|
||||||
return Commands.literal(command).apply {
|
|
||||||
then(argument("player", ArgumentTypes.player()).apply {
|
|
||||||
then(argument("message", StringArgumentType.greedyString()).apply {
|
|
||||||
executes {
|
|
||||||
val sender = it.source.sender
|
|
||||||
val targetResolver = it.getArgument("player", PlayerSelectorArgumentResolver::class.java)
|
|
||||||
val target = targetResolver.resolve(it.source).first()
|
|
||||||
val message = it.getArgument("message", String::class.java)
|
|
||||||
sender.sendMessage("${target.name} will receive your message in 1 second")
|
|
||||||
|
|
||||||
Core.instance.launch {
|
|
||||||
delay(1000)
|
|
||||||
target.sendMessage(Component.text("${sender.name}: $message"))
|
|
||||||
}
|
|
||||||
Command.SINGLE_SUCCESS
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package dev.marrow.plugin
|
package dev.marrow.zsign
|
||||||
|
|
||||||
import com.github.shynixn.mccoroutine.bukkit.SuspendingJavaPlugin
|
import com.github.shynixn.mccoroutine.bukkit.SuspendingJavaPlugin
|
||||||
import dev.marrow.plugin.commands.Example
|
import dev.marrow.zsign.listeners.MapLaminationListener
|
||||||
import dev.marrow.plugin.utils.CommonUtils.gson
|
import dev.marrow.zsign.utils.CommonUtils.gson
|
||||||
import dev.marrow.plugin.utils.ComponentExtension.deserializeMiniMessage
|
import dev.marrow.zsign.utils.ComponentExtension.deserializeMiniMessage
|
||||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
|
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -12,7 +12,6 @@ import java.io.FileWriter
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
|
||||||
class Core : SuspendingJavaPlugin() {
|
class Core : SuspendingJavaPlugin() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var instance: Core
|
lateinit var instance: Core
|
||||||
lateinit var config: Configuration
|
lateinit var config: Configuration
|
||||||
|
|
@ -23,9 +22,11 @@ class Core : SuspendingJavaPlugin() {
|
||||||
instance = this
|
instance = this
|
||||||
console = logger
|
console = logger
|
||||||
|
|
||||||
this.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS, {
|
// Только наш cartography-слушатель
|
||||||
it.registrar().register(Example("example"), listOf("example_alias"))
|
server.pluginManager.registerEvents(MapLaminationListener(this), this)
|
||||||
})
|
|
||||||
|
this.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) {
|
||||||
|
}
|
||||||
|
|
||||||
server.consoleSender.sendMessage(Companion.config.enabledMessage.deserializeMiniMessage())
|
server.consoleSender.sendMessage(Companion.config.enabledMessage.deserializeMiniMessage())
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
package dev.marrow.zsign.listeners
|
||||||
|
|
||||||
|
import com.destroystokyo.paper.event.inventory.PrepareResultEvent
|
||||||
|
import dev.marrow.zsign.Core
|
||||||
|
import io.papermc.paper.event.player.CartographyItemEvent
|
||||||
|
import io.papermc.paper.threadedregions.scheduler.ScheduledTask
|
||||||
|
import net.kyori.adventure.text.Component
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.EventPriority
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.inventory.*
|
||||||
|
import org.bukkit.inventory.CartographyInventory
|
||||||
|
import org.bukkit.inventory.Inventory
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.meta.MapMeta
|
||||||
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
|
class MapLaminationListener(private val plugin: Core) : Listener {
|
||||||
|
companion object {
|
||||||
|
private const val TOP_SLOT = 1
|
||||||
|
private val RED_PANE = Material.RED_STAINED_GLASS_PANE
|
||||||
|
|
||||||
|
val laminatedKey: NamespacedKey by lazy { NamespacedKey(Core.instance, "laminated") }
|
||||||
|
|
||||||
|
private fun ItemStack?.isAir(): Boolean = this == null || type == Material.AIR
|
||||||
|
private fun ItemStack?.isRedPane(): Boolean = this != null && type == RED_PANE
|
||||||
|
private fun air(): ItemStack = ItemStack(Material.AIR)
|
||||||
|
|
||||||
|
private fun isLaminated(item: ItemStack?): Boolean {
|
||||||
|
if (item == null || item.type != Material.FILLED_MAP) return false
|
||||||
|
val mm = item.itemMeta as? MapMeta ?: return false
|
||||||
|
return mm.persistentDataContainer.has(laminatedKey, PersistentDataType.BYTE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun markLaminated(copy: ItemStack): ItemStack = copy.apply {
|
||||||
|
val mm = itemMeta as MapMeta
|
||||||
|
mm.persistentDataContainer.set(laminatedKey, PersistentDataType.BYTE, 1.toByte())
|
||||||
|
mm.lore(listOf(Component.text("Заламинирована")))
|
||||||
|
itemMeta = mm
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MapMeta.isAlreadyLaminated(): Boolean =
|
||||||
|
persistentDataContainer.has(laminatedKey, PersistentDataType.BYTE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleRecalcFor(player: Player, inv: Inventory) {
|
||||||
|
player.scheduler.runDelayed(
|
||||||
|
plugin,
|
||||||
|
{ _: ScheduledTask ->
|
||||||
|
try {
|
||||||
|
if (player.openInventory.topInventory == inv) {
|
||||||
|
player.updateInventory()
|
||||||
|
}
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
plugin.logger.warning("Failed to recalc inventory for ${player.name}: ${t.message}")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
1L
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Player.sync() = updateInventory()
|
||||||
|
|
||||||
|
private fun CartographyInventory.spaceInTop(): Int {
|
||||||
|
val target = getItem(TOP_SLOT)
|
||||||
|
return when {
|
||||||
|
target.isAir() -> RED_PANE.maxStackSize
|
||||||
|
target?.type == RED_PANE -> (RED_PANE.maxStackSize - target.amount).coerceAtLeast(0)
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CartographyInventory.addToTop(amount: Int) {
|
||||||
|
val target = getItem(TOP_SLOT)
|
||||||
|
if (target.isAir()) {
|
||||||
|
setItem(TOP_SLOT, ItemStack(RED_PANE, amount))
|
||||||
|
} else {
|
||||||
|
target!!.amount += amount
|
||||||
|
setItem(TOP_SLOT, target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
fun onPrepareResult(e: PrepareResultEvent) {
|
||||||
|
val inv = e.inventory as? CartographyInventory ?: return
|
||||||
|
val base = inv.getItem(0) ?: return
|
||||||
|
if (base.type != Material.FILLED_MAP) return
|
||||||
|
val baseMeta = base.itemMeta as? MapMeta ?: return
|
||||||
|
|
||||||
|
if (baseMeta.isAlreadyLaminated()) {
|
||||||
|
e.result = air()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val top = inv.getItem(TOP_SLOT)
|
||||||
|
val cursor = inv.viewers.firstOrNull()?.itemOnCursor
|
||||||
|
if (top.isRedPane() || (top.isAir() && cursor.isRedPane())) {
|
||||||
|
val out = markLaminated(base.clone())
|
||||||
|
out.amount = 1
|
||||||
|
e.result = out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
fun onCartographyInsertRedPane(e: InventoryClickEvent) {
|
||||||
|
val inv = e.inventory as? CartographyInventory ?: return
|
||||||
|
val p = e.whoClicked as? Player ?: return
|
||||||
|
val cursor = p.itemOnCursor
|
||||||
|
|
||||||
|
if (e.clickedInventory === inv && e.rawSlot == TOP_SLOT && cursor.type == RED_PANE) {
|
||||||
|
e.isCancelled = true
|
||||||
|
val placeAmount = if (e.click == ClickType.RIGHT) 1 else cursor.amount
|
||||||
|
val toPlace = placeAmount.coerceAtMost(inv.spaceInTop())
|
||||||
|
if (toPlace > 0) {
|
||||||
|
inv.addToTop(toPlace)
|
||||||
|
if (cursor.amount == toPlace) p.setItemOnCursor(air()) else {
|
||||||
|
cursor.amount -= toPlace
|
||||||
|
p.setItemOnCursor(cursor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.updateInventory()
|
||||||
|
scheduleRecalcFor(p, inv)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.clickedInventory === inv && e.rawSlot == TOP_SLOT && e.click == ClickType.NUMBER_KEY) {
|
||||||
|
val idx = e.hotbarButton
|
||||||
|
if (idx in 0..8) {
|
||||||
|
val hot = p.inventory.getItem(idx)
|
||||||
|
if (hot?.type == RED_PANE && hot.amount > 0) {
|
||||||
|
e.isCancelled = true
|
||||||
|
val toMove = hot.amount.coerceAtMost(inv.spaceInTop())
|
||||||
|
if (toMove > 0) {
|
||||||
|
inv.addToTop(toMove)
|
||||||
|
hot.amount -= toMove
|
||||||
|
p.inventory.setItem(idx, if (hot.amount > 0) hot else air())
|
||||||
|
p.updateInventory()
|
||||||
|
scheduleRecalcFor(p, inv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.clickedInventory !== inv && e.isShiftClick) {
|
||||||
|
val clicked = e.currentItem ?: return
|
||||||
|
if (clicked.type != RED_PANE) return
|
||||||
|
e.isCancelled = true
|
||||||
|
val toMove = clicked.amount.coerceAtMost(inv.spaceInTop())
|
||||||
|
if (toMove > 0) {
|
||||||
|
inv.addToTop(toMove)
|
||||||
|
clicked.amount -= toMove
|
||||||
|
e.clickedInventory?.setItem(e.slot, if (clicked.amount > 0) clicked else air())
|
||||||
|
p.updateInventory()
|
||||||
|
scheduleRecalcFor(p, inv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
fun onCartographyDrag(e: InventoryDragEvent) {
|
||||||
|
if (TOP_SLOT in e.rawSlots && e.oldCursor.type == RED_PANE) {
|
||||||
|
e.isCancelled = true
|
||||||
|
(e.whoClicked as? Player)?.sync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
fun onCartographyTake(e: CartographyItemEvent) {
|
||||||
|
val inv = e.inventory
|
||||||
|
val base = inv.getItem(0) ?: return
|
||||||
|
if (base.type != Material.FILLED_MAP) return
|
||||||
|
val baseMeta = base.itemMeta as? MapMeta ?: return
|
||||||
|
|
||||||
|
if (baseMeta.isAlreadyLaminated()) {
|
||||||
|
e.isCancelled = true
|
||||||
|
inv.result = air()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val res = inv.result ?: return
|
||||||
|
val rMeta = res.itemMeta as? MapMeta ?: return
|
||||||
|
if (!rMeta.isAlreadyLaminated()) return
|
||||||
|
|
||||||
|
val p = e.whoClicked as? Player ?: return
|
||||||
|
val add = inv.getItem(TOP_SLOT)
|
||||||
|
val paneInTop = add.isRedPane() && add!!.amount > 0
|
||||||
|
|
||||||
|
if (!paneInTop) {
|
||||||
|
when {
|
||||||
|
p.itemOnCursor.type == RED_PANE && p.itemOnCursor.amount > 0 -> {
|
||||||
|
val cur = p.itemOnCursor
|
||||||
|
cur.amount -= 1
|
||||||
|
p.setItemOnCursor(if (cur.amount > 0) cur else air())
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val idx = p.inventory.first(RED_PANE)
|
||||||
|
if (idx < 0) {
|
||||||
|
e.isCancelled = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val st = p.inventory.getItem(idx)
|
||||||
|
if (st != null && st.amount > 1) {
|
||||||
|
st.amount -= 1
|
||||||
|
p.inventory.setItem(idx, st)
|
||||||
|
} else {
|
||||||
|
p.inventory.setItem(idx, air())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base.amount <= 1) {
|
||||||
|
inv.setItem(0, air())
|
||||||
|
} else {
|
||||||
|
base.amount -= 1
|
||||||
|
inv.setItem(0, base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baseMeta.mapView?.isLocked = true
|
||||||
|
base.itemMeta = baseMeta
|
||||||
|
|
||||||
|
scheduleRecalcFor(p, inv)
|
||||||
|
p.updateInventory()
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
fun onPrepareCraft(e: PrepareItemCraftEvent) {
|
||||||
|
val inv = e.inventory
|
||||||
|
val matrix = inv.matrix
|
||||||
|
if (matrix.any { isLaminated(it) }) {
|
||||||
|
inv.result = air()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
fun onCraftClick(e: CraftItemEvent) {
|
||||||
|
val inv = e.inventory
|
||||||
|
val matrix = inv.matrix
|
||||||
|
if (matrix.any { isLaminated(it) }) {
|
||||||
|
e.isCancelled = true
|
||||||
|
inv.result = air()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.marrow.plugin.utils
|
package dev.marrow.zsign.utils
|
||||||
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
@file:Suppress("unused")
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package dev.marrow.plugin.utils
|
package dev.marrow.zsign.utils
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component
|
import net.kyori.adventure.text.Component
|
||||||
import net.kyori.adventure.text.format.TextDecoration
|
import net.kyori.adventure.text.format.TextDecoration
|
||||||
|
|
@ -1 +1 @@
|
||||||
enabled-message: "plugin enabled!"
|
enabled-message: "ZSign enabled!"
|
||||||
0
src/main/resources/plugin.yml
Normal file
0
src/main/resources/plugin.yml
Normal file
Loading…
Add table
Add a link
Reference in a new issue