Skip to content

Commit 01b68fb

Browse files
committed
[EssentialCommands] Add Experimental openInventory and enderChest command
1 parent 0f92645 commit 01b68fb

File tree

6 files changed

+493
-2
lines changed

6 files changed

+493
-2
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ object EssentialCommandsModule: BukkitModule<BaseModuleConfiguration, EssentialC
1010

1111
init {
1212
listOf(
13-
ClientLocale, DimensionTravel,
13+
ClientLocale, DimensionTravel, EnderChest,
1414
Feed, Heal, Invulnerable, Ip,
15-
IpGroup, Kill, NoFall, Ping,
15+
IpGroup, Kill, NoFall,
16+
OpenInventory, Ping,
1617
PlayerChunkTickets, Spectate,
1718
Speed, Suicide, TpChunk
1819
).forEach { cmd -> registerFeature(cmd) }
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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.extension.register
5+
import io.github.rothes.esu.bukkit.util.extension.unregister
6+
import io.github.rothes.esu.bukkit.util.scheduler.Scheduler.nextTick
7+
import io.github.rothes.esu.bukkit.util.scheduler.Scheduler.syncTick
8+
import io.github.rothes.esu.bukkit.util.version.adapter.PlayerAdapter.Companion.connected
9+
import io.github.rothes.esu.core.command.annotation.ShortPerm
10+
import io.github.rothes.esu.core.module.configuration.FeatureToggle
11+
import org.bukkit.entity.Player
12+
import org.bukkit.event.EventHandler
13+
import org.bukkit.event.Listener
14+
import org.bukkit.event.inventory.InventoryClickEvent
15+
import org.bukkit.event.inventory.InventoryCloseEvent
16+
import org.bukkit.event.inventory.InventoryDragEvent
17+
import org.bukkit.event.player.PlayerQuitEvent
18+
import org.bukkit.inventory.InventoryView
19+
import org.incendo.cloud.annotations.Command
20+
import java.util.concurrent.ConcurrentHashMap
21+
22+
object EnderChest: BaseCommand<FeatureToggle.DefaultTrue, Unit>() {
23+
24+
private val viewMap = ConcurrentHashMap<InventoryView, Boolean>() // View -> AllowEdit
25+
26+
override fun onEnable() {
27+
Listeners.register()
28+
registerCommands(object {
29+
@Command("esuExperimental openEnderChest|enderChest")
30+
@ShortPerm
31+
fun openEnderChest(sender: PlayerUser) {
32+
openEnderChest(sender, sender.player)
33+
}
34+
35+
@Command("esuExperimental openEnderChest|enderChest <player>")
36+
@ShortPerm("others")
37+
fun openEnderChest(sender: PlayerUser, player: Player) {
38+
val senderPlayer = sender.player
39+
senderPlayer.syncTick {
40+
val enderChest = player.enderChest
41+
val openInventory = senderPlayer.openInventory(enderChest) ?: return@syncTick
42+
val editPerm = cmdShortPerm(if (player == senderPlayer) "edit" else "others.edit")
43+
viewMap[openInventory] = sender.hasPermission(editPerm)
44+
45+
fun checkAvailable() {
46+
senderPlayer.nextTick {
47+
if (senderPlayer.openInventory != openInventory) {
48+
return@nextTick
49+
}
50+
51+
if (!player.connected) {
52+
senderPlayer.closeInventory()
53+
viewMap.remove(openInventory)
54+
}
55+
checkAvailable()
56+
}
57+
}
58+
checkAvailable()
59+
}
60+
}
61+
62+
}) { parser ->
63+
parser.registerBuilderDecorator {
64+
it.senderType(PlayerUser::class.java)
65+
}
66+
}
67+
}
68+
69+
override fun onDisable() {
70+
super.onDisable()
71+
for (view in viewMap.keys) {
72+
view.close()
73+
}
74+
viewMap.clear()
75+
Listeners.unregister()
76+
}
77+
78+
// private class EnderChestInv(
79+
// val viewer: PlayerUser,
80+
// val target: Player,
81+
// ): EsuInvHolder<Unit>(InternalInvData) {
82+
//
83+
// private val modifiedSlots = Int2ReferenceOpenHashMap<ItemStack?>() // Slot -> Original Item
84+
// private val enderChest = target.enderChest
85+
// private var task: ScheduledTask?
86+
// private val lock = ReentrantLock()
87+
//
88+
// init {
89+
// update()
90+
//
91+
// task = Scheduler.schedule(target, 1, 1) {
92+
// lock.withLock {
93+
// // Apply edits
94+
// for (entry in modifiedSlots.int2ReferenceEntrySet()) {
95+
// fun rollbackTransaction(item: ItemStack?) {
96+
// item?.let { viewer.player.inventory.addItem(item) }
97+
// }
98+
//
99+
// val new = inventory.getItem(entry.intKey)
100+
// val slot = entry.intKey
101+
// val originalItem = entry.value
102+
//
103+
// if (enderChest.getItem(slot) == originalItem) {
104+
// enderChest.setItem(slot, new)
105+
// } else {
106+
// rollbackTransaction(new)
107+
// }
108+
// }
109+
// modifiedSlots.clear()
110+
//
111+
// if (target.connected) update() else close()
112+
// }
113+
// }
114+
// }
115+
//
116+
// override fun onClose() {
117+
// task?.cancel()
118+
// task = null
119+
// }
120+
//
121+
// private fun update() {
122+
// inventory.contents = enderChest.contents
123+
// }
124+
//
125+
// private object InternalInvData: InventoryData<Unit>(size = 3 * 9)
126+
// }
127+
128+
private object Listeners: Listener {
129+
130+
@EventHandler
131+
fun onClick(e: InventoryClickEvent) {
132+
val allowEdit = viewMap[e.view] ?: return
133+
if (!allowEdit)
134+
e.isCancelled = true
135+
}
136+
137+
@EventHandler
138+
fun onDrag(e: InventoryDragEvent) {
139+
val allowEdit = viewMap[e.view] ?: return
140+
if (!allowEdit)
141+
e.isCancelled = true
142+
}
143+
144+
@EventHandler
145+
fun onClose(e: InventoryCloseEvent) {
146+
viewMap.remove(e.view)
147+
}
148+
149+
@EventHandler
150+
fun onQuit(e: PlayerQuitEvent) {
151+
viewMap.remove(e.player.openInventory)
152+
}
153+
154+
}
155+
156+
}

0 commit comments

Comments
 (0)