1.1 Миллиард хотфиксов, но теперь без ошибок и всё работает. У меня детокс, голова болит пздц

This commit is contained in:
lonewo 2025-08-09 07:39:59 +05:00
parent 2b5a19c41b
commit 4d6cf540ef
9 changed files with 266 additions and 57 deletions

View file

@ -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")
}

View file

@ -1 +1 @@
rootProject.name = "plugin"
rootProject.name = "ZSign"

View file

@ -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()
}
}
}

View file

@ -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())
}

View file

@ -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()
}
}
}

View file

@ -1,4 +1,4 @@
package dev.marrow.plugin.utils
package dev.marrow.zsign.utils
import com.google.gson.Gson
import com.google.gson.GsonBuilder

View file

@ -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

View file

@ -1 +1 @@
enabled-message: "plugin enabled!"
enabled-message: "ZSign enabled!"

View file