1717
1818package com.lambda.interaction.construction
1919
20+ import com.lambda.Lambda.LOG
2021import com.lambda.core.Loadable
21- import com.lambda.util.Communication.logError
2222import com.lambda.util.FolderRegister
23+ import com.lambda.util.FolderRegister.structure
2324import com.lambda.util.extension.readLitematicaOrException
2425import com.lambda.util.extension.readNbtOrException
2526import com.lambda.util.extension.readSchematicOrException
@@ -45,10 +46,10 @@ import kotlin.io.path.*
4546 */
4647@OptIn(ExperimentalPathApi ::class )
4748@Suppress(" JavaIoSerializableObjectMustHaveReadResolve" )
48- object StructureRegistry : ConcurrentHashMap<String, StructureTemplate? >(), Loadable {
49+ object StructureRegistry : ConcurrentHashMap<String, StructureTemplate>(), Loadable {
4950 private val pathWatcher by lazy {
5051 FileSystems .getDefault().newWatchService()
51- .apply { FolderRegister . structure.register(this , ENTRY_CREATE , ENTRY_DELETE ) }
52+ .apply { structure.register(this , ENTRY_CREATE , ENTRY_DELETE ) }
5253 }
5354
5455 /* *
@@ -69,12 +70,13 @@ object StructureRegistry : ConcurrentHashMap<String, StructureTemplate?>(), Load
6970 *
7071 * @param relativePath The name of the structure to load (without extension).
7172 * @param convert Whether to replace the file after converting it.
72- * @return The loaded [StructureTemplate], or null if the structure is not found.
73+ *
74+ * @throws IllegalStateException if there was an error while parsing the data
7375 */
7476 fun loadStructureByRelativePath (
7577 relativePath : Path ,
7678 convert : Boolean = true,
77- ): StructureTemplate ? {
79+ ): StructureTemplate {
7880 updateFileWatcher()
7981
8082 return computeIfAbsent(relativePath.pathString.lowercase()) {
@@ -115,52 +117,49 @@ object StructureRegistry : ConcurrentHashMap<String, StructureTemplate?>(), Load
115117 * Loads the structure file and creates a [StructureTemplate].
116118 *
117119 * @param convert Whether to replace the file after converting it.
120+ * @throws IllegalStateException if the parsed data is corrupted
121+ *
118122 * @return The created [StructureTemplate], or null if the structure is not found or invalid.
119123 */
120124 private fun loadFileAndCreate (path : Path , convert : Boolean ) =
121- FolderRegister . structure.resolve(path).inputStream().use { templateStream ->
125+ structure.resolve(path).inputStream().use { templateStream ->
122126 val compound = NbtIo .readCompressed(templateStream, NbtSizeTracker .ofUnlimitedBytes())
123127 val extension = path.extension
124128 val template = createStructure(compound, extension)
125129
126130 if (convert && extension != " nbt" ) {
127- template?. let { saveStructure(path.pathString, it) }
131+ saveStructure(path.nameWithoutExtension, template)
128132 }
129133
130134 // Verify the structure integrity after it had been
131135 // converted to a regular structure template
132- if (compound.isValidStructureTemplate()) {
133- template
134- } else {
135- logError(" Corrupted structure file: ${path.pathString} " )
136- null
137- }
136+ if (compound.isValidStructureTemplate()) template
137+ else throw IllegalStateException (" Corrupted structure file: ${path.pathString} " )
138138 }
139139
140140 /* *
141141 * Creates a [StructureTemplate] from the provided NBT data.
142142 *
143143 * @param nbt The [NbtCompound] containing the structure's data.
144- * @return The created [StructureTemplate], or null if there was an error.
144+ * @throws IllegalStateException if there was an error while parsing the data
145145 */
146- private fun createStructure (nbt : NbtCompound , suffix : String ): StructureTemplate ? =
146+ private fun createStructure (nbt : NbtCompound , suffix : String ): StructureTemplate =
147147 StructureTemplate ().apply {
148148 serializers[suffix]
149149 ?.invoke(this , Registries .BLOCK .readOnlyWrapper, nbt)
150150 ?.let { error ->
151- logError(" Could not create structure from file: ${error.message} " )
152- return null
151+ throw IllegalStateException (" Could not create structure: ${error.message} " )
153152 }
154153 }
155154
156155 /* *
157156 * Saves the provided [structure] to disk under the specified [name].
158157 *
159- * @param relativePath The relative path of the structure to save.
158+ * @param relativePath The relative path of the structure to save without the extension .
160159 * @param structure The [StructureTemplate] to save.
161160 */
162161 private fun saveStructure (relativePath : String , structure : StructureTemplate ) {
163- val path = FolderRegister .structure.resolve(relativePath)
162+ val path = FolderRegister .structure.resolve(" $ relativePath.nbt " )
164163 val compound = structure.writeNbt(NbtCompound ())
165164
166165 Files .createDirectories(path.parent)
@@ -179,9 +178,13 @@ object StructureRegistry : ConcurrentHashMap<String, StructureTemplate?>(), Load
179178 contains(" DataVersion" ) && contains(" blocks" ) && contains(" palette" ) && contains(" size" )
180179
181180 override fun load (): String {
182- FolderRegister .structure.walk()
183- .filter { it.extension in serializers.keys }
184- .forEach { loadStructureByRelativePath(FolderRegister .structure.relativize(it)) }
181+ runCatching {
182+ structure.walk()
183+ .filter { it.extension in serializers.keys }
184+ .sortedBy { it.extension.length } // Don’t walk lexicographically -Constructor
185+ .distinctBy { it.nameWithoutExtension }
186+ .forEach { loadStructureByRelativePath(structure.relativize(it)) }
187+ }.onFailure { LOG .warn(it.message) }
185188
186189 return " Loaded $size structure templates"
187190 }
0 commit comments