parse builder ("multipart") block models

This commit is contained in:
Bixilon 2023-03-30 10:55:44 +02:00
parent 20d0083973
commit b545d930f4
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
8 changed files with 290 additions and 17 deletions

View File

@ -13,11 +13,13 @@
package de.bixilon.minosoft.gui.rendering.models.block.state
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.kutil.cast.CollectionCast.asAnyList
import de.bixilon.kutil.json.JsonObject
import de.bixilon.kutil.json.JsonUtil.toJsonObject
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.gui.rendering.models.block.state.apply.BlockStateApply
import de.bixilon.minosoft.gui.rendering.models.block.state.condition.ConditionBlockModel
import de.bixilon.minosoft.gui.rendering.models.block.state.builder.BuilderBlockModel
import de.bixilon.minosoft.gui.rendering.models.block.state.variant.VariantBlockModel
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
@ -29,7 +31,7 @@ interface DirectBlockModel {
fun deserialize(loader: BlockLoader, data: JsonObject): DirectBlockModel? {
data["variants"]?.toJsonObject()?.let { return VariantBlockModel.deserialize(loader, it) }
data["multipart"]?.toJsonObject()?.let { return ConditionBlockModel.deserialize(loader, it) }
data["multipart"]?.asAnyList()?.let { return BuilderBlockModel.deserialize(loader, it.unsafeCast()) }
return null
}

View File

@ -11,25 +11,17 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.condition
package de.bixilon.minosoft.gui.rendering.models.block.state.builder
import de.bixilon.kutil.json.JsonObject
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.gui.rendering.models.block.state.DirectBlockModel
import de.bixilon.minosoft.gui.rendering.models.block.state.apply.BlockStateApply
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
@Deprecated("TODO")
class ConditionBlockModel : DirectBlockModel {
class BuilderApply(
val applies: List<BlockStateApply>
) : BlockStateApply {
override fun choose(state: BlockState): BlockStateApply? {
override fun bake(textures: TextureManager): BlockRender? {
TODO("Not yet implemented")
}
companion object {
fun deserialize(loader: BlockLoader, data: JsonObject): ConditionBlockModel? {
TODO()
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.builder
import de.bixilon.kutil.json.JsonObject
import de.bixilon.kutil.json.JsonUtil.asJsonObject
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.state.PropertyBlockState
import de.bixilon.minosoft.gui.rendering.models.block.state.DirectBlockModel
import de.bixilon.minosoft.gui.rendering.models.block.state.apply.BlockStateApply
import de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition.AndCondition
import de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition.BuilderCondition
import de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition.PrimitiveCondition
import de.bixilon.minosoft.gui.rendering.models.loader.BlockLoader
class BuilderBlockModel(
val parts: List<Apply>,
) : DirectBlockModel {
override fun choose(state: BlockState): BlockStateApply? {
val applies: MutableList<BlockStateApply> = mutableListOf()
val properties = if (state is PropertyBlockState) state.properties else emptyMap()
for ((condition, apply) in parts) {
if (!condition.matches(properties)) continue
applies += apply
}
if (applies.isEmpty()) return null
return BuilderApply(applies)
}
data class Apply(
val condition: BuilderCondition,
val apply: BlockStateApply,
)
companion object {
fun deserialize(loader: BlockLoader, data: List<JsonObject>): BuilderBlockModel? {
val parts: MutableList<Apply> = mutableListOf()
for (entry in data) {
val apply = entry["apply"]?.let { BlockStateApply.deserialize(loader, it) } ?: continue
val condition = entry["when"]?.asJsonObject()?.let { AndCondition.deserialize(it) } ?: PrimitiveCondition.TRUE
parts += Apply(condition, apply)
}
if (parts.isEmpty()) return null
return BuilderBlockModel(parts)
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.kutil.json.JsonObject
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
class AndCondition(
val conditions: Set<BuilderCondition>,
) : BuilderCondition {
override fun matches(properties: Map<BlockProperties, Any>): Boolean {
for (condition in conditions) {
if (!condition.matches(properties)) return false
}
return true
}
companion object {
fun deserialize(data: JsonObject): BuilderCondition? {
if (data.isEmpty()) return null
val property = PropertyCondition.deserialize(data)
val or = data[OrCondition.KEY]?.let { OrCondition.deserialize(it.unsafeCast()) } ?: return property
if (property == null) return or
return AndCondition(mutableSetOf(property, or))
}
}
}

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
interface BuilderCondition {
fun matches(properties: Map<BlockProperties, Any>): Boolean
}

View File

@ -0,0 +1,37 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition
import de.bixilon.kutil.json.JsonObject
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
class OrCondition(
val conditions: Set<BuilderCondition>,
) : BuilderCondition {
override fun matches(properties: Map<BlockProperties, Any>): Boolean {
for (condition in conditions) {
if (condition.matches(properties)) return true
}
return false
}
companion object {
const val KEY = "OR"
fun deserialize(data: List<JsonObject>): OrCondition? {
TODO()
}
}
}

View File

@ -0,0 +1,27 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
class PrimitiveCondition private constructor(val matches: Boolean) : BuilderCondition {
override fun matches(properties: Map<BlockProperties, Any>) = matches
companion object {
val TRUE = PrimitiveCondition(true)
val FALSE = PrimitiveCondition(false)
}
}

View File

@ -0,0 +1,82 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.state.builder.condition
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.kutil.json.JsonObject
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
class PropertyCondition(
val conditions: Map<BlockProperties, Any>,
) : BuilderCondition {
override fun matches(properties: Map<BlockProperties, Any>): Boolean {
for ((property, value) in this.conditions) {
val target = properties[property] ?: return false
if (value is Set<*>) {
if (target !in value) return false
} else {
if (value != target) return false
}
}
return true
}
companion object {
private fun deserializeOr(property: String, list: List<String>): Pair<BlockProperties, Any> {
if (list.size == 1) {
return BlockProperties.parseProperty(property, list.first())
}
val values: MutableSet<Any> = mutableSetOf()
var blockProperty: BlockProperties? = null
for (entry in list) {
val (entryProperty, entryValue) = BlockProperties.parseProperty(property, entry)
if (blockProperty == null) {
blockProperty = entryProperty
}
values += entryValue
}
if (blockProperty == null) {
throw IllegalStateException("List is empty!")
}
return Pair(blockProperty, values)
}
fun deserialize(data: JsonObject): PropertyCondition? {
val properties: MutableMap<BlockProperties, Any> = mutableMapOf()
for ((key, value) in data) {
if (key == OrCondition.KEY) continue
if (value is List<*>) {
val (property, values) = deserializeOr(key, value.unsafeCast())
properties[property] = values
continue
}
val split = value.toString().split('|')
val (property, values) = deserializeOr(key, split)
properties[property] = values
}
if (properties.isEmpty()) return null
return PropertyCondition(properties)
}
}
}