Skip to content

Commit 1cbb3f9

Browse files
committed
Add speed command
1 parent 9affc91 commit 1cbb3f9

File tree

3 files changed

+217
-1
lines changed

3 files changed

+217
-1
lines changed

bukkit/src/main/kotlin/io/github/rothes/esu/bukkit/module/EssentialCommandsModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object EssentialCommandsModule: BukkitModule<BaseModuleConfiguration, EssentialC
1010

1111
init {
1212
listOf(
13-
ClientLocale, DimensionTravel, Feed, Heal, Ip, IpGroup, Ping, PlayerChunkTickets, Suicide, TpChunk
13+
ClientLocale, DimensionTravel, Feed, Heal, Ip, IpGroup, Ping, PlayerChunkTickets, Speed, Suicide, TpChunk
1414
).forEach { cmd -> registerFeature(cmd) }
1515
}
1616

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
package io.github.rothes.esu.bukkit.module.essentialcommands
2+
3+
import io.github.rothes.esu.bukkit.user.PlayerUser
4+
import io.github.rothes.esu.bukkit.util.ComponentBukkitUtils.player
5+
import io.github.rothes.esu.bukkit.util.extension.ListenerExt.register
6+
import io.github.rothes.esu.bukkit.util.extension.ListenerExt.unregister
7+
import io.github.rothes.esu.bukkit.util.version.Versioned
8+
import io.github.rothes.esu.core.configuration.ConfigurationPart
9+
import io.github.rothes.esu.core.configuration.data.MessageData
10+
import io.github.rothes.esu.core.configuration.data.MessageData.Companion.message
11+
import io.github.rothes.esu.core.configuration.meta.Comment
12+
import io.github.rothes.esu.core.module.CommonFeature
13+
import io.github.rothes.esu.core.module.configuration.BaseFeatureConfiguration
14+
import io.github.rothes.esu.core.user.User
15+
import io.github.rothes.esu.core.util.ComponentUtils.component
16+
import io.github.rothes.esu.core.util.ComponentUtils.unparsed
17+
import org.bukkit.entity.Player
18+
import org.bukkit.event.EventHandler
19+
import org.bukkit.event.Listener
20+
import org.bukkit.event.player.PlayerQuitEvent
21+
import org.incendo.cloud.bukkit.parser.PlayerParser
22+
import org.incendo.cloud.kotlin.MutableCommandBuilder
23+
import org.incendo.cloud.kotlin.extension.commandBuilder
24+
import org.incendo.cloud.kotlin.extension.getOrNull
25+
import org.incendo.cloud.parser.standard.FloatParser
26+
import org.incendo.cloud.suggestion.SuggestionProvider
27+
import java.util.concurrent.ConcurrentHashMap
28+
29+
object Speed : BaseCommand<Speed.Config, Speed.Lang>() {
30+
31+
init {
32+
registerFeature(WalkSpeed)
33+
registerFeature(FlySpeed)
34+
}
35+
36+
private val speedHandler by Versioned(NmsPlayerSpeedHandler::class.java)
37+
38+
override fun onEnable() {
39+
registerSpeedCommands("speed") { player ->
40+
if (player.isFlying) FlySpeed else WalkSpeed
41+
}
42+
}
43+
44+
private fun CommonFeature<*, *>.registerSpeedCommands(rootName: String, getter: (Player) -> SpeedCommand<out SpeedType>) {
45+
withCommandManager {
46+
commandBuilder(rootName + "Get") {
47+
permission(cmdShortPerm())
48+
handler { ctx ->
49+
val sender = ctx.sender()
50+
val player = ctx.getOrSupplyDefault("player") { (sender as PlayerUser).player }
51+
getter(player).getSpeed(sender, player)
52+
}.regCmd()
53+
54+
permission(cmdShortPerm("others"))
55+
optional("player", PlayerParser.playerParser())
56+
regCmd()
57+
}
58+
commandBuilder(rootName) {
59+
permission(cmdShortPerm())
60+
61+
handler { ctx ->
62+
val sender = ctx.sender()
63+
val player = ctx.getOrSupplyDefault("player") { (sender as PlayerUser).player }
64+
val speedCommand = getter(player)
65+
val value = ctx.getOrNull("value") ?: speedCommand.defaultValue
66+
speedCommand.setSpeed(sender, value, player)
67+
}
68+
69+
fun argType(scope: MutableCommandBuilder<User>.() -> Unit) {
70+
copy {
71+
scope()
72+
regCmd()
73+
74+
permission(cmdShortPerm("others"))
75+
optional("player", PlayerParser.playerParser())
76+
regCmd()
77+
}
78+
}
79+
80+
argType {
81+
literal("reset")
82+
}
83+
argType {
84+
required("value", FloatParser.floatParser()) {
85+
suggestionProvider(SuggestionProvider.blockingStrings { ctx, _ ->
86+
val sender = ctx.sender()
87+
val player = if (sender is PlayerUser) sender.player else null
88+
val current = if (player != null) with(getter(player)) { player.speed } else 0.1f
89+
listOf(current.toString())
90+
})
91+
}
92+
}
93+
}
94+
}
95+
}
96+
97+
data class Config(
98+
@Comment("""
99+
Reset speed for players leaving the server or on disable.
100+
If not enabled, modified speed may exist forever.
101+
""")
102+
val autoResetSpeed: Boolean = true,
103+
): BaseFeatureConfiguration(true)
104+
105+
data class Lang(
106+
val speedGet: MessageData = "<pc><capitalize:'<type>'> speed of <pdc><player><pc> is <pdc><value><pc>.".message,
107+
val speedSet: MessageData = "<pc>Set <type> speed of <pdc><player><pc> to <pdc><value><pc>.".message,
108+
)
109+
110+
interface NmsPlayerSpeedHandler {
111+
fun getWalkSpeed(bukkitPlayer: Player): Float
112+
fun getFlySpeed(bukkitPlayer: Player): Float
113+
fun setWalkSpeed(bukkitPlayer: Player, speed: Float)
114+
fun setFlySpeed(bukkitPlayer: Player, speed: Float)
115+
}
116+
117+
abstract class SpeedCommand<L: SpeedType> : BaseCommand<Unit, L>() {
118+
119+
abstract var Player.speed: Float
120+
abstract val defaultValue: Float
121+
private val changed = ConcurrentHashMap.newKeySet<Player>()
122+
private val listener = Listeners()
123+
124+
fun getSpeed(sender: User, player: Player) {
125+
sender.message(
126+
Speed.lang, { speedGet }, player(player), unparsed("value", player.speed),
127+
component("type", sender.buildMiniMessage(lang, { typeName })),
128+
)
129+
}
130+
131+
fun setSpeed(sender: User, speed: Float, player: Player) {
132+
player.speed = speed
133+
sender.message(
134+
Speed.lang, { speedSet }, player(player), unparsed("value", speed),
135+
component("type", sender.buildMiniMessage(lang, { typeName })),
136+
)
137+
changed.add(player)
138+
}
139+
140+
override fun onEnable() {
141+
registerSpeedCommands(name) { this }
142+
listener.register()
143+
}
144+
145+
override fun onDisable() {
146+
super.onDisable()
147+
listener.unregister()
148+
if (Speed.config.autoResetSpeed) {
149+
for (player in changed) {
150+
player.speed = defaultValue
151+
}
152+
}
153+
changed.clear()
154+
}
155+
156+
inner class Listeners : Listener {
157+
@EventHandler
158+
fun onQuit(event: PlayerQuitEvent) {
159+
if (changed.remove(event.player) && Speed.config.autoResetSpeed)
160+
event.player.speed = defaultValue
161+
}
162+
}
163+
}
164+
165+
abstract class SpeedType(val typeName: String) : ConfigurationPart
166+
167+
object WalkSpeed : SpeedCommand<WalkSpeed.WalkSpeedType>() {
168+
169+
override var Player.speed: Float
170+
get() = speedHandler.getWalkSpeed(this)
171+
set(value) { speedHandler.setWalkSpeed(this, value) }
172+
override val defaultValue: Float = 0.1f
173+
174+
class WalkSpeedType: SpeedType("walk")
175+
176+
}
177+
178+
object FlySpeed : SpeedCommand<FlySpeed.FlySpeedType>() {
179+
180+
override var Player.speed: Float
181+
get() = speedHandler.getFlySpeed(this)
182+
set(value) { speedHandler.setFlySpeed(this, value) }
183+
override val defaultValue: Float = 0.05f
184+
185+
class FlySpeedType: SpeedType("fly")
186+
187+
}
188+
189+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.github.rothes.esu.bukkit.module.essentialcommands.v1
2+
3+
import io.github.rothes.esu.bukkit.module.essentialcommands.Speed
4+
import io.github.rothes.esu.bukkit.util.version.adapter.AttributeAdapter
5+
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer
6+
import org.bukkit.entity.Player as BukkitPlayer
7+
8+
object NmsPlayerSpeedHandlerImpl: Speed.NmsPlayerSpeedHandler {
9+
10+
override fun getWalkSpeed(bukkitPlayer: BukkitPlayer) = bukkitPlayer.nms.abilities.walkingSpeed
11+
override fun getFlySpeed(bukkitPlayer: BukkitPlayer) = bukkitPlayer.nms.abilities.flyingSpeed
12+
13+
override fun setWalkSpeed(bukkitPlayer: BukkitPlayer, speed: Float) {
14+
val player = bukkitPlayer.nms
15+
player.abilities.walkingSpeed = speed
16+
player.onUpdateAbilities()
17+
bukkitPlayer.getAttribute(AttributeAdapter.MOVEMENT_SPEED)!!.baseValue = speed.toDouble()
18+
}
19+
override fun setFlySpeed(bukkitPlayer: BukkitPlayer, speed: Float) {
20+
val player = bukkitPlayer.nms
21+
player.abilities.flyingSpeed = speed
22+
player.onUpdateAbilities()
23+
}
24+
25+
private val BukkitPlayer.nms
26+
get() = (this as CraftPlayer).handle
27+
}

0 commit comments

Comments
 (0)