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