Skip to content

Commit 7eacafc

Browse files
committed
feat: StructureRegistry
1 parent ecb0418 commit 7eacafc

File tree

5 files changed

+106
-43
lines changed

5 files changed

+106
-43
lines changed

common/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,12 @@ import com.lambda.brigadier.CommandResult
44
import com.lambda.brigadier.argument.identifier
55
import com.lambda.brigadier.argument.literal
66
import com.lambda.brigadier.argument.value
7-
import com.lambda.brigadier.execute
87
import com.lambda.brigadier.executeWithResult
98
import com.lambda.brigadier.required
109
import com.lambda.command.LambdaCommand
11-
import com.lambda.interaction.construction.Blueprint.Companion.toStructure
12-
import com.lambda.interaction.construction.DynamicBlueprint.Companion.toBlueprint
13-
import com.lambda.interaction.construction.StructureManager
14-
import com.lambda.interaction.construction.StructureManager.templateManager
15-
import com.lambda.interaction.construction.verify.TargetState
16-
import com.lambda.task.tasks.BuildTask.Companion.build
17-
import com.lambda.threading.runSafe
10+
import com.lambda.interaction.construction.StructureRegistry
1811
import com.lambda.util.Communication.info
1912
import com.lambda.util.extension.CommandBuilder
20-
import net.minecraft.block.Blocks
21-
import net.minecraft.util.Identifier
22-
import net.minecraft.util.math.BlockBox
2313

