Skip to content

Commit e82f53b

Browse files
committed
refactor: Update to guiy 0.14
refactor: Use a viewmodel to simplify resourcepack menu logic
1 parent cc5bb61 commit e82f53b

12 files changed

Lines changed: 252 additions & 236 deletions

File tree

.editorconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[*.kt]
2+
max_line_length = off

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[libraries]
22
geary-papermc = "com.mineinabyss:geary-papermc:0.33.0"
3-
guiy = "com.mineinabyss:guiy-compose:0.13.0"
3+
guiy = "com.mineinabyss:guiy-compose:0.14.2"

src/main/kotlin/com/mineinabyss/packy/PackyCommands.kt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
11
package com.mineinabyss.packy
22

33
import com.github.shynixn.mccoroutine.bukkit.launch
4-
import com.github.shynixn.mccoroutine.bukkit.ticks
5-
import com.mineinabyss.guiy.inventory.guiy
4+
import com.mineinabyss.guiy.canvas.guiy
65
import com.mineinabyss.idofront.commands.brigadier.commands
7-
import com.mineinabyss.idofront.commands.brigadier.executes
86
import com.mineinabyss.idofront.messaging.error
9-
import com.mineinabyss.idofront.messaging.info
107
import com.mineinabyss.idofront.messaging.success
11-
import com.mineinabyss.idofront.textcomponents.miniMsg
128
import com.mineinabyss.packy.components.packyData
139
import com.mineinabyss.packy.config.packy
14-
import com.mineinabyss.packy.menus.picker.PackyMainMenu
15-
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
16-
import kotlinx.coroutines.delay
10+
import com.mineinabyss.packy.menus.picker.PackyMenu
1711
import net.kyori.adventure.text.Component
1812
import net.kyori.adventure.text.format.NamedTextColor
19-
import org.bukkit.Bukkit
20-
import org.bukkit.entity.Player
2113

