1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
package moe.nea.firmament.features.chat
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.StringReader
import com.mojang.brigadier.exceptions.CommandSyntaxException
import com.mojang.brigadier.tree.LiteralCommandNode
import kotlin.time.Duration.Companion.seconds
import net.minecraft.util.math.BlockPos
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.commands.CaseInsensitiveLiteralCommandNode
import moe.nea.firmament.commands.thenExecute
import moe.nea.firmament.events.CommandEvent
import moe.nea.firmament.events.PartyMessageReceivedEvent
import moe.nea.firmament.events.ProcessChatEvent
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.TimeMark
import moe.nea.firmament.util.tr
import moe.nea.firmament.util.useMatch
object PartyCommands {
val messageInChannel = "(?<channel>Party|Guild) >([^:]+?)? (?<name>[^: ]+): (?<message>.+)".toPattern()
@Subscribe
fun onChat(event: ProcessChatEvent) {
messageInChannel.useMatch(event.unformattedString) {
val channel = group("channel")
val message = group("message")
val name = group("name")
if (channel == "Party") {
PartyMessageReceivedEvent.publish(PartyMessageReceivedEvent(
event, message, name
))
}
}
}
val commandPrefixes = "!-?$.&#+~€\"@°_;:³²`'´ß\\,|".toSet()
data class PartyCommandContext(
val name: String
)
val dispatch = CommandDispatcher<PartyCommandContext>().also { dispatch ->
fun register(
name: String,
vararg alias: String,
block: CaseInsensitiveLiteralCommandNode.Builder<PartyCommandContext>.() -> Unit = {},
): LiteralCommandNode<PartyCommandContext> {
val node =
dispatch.register(CaseInsensitiveLiteralCommandNode.Builder<PartyCommandContext>(name).also(block))
alias.forEach { register(it) { redirect(node) } }
return node
}
register("warp", "pw", "pwarp", "partywarp") {
executes {
// TODO: add check if you are the party leader
MC.sendCommand("p warp")
0
}
}
register("transfer", "pt", "ptme") {
executes {
MC.sendCommand("p transfer ${it.source.name}")
0
}
}
register("allinvite", "allinv") {
executes {
MC.sendCommand("p settings allinvite")
0
}
}
register("coords") {
executes {
val p = MC.player?.blockPos ?: BlockPos.ORIGIN
MC.sendCommand("pc x: ${p.x}, y: ${p.y}, z: ${p.z}")
0
}
}
// TODO: downtime tracker (display message again at end of dungeon)
// instance ends: kuudra, dungeons, bacte
// TODO: at TPS command
}
object TConfig : ManagedConfig("party-commands", Category.CHAT) {
val enable by toggle("enable") { false }
val cooldown by duration("cooldown", 0.seconds, 20.seconds) { 2.seconds }
val ignoreOwnCommands by toggle("ignore-own") { false }
}
var lastCommand = TimeMark.farPast()
@Subscribe
fun listPartyCommands(event: CommandEvent.SubCommand) {
event.subcommand("partycommands") {
thenExecute {
// TODO: Better help, including descriptions and redirect detection
MC.sendChat(tr("firmament.partycommands.help", "Available party commands: ${dispatch.root.children.map { it.name }}. Available prefixes: $commandPrefixes"))
}
}
}
@Subscribe
fun onPartyMessage(event: PartyMessageReceivedEvent) {
if (!TConfig.enable) return
if (event.message.firstOrNull() !in commandPrefixes) return
if (event.name == MC.playerName && TConfig.ignoreOwnCommands) return
if (lastCommand.passedTime() < TConfig.cooldown) {
MC.sendChat(tr("firmament.partycommands.cooldown", "Skipping party command. Cooldown not passed."))
return
}
// TODO: add trust levels
val commandLine = event.message.substring(1)
try {
dispatch.execute(StringReader(commandLine), PartyCommandContext(event.name))
} catch (ex: Exception) {
if (ex is CommandSyntaxException) {
MC.sendChat(tr("firmament.partycommands.unknowncommand", "Unknown party command."))
return
} else {
MC.sendChat(tr("firmament.partycommands.unknownerror", "Unknown error during command execution."))
ErrorUtil.softError("Unknown error during command execution.", ex)
}
}
lastCommand = TimeMark.now()
}
}
|