diff --git a/gradle.properties b/gradle.properties index e4934ece5..ead2e85bf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled javaVersion=25 mcVersion=26.1.2 group=dev.slne.surf.api -version=3.17.1 +version=3.17.2 relocationPrefix=dev.slne.surf.api.libs snapshot=false diff --git a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/AbstractSurfView.kt b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/AbstractSurfView.kt index 0723be608..8a40c5718 100644 --- a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/AbstractSurfView.kt +++ b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/AbstractSurfView.kt @@ -9,12 +9,10 @@ import dev.slne.surf.api.paper.inventory.framework.view.container.dsl.addChild import dev.slne.surf.api.paper.inventory.framework.view.container.dsl.backHint import dev.slne.surf.api.paper.inventory.framework.view.settings.SimpleViewSettings import dev.slne.surf.api.paper.inventory.framework.view.settings.SurfViewSettings -import dev.slne.surf.api.paper.inventory.framework.viewFrame import me.devnatan.inventoryframework.View import me.devnatan.inventoryframework.ViewConfigBuilder import me.devnatan.inventoryframework.ViewType import me.devnatan.inventoryframework.context.* -import org.bukkit.plugin.java.JavaPlugin /** * Abstract base class for all Surf inventory views built on top of the inventory framework. @@ -145,7 +143,7 @@ abstract class AbstractSurfView( ViewContainerTitleComponent( title = defaultHeader, font = settings.font, - charSpacing = ViewContainerTitleComponent.Companion.CHAR_SPACING, + charSpacing = ViewContainerTitleComponent.CHAR_SPACING, textAlignment = settings.headerTextAlignment ) ) @@ -183,10 +181,22 @@ abstract class AbstractSurfView( } final override fun onOpen(open: OpenContext) { + recordHistory(open) applyContainerDefaults(open) onViewOpen(open) } + private fun recordHistory(open: OpenContext) { + val player = open.player + val entry = ViewNavigationHistory.NavEntry(javaClass, open.initialData) + + when { + ViewNavigationHistory.consumeBackNavigation(player) -> Unit + open.viewer.isSwitching -> ViewNavigationHistory.pushForward(player, entry) + else -> ViewNavigationHistory.reset(player, entry) + } + } + final override fun onFirstRender(render: RenderContext) { onViewRender(render) } @@ -201,6 +211,10 @@ abstract class AbstractSurfView( } final override fun onClose(close: CloseContext) { + val player = close.player + if (!close.viewer.isSwitching && !ViewNavigationHistory.isPending(player.uniqueId)) { + ViewNavigationHistory.clear(player) + } onViewClose(close) } @@ -209,27 +223,16 @@ abstract class AbstractSurfView( } private fun handleOutsideClick(click: SlotClickContext) { - val viewer = click.viewer - val previousContext = viewer.previousContext + val player = click.player + val target = ViewNavigationHistory.popToPrevious(player) - if (previousContext == null) { + if (target == null) { + ViewNavigationHistory.clear(player) click.closeForPlayer() - } else { - val previousView = previousContext.root - if (previousView !is View) { - click.closeForPlayer() - return - } - - val player = click.player - val previousState = viewer.previousContext.initialData - - viewer.previousContext = null - click.closeForPlayer() - - player.scheduler.run(JavaPlugin.getProvidingPlugin(javaClass), { - viewFrame.open(previousView.javaClass, player, previousState) - }, null) + return } + + ViewNavigationHistory.markBackNavigation(player) + click.openForPlayer(target.viewClass, target.data) } } \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/ViewNavigationHistory.kt b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/ViewNavigationHistory.kt new file mode 100644 index 000000000..0d93a0f9d --- /dev/null +++ b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/ViewNavigationHistory.kt @@ -0,0 +1,41 @@ +package dev.slne.surf.api.paper.inventory.framework.view + +import me.devnatan.inventoryframework.View +import org.bukkit.entity.Player +import java.util.UUID +import java.util.concurrent.ConcurrentHashMap +import kotlin.collections.ArrayDeque + +internal object ViewNavigationHistory { + private val paths = ConcurrentHashMap>() + private val backNav = ConcurrentHashMap.newKeySet() + + private fun deque(player: Player) = paths.computeIfAbsent(player.uniqueId) { ArrayDeque() } + + fun reset(player: Player, entry: NavEntry) { + val deque = deque(player) + deque.clear() + deque.addLast(entry) + } + + fun pushForward(player: Player, entry: NavEntry) = deque(player).addLast(entry) + + fun markBackNavigation(player: Player) = backNav.add(player.uniqueId) + + fun consumeBackNavigation(player: Player) = backNav.remove(player.uniqueId) + + fun popToPrevious(player: Player): NavEntry? { + val deque = paths[player.uniqueId] ?: return null + deque.removeLastOrNull() + return deque.lastOrNull() + } + + fun isPending(uuid: UUID): Boolean = backNav.contains(uuid) + + fun clear(player: Player) { + paths.remove(player.uniqueId) + backNav.remove(player.uniqueId) + } + + internal data class NavEntry(val viewClass: Class, val data: Any?) +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/pagination/AbstractPaginatedSurfView.kt b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/pagination/AbstractPaginatedSurfView.kt index 60f4977e6..767e6fe54 100644 --- a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/pagination/AbstractPaginatedSurfView.kt +++ b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/inventory/framework/view/pagination/AbstractPaginatedSurfView.kt @@ -1,8 +1,5 @@ package dev.slne.surf.api.paper.inventory.framework.view.pagination -import com.github.shynixn.mccoroutine.folia.entityDispatcher -import com.github.shynixn.mccoroutine.folia.launch -import com.github.shynixn.mccoroutine.folia.ticks import dev.slne.surf.api.core.util.prepend import dev.slne.surf.api.paper.inventory.framework.view.AbstractSurfView import dev.slne.surf.api.paper.inventory.framework.view.container.dsl.ViewContainerModificationContext @@ -10,7 +7,6 @@ import dev.slne.surf.api.paper.inventory.framework.view.container.dsl.addChild import dev.slne.surf.api.paper.inventory.framework.view.container.dsl.blockCell import dev.slne.surf.api.paper.inventory.framework.view.container.dsl.removeChildrenOfType import dev.slne.surf.api.paper.inventory.framework.view.settings.PaginatedViewSettings -import kotlinx.coroutines.delay import me.devnatan.inventoryframework.ViewConfigBuilder import me.devnatan.inventoryframework.component.BukkitItemComponentBuilder import me.devnatan.inventoryframework.component.Pagination @@ -190,7 +186,13 @@ abstract class AbstractPaginatedSurfView(header: String) : AbstractSurfView(head val pagination = paginationState.get(render) ?: return val paginationButtonRow = settings.paginationButtonRow - render.watchState(pagination.id, InitialPaginationStateWatcher()) + if (pagination.isStatic) { + render.player.scheduler.run(JavaPlugin.getProvidingPlugin(javaClass), { + updatePaginationGlyph(render) + }, null) + } else { + render.watchState(pagination.id, InitialPaginationStateWatcher()) + } render.slot(PaginationButton.LEFT.clickSlot(paginationButtonRow)) .withItem(ItemStack.empty()) @@ -217,6 +219,11 @@ abstract class AbstractPaginatedSurfView(header: String) : AbstractSurfView(head final override fun onViewUpdate(update: Context) { + val pagination = paginationState.get(update) + if (pagination != null) { + pagination.switchTo(pagination.currentPageIndex()) // trigger pagination state update to refresh dynamic elements + } + onPaginatedUpdate(update) } @@ -244,11 +251,9 @@ abstract class AbstractPaginatedSurfView(header: String) : AbstractSurfView(head if (!initialHandled.compareAndSet(false, true)) return if (host !is Context) return - val plugin = JavaPlugin.getProvidingPlugin(javaClass) - plugin.launch(plugin.entityDispatcher(host.player)) { - delay(1.ticks) + host.player.scheduler.run(JavaPlugin.getProvidingPlugin(javaClass), { updatePaginationGlyph(host) - } + }, null) } }