aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/repo/RepoModResourcePack.kt
blob: cd0bc63d0362db7b51ef1215b4de78deae695e18 (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
127
128
129
130
package moe.nea.firmament.repo

import java.io.InputStream
import java.nio.file.Files
import java.nio.file.Path
import java.util.Optional
import net.fabricmc.fabric.api.resource.ModResourcePack
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackSorter
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.server.packs.AbstractPackResources
import net.minecraft.server.packs.resources.IoSupplier
import net.minecraft.server.packs.resources.FallbackResourceManager
import net.minecraft.server.packs.resources.Resource
import net.minecraft.server.packs.PackResources
import net.minecraft.server.packs.PackLocationInfo
import net.minecraft.server.packs.repository.PackSource
import net.minecraft.server.packs.PackType
import net.minecraft.server.packs.resources.ResourceMetadata
import net.minecraft.server.packs.metadata.MetadataSectionType
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.FileUtil
import moe.nea.firmament.Firmament

class RepoModResourcePack(val basePath: Path) : ModResourcePack {
	companion object {
		fun append(packs: ModResourcePackSorter) {
			Firmament.logger.info("Registering mod resource pack")
			packs.addPack(RepoModResourcePack(RepoDownloadManager.repoSavedLocation))
		}

		fun createResourceDirectly(identifier: ResourceLocation): Optional<Resource> {
			val pack = RepoModResourcePack(RepoDownloadManager.repoSavedLocation)
			return Optional.of(
				Resource(
					pack,
					pack.getResource(PackType.CLIENT_RESOURCES, identifier) ?: return Optional.empty()
				) {
					val base =
						pack.getResource(PackType.CLIENT_RESOURCES, identifier.withPath(identifier.path + ".mcmeta"))
					if (base == null)
						ResourceMetadata.EMPTY
					else
						FallbackResourceManager.parseMetadata(base)
				}
			)
		}
	}

	override fun close() {
	}

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

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

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

	override fun listResources(
		type: PackType?,
		namespace: String,
		prefix: String,
		consumer: PackResources.ResourceOutput
	) {
		if (namespace != "neurepo") return
		if (type != PackType.CLIENT_RESOURCES) return

		val prefixPath = basePath.resolve(prefix)
		if (!prefixPath.exists())
			return
		Files.walk(prefixPath)
			.asSequence()
			.map { it.relativeTo(basePath) }
			.forEach {
				consumer.accept(
					ResourceLocation.tryBuild("neurepo", it.toString()) ?: return@forEach,
					IoSupplier.create(it)
				)
			}
	}

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

	override fun <T : Any?> getMetadataSection(metadataSerializer: MetadataSectionType<T>?): T? {
		return AbstractPackResources.getMetadataFromStream(
			metadataSerializer, """
{
    "pack": {
        "pack_format": 12,
        "description": "NEU Repo Resources"
    }
}
""".trimIndent().byteInputStream(), location()
		)
	}


	override fun location(): PackLocationInfo {
		return PackLocationInfo("neurepo", Component.literal("NEU Repo"), PackSource.BUILT_IN, Optional.empty())
	}

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

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