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
|
||||
|
||||
group = "dev.marrow"
|
||||
version = "1.0"
|
||||
description = "paper plugin template"
|
||||
version = "1.1"
|
||||
description = "listener of labels and maps"
|
||||
|
||||
// paper-plugin.yml
|
||||
paper {
|
||||
|
|
@ -25,10 +25,10 @@ paper {
|
|||
// version is version value
|
||||
|
||||
foliaSupported = true
|
||||
author = "You"
|
||||
author = "Lonewoss"
|
||||
main = "$group.${project.name.lowercase()}.Core"
|
||||
apiVersion = "1.21"
|
||||
prefix = "example"
|
||||
prefix = "ZSign"
|
||||
|
||||
load = BukkitPluginDescription.PluginLoadOrder.STARTUP
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ publishing {
|
|||
tasks {
|
||||
|
||||
runServer {
|
||||
//dependsOn(build)
|
||||
serverJar(file("run/prismatic-bundler-1.21.8-R0.1-SNAPSHOT-mojmap.jar"))
|
||||
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 dev.marrow.plugin.commands.Example
|
||||
import dev.marrow.plugin.utils.CommonUtils.gson
|
||||
import dev.marrow.plugin.utils.ComponentExtension.deserializeMiniMessage
|
||||
import dev.marrow.zsign.listeners.MapLaminationListener
|
||||
import dev.marrow.zsign.utils.CommonUtils.gson
|
||||
import dev.marrow.zsign.utils.ComponentExtension.deserializeMiniMessage
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
|
|
@ -12,7 +12,6 @@ import java.io.FileWriter
|
|||
import java.util.logging.Logger
|
||||
|
||||
class Core : SuspendingJavaPlugin() {
|
||||
|
||||
companion object {
|
||||
lateinit var instance: Core
|
||||
lateinit var config: Configuration
|
||||
|
|
@ -23,9 +22,11 @@ class Core : SuspendingJavaPlugin() {
|
|||
instance = this
|
||||
console = logger
|
||||
|
||||
this.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS, {
|
||||
it.registrar().register(Example("example"), listOf("example_alias"))
|
||||
})
|
||||
// Только наш cartography-слушатель
|
||||
server.pluginManager.registerEvents(MapLaminationListener(this), this)
|
||||
|
||||
this.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) {
|
||||
}
|
||||
|
||||
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.GsonBuilder
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package dev.marrow.plugin.utils
|
||||
package dev.marrow.zsign.utils
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
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