Skip to content

Commit 853e5ff

Browse files
committed
initial commit
1 parent 97edaef commit 853e5ff

File tree

3 files changed

+346
-0
lines changed

3 files changed

+346
-0
lines changed

menu/Menu.kt

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
package me.cepi.gameplay.util.menu
2+
3+
import me.cepi.gameplay.GameplayPlugin
4+
import me.cepi.gameplay.modules.MenuItemListener
5+
import me.cepi.gameplay.util.items.ItemBuilder
6+
import org.bukkit.Bukkit
7+
import org.bukkit.Material
8+
import org.bukkit.entity.Player
9+
import org.bukkit.event.inventory.InventoryCloseEvent
10+
import org.bukkit.inventory.Inventory
11+
import org.bukkit.inventory.ItemStack
12+
import org.bukkit.inventory.meta.ItemMeta
13+
import java.util.*
14+
15+
/**
16+
* Basic Menu class for creating advanced Menus with multiple click events
17+
* easily
18+
*
19+
* @author LeoDog896, jeremy
20+
*/
21+
class Menu(player: Player, inventoryRows: Int, inventoryTitle: String) {
22+
23+
val inventory: Inventory
24+
25+
val player: Player
26+
27+
val title: String
28+
29+
private val menuItems: MutableList<MenuItem> = ArrayList()
30+
31+
private val dataStorage: MutableMap<Int, Any> = HashMap()
32+
33+
private var closeConsumer: (InventoryCloseEvent.Reason) -> Unit = { }
34+
35+
fun setBorder(border: ItemStack) {
36+
setRow(0, border).onClick(true)
37+
setRow(rows - 1, border).onClick(true)
38+
setColumn(0, border).onClick(true)
39+
setColumn(8, border).onClick(true)
40+
}
41+
42+
fun setBorder(mainBorder: Material) = setBorder(ItemBuilder(mainBorder).setName(" ").toItem())
43+
44+
/**
45+
* Basic method for setting items
46+
*
47+
* @param slot Slot starting at 0s
48+
* @param item basic ItemStack
49+
* @return An editable MenuItem class for click events and editing
50+
*/
51+
fun setItem(slot: Int, item: ItemStack): MenuItem {
52+
inventory.setItem(slot, item)
53+
val menuItem = MenuItem(slot, this)
54+
menuItems.add(menuItem)
55+
return menuItem
56+
}
57+
58+
fun setItem(slot: Int, item: ItemBuilder) = setItem(slot, item.toItem())
59+
60+
fun setItems(slotFrom: Int, slotTo: Int, item: ItemStack): MenuItems {
61+
val items: MutableList<MenuItem> = ArrayList()
62+
for (i in slotFrom..slotTo) {
63+
items.add(setItem(i, item))
64+
}
65+
return MenuItems(items)
66+
}
67+
68+
fun setItems(slotFrom: Int, slotTo: Int, slotSpacing: Int, item: ItemStack): MenuItems {
69+
val items: MutableList<MenuItem> = ArrayList()
70+
var i = slotFrom
71+
while (i <= slotTo) {
72+
items.add(setItem(i, item))
73+
i += slotSpacing
74+
}
75+
return MenuItems(items)
76+
}
77+
78+
private val rows: Int
79+
get() = inventory.size / 9
80+
81+
/**
82+
* Clears the menu without removing any data
83+
*/
84+
fun clearMenu() {
85+
killAllClickers()
86+
inventory.clear()
87+
menuItems.clear()
88+
}
89+
90+
/**
91+
* Clears the menu with an optional data removal
92+
*
93+
* @param trueWipe If data will be removed or not
94+
*/
95+
private fun clearMenu(trueWipe: Boolean = true) {
96+
killAllClickers()
97+
menuItems.clear()
98+
inventory.clear()
99+
if (trueWipe) dataStorage.clear()
100+
}
101+
102+
/**
103+
* Updates an item for refreshing
104+
*
105+
* @param item The item to refresh (checks by slot)
106+
*/
107+
fun reputItemBySlot(item: MenuItem) {
108+
for (i in menuItems.indices) {
109+
if (menuItems[i].slot == item.slot) {
110+
menuItems[i] = item
111+
}
112+
}
113+
}
114+
115+
/**
116+
* Finds and removes all clickers in the current menu
117+
*/
118+
private fun killAllClickers() {
119+
menuItems.forEach { item -> MenuItemListener.remove(item) }
120+
}
121+
122+
/**
123+
* Finds and removes all clickers at a specific slot
124+
*
125+
* @param slot The slot to remove clickers from
126+
*/
127+
fun killClickerAtSlot(slot: Int) {
128+
menuItems.stream()
129+
.filter { item: MenuItem -> item.slot == slot }
130+
.forEach { item: MenuItem -> MenuItemListener.remove(item) }
131+
}
132+
133+
/**
134+
* Set the row of a menu with an ItemStack.
135+
*
136+
* @param row The row, starting from 0
137+
* @param stack The ItemStack to use
138+
* @return [MenuItems] (a group of [MenuItem] for quick handling)
139+
*/
140+
fun setRow(row: Int, stack: ItemStack): MenuItems {
141+
var startIndex = row * 9
142+
if (startIndex > inventory.size) throw ArrayIndexOutOfBoundsException()
143+
val menuItems: MutableList<MenuItem> = ArrayList()
144+
val endIndex = startIndex + 9
145+
startIndex = row * 9
146+
while (startIndex < endIndex) {
147+
val menuItem = setItem(startIndex, stack)
148+
this.menuItems.add(menuItem)
149+
menuItems.add(menuItem)
150+
startIndex++
151+
}
152+
return MenuItems(menuItems)
153+
}
154+
155+
fun setRow(row: Int, builder: ItemBuilder) = setRow(row, builder.toItem())
156+
157+
private fun setColumn(column: Int, stack: ItemStack): MenuItems {
158+
if (column > 8) throw ArrayIndexOutOfBoundsException("Too many columns!")
159+
val menuItems: MutableList<MenuItem> = ArrayList()
160+
val endIndex = 9 * inventory.size / 9 + column
161+
var i = column
162+
while (i < endIndex) {
163+
val menuItem = setItem(i, stack)
164+
this.menuItems.add(menuItem)
165+
menuItems.add(menuItem)
166+
i += 9
167+
}
168+
return MenuItems(menuItems)
169+
}
170+
171+
fun setRows(stack: ItemStack, vararg rows: Int): MenuItems? {
172+
var initialMenuItems = setRow(rows[0], stack)
173+
for (i in 1 until rows.size) {
174+
initialMenuItems = initialMenuItems.concat(setRow(rows[i], stack))
175+
}
176+
return initialMenuItems
177+
}
178+
179+
fun setColumns(stack: ItemStack, vararg columns: Int): MenuItems? {
180+
var initialMenuItems = setColumn(columns[0], stack)
181+
for (i in 1 until columns.size) {
182+
initialMenuItems = initialMenuItems.concat(setColumn(columns[i], stack))
183+
}
184+
return initialMenuItems
185+
}
186+
187+
/**
188+
* Get an item from a slot
189+
*
190+
* @param slot The slot to get an item from
191+
* @return the [ItemStack] from there.
192+
*/
193+
fun getItem(slot: Int): ItemStack {
194+
return if (inventory.getItem(slot) == null) ItemStack(Material.AIR) else inventory.getItem(slot)!!
195+
}
196+
197+
/**
198+
* Close the menu
199+
*/
200+
fun close() {
201+
player.closeInventory(InventoryCloseEvent.Reason.PLUGIN)
202+
clearMenu()
203+
}
204+
205+
fun setData(slot: Int, `object`: Any) {
206+
dataStorage[slot] = `object`
207+
}
208+
209+
fun getData(slot: Int): Any? {
210+
return dataStorage[slot]
211+
}
212+
213+
fun setSlotMeta(slot: Int, meta: ItemMeta) {
214+
val item = inventory.getItem(slot)
215+
(item ?: return).itemMeta = meta
216+
inventory.setItem(slot, item)
217+
}
218+
219+
/**
220+
* Clear a specific value of a specific slot
221+
*
222+
* @param slot The slot to clear data from
223+
* @param value The value to remove
224+
*/
225+
fun clearData(slot: Int, value: String) = dataStorage.remove(slot, value)
226+
227+
/**
228+
* Clears a specific value
229+
*
230+
* @param slot The slot to remove
231+
*/
232+
fun clearData(slot: Int) = dataStorage.remove(slot)
233+
234+
/**
235+
* Set function to run when the menu closes.
236+
*
237+
* @param consumer The consumer to run when the menu closes.
238+
*/
239+
fun onClose(consumer: (InventoryCloseEvent.Reason) -> Unit) {
240+
closeConsumer = consumer
241+
}
242+
243+
fun triggerClose(reason: InventoryCloseEvent.Reason) {
244+
closeConsumer.invoke(reason)
245+
}
246+
247+
fun open() {
248+
Bukkit.getScheduler().runTask(GameplayPlugin.plugin, Runnable { player.openInventory(inventory) })
249+
}
250+
251+
fun open(player: Player) {
252+
Bukkit.getScheduler().runTask(GameplayPlugin.plugin, Runnable { player.openInventory(inventory) })
253+
}
254+
255+
init {
256+
val inventorySlots = inventoryRows * 9
257+
this.player = player
258+
title = inventoryTitle
259+
inventory = Bukkit.createInventory(null, inventorySlots, inventoryTitle)
260+
}
261+
}

