aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/repo/RepoModResourcePack.kt
blob: f92fe4f447d8f7e9767395bc47d9166ce6109566 (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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package moe.nea.firmament.repo

import java.io.InputStream
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
import net.fabricmc.fabric.api.resource.ModResourcePack
import net.fabricmc.loader.api.FabricLoader
import net.fabricmc.loader.api.metadata.ModMetadata
import kotlin.io.path.exists
import kotlin.io.path.isRegularFile
import kotlin.io.path.relativeTo
import kotlin.streams.asSequence
import net.minecraft.resource.AbstractFileResourcePack
import net.minecraft.resource.InputSupplier
import net.minecraft.resource.NamespaceResourceManager
import net.minecraft.resource.Resource
import net.minecraft.resource.ResourcePack
import net.minecraft.resource.ResourcePackInfo
import net.minecraft.resource.ResourcePackSource
import net.minecraft.resource.ResourceType
import net.minecraft.resource.metadata.ResourceMetadata
import net.minecraft.resource.metadata.ResourceMetadataReader
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.util.PathUtil
import moe.nea.firmament.Firmament

class RepoModResourcePack(val basePath: Path) : ModResourcePack {
    companion object {
        fun append(packs: MutableList<in ModResourcePack>) {
            Firmament.logger.info("Registering mod resource pack")
            packs.add(RepoModResourcePack(RepoDownloadManager.repoSavedLocation))
        }

        fun createResourceDirectly(identifier: Identifier): Optional<Resource> {
            val pack = RepoModResourcePack(RepoDownloadManager.repoSavedLocation)
            return Optional.of(
                Resource(
                    pack,
                    pack.open(ResourceType.CLIENT_RESOURCES, identifier) ?: return Optional.empty()
                ) {
                    val base =
                        pack.open(ResourceType.CLIENT_RESOURCES, identifier.withPath(identifier.path + ".mcmeta"))
                    if (base == null)
                        ResourceMetadata.NONE
                    else
                        NamespaceResourceManager.loadMetadata(base)
                }
            )
        }
    }

    override fun close() {
    }

    override fun openRoot(vararg segments: String): InputSupplier<InputStream>? {
        return getFile(segments)?.let { InputSupplier.create(it) }
    }

    fun getFile(segments: Array<out String>): Path? {
        PathUtil.validatePath(*segments)
        val path = segments.fold(basePath, Path::resolve)
        if (!path.isRegularFile()) return null
        return path
    }

    override fun open(type: ResourceType?, id: Identifier): InputSupplier<InputStream>? {
        if (type != ResourceType.CLIENT_RESOURCES) return null
        if (id.namespace != "neurepo") return null
        val file = getFile(id.path.split("/").toTypedArray())
        return file?.let { InputSupplier.create(it) }
    }

    override fun findResources(
        type: ResourceType?,
        namespace: String,
        prefix: String,
        consumer: ResourcePack.ResultConsumer
    ) {
        if (namespace != "neurepo") return
        if (type != ResourceType.CLIENT_RESOURCES) return

        val prefixPath = basePath.resolve(prefix)
        if (!prefixPath.exists())
            return
        Files.walk(prefixPath)
            .asSequence()
            .map { it.relativeTo(basePath) }
            .forEach {
                consumer.accept(Identifier.of("neurepo", it.toString()), InputSupplier.create(it))
            }
    }

    override fun getNamespaces(type: ResourceType?): Set<String> {
        if (type != ResourceType.CLIENT_RESOURCES) return emptySet()
        return setOf("neurepo")
    }

    override fun <T> parseMetadata(metaReader: ResourceMetadataReader<T>): T? {
        return AbstractFileResourcePack.parseMetadata(
            metaReader, """
{
    "pack": {
        "pack_format": 12,
        "description": "NEU Repo Resources"
    }
}
""".trimIndent().byteInputStream()
        )
    }

    override fun getInfo(): ResourcePackInfo {
        return ResourcePackInfo("neurepo", Text.literal("NEU Repo"), ResourcePackSource.BUILTIN, Optional.empty())
    }

    override fun getFabricModMetadata(): ModMetadata {
        return FabricLoader.getInstance().getModContainer("firmament")
            .get().metadata
    }

    override fun createOverlay(overlay: String): ModResourcePack {
        return RepoModResourcePack(basePath.resolve(overlay))
    }
}