diff --git a/src/main/kotlin/dev/marrow/zsign/Core.kt b/src/main/kotlin/dev/marrow/zsign/Core.kt index 77235a8..1e19e1e 100755 --- a/src/main/kotlin/dev/marrow/zsign/Core.kt +++ b/src/main/kotlin/dev/marrow/zsign/Core.kt @@ -1,6 +1,7 @@ package dev.marrow.zsign import com.github.shynixn.mccoroutine.bukkit.SuspendingJavaPlugin +import dev.marrow.zsign.listeners.AnvilUseListener import dev.marrow.zsign.listeners.MapLaminationListener import dev.marrow.zsign.utils.CommonUtils.gson import dev.marrow.zsign.utils.ComponentExtension.deserializeMiniMessage @@ -24,6 +25,7 @@ class Core : SuspendingJavaPlugin() { // Только наш cartography-слушатель server.pluginManager.registerEvents(MapLaminationListener(this), this) + server.pluginManager.registerEvents(AnvilUseListener(this), this) this.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) { } diff --git a/src/main/kotlin/dev/marrow/zsign/listeners/AnvilUseListener.kt b/src/main/kotlin/dev/marrow/zsign/listeners/AnvilUseListener.kt new file mode 100644 index 0000000..39ed2b4 --- /dev/null +++ b/src/main/kotlin/dev/marrow/zsign/listeners/AnvilUseListener.kt @@ -0,0 +1,202 @@ +package dev.marrow.zsign.listeners + +import dev.marrow.zsign.Core +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.TextColor +import net.kyori.adventure.text.format.TextDecoration +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer +import org.bukkit.Material +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.ClickType +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.InventoryType +import org.bukkit.event.inventory.PrepareAnvilEvent +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.Repairable + +class AnvilUseListener(private val plugin: Core) : Listener { + + private val config get() = plugin.config + private val banSymbols get() = config.getStringList("ban-symbols") + private val streamerWords get() = config.getStringList("streamer-words") + + companion object { + private const val SECOND_SLOT = 1 + private val colorMap = mapOf( + Material.RED_DYE to TextColor.color(0xE6060C), + Material.BROWN_DYE to TextColor.color(0xAA5500), + Material.ORANGE_DYE to TextColor.color(0xFFAA00), + Material.YELLOW_DYE to TextColor.color(0xFFEE4C), + Material.LIME_DYE to TextColor.color(0x55FF55), + Material.GREEN_DYE to TextColor.color(0x00AA00), + Material.LIGHT_BLUE_DYE to TextColor.color(0x55FFFF), + Material.CYAN_DYE to TextColor.color(0x00AAAA), + Material.BLUE_DYE to TextColor.color(0x4842EA), + Material.PURPLE_DYE to TextColor.color(0xAA00AA), + Material.MAGENTA_DYE to TextColor.color(0xDC89BF), + Material.PINK_DYE to TextColor.color(0xFFB6C1), + Material.WHITE_DYE to TextColor.color(0xFFFFFF), + Material.LIGHT_GRAY_DYE to TextColor.color(0xAAAAAA), + Material.GRAY_DYE to TextColor.color(0x555555), + Material.BLACK_DYE to TextColor.color(0x000000) + ) + private val plain = PlainTextComponentSerializer.plainText() + private fun ItemStack?.isAir(): Boolean = this == null || type == Material.AIR + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + fun onPrepareAnvil(e: PrepareAnvilEvent) { + val inv = e.inventory + val firstItem = inv.firstItem ?: return + val secondItem = inv.secondItem + val renameText = inv.renameText?.takeIf { it.isNotBlank() } + + if (secondItem != null && (secondItem.type == Material.NAME_TAG || secondItem.type in colorMap.keys) && secondItem.amount > 1) { + e.result = null + return + } + + var newName: String? = null + if (renameText != null) { + var censored = renameText + streamerWords.forEach { word -> + censored = censored?.replace(word, "*".repeat(word.length), ignoreCase = true) + } + banSymbols.forEach { symbol -> + if (censored?.contains(symbol) ?: false) { + e.result = null + return + } + } + newName = censored + } + + val isCustom = secondItem != null && (secondItem.type == Material.NAME_TAG || secondItem.type in colorMap.keys) + var result: ItemStack? = e.result + if (result == null && !isCustom && newName == null) return + if (result == null) result = firstItem.clone() + + val meta = result.itemMeta ?: run { + e.result = null + return + } + + if (newName != null) { + meta.displayName(Component.text(newName)) + } + + if (secondItem != null) { + val lore = meta.lore()?.toMutableList() ?: mutableListOf() + val hashtagIndex = lore.indexOfFirst { plain.serialize(it).startsWith("#") } + val hasHashtag = hashtagIndex != -1 + + if (secondItem.type == Material.NAME_TAG) { + if (hasHashtag) { + e.result = null + return + } + val playerName = e.viewers.firstOrNull()?.name ?: "player" + lore.add(Component.empty()) + lore.add(Component.text("#$playerName", NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, false)) + meta.lore(lore) + (meta as? Repairable)?.repairCost = 1 + inv.repairCost = 1 + } else if (secondItem.type in colorMap.keys) { + if (!hasHashtag) { + e.result = null + return + } + val currentHashtagText = plain.serialize(lore[hashtagIndex]) + val playerName = currentHashtagText.removePrefix("#") + val color = colorMap.getValue(secondItem.type) + lore[hashtagIndex] = Component.text("#$playerName", color).decoration(TextDecoration.ITALIC, false) + meta.lore(lore) + (meta as? Repairable)?.repairCost = 1 + inv.repairCost = 1 + } + } + + result.itemMeta = meta + + if (result.isSimilar(firstItem)) { + e.result = null + return + } + + e.result = result + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + fun onAnvilInsert(e: InventoryClickEvent) { + val inv = e.inventory + if (inv.type != InventoryType.ANVIL) return + val p = e.whoClicked as? Player ?: return + + val firstItem = inv.first() + if (firstItem.isAir()) return + + val cursor = p.itemOnCursor + + if (e.clickedInventory === inv && e.rawSlot == SECOND_SLOT && (cursor.type == Material.NAME_TAG || cursor.type in colorMap.keys)) { + e.isCancelled = true + val placeAmount = if (e.click == ClickType.RIGHT) 1 else cursor.amount + val toPlace = placeAmount.coerceAtMost(1) + if (toPlace > 0) { + val current = inv.getItem(SECOND_SLOT) + val newItem = cursor.clone() + newItem.amount = 1 + inv.setItem(SECOND_SLOT, newItem) + cursor.amount -= 1 + p.setItemOnCursor(if (cursor.amount > 0) cursor else ItemStack(Material.AIR)) + if (current != null && !current.isAir()) { + p.inventory.addItem(current.clone().apply { amount = 1 }) + } + p.scheduler.runDelayed(plugin, { _ -> p.updateInventory() }, null, 1L) + } + return + } + + if (e.clickedInventory === inv && e.rawSlot == SECOND_SLOT && e.click == ClickType.NUMBER_KEY) { + val idx = e.hotbarButton + if (idx in 0..8) { + val hot = p.inventory.getItem(idx) + if ((hot?.type == Material.NAME_TAG || hot?.type in colorMap.keys) && (hot?.amount ?: 0) > 0) { + e.isCancelled = true + val current = inv.getItem(SECOND_SLOT) + val newItem = hot!!.clone() + newItem.amount = 1 + inv.setItem(SECOND_SLOT, newItem) + hot.amount -= 1 + p.inventory.setItem(idx, if (hot.amount > 0) hot else ItemStack(Material.AIR)) + if (current != null && !current.isAir()) { + p.inventory.addItem(current.clone().apply { amount = 1 }) + } + p.scheduler.runDelayed(plugin, { _ -> p.updateInventory() }, null, 1L) + } + } + return + } + + if (e.clickedInventory !== inv && e.isShiftClick) { + val clicked = e.currentItem ?: return + if (clicked.type == Material.NAME_TAG || clicked.type in colorMap.keys) { + e.isCancelled = true + val current = inv.getItem(SECOND_SLOT) + val newItem = clicked.clone() + newItem.amount = 1 + inv.setItem(SECOND_SLOT, newItem) + clicked.amount -= 1 + e.clickedInventory?.setItem(e.slot, if (clicked.amount > 0) clicked else ItemStack(Material.AIR)) + if (current != null && !current.isAir()) { + p.inventory.addItem(current.clone().apply { amount = 1 }) + } + p.scheduler.runDelayed(plugin, { _ -> p.updateInventory() }, null, 1L) + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index d8fdf17..05d6759 100755 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1 +1,486 @@ -enabled-message: "ZSign enabled!" \ No newline at end of file +enabled-message: "ZSign enabled!" +ban-symbols: + - "卐" + - "卍" + - "☭" + - "ᛋ" +streamer-words: + - "пидор" + - "чурк" + - "чурок" + - "🅿️🆔🅾️®️" + - "пидо р" + - "п идор" + - "пид ор" + - "хутору" + - "хутор" + - "слава украiнe" + - "слава украинe" + - "слава россии" + - "слава украiне" + - "слава украине" + - "гoйдy" + - "гoйdу" + - "гойdу" + - "гoйду" + - "гойду" + - "гoйdа" + - "гойda" + - "гoйda" + - "гoйда" + - "гойдa" + - "гoйдa" + - "ZOV" + - "zov" + - "н3гр" + - "ПИДR" + - "бахмут" + - "ytuhs" + - "куколды" + - "куколд" + - "nigr" + - "PartyKirby" + - "n3gr" + - "пи дор" + - "черножопый" + - "нигры" + - "nigа" + - "РУСНЯ" + - "чурки" + - "хохлом" + - "kiggers" + - "глиномес" + - "нигр" + - "негер" + - "ЗИГ ХАЙЛЬ" + - "ХАЧА" + - "N1GG*" + - "даун" + - "дaун" + - "даyн" + - "dayн" + - "dаун" + - "дayн" + - "daун" + - "dаyн" + - "pиdor" + - "неggr" + - "додик" + - "P.!.D/0.R.bl" + - "NELPы" + - "HЕLРы" + - "HELРы" + - "HELPы" + - "D101R1А1" + - "И1Г1Е1Р" + - "!GGЕ" + - "D0RАС" + - "Pl!!D0RАСЫ" + - "NИ!!!GGЕRbl" + - "!ГEPb" + - "!ГЕРb" + - "!GЕРb" + - "H!!!GЕРbl" + - "П!!!ДОRАСЫ" + - "ДОRАС" + - "П!!ДОРАСЫ" + - "H!!ГЕРbl" + - "дорас" + - "Н!!Г" + - "H!!Г" + - "П!!Д" + - "ДAУH" + - "ДАУH" + - "П!ДOР" + - "H!ГЕР" + - "H!ГЕPЫ" + - "H!ГEРЫ" + - "H!ГЕРЫ" + - "П!ДОР" + - "П!ДОРАSЫ" + - "П!ДОРАСЫ" + - "Н!ГЕРЫ" + - "冂仈亼卩" + - "冂认亼口尸" + - "додiк" + - "додан" + - "додик" + - "хохлина" + - "хохлов" + - "хохла" + - "хохлы" + - "𝔤𝔞𝔫𝔡𝔬𝔫" + - "🅟︎🅘︎🅓︎🅞︎🅡︎" + - "🅟︎🅘︎🅓︎🅞︎🅡︎🅐︎🅢︎🅘︎🅝︎🅐︎" + - "Ⓟ︎Ⓘ︎Ⓓ︎Ⓞ︎Ⓡ︎Ⓐ︎Ⓢ︎Ⓘ︎Ⓝ︎Ⓐ︎" + - "N1GERS" + - "FA1OTS" + - "хохол" + - "incel" + - "инцел" + - "шлюха" + - "p..i..d..o..r..a..s" + - "ПЕДРИЛА" + - "nig" + - "хуесос" + - "П,И,Д,О,Р" + - "н.е.г.р.и" + - "негрыпидорас" + - "негр" + - "P.1.D.OO.RA.S" + - "N.E.G.R1" + - "N.E.G.R1 P.1.D.OO.RA.S" + - "пiдdop" + - "пiiдdopp" + - "даyn" + - "чypка" + - "4урка" + - "чурке" + - "чурка" + - "✖️⭕️✖️⭕️Л" + - "YappiDoor" + - "книгр" + - "дауны" + - "П.И.Д.О.R.A.S" + - "П3.14DOOR" + - "П.И.Д.О.Р.А.С.И.Н.А.А,А.А.А" + - "Н3гры" + - "падарас" + - "П.u.д.о.р.а.c." + - "П.u.д.о.р.а.c" + - "П.u.д.о.p.a" + - "П.u.д.o.р." + - "П.u.д.o.р" + - "П.u.д.o.p." + - "П.u.д.o.p" + - "П.u.д.о.p." + - "П.u.д.о.p" + - "П.u.д.о.р.а.s." + - "П.u.д.о.р.а.s" + - "П.u.д.о.р.a" + - "П.u.д.о.р.a." + - "П.u.д.о.р.а.с." + - "П.u.д.о.р.а" + - "П.u.д.о.р" + - "П.u.д.о.р.а.с" + - "каклошвайн" + - "хохiл" + - "хохіл" + - "пидр" + - "пидарасик" + - "пидорасик" + - "педерасик" + - "педрильник" + - "педрик" + - "педр" + - "педеряга" + - "полупокер" + - "гомик" + - "гомосек" + - "пидераст" + - "педераст" + - "f@gg0t" + - "f@ggot" + - "daun" + - "д@ун" + - "даун" + - "pedovka" + - "х@4" + - ") (@4" + - ")(ач" + - ")(о)(ол" + - "pidarac" + - "pidorok" + - "pidarok" + - "п1д@рок" + - "п1дарок" + - "пидорок" + - "пидарок" + - "хохлам" + - "хохолка" + - "хохлушка" + - "хахлушка" + - "хахлина" + - "пидриловна" + - "пидорёха" + - "пидарёха" + - "пидрилка" + - "пидарасина" + - "пидарас" + - "пидораска" + - "пидорасина" + - "хахолка" + - "xoxoл" + - "xoxol" + - "х@хол" + - "х@х0л" + - "хахол" + - "niгга" + - "ниgga" + - "нegr" + - "nегр" + - "пидop" + - "пидoр" + - "хoхoл" + - "х0х0л" + - "pedickson" + - "p1d4r8s8" + - "p3dik" + - "p3d1k" + - "pedick" + - "pedik" + - "жид9ра" + - "ж1д9ра" + - "ж1д" + - "н1г@" + - "н1чер" + - "н1гер" + - "н1га" + - "ниг@" + - "пид@р@с" + - "н?е?г?р" + - "н!е!г!р" + - "п!и!д!о!р!а!с" + - "п?и?д?о?р?а?с" + - "ж(и(д" + - "ж)и)д" + - "н(и(г(а" + - "н)и)г)а" + - "н(е(г(р" + - "н)е)г)р" + - "п)и)д)р)а)с" + - "п(и(д(а(р(а(с" + - "ж/и/д" + - "ж\\и\\д" + - "н/и/г/а" + - "н/е/г/р" + - "н\\и\\г\\г\\а" + - "н\\е\\г\\р" + - "п\\и\\д\\о\\р\\а\\с" + - "p/i/d/a/r/a/s" + - "n/i/g/g/a" + - "нигерас" + - "п.и.д.а.р.а.с" + - "н.и.г.е.р" + - "n.i.b.b.e.r" + - "n.1.g.e.r" + - "n.i.g.e.r" + - "n.i.g.a" + - "p.i.d.0r" + - "p.i.d.o.r" + - "p.i.d.a.r.a.s" + - "П. ИД.О.Р" + - "д4унbl" + - "п.и.д.о.р." + - "ж.и.д" + - "н.е.г.р" + - "п.и.д.о.р.ы." + - "P🆔🅾️R" + - "П🆔🅾️Р" + - "Р🆔🅾️Р" + - "🅿️🆔🅾️Р" + - "🅿️🆔о🅿️" + - "🅿️🆔0🅿️" + - "П🆔🅾️🅿️" + - "🅿️🆔🅾️🅿️" + - "жидомасон" + - "жиды" + - "линчевать" + - "жидовка" + - "жидовик" + - "еблан черножопый" + - "FUCK ŊIGGERS" + - "пiдор" + - "пидер" + - "пидур" + - "негроид" + - "нtгр" + - "негыр" + - "негор" + - "нe гр" + - "нeгр" + - "негритян" + - "пидараска" + - "пидогр" + - "нигорас" + - "пидрила" + - "п1др1ла" + - "п3др1ла" + - "п3д1к" + - "пед1к" + - "п3дик" + - "п1д4рас" + - "п1дор" + - "pid0r" + - "pid3r" + - "p1d3r" + - "p1d0r" + - "p1dor" + - "n1g3r" + - "n1g4" + - "n1ga" + - "nig4" + - "н...е...г...р" + - "пид🅾️🅿️" + - "🅿️🆔D🅾️🅿️" + - "🅿️🆔🅾️🅿️" + - "P🆔🅾️🅿️🅰️C" + - "🅿️ℹ️D🅾️🅿️🅰️S" + - "симп" + - "πдорасы" + - "НЕLРЫ" + - "πдорасы" + - "🅿️🆔0️⃣🅿️" + - "жидина" + - "H3гp" + - "⛩🆔🅾️🅿️" + - "peedooor" + - "нэгры" + - "нэгр" + - "трап" + - "жидяра" + - "𝐻𝑒г𝑝ы пид𝑜𝑝ы" + - "пидهpaح" + - "ПИДДОРЫ" + - "НЕГГРЫ" + - "пидар" + - "нидор*" + - "пегр*" + - "педар*" + - "pedor" + - "pee d" + - "Heг" + - "педор" + - "Hег" + - "Hеr" + - "nиd" + - "нir" + - "пid" + - "HNГ" + - "не гр" + - "ни га" + - "p1d" + - "Niг" + - "п1g" + - "nuг" + - "nиг" + - "nur" + - "nиr" + - "пеg" + - "neg" + - "пeg" + - "ттug" + - "ттиg" + - "ттuд" + - "нигe" + - "пидe" + - "n1д" + - "н1г" + - "п1d" + - "пидa" + - "пида" + - "piд" + - "ни ге" + - "ни гг" + - "TTug" + - "TTuд" + - "TTиg" + - "TTид" + - "Hiг" + - "Hug" + - "Hиg" + - "нигa" + - "niq" + - "пидp" + - "гамосек" + - "пиде" + - "П|/|Д" + - "ПI/IД" + - "Пl/lД" + - "Н|/|Г" + - "Нl/lГ" + - "нug" + - "нiг" + - "пig" + - "niд" + - "fag" + - "Heg" + - "Hig" + - "Hl/lГ" + - "пмдор" + - "пмдар" + - "пирадас" + - "Herp" + - "Herр" + - "Huг" + - "нeг" + - "негp" + - "ниg" + - "нuг" + - "НI/IГ" + - "Hиг" + - "питор" + - "питар" + - "ниr" + - "ниччер" + - "ничер" + - "ніг" + - "нig" + - "н и г" + - "Hиr" + - "нur" + - "nіg" + - "n i g" + - "NlG" + - "cmonBruh" + - "paydo" + - "peид" + - "негр" + - "ниге" + - "nige" + - "niga" + - "nigg" + - "нигг" + - "пи д" + - "пигор" + - "рid" + - "ттид" + - "p i d" + - "п и д" + - "фаг" + - "пиg" + - "пud" + - "пиd" + - "хачи" + - "під" + - "пuд" + - "п1д" + - "пeд" + - "пиндос" + - "пендос" + - "пug" + - "педи" + - "дaун" + - "p`id" + - "πuд" + - "πиg" + - "πug" + - "πид" + - "ПNД" + - "PlD" + - "nиg" + - "nид" + - "GBLFH" + - "GBLJH" + - "пидo" + - "пид0" + - "пидо" + - "pid" + - "пiд" + - "nud" + - "nuд" + - "nug" + - "пидор" + - "🅿️ℹ️D🅰️®️🅰️Sℹ️N🅰️" + - "нerp" + - "н е г р" \ No newline at end of file