menu/MenuItem.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package me.cepi.gameplay.util.menu
2+
3+
import me.cepi.gameplay.modules.MenuItemListener
4+
import org.bukkit.entity.Player
5+
import org.bukkit.event.inventory.ClickType
6+
import org.bukkit.event.inventory.InventoryAction
7+
8+
class MenuItem(val slot: Int, val menu: Menu) {
9+
val title: String = menu.title
10+
11+
val player: Player = menu.player
12+
13+
var codeBlock: ((InventoryAction, ClickType) -> Unit?)? = null
14+
private set
15+
16+
var shouldCancel = false
17+
private set
18+
19+
/**
20+
* A click event for a single item
21+
*
22+
* @param code the consumer to be run when a click happens
23+
* @param toCancel If to cancel the original event
24+
*/
25+
fun onClick(code: (InventoryAction, ClickType) -> Unit?, toCancel: Boolean) {
26+
codeBlock = code
27+
shouldCancel = toCancel
28+
menu.reputItemBySlot(this)
29+
MenuItemListener.add(this)
30+
}
31+
/**
32+
* A click event for a single item
33+
*
34+
* @param toCancel If to cancel the original event
35+
*/
36+
fun onClick(toCancel: Boolean) {
37+
shouldCancel = toCancel
38+
menu.reputItemBySlot(this)
39+
MenuItemListener.add(this)
40+
}
41+
42+
}

