mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 20:05:02 -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.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec3.Vec3
|
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.direction.Directions
|
||||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
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.ModelTestUtil.createAssets
|
||||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader
|
import de.bixilon.minosoft.gui.rendering.models.ModelTestUtil.createLoader
|
||||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader.Companion.model
|
|
||||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.BlockModel
|
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.ModelElement
|
||||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.element.face.FaceUV
|
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.display.ModelDisplay
|
||||||
import de.bixilon.minosoft.gui.rendering.models.raw.light.GUILights
|
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.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.Assert.assertEquals
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
@Test(groups = ["models"])
|
@Test(groups = ["models"])
|
||||||
class BlockModelTest {
|
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 {
|
private fun loadModel(json: String, files: Map<String, String> = emptyMap()): BlockModel {
|
||||||
val loader = createLoader()
|
val loader = createLoader()
|
||||||
|
val assets = loader.createAssets(files)
|
||||||
val assets = MemoryAssetsManager()
|
|
||||||
assets.push(minosoft("models/block/named.json"), json)
|
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"))
|
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.cast.CastUtil.unsafeCast
|
||||||
import de.bixilon.kutil.collections.CollectionUtil.extend
|
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.DirectBlockModel
|
||||||
import de.bixilon.minosoft.gui.rendering.models.raw.block.state.apply.BlockStateModel
|
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.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.Assert.assertEquals
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
@Test(groups = ["models"])
|
@Test(groups = ["models"])
|
||||||
class BlockStateModelTest {
|
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() {
|
fun redWool() {
|
||||||
@ -32,14 +53,36 @@ class BlockStateModelTest {
|
|||||||
val models = BlockModelTest.FILES.extend<String, String>(
|
val models = BlockModelTest.FILES.extend<String, String>(
|
||||||
"block/red_wool" to """{"parent":"minecraft:block/cube_all","textures":{"all":"minecraft:block/red_wool"}}""",
|
"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(
|
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,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
uvLock = false,
|
uvLock = false,
|
||||||
weight = 1,
|
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
|
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 {
|
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
|
package de.bixilon.minosoft.gui.rendering.models.loader
|
||||||
|
|
||||||
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
|
|
||||||
import de.bixilon.kutil.latch.CountUpAndDownLatch
|
import de.bixilon.kutil.latch.CountUpAndDownLatch
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readJsonObject
|
import de.bixilon.minosoft.assets.util.InputStreamUtil.readJsonObject
|
||||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
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) {
|
class BlockLoader(private val loader: ModelLoader) {
|
||||||
val assets = loader.context.connection.assetsManager
|
val assets = loader.context.connection.assetsManager
|
||||||
val version = loader.context.connection.version
|
val version = loader.context.connection.version
|
||||||
private val cache: MutableMap<ResourceLocation, BlockModel> = synchronizedMapOf()
|
|
||||||
|
|
||||||
fun loadBlock(name: ResourceLocation): BlockModel {
|
fun loadBlock(name: ResourceLocation): BlockModel {
|
||||||
val file = name.model("block/")
|
val file = name.model("block/")
|
||||||
@ -39,11 +37,11 @@ class BlockLoader(private val loader: ModelLoader) {
|
|||||||
return BlockModel.deserialize(parent, data)
|
return BlockModel.deserialize(parent, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadState(block: Block) {
|
fun loadState(block: Block): DirectBlockModel? {
|
||||||
val file = (if (block is CustomBlockModel) block.getModelName(version) else block.identifier)?.blockState() ?: return
|
val file = (if (block is CustomBlockModel) block.getModelName(version) else block.identifier)?.blockState() ?: return null
|
||||||
val data = assets[file].readJsonObject()
|
val data = assets[file].readJsonObject()
|
||||||
|
|
||||||
val model = DirectBlockModel.deserialize(this, data)
|
return DirectBlockModel.deserialize(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun load(latch: CountUpAndDownLatch) {
|
fun load(latch: CountUpAndDownLatch) {
|
||||||
@ -53,7 +51,7 @@ class BlockLoader(private val loader: ModelLoader) {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private fun ResourceLocation.blockState(): ResourceLocation {
|
fun ResourceLocation.blockState(): ResourceLocation {
|
||||||
return ResourceLocation(this.namespace, "blockstates/" + this.path + ".json")
|
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.DisplayPositions
|
||||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
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.models.raw.light.GUILights
|
||||||
|
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
data class BlockModel(
|
data class BlockModel(
|
||||||
val guiLight: GUILights,
|
val guiLight: GUILights,
|
||||||
val display: Map<DisplayPositions, ModelDisplay>?,
|
val display: Map<DisplayPositions, ModelDisplay>?,
|
||||||
val elements: List<ModelElement>?,
|
val elements: List<ModelElement>?,
|
||||||
val textures: Map<String, String>?,
|
val textures: Map<String, Any>?, // either String or ResourceLocation
|
||||||
val ambientOcclusion: Boolean,
|
val ambientOcclusion: Boolean,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -62,16 +64,41 @@ data class BlockModel(
|
|||||||
return elements
|
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
|
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) {
|
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 {
|
fun deserialize(parent: BlockModel?, data: JsonObject): BlockModel {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user