Skip to content

Commit

Permalink
doc: Document any user facing api like Composables and Modifiers
Browse files Browse the repository at this point in the history
refactor: Remove interactable inventory composable due to high exploit potential
feat: CreativeItem composable that mimics creative inventory item selector
chore: Clean up some code relying on index in inventory to use x-y coordinate pairs
chore: Update example to showcase CreativeItem
chore: Update idofront, compose compiler, Kotlin
  • Loading branch information
0ffz committed May 30, 2024
1 parent a3997b0 commit 1843bfc
Show file tree
Hide file tree
Showing 33 changed files with 499 additions and 316 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ guiy {

```kotlin
@Composable
fun GuiyOwner.ExampleMenu(player: Player) {
fun ExampleMenu(player: Player) {
val owner = LocalGuiyOwner.current
// Guiy will dynamically update players, title, or height if you use a state.
Chest(setOf(player), title = "Example", height = 4, onClose = { exit() /*reopen()*/ }) {
Chest(setOf(player), title = "Example", height = 4, onClose = { owner.exit() /*owner.reopen()*/ }) {
ToggleButton()
}
}
Expand Down Expand Up @@ -125,7 +126,7 @@ fun TimedToggle() {
### Real world use

We are using this project internally, so you should be able to find up-to-date usage in
our [main project](https://github.com/MineInAbyss/MineInAbyss/tree/master/mineinabyss-features/src/main/kotlin/com/mineinabyss/guilds/menus).
our [main project](https://github.com/MineInAbyss/MineInAbyss/tree/master/mineinabyss-features/src/main/kotlin/com/mineinabyss/features/guilds/menus).

## Usage

Expand Down
24 changes: 13 additions & 11 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,26 @@ plugins {
alias(idofrontLibs.plugins.mia.publication)
alias(idofrontLibs.plugins.mia.autoversion)
alias(idofrontLibs.plugins.mia.testing)
alias(idofrontLibs.plugins.compose)
alias(idofrontLibs.plugins.jetbrainsCompose)
alias(idofrontLibs.plugins.compose.compiler)
}


tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf(
kotlin {
compilerOptions {
freeCompilerArgs.addAll(
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
)
jvmTarget = "17"
}
}

repositories {
mavenCentral()
google()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
maven("https://repo.codemc.org/repository/maven-public/")
allprojects {
repositories {
mavenCentral()
google()
maven("https://repo.mineinabyss.com/snapshots")
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
maven("https://repo.codemc.org/repository/maven-public/")
}
}

dependencies {
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kotlin.code.style=official
group=com.mineinabyss
version=0.9
idofrontVersion=0.23.0
version=0.10
idofrontVersion=0.24.0
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
3 changes: 2 additions & 1 deletion guiy-example/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ plugins {
alias(idofrontLibs.plugins.mia.kotlin.jvm)
alias(idofrontLibs.plugins.mia.papermc)
alias(idofrontLibs.plugins.mia.copyjar)
alias(idofrontLibs.plugins.compose)
alias(idofrontLibs.plugins.jetbrainsCompose)
alias(idofrontLibs.plugins.compose.compiler)
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
package com.mineinabyss.guiy.example.gui

import androidx.compose.runtime.*
import com.mineinabyss.guiy.components.CreativeItem
import com.mineinabyss.guiy.components.Item
import com.mineinabyss.guiy.components.ItemGrid
import com.mineinabyss.guiy.components.canvases.Chest
import com.mineinabyss.guiy.components.rememberItemGridState
import com.mineinabyss.guiy.inventory.GuiyOwner
import com.mineinabyss.guiy.components.state.ItemPositions
import com.mineinabyss.guiy.inventory.LocalGuiyOwner
import com.mineinabyss.guiy.layout.Row
import com.mineinabyss.guiy.modifiers.Modifier
import com.mineinabyss.guiy.modifiers.clickable
import com.mineinabyss.guiy.modifiers.fillMaxWidth
import com.mineinabyss.guiy.modifiers.size
import kotlinx.coroutines.delay
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
import org.bukkit.inventory.ItemStack

@Composable
fun GuiyOwner.MainMenu(player: Player) {
fun MainMenu(player: Player) {
val owner = LocalGuiyOwner.current
val title = "Hello world"
val state = rememberItemGridState()
Chest(
setOf(player),
title,
onClose = { exit() },
modifier = Modifier.clickable {
if(clickType == ClickType.SHIFT_LEFT) {
cursor = cursor?.let { state.add(it, 4, 1) }
}
}
onClose = { owner.exit() },
) {
ItemGrid(state, Modifier.size(4, 1))
Row {
listOf(Material.DIAMOND, Material.EMERALD, Material.GOLD_INGOT, Material.IRON_INGOT)
.forEach {
CreativeItem(ItemStack(it))
}
Item(Material.BARRIER, "<red>No interaction here", modifier = Modifier.fillMaxWidth())
}
}
}
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pluginManagement {
google()
gradlePluginPortal()
maven("https://repo.mineinabyss.com/releases")
maven("https://repo.mineinabyss.com/snapshots")
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
maven("https://repo.papermc.io/repository/maven-public/")
}
Expand All @@ -22,6 +23,7 @@ dependencyResolutionManagement {

repositories {
maven("https://repo.mineinabyss.com/releases")
maven("https://repo.mineinabyss.com/snapshots")
}

versionCatalogs.create("idofrontLibs").from("com.mineinabyss:catalog:$idofrontVersion")
Expand Down
38 changes: 38 additions & 0 deletions src/main/kotlin/com/mineinabyss/guiy/components/CreativeItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.mineinabyss.guiy.components

import androidx.compose.runtime.Composable
import com.mineinabyss.guiy.modifiers.Modifier
import com.mineinabyss.guiy.modifiers.click.clickable
import org.bukkit.event.inventory.ClickType
import org.bukkit.inventory.ItemStack

/**
* An item that acts like a creative inventory item that can be copied on click.
*/
@Composable
fun CreativeItem(
itemStack: ItemStack?, modifier: Modifier = Modifier
) {
Item(itemStack, modifier.clickable {
// Mimic all vanilla interactions
val shiftClick = clickType == ClickType.SHIFT_LEFT || clickType == ClickType.SHIFT_RIGHT
val result: ItemStack? = when {
(shiftClick || clickType == ClickType.MIDDLE) && cursor == null -> itemStack?.clone()
?.apply { amount = maxStackSize }

clickType == ClickType.MIDDLE -> return@clickable

(clickType == ClickType.SHIFT_LEFT && cursor != null && cursor.isSimilar(itemStack)) ->
cursor.clone().apply { amount = maxStackSize }

cursor == null -> itemStack?.clone()?.apply { amount = 1 }

clickType == ClickType.RIGHT || clickType == ClickType.SHIFT_RIGHT -> cursor.clone().subtract()

(clickType == ClickType.LEFT || clickType == ClickType.SHIFT_LEFT) && !cursor.isSimilar(itemStack) -> null

else -> cursor.clone().add()
}
whoClicked.setItemOnCursor(result)
})
}
4 changes: 4 additions & 0 deletions src/main/kotlin/com/mineinabyss/guiy/components/Grid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import com.mineinabyss.guiy.layout.MeasurePolicy
import com.mineinabyss.guiy.layout.MeasureResult
import com.mineinabyss.guiy.modifiers.Modifier

/**
* A grid layout composable that arranges its children in a grid, left-to-right, top-to-bottom, wrapped
* to the next row when its width is exceeded.
*/
@Composable
fun Grid(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
Layout(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.mineinabyss.guiy.components

import androidx.compose.runtime.*

// TODO implement a component where inventory events are NOT cancelled and state is propagated both ways
// The current system makes it hard to do so safely (without allowing for dupes)
/**
* A grid of items that can be interacted with in an inventory.
*
* @param grid Positions of items in the grid.
* @param onItemsChanged Executes when an item is changed (added, removed, or moved.)
* @param modifier The modifier for the grid.
*/
//@Composable
//fun InteractableItemGrid(
// grid: ItemPositions,
// onItemsChanged: (pos: ItemPositions) -> Unit,
// modifier: Modifier = Modifier,
//) {
// var size by remember { mutableStateOf(Size(0, 0)) }
// Grid(modifier.onSizeChanged { size = it }.draggable {
// //TODO
//// grid.items + updatedItems.map { (i, item) -> IntCoordinates(i) to item }
//// updatedItems.forEach { (i, item) ->
//// cursor!!.amount -= abs(item.amount - (state.items[i]?.amount ?: 0))
//// state.items[i] = item
//// }
// }) {
// for (x in 0 until size.width) {
// for (y in 0 until size.height) {
// val item = grid[x, y]
// Item(item, Modifier.clickable(cancelClickEvent = true) {
// onItemsChanged(grid.with(x, y, resultItem))
// val newItem = when (clickType) {
// ClickType.LEFT -> {
// if (item != null && cursor?.isSimilar(item) == true) {
// val total = (item.amount + (cursor?.amount ?: 0))
// item.amount = total.coerceAtMost(item.maxStackSize)
// cursor?.amount = total - item.amount
// item
// } else {
// val temp = cursor
// cursor = item
// temp
// }
// }
//
// ClickType.RIGHT -> {
// when {
// cursor != null && item != null && cursor!!.type != item.type -> {
// val temp = cursor
// cursor = item
// temp
// }
//
// cursor == null && item != null -> {
// val c = item.clone()
// item.amount /= 2
// cursor = c.apply {
// amount -= item.amount
// }
// item
// }
//
// cursor != null -> {
// val newItem = cursor!!.clone().apply { amount = (item?.amount ?: 0) + 1 }
// cursor!!.amount -= 1
// newItem
// }
//
// else -> return@clickable
// }
// }
//
// else -> return@clickable
// }
// onItemsChanged(grid.with(x, y, newItem))
// })
// }
// }
// }
//}
36 changes: 35 additions & 1 deletion src/main/kotlin/com/mineinabyss/guiy/components/Item.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
package com.mineinabyss.guiy.components

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.mineinabyss.guiy.components.canvases.LocalInventory
import com.mineinabyss.guiy.layout.Layout
import com.mineinabyss.guiy.layout.MeasureResult
import com.mineinabyss.guiy.modifiers.Modifier
import com.mineinabyss.guiy.modifiers.sizeIn
import com.mineinabyss.idofront.items.editItemMeta
import com.mineinabyss.idofront.textcomponents.miniMsg
import org.bukkit.Material
import org.bukkit.inventory.ItemStack

/**
* An item to display in an inventory layout.
*
* @param itemStack The [ItemStack] to display.
*/
@Composable
fun Item(itemStack: ItemStack?, modifier: Modifier = Modifier) {
val canvas = LocalInventory.current
Layout(
measurePolicy = { measurables, constraints ->
measurePolicy = { _, constraints ->
MeasureResult(constraints.minWidth, constraints.minHeight) {}
},
renderer = { node ->
Expand All @@ -24,3 +33,28 @@ fun Item(itemStack: ItemStack?, modifier: Modifier = Modifier) {
modifier = Modifier.sizeIn(minWidth = 1, minHeight = 1).then(modifier)
)
}

/**
* An item to display in an inventory layout.
*
* @param material The [Material] of the item.
* @param title The item's display name (formatted by MiniMesssage).
* @param amount The amount of the item.
* @param lore The item's lore (formatted by MiniMessage).
*/
@Composable
fun Item(
material: Material,
title: String? = null,
amount: Int = 1,
lore: List<String> = listOf(),
modifier: Modifier = Modifier,
) {
val titleMM = remember(title) { title?.miniMsg() }
val loreMM = remember(lore) { lore.map { it.miniMsg() } }

Item(ItemStack(material, amount).editItemMeta {
displayName(titleMM)
lore(loreMM)
}, modifier)
}
Loading

0 comments on commit 1843bfc

Please sign in to comment.