menu/MenuItems.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package me.cepi.gameplay.util.menu
2+
3+
import org.bukkit.event.inventory.ClickType
4+
import org.bukkit.event.inventory.InventoryAction
5+
import java.util.function.Consumer
6+
7+
class MenuItems(val items: MutableList<MenuItem>) {
8+
9+
/**
10+
* The parent menu
11+
*/
12+
private val menu: Menu = items[0].menu
13+
14+
/**
15+
* On click for all the items with a handler
16+
* @param code The consumer that handles the onClick event
17+
* @param toCancel Cancel any raw clicking (picking up, etc.)
18+
*/
19+
fun onClick(code: (InventoryAction, ClickType) -> Unit, toCancel: Boolean) {
20+
items.forEach { item ->
21+
item.onClick(code, toCancel)
22+
menu.reputItemBySlot(item)
23+
}
24+
}
25+
26+
fun concat(items: MenuItems): MenuItems {
27+
val finalItems: MutableList<MenuItem> = items.items
28+
finalItems.addAll(this.items)
29+
return MenuItems(finalItems)
30+
}
31+
32+
/**
33+
* On click for all the items in this class
34+
* @param toCancel Cancel any raw clicking (picking up, etc.)
35+
*/
36+
fun onClick(toCancel: Boolean?) {
37+
items.forEach(Consumer { item: MenuItem ->
38+
item.onClick(toCancel ?: return@Consumer)
39+
menu.reputItemBySlot(item)
40+
})
41+
}
42+
43+
}

0 commit comments

Comments
 (0)