Skip to content

Commit

Permalink
Add spy feature
Browse files Browse the repository at this point in the history
  • Loading branch information
wtlgo committed Feb 28, 2023
1 parent 29e41a0 commit 43b9f87
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 32 deletions.
2 changes: 2 additions & 0 deletions src/main/java/dev/mikchan/mcnp/chat/ChatPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import dev.mikchan.mcnp.chat.commands.ICommandManager
import dev.mikchan.mcnp.chat.config.IConfig
import dev.mikchan.mcnp.chat.events.IEventManager
import dev.mikchan.mcnp.chat.formatting.IFormatter
import dev.mikchan.mcnp.chat.keys.IKeys
import dev.mikchan.mcnp.chat.users.IUserManager
import org.bstats.bukkit.Metrics
import org.bukkit.plugin.java.JavaPlugin
Expand All @@ -22,6 +23,7 @@ class ChatPlugin : JavaPlugin() {
val formatter: IFormatter = Creators.formatter.create(this)
val userManager: IUserManager = Creators.userManager.create(this)
val eventManager: IEventManager = Creators.eventManager.create(this)
val keys: IKeys = Creators.keys.create(this)

override fun onEnable() {
commandManager.enableAll()
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/dev/mikchan/mcnp/chat/Creators.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import dev.mikchan.mcnp.chat.events.DefaultEventManagerCreator
import dev.mikchan.mcnp.chat.events.IEventManagerCreator
import dev.mikchan.mcnp.chat.formatting.DefaultFormatterCreator
import dev.mikchan.mcnp.chat.formatting.IFormatterCreator
import dev.mikchan.mcnp.chat.keys.DefaultKeysCreator
import dev.mikchan.mcnp.chat.keys.IKeysCreator
import dev.mikchan.mcnp.chat.users.DefaultUserManagerCreator
import dev.mikchan.mcnp.chat.users.IUserManagerCreator

Expand Down Expand Up @@ -43,4 +45,9 @@ object Creators {
* The event manager builder.
*/
var eventManager: IEventManagerCreator = DefaultEventManagerCreator()

/**
* The keys' builder.
*/
var keys: IKeysCreator = DefaultKeysCreator()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.mikchan.mcnp.chat.commands

import dev.mikchan.mcnp.chat.ChatPlugin
import dev.mikchan.mcnp.chat.commands.command.*
import dev.mikchan.mcnp.chat.commands.command.ICommand
import dev.mikchan.mcnp.chat.commands.command.MsgCommand
import dev.mikchan.mcnp.chat.commands.command.ReloadCommand
Expand All @@ -12,7 +13,8 @@ internal class DefaultCommandManager(private val plugin: ChatPlugin) : ICommandM
private val executors: Map<String, ICommand> = mapOf(
"mcn_chat" to ReloadCommand(plugin),
"msg" to MsgCommand(plugin, messageHistory),
"reply" to ReplyCommand(plugin, messageHistory)
"reply" to ReplyCommand(plugin, messageHistory),
"spy" to SpyCommand(plugin),
)

override fun enableAll() {
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/dev/mikchan/mcnp/chat/commands/command/SpyCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package dev.mikchan.mcnp.chat.commands.command

import dev.mikchan.mcnp.chat.ChatPlugin
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player

class SpyCommand(private val plugin: ChatPlugin) : ICommand {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
val player = sender as? Player

if (player == null) {
sender.sendMessage("${ChatColor.DARK_RED}This action is only accessible to players.")
return false
}

if (!player.hasPermission("mcn.chat.spy")) {
sender.sendMessage("${ChatColor.DARK_RED}You have no permission to do that.")
return false
}

val prev = try {
player.persistentDataContainer.getOrDefault(plugin.keys.spy.key, plugin.keys.spy.type, 0.toByte())
} catch (ignore: Exception) {
0.toByte()
}

val next = ((prev + 1) % 2).toByte()
player.persistentDataContainer.set(plugin.keys.spy.key, plugin.keys.spy.type, next)

when (next) {
1.toByte() -> {
player.sendMessage("${ChatColor.DARK_GREEN}Spy is switched on!")
}

0.toByte() -> {
player.sendMessage("${ChatColor.DARK_GREEN}Spy is switched off!")
}

else -> {
player.sendMessage("${ChatColor.DARK_RED}Error.")
}
}

return true
}

override fun onTabComplete(
sender: CommandSender, command: Command, label: String, args: Array<out String>
): MutableList<String> {
return mutableListOf()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package dev.mikchan.mcnp.chat.events

import dev.mikchan.mcnp.chat.ChatPlugin
import dev.mikchan.mcnp.chat.events.listener.ChatListener
import dev.mikchan.mcnp.chat.events.listener.MCNCListener
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener

internal class DefaultEventManager(private val plugin: ChatPlugin) : IEventManager {
private val listeners: List<Listener> = listOf(
ChatListener(plugin),
MCNCListener(plugin),
)

override fun unregister() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ import org.bukkit.event.player.AsyncPlayerChatPreviewEvent
import kotlin.streams.asSequence

internal class ChatListener(private val plugin: ChatPlugin) : Listener {
private fun checkPermissions(player: Player, isGlobal: Boolean): Boolean {
if (!player.hasPermission("mcn.chat.global") && isGlobal) return false
if (!player.hasPermission("mcn.chat.local") && !isGlobal) return false
return true
}

private fun handleChatEvent(event: AsyncPlayerChatEvent, isPreview: Boolean): Boolean {
var msg = event.message.trim()
val isGlobal = !plugin.config.enableLocal || msg.startsWith(plugin.config.globalPrefix)

if ((!event.player.hasPermission("mcn.chat.global") && isGlobal) || (!event.player.hasPermission("mcn.chat.local") && !isGlobal)) {
if (!isPreview && !checkPermissions(event.player, isGlobal)) {
plugin.server.scheduler.scheduleSyncDelayedTask(plugin) {
event.player.sendMessage(ChatColor.RED.toString() + "You have no permission to do that!")
event.player.sendMessage("${ChatColor.RED}You have no permission to do that!")
}

return false
Expand All @@ -36,15 +42,15 @@ internal class ChatListener(private val plugin: ChatPlugin) : Listener {
} else {
val r = plugin.config.localRadius

recipients.addAll(plugin.server.onlinePlayers.stream()
.filter { player -> player.world == event.player.world && player.location.distance(event.player.location) < r }
.asSequence())
recipients.addAll(plugin.server.onlinePlayers.stream().filter { player ->
player.world == event.player.world && player.location.distance(event.player.location) < r
}.asSequence())
}

val mcncEvent = MCNChatEvent(
event.player, recipients, isGlobal, msg, if (isGlobal) plugin.formatter.formatGlobal(
event.player, msg
) else plugin.formatter.formatLocal(event.player, msg), isPreview, event.isAsynchronous
event.player, "%2\$s"
) else plugin.formatter.formatLocal(event.player, "%2\$s"), isPreview, event.isAsynchronous
)

plugin.server.pluginManager.callEvent(mcncEvent)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.mikchan.mcnp.chat.events.listener

import dev.mikchan.mcnp.chat.ChatPlugin
import dev.mikchan.mcnp.chat.events.event.MCNChatEvent
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener


internal class MCNCListener(private val plugin: ChatPlugin) : Listener {
private fun checkSpy(player: Player): Boolean {
return try {
player.persistentDataContainer.getOrDefault(
plugin.keys.spy.key, plugin.keys.spy.type, 0.toByte()
) != 0.toByte() && player.hasPermission("mcn.chat.spy")
} catch (ignore: Exception) {
false
}
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
fun onMCNCEvent(event: MCNChatEvent) {
if (event.isCancelled) return
if (event.isPreview) return
if (event.isGlobal) return

plugin.server.scheduler.scheduleSyncDelayedTask(plugin) {
val spies = plugin.server.onlinePlayers.filter { player -> !event.recipients.contains(player) }
.filter { player -> checkSpy(player) }.toSet()

if (spies.isEmpty()) return@scheduleSyncDelayedTask

val msg = plugin.formatter.formatSpy(event.sender, event.message)
for (spy in spies) {
spy.sendMessage(event.sender.uniqueId, msg)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import org.bukkit.ChatColor

internal abstract class CommonFormatter(private val plugin: ChatPlugin) : IFormatter {
protected fun prepareTemplate(
template: String, from: () -> String?, to: () -> String?, player: () -> String?, message: () -> String?
template: String,
from: () -> String?,
to: () -> String?,
player: () -> String?,
globalPlayer: () -> String?,
localPlayer: () -> String?,
spyPlayer: () -> String?,
message: () -> String?
): String {
var res = ChatColor.translateAlternateColorCodes('&', template)

Expand All @@ -24,6 +31,21 @@ internal abstract class CommonFormatter(private val plugin: ChatPlugin) : IForma
res = res.replace(":player:", defPlayer)
}

if (res.contains(":global_player:")) {
val defPlayer = globalPlayer() ?: ""
res = res.replace(":global_player:", defPlayer)
}

if (res.contains(":local_player:")) {
val defPlayer = localPlayer() ?: ""
res = res.replace(":local_player:", defPlayer)
}

if (res.contains(":spy_player:")) {
val defPlayer = spyPlayer() ?: ""
res = res.replace(":spy_player:", defPlayer)
}

if (res.contains(":message:")) {
val msg = message()

Expand Down
73 changes: 56 additions & 17 deletions src/main/java/dev/mikchan/mcnp/chat/formatting/DefaultFormatter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import org.bukkit.entity.Player
internal class DefaultFormatter(private val plugin: ChatPlugin) : CommonFormatter(plugin) {
override fun formatPrivate(from: Player, to: Player, message: String): String {
return prepareTemplate(plugin.config.privateTemplate,
{ from.displayName },
{ "%1\$s" },
{ to.displayName },
{ from.displayName },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{
if (from.hasPermission("mcn.chat.colors")) ChatColor.translateAlternateColorCodes(
'&', message
Expand All @@ -18,26 +21,62 @@ internal class DefaultFormatter(private val plugin: ChatPlugin) : CommonFormatte
}

override fun formatConsole(to: Player, message: String): String {
return prepareTemplate(plugin.config.consoleTemplate, { null }, { to.displayName }, { to.displayName }, {
ChatColor.translateAlternateColorCodes(
'&', message
)
})
return prepareTemplate(plugin.config.consoleTemplate,
{ to.displayName },
{ to.displayName },
{ to.displayName },
{ to.displayName },
{ to.displayName },
{ to.displayName },
{
ChatColor.translateAlternateColorCodes(
'&', message
)
})
}

override fun formatGlobal(from: Player, message: String): String {
return prepareTemplate(plugin.config.globalTemplate, { from.displayName }, { null }, { from.displayName }) {
if (from.hasPermission("mcn.chat.colors")) ChatColor.translateAlternateColorCodes(
'&', message
) else ChatColor.stripColor(message)
}
return prepareTemplate(plugin.config.globalTemplate,
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{
if (from.hasPermission("mcn.chat.colors")) ChatColor.translateAlternateColorCodes(
'&', message
) else ChatColor.stripColor(message)
})
}

override fun formatLocal(from: Player, message: String): String {
return prepareTemplate(plugin.config.localTemplate, { from.displayName }, { null }, { from.displayName }, {
if (from.hasPermission("mcn.chat.colors")) ChatColor.translateAlternateColorCodes(
'&', message
) else ChatColor.stripColor(message)
})
return prepareTemplate(plugin.config.localTemplate,
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{
if (from.hasPermission("mcn.chat.colors")) ChatColor.translateAlternateColorCodes(
'&', message
) else ChatColor.stripColor(message)
})
}

override fun formatSpy(from: Player, message: String): String {
return prepareTemplate(plugin.config.spyTemplate,
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{ "%1\$s" },
{
if (from.hasPermission("mcn.chat.colors")) ChatColor.translateAlternateColorCodes(
'&', message
) else ChatColor.stripColor(message)
})
}
}
10 changes: 10 additions & 0 deletions src/main/java/dev/mikchan/mcnp/chat/formatting/IFormatter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,14 @@ interface IFormatter {
* @return The formatted message.
*/
fun formatLocal(from: Player, message: String): String

/**
* Formats a local message.
*
* @param from The player that sent the message.
* @param message The text of the message.
*
* @return The formatted message.
*/
fun formatSpy(from: Player, message: String): String
}
Loading

0 comments on commit 43b9f87

Please sign in to comment.