2214
object PackyCommands {
2315
fun registerCommands() {
@@ -38,7 +30,7 @@ object PackyCommands {
3830
"menu" {
3931
requiresPermission("")
4032
playerExecutes {
41-
guiy { PackyMainMenu(player) }
33+
guiy(player) { PackyMenu() }
4234
}
4335
}
4436
"send" {

src/main/kotlin/com/mineinabyss/packy/PackyPlugin.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import com.charleskorn.kaml.PolymorphismStyle
44
import com.charleskorn.kaml.SingleLineStringStyle
55
import com.charleskorn.kaml.Yaml
66
import com.charleskorn.kaml.YamlConfiguration
7-
import com.github.shynixn.mccoroutine.bukkit.registerSuspendingEvents
87
import com.mineinabyss.geary.addons.dsl.createAddon
98
import com.mineinabyss.geary.autoscan.autoscan
10-
import com.mineinabyss.geary.modules.geary
119
import com.mineinabyss.geary.papermc.configure
1210
import com.mineinabyss.geary.papermc.gearyPaper
1311
import com.mineinabyss.idofront.config.ConfigFormats
@@ -20,9 +18,7 @@ import com.mineinabyss.idofront.plugin.listeners
2018
import com.mineinabyss.packy.config.*
2119
import com.mineinabyss.packy.listener.PlayerListener
2220
import com.mineinabyss.packy.listener.TemplateLoadTriggers
23-
import kotlinx.coroutines.Job
2421
import kotlinx.serialization.modules.EmptySerializersModule
25-
import org.bukkit.Bukkit
2622
import org.bukkit.plugin.java.JavaPlugin
2723
import team.unnamed.creative.ResourcePack
2824

src/main/kotlin/com/mineinabyss/packy/config/PackyMenu.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ data class PackyMenu(
2424
MENU, CYCLING
2525
}
2626

27+
/**
28+
* Describes a customization button displayed in the packy menu.
29+
*
30+
* - If [type] is `CYCLING`, will switch between different display items on click.
31+
* - If it is `MENU`, will open a submenu on click and let the user select a pack.
32+
*/
2733
@Serializable
2834
data class PackySubMenu(
2935
val title: String = "Packy SubMenu",
@@ -34,14 +40,18 @@ data class PackyMenu(
3440
val allSlotsEmptyExceptFirst: Boolean = false,
3541
val packs: Map<String, PackyPack> = mapOf()
3642
) {
37-
fun refreshItem(itemStack: ItemStack, state: Boolean) {
43+
fun buttonFor(state: Boolean): ItemStack {
44+
val item = button.toItemStack()
3845
val cmd = CustomModelData.customModelData().addFlag(state).build()
39-
itemStack.setData(DataComponentTypes.CUSTOM_MODEL_DATA, cmd)
46+
item.setData(DataComponentTypes.CUSTOM_MODEL_DATA, cmd)
47+
return item
4048
}
4149

42-
fun refreshItem(itemStack: ItemStack, index: Int) {
50+
fun buttonFor(parent: PackyPack, index: Int): ItemStack {
51+
val item = button.toItemStack(parent.button?.toItemStackOrNull() ?: ItemStack.empty())
4352
val cmd = CustomModelData.customModelData().addFloat(index.toFloat()).build()
44-
itemStack.setData(DataComponentTypes.CUSTOM_MODEL_DATA, cmd)
53+
item.setData(DataComponentTypes.CUSTOM_MODEL_DATA, cmd)
54+
return item
4555
}
4656
}
4757

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.mineinabyss.packy.menus.picker
2+
3+
import androidx.compose.runtime.Composable
4+
import com.mineinabyss.guiy.components.Item
5+
import com.mineinabyss.guiy.modifiers.Modifier
6+
import com.mineinabyss.guiy.navigation.LocalBackGestureDispatcher
7+
import com.mineinabyss.idofront.serialization.SerializableDataTypes
8+
import com.mineinabyss.idofront.serialization.SerializableItemStack
9+
import com.mineinabyss.idofront.textcomponents.miniMsg
10+
import com.mineinabyss.packy.menus.Button
11+
import io.papermc.paper.datacomponent.DataComponentTypes
12+
import io.papermc.paper.datacomponent.item.CustomModelData
13+
import org.bukkit.Material
14+
import org.bukkit.inventory.ItemStack
15+
16+
@Composable
17+
internal fun BackButton(modifier: Modifier = Modifier.Companion) {
18+
val backGesture = LocalBackGestureDispatcher.current
19+
Button(onClick = { backGesture.onBack() }, modifier = modifier) {
20+
SerializableItemStack(
21+
_customName = "<red><b>Back",
22+
customModelData = SerializableDataTypes.CustomModelData(floats = listOf(1f))
23+
)
24+
Item(ItemStack(Material.PAPER).apply {
25+
setData(DataComponentTypes.CUSTOM_NAME, "<red><b>Back".miniMsg())
26+
setData(
27+
DataComponentTypes.CUSTOM_MODEL_DATA,
28+
CustomModelData.customModelData().addFloat(1f).build()
29+
)
30+
})
31+
}
32+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.mineinabyss.packy.menus.picker
2+
3+
import androidx.compose.runtime.Composable
4+
import com.mineinabyss.guiy.components.Item
5+
import com.mineinabyss.guiy.components.VerticalGrid
6+
import com.mineinabyss.guiy.components.items.LocalItemTheme
7+
import com.mineinabyss.idofront.resourcepacks.ResourcePacks
8+
import com.mineinabyss.packy.config.PackyMenu
9+
import com.mineinabyss.packy.menus.Button
10+
import io.papermc.paper.datacomponent.DataComponentTypes
11+
import org.bukkit.inventory.ItemStack
12+
13+
@Composable
14+
fun CycleButton(subMenu: PackyMenu.PackySubMenu, pack: PackyMenu.PackyPack, onClick: () -> Unit) {
15+
val modifier = subMenu.modifiers.offset.toAtModifier()
16+
val size = subMenu.modifiers.size
17+
val item = subMenu.buttonFor(pack, subMenu.packs.values.indexOf(pack).coerceAtLeast(0))
18+
19+
VerticalGrid(subMenu.modifiers.size.toSizeModifier(modifier)) {
20+
Button(enabled = true, onClick = onClick) {
21+
val emptyItem = LocalItemTheme.current.invisible
22+
Item(if (subMenu.allSlotsEmptyExceptFirst) emptyItem else item, size.toSizeModifier())
23+
}
24+
}
25+
if (subMenu.allSlotsEmptyExceptFirst) Button(enabled = true, onClick = onClick) {
26+
Item(item, modifier)
27+
}
28+
}

src/main/kotlin/com/mineinabyss/packy/menus/picker/PackPicker.kt

Lines changed: 0 additions & 61 deletions
This file was deleted.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.mineinabyss.packy.menus.picker
2+
3+
import com.github.shynixn.mccoroutine.bukkit.launch
4+
import com.mineinabyss.guiy.viewmodel.GuiyViewModel
5+
import com.mineinabyss.idofront.messaging.info
6+
import com.mineinabyss.packy.PackyServer
7+
import com.mineinabyss.packy.components.packyData
8+
import com.mineinabyss.packy.config.PackyMenu
9+
import com.mineinabyss.packy.config.PackyTemplate
10+
import com.mineinabyss.packy.config.packy
11+
import kotlinx.coroutines.flow.*
12+
import org.bukkit.entity.Player
13+
import org.bukkit.inventory.ItemStack
14+
15+
class PackPickerViewModel(
16+
val player: Player,
17+
) : GuiyViewModel() {
18+
private val originalTemplates = player.packyData.templates.toMap()
19+
private val _packyData = MutableStateFlow(player.packyData)
20+
val packyData = _packyData.asStateFlow()
21+
val subPackList = packy.menu.subMenus.map { it.value to it.value.packs.toList() }.toMap()
22+
23+
fun itemFor(
24+
templateId: String,
25+
subMenu: PackyMenu.PackySubMenu,
26+
): StateFlow<ItemStack> = packyData.map {
27+
subMenu.buttonFor(state = it.enabledPackIds.contains(templateId))
28+
}.stateIn(viewModelScope, SharingStarted.Eagerly, ItemStack.empty())
29+
30+
/**
31+
* Resends the resourcepack with any changes made by the player in the menu.
32+
*/
33+
fun sendPackChanges() {
34+
val packyData = _packyData.value
35+
if (originalTemplates != packyData.templates) {
36+
// todo send message listing packs that were enabled/disabled
37+
val enabledPacks = packyData.templates.filter { it.value }
38+
.keys.filter { !originalTemplates[it]!! }
39+
val disabledPacks = packyData.templates.filter { !it.value }
40+
.keys.filter { originalTemplates[it]!! }
41+
42+
player.info(buildString {
43+
appendLine("<gray>Changed resourcepacks:")
44+
if (enabledPacks.isNotEmpty())
45+
append(" • Enabled <green>${enabledPacks.joinToString(", ")}</green>")
46+
if (disabledPacks.isNotEmpty()) {
47+
if (enabledPacks.isNotEmpty()) appendLine()
48+
append(" • Disabled <red>${disabledPacks.joinToString(", ")}</red>")
49+
}
50+
})
51+
52+
packy.plugin.launch {
53+
player.packyData = packyData
54+
PackyServer.sendPack(player)
55+
}
56+
}
57+
}
58+
59+
fun togglePack(templateId: String) {
60+
val isEnabled = _packyData.value.templates[templateId] == true
61+
if (isEnabled) disablePack(templateId)
62+
else enablePack(templateId)
63+
}
64+
65+
fun enablePack(pack: String) {
66+
packy.templates[pack]?.let { template ->
67+
disableConflictingPacks(template)
68+
if (_packyData.value.templates[template.id] == true) return // Don't do anything if already enabled
69+
_packyData.update {
70+
it.copy(
71+
//TODO make packyData immutable
72+
templates = it.templates.plus(template.id to true).toMutableMap()
73+
)
74+
}
75+
}
76+
}
77+
78+
fun disablePack(pack: String) {
79+
packy.templates[pack]?.let { template ->
80+
if (_packyData.value.templates[template.id] == false) return // Don't do anything if already disabled
81+
_packyData.update {
82+
it.copy(
83+
//TODO immutable, as above
84+
templates = it.templates.plus(template.id to false).toMutableMap()
85+
)
86+
}
87+
}
88+
}
89+
90+
private fun disableConflictingPacks(template: PackyTemplate) {
91+
_packyData.update {
92+
val conflictingDisabled = it.templates.keys
93+
.mapNotNull(packy.templates::get)
94+
.filter(template::conflictsWith)
95+
.associate { it.id to false }
96+
97+
it.copy(
98+
templates = it.templates.plus(conflictingDisabled).toMutableMap()
99+
)
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)