2414
object BuildCommand : LambdaCommand(
2515
name = "Build",
@@ -30,16 +20,20 @@ object BuildCommand : LambdaCommand(
3020
required(literal("place")) {
3121
required(identifier("structure")) { structure ->
3222
suggests { _, builder ->
33-
templateManager.streamTemplates().forEach {
34-
builder.suggest(it.path)
35-
}
23+
StructureRegistry.keys
24+
.forEach { builder.suggest(it.path) }
25+
3626
builder.buildFuture()
3727
}
28+
3829
executeWithResult {
39-
templateManager.getTemplate(structure().value()).ifPresent { template ->
40-
info("Building structure: ${template.size} author: ${template.author}")
30+
StructureRegistry.loadStructure(structure().value())?.let { template ->
31+
info("Building structure: ${template.size}")
32+
33+
return@executeWithResult CommandResult.success()
4134
}
42-
CommandResult.success()
35+
36+
CommandResult.failure("Structure not found")
4337
}
4438

4539
// execute {
@@ -68,4 +62,4 @@ object BuildCommand : LambdaCommand(
6862
}
6963
}
7064
}
71-
}
65+
}

common/src/main/kotlin/com/lambda/core/Loader.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.lambda.gui.GuiConfigurable
1010
import com.lambda.gui.HudGuiConfigurable
1111
import com.lambda.interaction.PlayerPacketManager
1212
import com.lambda.interaction.RotationManager
13-
import com.lambda.interaction.construction.StructureManager
1413
import com.lambda.interaction.material.ContainerManager
1514
import com.lambda.module.ModuleRegistry
1615
import com.lambda.sound.SoundRegistry
@@ -39,7 +38,6 @@ object Loader {
3938
TimerManager,
4039
PingManager,
4140
ContainerManager,
42-
StructureManager
4341
)
4442

4543
fun initialize() {

common/src/main/kotlin/com/lambda/interaction/construction/StructureManager.kt

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.lambda.interaction.construction
2+
3+
import com.lambda.Lambda.mc
4+
import com.lambda.util.Communication.logError
5+
import com.lambda.util.FolderRegister
6+
import com.lambda.util.extension.readNbtOrException
7+
import net.minecraft.datafixer.DataFixTypes
8+
import net.minecraft.nbt.NbtCompound
9+
import net.minecraft.nbt.NbtHelper
10+
import net.minecraft.nbt.NbtIo
11+
import net.minecraft.nbt.NbtSizeTracker
12+
import net.minecraft.registry.Registries
13+
import net.minecraft.structure.StructureTemplate
14+
import net.minecraft.util.Identifier
15+
import net.minecraft.util.PathUtil
16+
import net.minecraft.util.WorldSavePath
17+
import java.nio.file.Files
18+
import java.nio.file.LinkOption
19+
import java.nio.file.StandardOpenOption
20+
import java.util.concurrent.ConcurrentHashMap
21+
import kotlin.io.path.inputStream
22+
import kotlin.io.path.notExists
23+
24+
@Suppress("JavaIoSerializableObjectMustHaveReadResolve")
25+
object StructureRegistry : ConcurrentHashMap<Identifier, StructureTemplate?>() {
26+
private val levelSession = mc.levelStorage.createSession(FolderRegister.structure.path)
27+
private val generatedPath = levelSession.getDirectory(WorldSavePath.ROOT).normalize()
28+
29+
/**
30+
* Loads a structure from disk based on the provided [id].
31+
*
32+
* @param id The identifier of the structure to load.
33+
* @return The loaded [StructureTemplate], or null if the structure is not found.
34+
*/
35+
fun loadStructure(id: Identifier): StructureTemplate? {
36+
val path = PathUtil.getResourcePath(generatedPath, id.path, ".nbt")
37+
38+
return if (!Files.isDirectory(generatedPath, LinkOption.NOFOLLOW_LINKS) || path.notExists()) null
39+
else computeIfAbsent(id) {
40+
val compound = path.inputStream(StandardOpenOption.READ)
41+
.use { template ->
42+
NbtIo.readCompressed(
43+
template,
44+
NbtSizeTracker.ofUnlimitedBytes()
45+
).also { template.close() }
46+
}
47+
48+
createStructure(nbt = compound)
49+
}
50+
}
51+
52+
/**
53+
* Creates a [StructureTemplate] from the provided NBT data.
54+
*
55+
* @param nbt The [NbtCompound] containing the structure's data.
56+
* @return The created [StructureTemplate], or null if there was an error.
57+
*/
58+
private fun createStructure(nbt: NbtCompound): StructureTemplate? {
59+
val template = StructureTemplate()
60+
val version = NbtHelper.getDataVersion(nbt, 500)
61+
62+
template.readNbtOrException(
63+
Registries.BLOCK.readOnlyWrapper,
64+
DataFixTypes.STRUCTURE.update(mc.dataFixer, nbt, version),
65+
)?.let { err ->
66+
this@StructureRegistry.logError("Could not create structure from file", err.message ?: "")
67+
return null
68+
}
69+
70+
return template
71+
}
72+
73+
/**
74+
* Saves the provided [structure] to disk under the specified [name].
75+
*
76+
* @param name The name of the structure file (without the ".nbt" extension).
77+
* @param structure The [StructureTemplate] to save.
78+
*/
79+
fun saveStructure(name: String, structure: StructureTemplate) {
80+
val path = PathUtil.getResourcePath(generatedPath, name, ".nbt")
81+
val compound = structure.writeNbt(NbtCompound())
82+
83+
NbtIo.writeCompressed(compound, path)
84+
}
85+
}

common/src/main/kotlin/com/lambda/util/extension/World.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import com.lambda.util.world.FastVector
44
import com.lambda.util.world.x
55
import com.lambda.util.world.y
66
import com.lambda.util.world.z
7+
import net.minecraft.block.Block
78
import net.minecraft.block.BlockState
89
import net.minecraft.block.Blocks
910
import net.minecraft.fluid.FluidState
1011
import net.minecraft.fluid.Fluids
12+
import net.minecraft.nbt.NbtCompound
13+
import net.minecraft.registry.RegistryEntryLookup
14+
import net.minecraft.structure.StructureTemplate
1115
import net.minecraft.world.World
1216

1317
fun World.getBlockState(x: Int, y: Int, z: Int): BlockState {
@@ -34,3 +38,8 @@ fun World.getFluidState(x: Int, y: Int, z: Int): FluidState {
3438

3539
fun World.getBlockState(vec: FastVector): BlockState = getBlockState(vec.x, vec.y, vec.z)
3640
fun World.getFluidState(vec: FastVector): FluidState = getFluidState(vec.x, vec.y, vec.z)
41+
42+
fun StructureTemplate.readNbtOrException(
43+
lookup: RegistryEntryLookup<Block>,
44+
nbt: NbtCompound,
45+
): Throwable? = runCatching { readNbt(lookup, nbt) }.exceptionOrNull()

0 commit comments

Comments
 (0)