mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 03:44:54 -04:00
wip block state loading, wip texture resolving
This commit is contained in:
parent
41d7001389
commit
f6ef634b69
@ -15,13 +15,10 @@ package de.bixilon.minosoft.gui.rendering.models
|
||||
|
||||
import de.bixilon.kotlinglm.vec2.Vec2
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kutil.reflection.ReflectionUtil.forceSet
|
||||
import de.bixilon.minosoft.assets.MemoryAssetsManager
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader.Companion.model
|
||||
import de.bixilon.minosoft.gui.rendering.models.ModelTestUtil.createAssets
|
||||
import de.bixilon.minosoft.gui.rendering.models.ModelTestUtil.createLoader
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.BlockModel
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.element.ModelElement
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.element.face.FaceUV
|
||||
@ -30,32 +27,18 @@ import de.bixilon.minosoft.gui.rendering.models.raw.display.DisplayPositions
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.light.GUILights
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
import de.bixilon.minosoft.test.IT.OBJENESIS
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import org.testng.Assert.assertEquals
|
||||
import org.testng.annotations.Test
|
||||
|
||||
@Test(groups = ["models"])
|
||||
class BlockModelTest {
|
||||
|
||||
private fun createLoader(): ModelLoader {
|
||||
val instance = OBJENESIS.newInstance(ModelLoader::class.java)
|
||||
instance::block.forceSet(OBJENESIS.newInstance(BlockLoader::class.java))
|
||||
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
private fun loadModel(json: String, files: Map<String, String> = emptyMap()): BlockModel {
|
||||
val loader = createLoader()
|
||||
|
||||
val assets = MemoryAssetsManager()
|
||||
val assets = loader.createAssets(files)
|
||||
assets.push(minosoft("models/block/named.json"), json)
|
||||
|
||||
for ((name, value) in files) {
|
||||
assets.push(name.toResourceLocation().model(), value)
|
||||
}
|
||||
loader.block::assets.forceSet(assets)
|
||||
|
||||
return loader.block.loadBlock(minosoft("block/named"))
|
||||
}
|
||||
|
@ -15,16 +15,37 @@ package de.bixilon.minosoft.gui.rendering.models
|
||||
|
||||
import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
||||
import de.bixilon.kutil.collections.CollectionUtil.extend
|
||||
import de.bixilon.kutil.reflection.ReflectionUtil.forceSet
|
||||
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.building.WoolBlock
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.legacy.CustomBlockModel
|
||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||
import de.bixilon.minosoft.gui.rendering.models.ModelTestUtil.createAssets
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader.Companion.blockState
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.BlockModel
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.state.DirectBlockModel
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.state.apply.BlockStateModel
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.state.variant.SingleVariantBlockModel
|
||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||
import de.bixilon.minosoft.protocol.versions.Version
|
||||
import de.bixilon.minosoft.test.IT
|
||||
import org.testng.Assert.assertEquals
|
||||
import org.testng.annotations.Test
|
||||
|
||||
@Test(groups = ["models"])
|
||||
class BlockStateModelTest {
|
||||
|
||||
private fun loadModel(state: String, files: Map<String, String>): DirectBlockModel = TODO()
|
||||
private fun loadModel(block: Block, state: String, version: Version = IT.VERSION, files: Map<String, String>): DirectBlockModel {
|
||||
val loader = ModelTestUtil.createLoader()
|
||||
loader.block::version.forceSet(version)
|
||||
val assets = loader.createAssets(files)
|
||||
val modelName = (if (block is CustomBlockModel) block.getModelName(version) else block.identifier)?.blockState() ?: throw NullPointerException("Can not get model name: $block")
|
||||
assets.push(modelName, state)
|
||||
|
||||
|
||||
return loader.block.loadState(block) ?: throw NullPointerException("empty block model!")
|
||||
}
|
||||
|
||||
|
||||
fun redWool() {
|
||||
@ -32,14 +53,36 @@ class BlockStateModelTest {
|
||||
val models = BlockModelTest.FILES.extend<String, String>(
|
||||
"block/red_wool" to """{"parent":"minecraft:block/cube_all","textures":{"all":"minecraft:block/red_wool"}}""",
|
||||
)
|
||||
val model = loadModel(state, models)
|
||||
val model = loadModel(WoolBlock.RedWool(settings = BlockSettings()), state, files = models)
|
||||
val texture = minecraft("block/red_wool").texture()
|
||||
|
||||
assertEquals(model.unsafeCast<SingleVariantBlockModel>().apply, BlockStateModel(
|
||||
model = BlockModelTest.CUBE_ALL_MODEL,
|
||||
model = BlockModel(
|
||||
BlockModelTest.CUBE_ALL_MODEL.guiLight,
|
||||
BlockModelTest.CUBE_ALL_MODEL.display,
|
||||
BlockModelTest.CUBE_ALL_MODEL.elements,
|
||||
textures = mapOf(
|
||||
"particle" to texture,
|
||||
"down" to texture,
|
||||
"up" to texture,
|
||||
"north" to texture,
|
||||
"east" to texture,
|
||||
"south" to texture,
|
||||
"west" to texture,
|
||||
"all" to texture,
|
||||
),
|
||||
BlockModelTest.CUBE_ALL_MODEL.ambientOcclusion,
|
||||
),
|
||||
x = 0,
|
||||
y = 0,
|
||||
uvLock = false,
|
||||
weight = 1,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
// TODO: simple, variants, pre-flattening variants (e.g. grass snowy), multipart, multipart pre-flattening
|
||||
// TODO: model rename (silver wool vs light_gray_wool)
|
||||
|
||||
// TODO: bakery
|
||||
}
|
||||
|
@ -13,9 +13,32 @@
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.models
|
||||
|
||||
import de.bixilon.kutil.reflection.ReflectionUtil.forceSet
|
||||
import de.bixilon.minosoft.assets.MemoryAssetsManager
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader.Companion.model
|
||||
import de.bixilon.minosoft.test.IT
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
|
||||
object ModelTestUtil {
|
||||
|
||||
fun createAssets(vararg files: Pair<String, String>) {
|
||||
fun createLoader(): ModelLoader {
|
||||
val instance = IT.OBJENESIS.newInstance(ModelLoader::class.java)
|
||||
instance::block.forceSet(IT.OBJENESIS.newInstance(BlockLoader::class.java))
|
||||
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
fun ModelLoader.createAssets(files: Map<String, String>): MemoryAssetsManager {
|
||||
val assets = MemoryAssetsManager()
|
||||
|
||||
for ((name, value) in files) {
|
||||
assets.push(name.toResourceLocation().model(), value)
|
||||
}
|
||||
this.block::assets.forceSet(assets)
|
||||
|
||||
return assets
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.models.loader
|
||||
|
||||
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
|
||||
import de.bixilon.kutil.latch.CountUpAndDownLatch
|
||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readJsonObject
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
@ -27,7 +26,6 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
class BlockLoader(private val loader: ModelLoader) {
|
||||
val assets = loader.context.connection.assetsManager
|
||||
val version = loader.context.connection.version
|
||||
private val cache: MutableMap<ResourceLocation, BlockModel> = synchronizedMapOf()
|
||||
|
||||
fun loadBlock(name: ResourceLocation): BlockModel {
|
||||
val file = name.model("block/")
|
||||
@ -39,11 +37,11 @@ class BlockLoader(private val loader: ModelLoader) {
|
||||
return BlockModel.deserialize(parent, data)
|
||||
}
|
||||
|
||||
private fun loadState(block: Block) {
|
||||
val file = (if (block is CustomBlockModel) block.getModelName(version) else block.identifier)?.blockState() ?: return
|
||||
fun loadState(block: Block): DirectBlockModel? {
|
||||
val file = (if (block is CustomBlockModel) block.getModelName(version) else block.identifier)?.blockState() ?: return null
|
||||
val data = assets[file].readJsonObject()
|
||||
|
||||
val model = DirectBlockModel.deserialize(this, data)
|
||||
return DirectBlockModel.deserialize(this, data)
|
||||
}
|
||||
|
||||
fun load(latch: CountUpAndDownLatch) {
|
||||
@ -53,7 +51,7 @@ class BlockLoader(private val loader: ModelLoader) {
|
||||
|
||||
companion object {
|
||||
|
||||
private fun ResourceLocation.blockState(): ResourceLocation {
|
||||
fun ResourceLocation.blockState(): ResourceLocation {
|
||||
return ResourceLocation(this.namespace, "blockstates/" + this.path + ".json")
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,15 @@ import de.bixilon.minosoft.gui.rendering.models.raw.block.element.ModelElement
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.DisplayPositions
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.light.GUILights
|
||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import java.util.*
|
||||
|
||||
data class BlockModel(
|
||||
val guiLight: GUILights,
|
||||
val display: Map<DisplayPositions, ModelDisplay>?,
|
||||
val elements: List<ModelElement>?,
|
||||
val textures: Map<String, String>?,
|
||||
val textures: Map<String, Any>?, // either String or ResourceLocation
|
||||
val ambientOcclusion: Boolean,
|
||||
) {
|
||||
|
||||
@ -62,16 +64,41 @@ data class BlockModel(
|
||||
return elements
|
||||
}
|
||||
|
||||
private fun textures(data: JsonObject, parent: Map<String, String>?): Map<String, String>? {
|
||||
private fun textures(data: JsonObject, parent: Map<String, Any>?): Map<String, Any>? {
|
||||
if (data.isEmpty()) return parent
|
||||
|
||||
val textures: MutableMap<String, String> = parent?.toMutableMap() ?: mutableMapOf()
|
||||
val textures: MutableMap<String, Any> = parent?.toMutableMap() ?: mutableMapOf()
|
||||
|
||||
for ((name, value) in data) {
|
||||
textures[name] = value.toString()
|
||||
val string = value.toString()
|
||||
if (!string.startsWith('#')) {
|
||||
// not a variable
|
||||
textures[name] = string.toResourceLocation().texture()
|
||||
} else {
|
||||
textures[name] = string.substring(1)
|
||||
}
|
||||
}
|
||||
|
||||
return textures
|
||||
return textures.resolveTextures()
|
||||
}
|
||||
|
||||
private fun Map<String, Any>.resolve(value: Any, output: MutableMap<String, Any>): Any {
|
||||
if (value !is String) return value // texture identifier
|
||||
val resolved = this[value] ?: return value
|
||||
output[value] = resolved // cache result, even if not needed
|
||||
return resolved
|
||||
}
|
||||
|
||||
private fun Map<String, Any>.resolveTextures(): Map<String, Any> {
|
||||
if (size <= 1) return this // if it has just one element, we can not resolve anything
|
||||
|
||||
val output: MutableMap<String, Any> = mutableMapOf()
|
||||
|
||||
for ((entry, value) in this) {
|
||||
output[entry] = resolve(value, output)
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
fun deserialize(parent: BlockModel?, data: JsonObject): BlockModel {
|
||||
|
Loading…
x
Reference in New Issue
Block a user