aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt
blob: 5c1ac3499a989e88606f7d3f4b53663af60beb9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@file:OptIn(ExperimentalContracts::class)

package moe.nea.firmament.features.inventory.storageoverlay

import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
import net.minecraft.screen.GenericContainerScreenHandler
import moe.nea.firmament.util.ifMatches
import moe.nea.firmament.util.unformattedString

/**
 * A handle representing the state of the "server side" screens.
 */
sealed interface StorageBackingHandle {

    sealed interface HasBackingScreen {
        val handler: GenericContainerScreenHandler
    }

    /**
     * The main storage overview is open. Clicking on a slot will open that page. This page is accessible via `/storage`
     */
    data class Overview(override val handler: GenericContainerScreenHandler) : StorageBackingHandle, HasBackingScreen

    /**
     * An individual storage page is open. This may be a backpack or an enderchest page. This page is accessible via
     * the [Overview] or via `/ec <index + 1>` for enderchest pages.
     */
    data class Page(override val handler: GenericContainerScreenHandler, val storagePageSlot: StoragePageSlot) :
        StorageBackingHandle, HasBackingScreen

    companion object {
        private val enderChestName = "^Ender Chest \\(([1-9])/[1-9]\\)$".toRegex()
        private val backPackName = "^.+Backpack \\(Slot #([0-9]+)\\)$".toRegex()

        /**
         * Parse a screen into a [StorageBackingHandle]. If this returns null it means that the screen is not
         * representable as a [StorageBackingHandle], meaning another screen is open, for example the enderchest icon
         * selection screen.
         */
        fun fromScreen(screen: Screen?): StorageBackingHandle? {
	        contract {
		        returnsNotNull() implies (screen != null)
	        }
            if (screen == null) return null
            if (screen !is GenericContainerScreen) return null
            val title = screen.title.unformattedString
            if (title == "Storage") return Overview(screen.screenHandler)
            return title.ifMatches(enderChestName) {
                Page(screen.screenHandler, StoragePageSlot.ofEnderChestPage(it.groupValues[1].toInt()))
            } ?: title.ifMatches(backPackName) {
                Page(screen.screenHandler, StoragePageSlot.ofBackPackPage(it.groupValues[1].toInt()))
            }
        }
    }
}