model loading

This commit is contained in:
Bixilon 2021-11-04 16:27:29 +01:00
parent d9e1c3b97f
commit 596866c3ee
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
32 changed files with 727 additions and 417 deletions

View File

@ -164,7 +164,7 @@ class MinecraftAssetsManager(
}
private fun parseAssetsIndex(hash: String): Map<ResourceLocation, String> {
return parseAssetsIndex(Util.readJsonFromStream(readAssetAsStream(hash)))
return parseAssetsIndex(Util.readJsonFromStream(readAssetAsStream(hash), true))
}
private fun parseAssetsIndex(json: JsonObject): Map<ResourceLocation, String> {

View File

@ -14,12 +14,9 @@ package de.bixilon.minosoft.data.direction
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.registries.blocks.properties.serializer.BlockPropertiesSerializer
import de.bixilon.minosoft.gui.rendering.block.models.BlockModelElement
import de.bixilon.minosoft.gui.rendering.block.models.FaceSize
import de.bixilon.minosoft.gui.rendering.util.VecUtil.get
import de.bixilon.minosoft.util.KUtil
import de.bixilon.minosoft.util.enum.ValuesEnum
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
import glm_.vec3.Vec3d
import glm_.vec3.Vec3i
@ -53,48 +50,6 @@ enum class Directions(
}
}
fun sidesNextTo(direction: Directions): Set<Directions> {
return when (direction) {
NORTH, SOUTH -> setOf(EAST, WEST)
EAST, WEST -> setOf(NORTH, SOUTH)
else -> emptySet()
}
}
/**
* @return the size of the face in this direction. null if the face is not touching the border (determinated by the block resolution)
*/
fun getFaceBorderSizes(start: Vec3, end: Vec3): FaceSize? {
// check if face is touching the border of a block
if (!isBlockResolutionBorder(start, end)) {
return null
}
return getFaceSize(start, end)
}
fun getFaceSize(start: Vec3, end: Vec3): FaceSize {
return when (this) {
DOWN, UP -> FaceSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
NORTH, SOUTH -> FaceSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
EAST, WEST -> FaceSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
}
}
private fun isBlockResolutionBorder(start: Vec3, end: Vec3): Boolean {
return isCoordinateBorder(vector.x, start.x, end.x) || isCoordinateBorder(vector.y, start.y, end.y) || isCoordinateBorder(vector.z, start.z, end.z)
}
private fun isCoordinateBorder(directionValue: Int, start: Float, end: Float): Boolean {
if (directionValue == 1) {
return start == BlockModelElement.BLOCK_RESOLUTION_FLOAT || end == BlockModelElement.BLOCK_RESOLUTION_FLOAT
}
if (directionValue == -1) {
return start == 0.0f || end == 0.0f
}
return false
}
operator fun get(axis: Axes): Int {
return vector[axis]
}
@ -121,6 +76,13 @@ enum class Directions(
return NAME_MAP[value] ?: throw IllegalArgumentException("No such property: $value")
}
override fun get(name: String): Directions {
if (name.lowercase() == "bottom") {
return DOWN
}
return super.get(name)
}
@JvmStatic
fun byId(id: Int): Directions {
return VALUES[id]

View File

@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.ONE
import de.bixilon.minosoft.gui.rendering.util.VecUtil.get
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3
import de.bixilon.minosoft.util.MMath.ceil
import de.bixilon.minosoft.util.MMath.floor
import glm_.Java.Companion.glm

View File

@ -94,7 +94,7 @@ open class Registry<T : RegistryItem>(
}
open operator fun get(resourceLocation: String): T? {
return get(ResourceLocation.getPathResourceLocation(resourceLocation))
return get(resourceLocation.toResourceLocation())
}
open operator fun get(resourceLocation: ResourceLocationAble): T? {

View File

@ -11,16 +11,22 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.block.mesh
package de.bixilon.minosoft.gui.rendering.block
import de.bixilon.minosoft.data.world.ChunkSection
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
class ChunkSectionMeshCollection(
renderWindow: RenderWindow,
val opaqueMesh: ChunkSectionArrayMesh = ChunkSectionArrayMesh(renderWindow),
var translucentMesh: ChunkSectionArrayMesh? = ChunkSectionArrayMesh(renderWindow),
var transparentMesh: ChunkSectionArrayMesh? = ChunkSectionArrayMesh(renderWindow),
class SectionPreparer(
val renderWindow: RenderWindow,
) {
var lowestBlockHeight = 0
var highestBlockHeight = 0
fun prepare(section: ChunkSection): ChunkSectionMesh {
val mesh = ChunkSectionMesh(renderWindow)
return mesh
}
}

View File

@ -13,24 +13,65 @@
package de.bixilon.minosoft.gui.rendering.block
import de.bixilon.minosoft.data.assets.AssetsUtil
import de.bixilon.minosoft.data.assets.Resources
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.direction.FakeDirection
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.world.ChunkSection
import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Renderer
import de.bixilon.minosoft.gui.rendering.RendererBuilder
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
import de.bixilon.minosoft.gui.rendering.models.ModelLoader
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import glm_.vec2.Vec2i
import java.io.FileInputStream
import java.util.zip.GZIPInputStream
import java.util.zip.ZipInputStream
class WorldRenderer(
private val connection: PlayConnection,
override val renderWindow: RenderWindow,
) : Renderer {
) : Renderer, OpaqueDrawable {
override val renderSystem: RenderSystem = renderWindow.renderSystem
private val shader = renderSystem.createShader("minosoft:world".toResourceLocation())
private val world: World = connection.world
private val sectionPreparer = SectionPreparer(renderWindow)
private lateinit var mesh: ChunkSectionMesh
override fun init() {
val asset = Resources.getAssetVersionByVersion(connection.version)
val zip = ZipInputStream(GZIPInputStream(FileInputStream(AssetsUtil.getAssetDiskPath(asset.clientJarHash!!, true))))
val modelLoader = ModelLoader(zip)
modelLoader.load()
val dirt = connection.registries.blockRegistry["dirt"]?.defaultState
val chunk = ChunkSection(Array(4096) { dirt })
mesh = sectionPreparer.prepare(chunk)
mesh.load()
}
override fun postInit() {
shader.load()
renderWindow.textureManager.staticTextures.use(shader)
renderWindow.textureManager.staticTextures.animator.use(shader)
}
override fun setupOpaque() {
super.setupOpaque()
shader.use()
}
override fun drawOpaque() {
mesh.draw()
}
companion object : RendererBuilder<WorldRenderer> {

View File

@ -23,7 +23,7 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct
import glm_.vec2.Vec2
import glm_.vec3.Vec3
class ChunkSectionArrayMesh(renderWindow: RenderWindow) : Mesh(renderWindow, SectionArrayMeshStruct, initialCacheSize = 100000) {
class ChunkSectionMesh(renderWindow: RenderWindow) : Mesh(renderWindow, SectionArrayMeshStruct, initialCacheSize = 100000) {
fun addVertex(position: Vec3, uv: Vec2, texture: AbstractTexture, tintColor: RGBColor?, light: Int) {
val color = tintColor ?: ChatColors.WHITE

View File

@ -0,0 +1,32 @@
/*
* Minosoft
* Copyright (C) 2021 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.block.mesh
import de.bixilon.minosoft.data.registries.AABB
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import glm_.vec3.Vec3i
class ChunkSectionMeshes(
renderWindow: RenderWindow,
val opaqueMesh: ChunkSectionMesh = ChunkSectionMesh(renderWindow),
var translucentMesh: ChunkSectionMesh? = ChunkSectionMesh(renderWindow),
var transparentMesh: ChunkSectionMesh? = ChunkSectionMesh(renderWindow),
) {
val minPosition = Vec3i.EMPTY
val maxPosition = Vec3i.EMPTY
lateinit var aabb: AABB
private set
}

View File

@ -1,66 +0,0 @@
/*
* Minosoft
* Copyright (C) 2021 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.block.models
import de.bixilon.minosoft.gui.rendering.util.VecUtil.rad
import de.bixilon.minosoft.util.KUtil.listCast
import de.bixilon.minosoft.util.KUtil.nullCast
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast
import glm_.vec3.Vec3
open class BlockModel(
val parent: BlockModel? = null,
data: Map<String, Any>,
) {
val textures: Map<String, String>
val elements: List<BlockModelElement>
val rotation: Vec3 = Vec3(data["x"]?.unsafeCast<Double>() ?: parent?.rotation?.x ?: 0.0f, data["y"]?.unsafeCast<Double>() ?: parent?.rotation?.y ?: 0.0f, data["z"]?.unsafeCast<Double>() ?: parent?.rotation?.z ?: 0.0f).rad
val uvLock: Boolean = data["uvlock"].nullCast<Boolean>() ?: parent?.uvLock ?: false
val rescale: Boolean = data["rescale"].nullCast<Boolean>() ?: parent?.rescale ?: false
val ambientOcclusion: Boolean = data["ambientocclusion"].nullCast<Boolean>() ?: parent?.ambientOcclusion ?: true
init {
textures = data["textures"]?.compoundCast()?.let {
val textures: MutableMap<String, String> = parent?.textures?.toMutableMap() ?: mutableMapOf()
for ((type, value) in it) {
textures[type] = value.unsafeCast()
}
for ((type, texture) in textures) {
textures[type] = getTextureByType(textures, texture)
}
textures.toMap()
} ?: parent?.textures ?: mapOf()
elements = data["elements"]?.listCast()?.let {
val elements: MutableList<BlockModelElement> = mutableListOf()
for (element in it) {
elements += BlockModelElement(element.asCompound())
}
elements.toList()
} ?: parent?.elements ?: listOf()
}
private fun getTextureByType(textures: Map<String, String>, type: String): String {
var currentValue: String = type
while (currentValue.startsWith("#")) {
textures[currentValue.removePrefix("#")].let {
currentValue = it ?: return currentValue
}
}
return currentValue
}
}

View File

@ -1,102 +0,0 @@
/*
* Minosoft
* Copyright (C) 2021 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.block.models
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.rotate
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3
import de.bixilon.minosoft.util.KUtil.nullCast
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast
import glm_.func.rad
import glm_.vec3.Vec3
open class BlockModelElement(
data: Map<String, Any>,
) {
val from: Vec3 = data["from"]?.toVec3() ?: Vec3.EMPTY
val to: Vec3 = data["to"]?.toVec3() ?: Vec3(BLOCK_RESOLUTION)
val shade: Boolean = data["shade"].nullCast<Boolean>() ?: true
val faces: MutableMap<Directions, BlockModelFace> = mutableMapOf()
val transformedPositions: Array<Vec3> = arrayOf(
Vec3(from.x, from.y, from.z),
Vec3(to.x, from.y, from.z),
Vec3(from.x, from.y, to.z),
Vec3(to.x, from.y, to.z),
Vec3(from.x, to.y, from.z),
Vec3(to.x, to.y, from.z),
Vec3(from.x, to.y, to.z),
Vec3(to.x, to.y, to.z),
)
init {
data["rotation"]?.compoundCast()?.let {
val axis = Axes[it["axis"].unsafeCast<String>()]
val angle = it["angle"].unsafeCast<Double>().toFloat().rad
val rescale = it["rescale"].nullCast<Boolean>() ?: false
rotatePositions(transformedPositions, axis, angle, it["origin"]!!.toVec3(), rescale)
}
data["faces"]?.compoundCast()?.let {
for ((directionName, json) in it) {
val direction = Directions[directionName]
faces[direction] = BlockModelFace(json.asCompound(), from, to, direction)
}
}
// transformed positions
for ((index, position) in transformedPositions.withIndex()) {
transformedPositions[index] = transformPosition(position)
}
}
companion object {
const val BLOCK_RESOLUTION = 16
const val BLOCK_RESOLUTION_FLOAT = BLOCK_RESOLUTION.toFloat()
val FACE_POSITION_MAP_TEMPLATE = arrayOf(
intArrayOf(0, 2, 3, 1),
intArrayOf(6, 4, 5, 7),
intArrayOf(1, 5, 4, 0),
intArrayOf(2, 6, 7, 3),
intArrayOf(6, 2, 0, 4),
intArrayOf(5, 1, 3, 7)
)
fun rotatePositions(positions: Array<Vec3>, axis: Axes, angle: Float, origin: Vec3, rescale: Boolean) {
// TODO: optimize for 90deg, 180deg, 270deg rotations
if (angle == 0.0f) {
return
}
for ((i, position) in positions.withIndex()) {
var transformedPosition = position - origin
transformedPosition = transformedPosition.rotate(angle, axis, rescale)
positions[i] = transformedPosition + origin
}
}
fun transformPosition(position: Vec3): Vec3 {
fun positionToFloat(uv: Float): Float {
return (uv - (BLOCK_RESOLUTION / 2)) / BLOCK_RESOLUTION
}
return Vec3(positionToFloat(position.x), positionToFloat(position.y), positionToFloat(position.z))
}
}
}

View File

@ -1,156 +0,0 @@
/*
* Minosoft
* Copyright (C) 2021 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.block.models
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.AABB
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.readUV
import de.bixilon.minosoft.util.KUtil.nullCast
import de.bixilon.minosoft.util.KUtil.toInt
import de.bixilon.minosoft.util.KUtil.unsafeCast
import glm_.func.cos
import glm_.func.sin
import glm_.vec2.Vec2
import glm_.vec3.Vec3
import java.util.*
class BlockModelFace {
val textureName: String?
val cullFace: Directions?
val tint: Boolean
val positions: List<Vec2>
constructor(textureName: String?, cullFace: Directions?, tint: Boolean, positions: List<Vec2>) {
this.textureName = textureName
this.cullFace = cullFace
this.tint = tint
this.positions = positions
}
constructor(data: Map<String, Any>, from: Vec3, to: Vec3, direction: Directions) {
tint = data.containsKey("tintindex")
textureName = data["texture"].unsafeCast<String>().removePrefix("#")
cullFace = data["cullface"].nullCast<String>()?.let {
if (it == "bottom") {
Directions.DOWN
} else {
Directions[it]
}
}
val positions = calculateTexturePositions(data, from, to, direction)
val rotation = data["rotation"]?.toInt()?.div(90) ?: 0
Collections.rotate(positions, rotation)
this.positions = positions.toList()
}
private fun calculateTexturePositions(data: Map<String, Any>?, from: Vec3, to: Vec3, direction: Directions): MutableList<Vec2> {
val (textureTopLeft: Vec2, textureBottomRight: Vec2) = data?.get("uv")?.unsafeCast<List<Float>>()?.readUV() ?: getTexturePositionsFromRegion(AABB(from, to), direction)
return mutableListOf(
uvToFloat(Vec2(textureTopLeft.x, textureTopLeft.y)),
uvToFloat(Vec2(textureTopLeft.x, textureBottomRight.y)),
uvToFloat(Vec2(textureBottomRight.x, textureBottomRight.y)),
uvToFloat(Vec2(textureBottomRight.x, textureTopLeft.y)),
)
}
private fun getTexturePositionsFromRegion(aabb: AABB, direction: Directions): Pair<Vec2, Vec2> {
// ToDo: Remove the duplicated code in Directions
return when (direction) {
Directions.UP, Directions.DOWN -> Pair(Vec2(aabb.min.x.toInt(), aabb.max.z.toInt()), Vec2(aabb.max.x.toInt(), aabb.min.z.toInt()))
Directions.NORTH, Directions.SOUTH -> Pair(Vec2(aabb.min.x.toInt(), aabb.max.y.toInt()), Vec2(aabb.max.x.toInt(), aabb.min.y.toInt()))
Directions.EAST, Directions.WEST -> Pair(Vec2(aabb.min.z.toInt(), aabb.max.y.toInt()), Vec2(aabb.max.z.toInt(), aabb.min.y.toInt()))
}
}
constructor(other: BlockModelFace) {
textureName = other.textureName
cullFace = other.cullFace
tint = other.tint
this.positions = other.positions
}
constructor(vertexPositions: List<Vec3>, direction: Directions) {
textureName = null
cullFace = null
tint = false
val template = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[direction.ordinal]
val positions: MutableList<Vec2> = mutableListOf()
for (templatePosition in template) {
positions += calculateTexturePosition(vertexPositions[templatePosition], direction)
}
this.positions = positions.toList()
}
private fun calculateTexturePosition(position: Vec3, direction: Directions): Vec2 {
return when (direction) {
Directions.UP, Directions.DOWN -> Vec2(position.x, BlockModelElement.BLOCK_RESOLUTION - position.z)
Directions.NORTH, Directions.SOUTH -> Vec2(position.x, position.y)
Directions.EAST, Directions.WEST -> Vec2(position.z, BlockModelElement.BLOCK_RESOLUTION - position.y)
}
}
fun getTexturePositionArray(direction: Directions): Array<Vec2?> {
val template = textureTemplate[direction.ordinal]
val ret: MutableList<Vec2> = mutableListOf()
for (i in template.indices) {
ret += positions[template[i]]
}
return ret.toTypedArray()
}
fun rotate(angle: Float): BlockModelFace {
if (angle == 0.0f) {
return this
}
val sin = angle.sin
val cos = angle.cos
val positions = this.positions.toMutableList()
for ((i, position) in positions.withIndex()) {
val offset = position - TEXTURE_MIDDLE
positions[i] = VecUtil.getRotatedValues(offset.x, offset.y, sin, cos, false) + TEXTURE_MIDDLE
}
return BlockModelFace(textureName, cullFace, tint, positions.toList())
}
fun scale(scaleFactor: Double): BlockModelFace {
val positions = positions.toMutableList()
for ((i, position) in positions.withIndex()) {
positions[i] = position * scaleFactor
}
return BlockModelFace(textureName, cullFace, tint, positions.toList())
}
companion object {
private fun uvToFloat(uv: Float): Float {
return (uv) / BlockModelElement.BLOCK_RESOLUTION
}
fun uvToFloat(vec2: Vec2): Vec2 {
return Vec2(uvToFloat(vec2.x), uvToFloat(BlockModelElement.BLOCK_RESOLUTION - vec2.y))
}
val textureTemplate = arrayOf(
arrayOf(0, 1, 2, 3),
arrayOf(0, 1, 2, 3),
arrayOf(3, 2, 1, 0),
arrayOf(0, 1, 2, 3),
arrayOf(2, 3, 0, 1),
arrayOf(1, 0, 3, 2),
)
val TEXTURE_MIDDLE = Vec2(0.5, 0.5)
}
}

View File

@ -0,0 +1,29 @@
/*
* Minosoft
* Copyright (C) 2021 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
import de.bixilon.minosoft.util.KUtil
import de.bixilon.minosoft.util.enum.ValuesEnum
enum class GUILights {
FRONT,
SIDE,
;
companion object : ValuesEnum<GUILights> {
override val VALUES: Array<GUILights> = values()
override val NAME_MAP: Map<String, GUILights> = KUtil.getEnumValues(VALUES)
}
}

View File

@ -0,0 +1,105 @@
/*
* Minosoft
* Copyright (C) 2021 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
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.models.builtin.BuiltinModels
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedBlockModel
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedItemModel
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel
import de.bixilon.minosoft.util.KUtil.fromJson
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.Util
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
class ModelLoader(
val jar: ZipInputStream,
) {
private val unbakedBlockModels: MutableMap<ResourceLocation, UnbakedModel> = BuiltinModels.BUILTIN_MODELS.toMutableMap()
private val blockStateJsons: MutableMap<ResourceLocation, Map<String, Any>> = mutableMapOf()
private val modelJsons: MutableMap<ResourceLocation, Map<String, Any>> = mutableMapOf()
private fun loadJsons() {
// ToDo: Integrate in assets manager
var entry: ZipEntry? = jar.nextEntry
while (entry != null) {
if (!entry.name.startsWith("assets/minecraft/models/") && !entry.name.startsWith("assets/minecraft/blockstates/")) {
entry = jar.nextEntry
continue
}
val name = entry.name.removePrefix("assets/minecraft/").removeSuffix(".json")
val jsonString = Util.readReader(BufferedReader(InputStreamReader(jar)), false)
val json = jsonString.fromJson().asCompound()
if (name.startsWith("models/")) {
modelJsons[name.removePrefix("models/").toResourceLocation()] = json
} else {
blockStateJsons[name.removePrefix("blockstates/").toResourceLocation()] = json
}
entry = jar.nextEntry
}
}
fun load() {
loadJsons()
Log.log(LogMessageType.VERSION_LOADING, LogLevels.VERBOSE) { "Loaded ${blockStateJsons.size} block states and ${modelJsons.size} model jsons!" }
fun loadBlockModel(name: ResourceLocation, json: Map<String, Any>? = null): UnbakedModel {
unbakedBlockModels[name]?.let { return it.unsafeCast() }
val data = json ?: modelJsons[name] ?: error("Can not find json: $name")
val parent = data["parent"]?.toResourceLocation()?.let { loadBlockModel(it) }
val model = UnbakedBlockModel(parent, data)
unbakedBlockModels[name] = model
return model
}
fun loadItemModel(name: ResourceLocation, json: Map<String, Any>? = null): UnbakedModel {
unbakedBlockModels[name]?.let { return it.unsafeCast() }
val data = json ?: modelJsons[name] ?: error("Can not find json: $name")
val parent = data["parent"]?.toResourceLocation()?.let { loadItemModel(it) }
val model = UnbakedItemModel(parent, data)
unbakedBlockModels[name] = model
return model
}
for ((name, json) in modelJsons) {
if (name.path.startsWith("block/")) {
loadBlockModel(name, json)
} else if (name.path.startsWith("item/")) {
loadItemModel(name, json)
} else {
TODO("Unknown block model type: $name")
}
}
Log.log(LogMessageType.VERSION_LOADING, LogLevels.VERBOSE) { "Done loading models!" }
}
}

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2021 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.builtin
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel
object BuiltinModels {
val BUILTIN_MODELS: Map<ResourceLocation, UnbakedModel> = mapOf(
UnbakedBlockEntityModel.RESOURCE_LOCATION to UnbakedBlockEntityModel,
UnbakedGeneratedModel.RESOURCE_LOCATION to UnbakedGeneratedModel,
)
}

View File

@ -0,0 +1,25 @@
/*
* Minosoft
* Copyright (C) 2021 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.builtin
import de.bixilon.minosoft.data.registries.CompanionResourceLocation
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel
import de.bixilon.minosoft.util.KUtil.toResourceLocation
@Deprecated("TODO")
object UnbakedBlockEntityModel : UnbakedModel(null, mapOf()), CompanionResourceLocation {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:builtin/entity".toResourceLocation()
}

View File

@ -0,0 +1,25 @@
/*
* Minosoft
* Copyright (C) 2021 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.builtin
import de.bixilon.minosoft.data.registries.CompanionResourceLocation
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel
import de.bixilon.minosoft.util.KUtil.toResourceLocation
@Deprecated("TODO")
object UnbakedGeneratedModel : UnbakedModel(null, mapOf()), CompanionResourceLocation {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:builtin/generated".toResourceLocation()
}

View File

@ -0,0 +1,37 @@
/*
* Minosoft
* Copyright (C) 2021 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.display
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.ONE
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3i
import glm_.vec3.Vec3
import glm_.vec3.Vec3i
data class ModelDisplay(
val rotation: Vec3i,
val translation: Vec3i,
val scale: Vec3,
) {
companion object {
operator fun invoke(data: Map<String, Any>): ModelDisplay {
return ModelDisplay(
rotation = data["rotation"]?.toVec3i() ?: Vec3i.EMPTY,
translation = data["translation"]?.toVec3i() ?: Vec3i.EMPTY,
scale = data["scale"]?.toVec3() ?: Vec3.ONE,
)
}
}
}

View File

@ -0,0 +1,39 @@
/*
* Minosoft
* Copyright (C) 2021 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.display
import de.bixilon.minosoft.util.KUtil
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.enum.AliasableEnum
import de.bixilon.minosoft.util.enum.ValuesEnum
enum class ModelDisplayPositions(vararg names: String = arrayOf()) : AliasableEnum {
THIRD_PERSON_RIGHT_HAND("thirdperson_righthand"),
THIRD_PERSON_LEFT_HAND("thirdperson_lefthand"),
FIRST_PERSON_RIGHT_HAND("firstperson_righthand"),
FIRST_PERSON_LEFT_HAND("firstperson_lefthand"),
GUI,
HEAD,
GROUND,
FIXED,
;
override val names: Array<String> = names.unsafeCast()
companion object : ValuesEnum<ModelDisplayPositions> {
override val VALUES: Array<ModelDisplayPositions> = values()
override val NAME_MAP: Map<String, ModelDisplayPositions> = KUtil.getEnumValues(VALUES)
}
}

View File

@ -11,11 +11,6 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.block.models
package de.bixilon.minosoft.gui.rendering.models.unbaked
import glm_.vec2.Vec2i
data class FaceSize(
val start: Vec2i = Vec2i(0, 0),
val end: Vec2i = Vec2i(BlockModelElement.BLOCK_RESOLUTION, BlockModelElement.BLOCK_RESOLUTION),
)
interface Model

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2021 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.unbaked
import de.bixilon.minosoft.util.KUtil.toBoolean
class UnbakedBlockModel(
parent: UnbakedModel?,
json: Map<String, Any>,
) : UnbakedModel(parent, json) {
val ambientOcclusion: Boolean = json["ambientocclusion"]?.toBoolean() ?: parent?.let { return@let if (parent is UnbakedBlockModel) parent.ambientOcclusion else null } ?: true
}

View File

@ -0,0 +1,25 @@
/*
* Minosoft
* Copyright (C) 2021 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.unbaked
import de.bixilon.minosoft.gui.rendering.models.GUILights
class UnbakedItemModel(
parent: UnbakedModel?,
json: Map<String, Any>,
) : UnbakedModel(parent, json) {
val guiLight: GUILights = json["gui_light"]?.toString()?.let { GUILights[it] } ?: parent?.let { return@let if (parent is UnbakedItemModel) parent.guiLight else null } ?: GUILights.SIDE
// ToDo: Overrides (predicates)
}

View File

@ -0,0 +1,68 @@
/*
* Minosoft
* Copyright (C) 2021 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.unbaked
import de.bixilon.minosoft.gui.rendering.models.display.ModelDisplay
import de.bixilon.minosoft.gui.rendering.models.display.ModelDisplayPositions
import de.bixilon.minosoft.gui.rendering.models.unbaked.element.UnbakedElement
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast
abstract class UnbakedModel(
parent: UnbakedModel?,
json: Map<String, Any>,
) : Model {
val display: Map<ModelDisplayPositions, ModelDisplay>
val elements: Set<UnbakedElement>
init {
val display = parent?.display?.toMutableMap() ?: mutableMapOf()
json["display"]?.compoundCast()?.let {
for ((name, value) in it) {
display[ModelDisplayPositions[name]] = ModelDisplay(data = value.unsafeCast())
}
}
this.display = display
}
val textures: Map<String, String>
init {
val textures = parent?.textures?.toMutableMap() ?: mutableMapOf()
json["textures"]?.compoundCast()?.let {
for ((name, value) in it) {
textures[name] = value.toString()
}
}
this.textures = textures
}
init {
val elements = parent?.elements?.toMutableSet() ?: mutableSetOf()
json["elements"]?.listCast<Map<String, Any>>()?.let {
for (element in it) {
elements += UnbakedElement(data = element)
}
}
this.elements = elements
}
}

View File

@ -0,0 +1,51 @@
/*
* Minosoft
* Copyright (C) 2021 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.unbaked.element
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3
import de.bixilon.minosoft.util.KUtil.toBoolean
import de.bixilon.minosoft.util.KUtil.unsafeCast
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast
import glm_.vec3.Vec3
data class UnbakedElement(
val from: Vec3,
val to: Vec3,
val rotation: UnbakedElementRotation?,
val shade: Boolean,
val faces: Set<UnbakedElementFace>,
) {
companion object {
operator fun invoke(data: Map<String, Any>): UnbakedElement {
val faces: MutableSet<UnbakedElementFace> = mutableSetOf()
data["faces"].asCompound().let {
for ((direction, faceData) in it) {
faces += UnbakedElementFace(direction = Directions[direction], data = faceData.unsafeCast())
}
}
return UnbakedElement(
from = data["from"].toVec3(),
to = data["to"].toVec3(),
rotation = data["rotation"]?.compoundCast()?.let { return@let UnbakedElementRotation(data = it) },
shade = data["shade"]?.toBoolean() ?: true,
faces = faces,
)
}
}
}

View File

@ -0,0 +1,47 @@
/*
* Minosoft
* Copyright (C) 2021 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.unbaked.element
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.util.KUtil.toInt
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast
import glm_.vec2.Vec2
data class UnbakedElementFace(
val direction: Directions,
val uvStart: Vec2,
val uvEnd: Vec2,
val texture: String,
val cullFace: Directions?,
val rotation: Int,
val tintIndex: Int,
) {
companion object {
operator fun invoke(direction: Directions, data: Map<String, Any>): UnbakedElementFace {
val uv = data["uv"]?.listCast<Number>()
val uvStart = Vec2(uv?.get(0) ?: 0.0f, uv?.get(2) ?: 0.0f)
val uvEnd = Vec2(uv?.get(1) ?: 16.0f, uv?.get(3) ?: 16.0f)
return UnbakedElementFace(
direction = direction,
uvStart = uvStart,
uvEnd = uvEnd,
texture = data["texture"].toString(),
cullFace = data["cullface"]?.toString()?.let { return@let Directions[it] },
rotation = data["rotation"]?.toInt() ?: 0,
tintIndex = data["tintindex"]?.toInt() ?: -1,
)
}
}
}

View File

@ -0,0 +1,40 @@
/*
* Minosoft
* Copyright (C) 2021 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.unbaked.element
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3
import de.bixilon.minosoft.util.KUtil.toBoolean
import de.bixilon.minosoft.util.KUtil.toFloat
import glm_.vec3.Vec3
data class UnbakedElementRotation(
val origin: Vec3,
val axis: Axes,
val angle: Float,
val rescale: Boolean,
) {
companion object {
operator fun invoke(data: Map<String, Any>): UnbakedElementRotation {
return UnbakedElementRotation(
origin = data["origin"]?.toVec3() ?: Vec3.EMPTY,
axis = Axes[data["axis"].toString()],
angle = data["angle"].toFloat(),
rescale = data["rescale"]?.toBoolean() ?: false,
)
}
}
}

View File

@ -13,9 +13,6 @@
package de.bixilon.minosoft.gui.rendering.util
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.direction.AbstractDirection
@ -23,9 +20,7 @@ import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.AABB
import de.bixilon.minosoft.data.registries.blocks.RandomOffsetTypes
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.gui.rendering.block.models.BlockModelElement
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.unsafeCast
import glm_.func.common.ceil
import glm_.func.common.clamp
import glm_.func.common.floor
@ -58,19 +53,6 @@ object VecUtil {
val Vec3d.Companion.ONE: Vec3d
get() = Vec3d(1.0, 1.0, 1.0)
fun Any.toVec3(default: Vec3? = null): Vec3 {
return when (this) {
is List<*> -> Vec3(this[0] as Double, this[1] as Double, this[2] as Double)
is JsonArray -> Vec3(this[0].asFloat, this[1].asFloat, this[2].asFloat)
is JsonObject -> Vec3(this["x"]?.asFloat ?: 0, this["y"]?.asFloat ?: 0, this["z"]?.asFloat ?: 0)
is Map<*, *> -> Vec3(this["x"]?.unsafeCast<Double>() ?: 0, this["y"]?.unsafeCast<Double>() ?: 0, this["z"]?.unsafeCast<Double>() ?: 0)
is JsonPrimitive -> Vec3(this.asFloat)
is Float -> Vec3(this)
is Double -> Vec3(this)
else -> default ?: throw IllegalArgumentException("Not a Vec3!")
}
}
fun Vec3.clear() {
x = 0.0f
y = 0.0f
@ -204,10 +186,6 @@ object VecUtil {
return this * cos + (axis cross this) * sin + axis * (axis dot this) * (1 - cos)
}
fun List<Float>.readUV(): Pair<Vec2, Vec2> {
return Pair(Vec2(this[0], BlockModelElement.BLOCK_RESOLUTION - this[1]), Vec2(this[2], BlockModelElement.BLOCK_RESOLUTION - this[3]))
}
fun Int.chunkPosition(multiplier: Int): Int {
return if (this >= 0) {
this / multiplier

View File

@ -74,7 +74,7 @@ object Vec2Util {
is List<*> -> Vec2i(this[0].toInt(), this[1].toInt())
is Map<*, *> -> Vec2i(this["x"]?.toInt() ?: 0, this["y"]?.toInt() ?: 0)
is Number -> Vec2i(this.toInt())
else -> default ?: throw IllegalArgumentException("Not a Vec2i!")
else -> default ?: throw IllegalArgumentException("Not a Vec2i: $this")
}
}
}

View File

@ -0,0 +1,39 @@
/*
* Minosoft
* Copyright (C) 2021 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.util.vec.vec3
import de.bixilon.minosoft.util.KUtil.toFloat
import glm_.vec3.Vec3
object Vec3Util {
val Vec3.Companion.MIN: Vec3
get() = Vec3(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE)
val Vec3.Companion.EMPTY: Vec3
get() = Vec3(0.0f, 0.0f, 0.0f)
val Vec3.Companion.MAX: Vec3
get() = Vec3(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE)
fun Any?.toVec3(default: Vec3? = null): Vec3 {
return when (this) {
is List<*> -> Vec3(this[0].toFloat(), this[1].toFloat(), this[2].toFloat())
is Map<*, *> -> Vec3(this["x"]?.toFloat() ?: 0.0f, this["y"]?.toFloat() ?: 0.0f, this["z"]?.toFloat() ?: 0.0f)
is Number -> Vec3(this.toFloat())
else -> default ?: throw IllegalArgumentException("Not a Vec3: $this")
}
}
}

View File

@ -0,0 +1,40 @@
/*
* Minosoft
* Copyright (C) 2021 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.util.vec.vec3
import de.bixilon.minosoft.util.KUtil.toInt
import glm_.vec3.Vec3
import glm_.vec3.Vec3i
object Vec3iUtil {
val Vec3i.Companion.MIN: Vec3i
get() = Vec3i(Int.MIN_VALUE, Int.MIN_VALUE, Int.MIN_VALUE)
val Vec3.Companion.EMPTY: Vec3i
get() = Vec3i(0, 0, 0)
val Vec3.Companion.MAX: Vec3i
get() = Vec3i(Int.MAX_VALUE, Int.MAX_VALUE, Int.MAX_VALUE)
fun Any?.toVec3i(default: Vec3i? = null): Vec3i {
return when (this) {
is List<*> -> Vec3i(this[0].toInt(), this[1].toInt(), this[2].toInt())
is Map<*, *> -> Vec3i(this["x"]?.toInt() ?: 0.0f, this["y"]?.toInt() ?: 0.0f, this["z"]?.toInt() ?: 0.0f)
is Number -> Vec3i(this.toInt())
else -> default ?: throw IllegalArgumentException("Not a Vec3i: $this")
}
}
}

View File

@ -34,9 +34,9 @@ object ShutdownManager {
connection.disconnect()
}
if (Minosoft.configInitialized) {
Minosoft.config.saveToFile()
// Minosoft.config.saveToFile()
}
DefaultThreadPool.shutdown()
DefaultThreadPool.shutdownNow() // ToDo: Save config
exitProcess(reason.exitCode)
}

View File

@ -339,10 +339,13 @@ public final class Util {
}
@NotNull
public static JsonObject readJsonFromStream(@NotNull InputStream stream) throws IOException {
@Deprecated
public static JsonObject readJsonFromStream(@NotNull InputStream stream, boolean close) throws IOException {
InputStreamReader reader = new InputStreamReader(stream);
JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
reader.close();
if (close) {
reader.close();
}
return json;
}
}

View File

@ -22,7 +22,7 @@ interface ValuesEnum<T : Enum<*>> {
}
operator fun get(name: String): T {
return NAME_MAP[name]!!
return NAME_MAP[name] ?: throw IllegalArgumentException("Can not find enum value: $name")
}
fun next(current: T): T {