aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/repo/RepoModResourcePack.kt
blob: 810e2a4abf8b5eb073216bb3f07c4ae4e3117ff2 (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
/*
 * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

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.ResourceType
import net.minecraft.resource.metadata.ResourceMetadata
import net.minecraft.resource.metadata.ResourceMetadataReader
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 getName(): String {
        return "NEU Repo Resources"
    }

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