door block, block collision and outline changes

This commit is contained in:
Moritz Zwerger 2023-10-14 00:57:03 +02:00
parent 4b3298c6f3
commit 9afbe0dfb5
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
47 changed files with 402 additions and 114 deletions

View File

@ -38,6 +38,7 @@ import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
import de.bixilon.minosoft.protocol.network.connection.play.ConnectionTestUtil.createConnection
import de.bixilon.minosoft.protocol.versions.Version
import de.bixilon.minosoft.test.IT.NULL_CONNECTION
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.logging.Log
@ -68,8 +69,8 @@ object VerifyIntegratedBlockRegistry {
private fun compareCollisionShape(pixlyzer: BlockState, integrated: BlockState, errors: StringBuilder) {
if (integrated.block is OutlinedBlock && integrated.block !is FixedCollidable) return // not checkable without context
val expected = if (pixlyzer.block is CollidableBlock) pixlyzer.block.unsafeCast<CollidableBlock>().getCollisionShape(EmptyCollisionContext, Vec3i.EMPTY, pixlyzer, null) else null
val actual = if (integrated.block is CollidableBlock) integrated.block.unsafeCast<CollidableBlock>().getCollisionShape(EmptyCollisionContext, Vec3i.EMPTY, pixlyzer, null) else null
val expected = if (pixlyzer.block is CollidableBlock) pixlyzer.block.unsafeCast<CollidableBlock>().getCollisionShape(NULL_CONNECTION, EmptyCollisionContext, Vec3i.EMPTY, pixlyzer, null) else null
val actual = if (integrated.block is CollidableBlock) integrated.block.unsafeCast<CollidableBlock>().getCollisionShape(NULL_CONNECTION, EmptyCollisionContext, Vec3i.EMPTY, pixlyzer, null) else null
if (expected == actual) {
return
@ -85,8 +86,8 @@ object VerifyIntegratedBlockRegistry {
if (integrated.block is ScaffoldingBlock) return
if (integrated.block is OffsetBlock) return // Don't compare, pixlyzer is probably wrong
val expected = if (pixlyzer.block is OutlinedBlock) pixlyzer.block.unsafeCast<OutlinedBlock>().getOutlineShape(connection, pixlyzer) else null
val actual = if (integrated.block is OutlinedBlock) integrated.block.unsafeCast<OutlinedBlock>().getOutlineShape(connection, pixlyzer) else null
val expected = if (pixlyzer.block is OutlinedBlock) pixlyzer.block.unsafeCast<OutlinedBlock>().getOutlineShape(connection, Vec3i.EMPTY, pixlyzer) else null
val actual = if (integrated.block is OutlinedBlock) integrated.block.unsafeCast<OutlinedBlock>().getOutlineShape(connection, Vec3i.EMPTY, pixlyzer) else null
if (expected == actual) {
return
@ -156,7 +157,7 @@ object VerifyIntegratedBlockRegistry {
continue
}
val parsed = PixLyzerBlock.deserialize(registries, identifier, value).unsafeCast<PixLyzerBlock>()
registries.block.flattened(parsed, integrated.properties, value, registries, false)
registries.block.flattened(parsed, integrated.properties, value, registries, version, false)
parsed.postInit(registries)
parsed.inject(registries)

View File

@ -24,6 +24,7 @@ import de.bixilon.minosoft.data.registries.blocks.types.properties.shape.outline
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
import de.bixilon.minosoft.protocol.network.connection.play.ConnectionTestUtil.createConnection
import de.bixilon.minosoft.test.IT.NULL_CONNECTION
import org.testng.Assert.assertEquals
import org.testng.Assert.assertTrue
import org.testng.annotations.Test
@ -41,12 +42,12 @@ class CobwebTest : BlockTest<Block>() {
fun testOutlineShape() {
if (block !is OutlinedBlock) throw AssertionError("Not shaped!")
assertEquals(AbstractVoxelShape.FULL, block.getOutlineShape(createConnection(), state))
assertEquals(AbstractVoxelShape.FULL, block.getOutlineShape(createConnection(), Vec3i.EMPTY, state))
}
fun testCollisionShape() {
if (block !is CollidableBlock) return
assertEquals(AbstractVoxelShape.EMPTY, block.getCollisionShape(EmptyCollisionContext, Vec3i.EMPTY, state, null))
assertEquals(AbstractVoxelShape.EMPTY, block.getCollisionShape(NULL_CONNECTION, EmptyCollisionContext, Vec3i.EMPTY, state, null))
}
fun testStates() {

View File

@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.registries.blocks.state.manager.SimpleStateManag
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
import de.bixilon.minosoft.protocol.network.connection.play.ConnectionTestUtil.createConnection
import de.bixilon.minosoft.test.IT.NULL_CONNECTION
import org.testng.Assert.assertEquals
import org.testng.Assert.assertTrue
import org.testng.annotations.Test
@ -37,11 +38,11 @@ class StoneTest : BlockTest<RockBlock.Stone>() {
}
fun testOutlineShape() {
assertEquals(AbstractVoxelShape.FULL, block.getOutlineShape(createConnection(), state))
assertEquals(AbstractVoxelShape.FULL, block.getOutlineShape(createConnection(), Vec3i.EMPTY, state))
}
fun testCollisionShape() {
assertEquals(AbstractVoxelShape.FULL, block.getCollisionShape(EmptyCollisionContext, Vec3i.EMPTY, state, null))
assertEquals(AbstractVoxelShape.FULL, block.getCollisionShape(NULL_CONNECTION, EmptyCollisionContext, Vec3i.EMPTY, state, null))
}
fun testStates() {

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.test
import de.bixilon.kutil.cast.CastUtil.unsafeNull
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
import de.bixilon.minosoft.tags.TagManager
import org.objenesis.ObjenesisStd
@ -25,6 +26,7 @@ object IT {
var VERSION: Version = unsafeNull()
var REGISTRIES: Registries = unsafeNull()
var FALLBACK_TAGS: TagManager = unsafeNull()
val NULL_CONNECTION = OBJENESIS.newInstance(PlayConnection::class.java)
val references: MutableList<Any> = mutableListOf()

View File

@ -100,7 +100,7 @@ class TargetHandler(
// no block, continue going into that direction
return null
}
var shape = state.block.getOutlineShape(camera.connection, state) ?: return null
var shape = state.block.getOutlineShape(camera.connection, blockPosition, state) ?: return null
state.block.nullCast<OffsetBlock>()?.offsetShape(blockPosition)?.let { shape += it }
shape += blockPosition

View File

@ -44,7 +44,7 @@ class BlockRegistry(
) : Registry<Block>(parent = parent, codec = PixLyzerBlock, flattened = flattened, metaType = MetaTypes.BLOCK) {
private fun legacy(block: Block, data: JsonObject, registries: Registries) {
private fun legacy(block: Block, data: JsonObject, version: Version, registries: Registries) {
val statesData = data["states"]?.nullCast<List<JsonObject>>()
val id = data["id"]?.toInt()
val meta = data["meta"]?.toInt()
@ -53,7 +53,7 @@ class BlockRegistry(
// block has only a single state
if (id == null) throw IllegalArgumentException("Missing id (block=$block)!")
val settings = BlockStateSettings.of(block, block.properties, registries, data)
val state = if (block is BlockStateBuilder) block.buildState(settings) else AdvancedBlockState(block, settings)
val state = if (block is BlockStateBuilder) block.buildState(version, settings) else AdvancedBlockState(block, settings)
block.updateStates(setOf(state), state, emptyMap())
registries.blockState[id, meta] = state
return
@ -65,7 +65,7 @@ class BlockRegistry(
val states: MutableSet<BlockState> = ObjectOpenHashSet()
for (stateJson in statesData) {
val settings = BlockStateSettings.of(block, block.properties, registries, stateJson.unsafeCast())
val state = if (block is BlockStateBuilder) block.buildState(settings) else AdvancedBlockState(block, settings)
val state = if (block is BlockStateBuilder) block.buildState(version, settings) else AdvancedBlockState(block, settings)
states += state
val id = stateJson["id"]?.toInt() ?: id ?: throw IllegalArgumentException("Missing block id: $block!")
@ -84,13 +84,13 @@ class BlockRegistry(
block.updateStates(states, default, properties.mapValues { it.value.toTypedArray() })
}
fun flattened(block: Block, list: BlockPropertyList?, data: JsonObject, registries: Registries, addBlockStates: Boolean) {
fun flattened(block: Block, list: BlockPropertyList?, data: JsonObject, registries: Registries, version: Version, addBlockStates: Boolean) {
val properties: MutableMap<BlockProperty<*>, MutableSet<Any>> = mutableMapOf()
val states: MutableSet<BlockState> = ObjectOpenHashSet()
for ((stateId, stateJson) in data["states"].asAnyMap()) {
val settings = BlockStateSettings.of(block, list, registries, stateJson.unsafeCast())
val state = if (block is BlockStateBuilder) block.buildState(settings) else AdvancedBlockState(block, settings)
val state = if (block is BlockStateBuilder) block.buildState(version, settings) else AdvancedBlockState(block, settings)
states += state
if (addBlockStates) {
@ -123,9 +123,9 @@ class BlockRegistry(
}
if (flattened) {
flattened(block, block.properties, data, registries, true)
flattened(block, block.properties, data, registries, version, true)
} else {
legacy(block, data, registries)
legacy(block, data, version, registries)
}
return block

View File

@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.registries.blocks.types.air.AirBlock
import de.bixilon.minosoft.data.registries.blocks.types.bee.HoneyBlock
import de.bixilon.minosoft.data.registries.blocks.types.building.WoolBlock
import de.bixilon.minosoft.data.registries.blocks.types.building.dirt.GrassBlock
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.blocks.types.building.plants.DoublePlant
import de.bixilon.minosoft.data.registries.blocks.types.building.plants.FernBlock
import de.bixilon.minosoft.data.registries.blocks.types.building.snow.SnowBlock
@ -61,17 +62,18 @@ object BlockFactories : DefaultFactory<BlockFactory<*>>(
PowderSnowBlock,
DoorBlock.IronDoor,
Oak.Leaves,
Spruce.Leaves,
Birch.Leaves,
Jungle.Leaves,
Acacia.Leaves,
DarkOak.Leaves,
Mangrove.Leaves,
Cherry.Leaves,
Azalea.Leaves,
FloweringAzalea.Leaves,
Oak.Leaves, Oak.Door,
Spruce.Leaves, Spruce.Door,
Birch.Leaves, Birch.Door,
Jungle.Leaves, Jungle.Door,
Acacia.Leaves, Acacia.Door,
DarkOak.Leaves, DarkOak.Door,
Mangrove.Leaves, Mangrove.Door,
Cherry.Leaves, Cherry.Door,
Azalea.Leaves, Azalea.Door,
FloweringAzalea.Leaves, FloweringAzalea.Door,
SnowBlock, SnowLayerBlock,
FernBlock.DeadBush, FernBlock.Grass, FernBlock.Fern,

View File

@ -51,7 +51,6 @@ import de.bixilon.minosoft.data.registries.factory.clazz.DefaultClassFactory
@Deprecated("BlockFactories")
object PixLyzerBlockFactories : DefaultClassFactory<PixLyzerBlockFactory<*>>(
PixLyzerBlock,
DoorBlock,
LeverBlock,
NoteBlock,
RepeaterBlock,

View File

@ -35,7 +35,8 @@ object BlockProperties {
val LIT = BooleanProperty("lit").register()
val WATERLOGGED = BooleanProperty("waterlogged").register()
val STAIR_DIRECTIONAL = EnumProperty("shape", Shapes).register()
val STAIR_HALF = EnumProperty("half", Halves).register()
val SLAB_HALF = EnumProperty("half", Halves).register()
val STAIR_HALF = EnumProperty("half", Halves, EnumSet.of(Halves.UPPER, Halves.LOWER))
val SLAB_TYPE = EnumProperty("type", Halves).register()
val FLUID_LEVEL = FluidBlock.LEVEL.register()
val MOISTURE_LEVEL = IntProperty("moisture").register()

View File

@ -14,8 +14,9 @@
package de.bixilon.minosoft.data.registries.blocks.state.builder
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.protocol.versions.Version
interface BlockStateBuilder {
fun buildState(settings: BlockStateSettings): BlockState
fun buildState(version: Version, settings: BlockStateSettings): BlockState
}

View File

@ -40,6 +40,7 @@ import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.physics.PhysicsConstants
import de.bixilon.minosoft.physics.entities.EntityPhysics
import de.bixilon.minosoft.protocol.versions.Version
import kotlin.math.abs
open class HoneyBlock(identifier: ResourceLocation = Companion.identifier, settings: BlockSettings) : Block(identifier, settings), EntityCollisionHandler, JumpBlock, VelocityBlock, BeeBlock, TranslucentBlock, InstantBreakableBlock, StatelessCollidable, FullOutlinedBlock, BlockWithItem<Item>, BlockStateBuilder {
@ -48,7 +49,7 @@ open class HoneyBlock(identifier: ResourceLocation = Companion.identifier, setti
override val jumpBoost: Float get() = 0.5f
override val collisionShape: AbstractVoxelShape get() = COLLISION_BOX
override fun buildState(settings: BlockStateSettings) = BlockState(this, settings)
override fun buildState(version: Version, settings: BlockStateSettings) = BlockState(this, settings)
private fun isSliding(position: BlockPosition, physics: EntityPhysics<*>): Boolean {
if (physics.onGround) {

View File

@ -31,12 +31,13 @@ import de.bixilon.minosoft.data.registries.item.items.Item
import de.bixilon.minosoft.data.registries.item.items.tool.shears.ShearsItem
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
abstract class WoolBlock(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), FullOpaqueBlock, BlockStateBuilder, CustomDiggingBlock, DyedBlock, BlockWithItem<Item> {
override val item: Item = this::item.inject(identifier)
override val hardness: Float get() = 0.8f
override fun buildState(settings: BlockStateSettings): BlockState {
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
return BlockState(this, settings.luminance)
}

View File

@ -0,0 +1,205 @@
/*
* 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.data.registries.blocks.types.building.door
import de.bixilon.kotlinglm.vec3.Vec3i
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.kutil.exception.Broken
import de.bixilon.kutil.primitive.BooleanUtil.toBoolean
import de.bixilon.minosoft.camera.target.targets.BlockTarget
import de.bixilon.minosoft.data.container.stack.ItemStack
import de.bixilon.minosoft.data.direction.DirectionUtil.rotateY
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.entities.block.BlockEntity
import de.bixilon.minosoft.data.entities.entities.player.Hands
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.properties.*
import de.bixilon.minosoft.data.registries.blocks.properties.list.MapPropertyList
import de.bixilon.minosoft.data.registries.blocks.properties.primitives.BooleanProperty
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.shapes.collision.context.CollisionContext
import de.bixilon.minosoft.data.registries.blocks.state.AdvancedBlockState
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.state.PropertyBlockState
import de.bixilon.minosoft.data.registries.blocks.state.builder.BlockStateBuilder
import de.bixilon.minosoft.data.registries.blocks.state.builder.BlockStateSettings
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.data.registries.blocks.types.properties.InteractBlockHandler
import de.bixilon.minosoft.data.registries.blocks.types.properties.item.BlockWithItem
import de.bixilon.minosoft.data.registries.blocks.types.properties.shape.collision.CollidableBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.shape.outline.OutlinedBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.size.DoubleSizeBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.item.items.Item
import de.bixilon.minosoft.data.registries.item.items.tool.axe.AxeRequirement
import de.bixilon.minosoft.data.registries.item.items.tool.pickaxe.PickaxeRequirement
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.models.block.state.DirectBlockModel
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
import de.bixilon.minosoft.gui.rendering.models.block.state.render.PickedBlockRender
import de.bixilon.minosoft.gui.rendering.models.loader.legacy.ModelChooser
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.input.interaction.InteractionResults
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
import java.util.*
abstract class DoorBlock(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), BlockWithItem<Item>, ModelChooser, DoubleSizeBlock, InteractBlockHandler, OutlinedBlock, CollidableBlock, BlockStateBuilder {
override val item: Item = this::item.inject(identifier)
override fun register(version: Version, list: MapPropertyList) {
super<Block>.register(version, list)
list += HALF; list += HINGE; list += POWERED; list += FACING; list += OPEN
}
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
if (!version.flattened) return PropertyBlockState(this, settings)
val hinge = settings.properties!![HINGE].unsafeCast<Sides>()
val open = settings.properties[OPEN].toBoolean()
val facing = settings.properties[FACING].unsafeCast<Directions>()
val shape = getShape(hinge, open, facing)
return AdvancedBlockState(this, settings.properties, 0, shape, shape, settings.lightProperties, settings.solidRenderer)
}
fun cycleOpen(connection: PlayConnection, position: BlockPosition, state: BlockState) {
}
private fun getShape(hinge: Sides, open: Boolean, facing: Directions): VoxelShape {
val direction = when {
!open -> facing.inverted
hinge == Sides.LEFT -> facing.rotateY(-1)
hinge == Sides.RIGHT -> facing.rotateY(1)
else -> Broken()
}
return SHAPES[direction.ordinal - Directions.SIDE_OFFSET]
}
private fun getLegacyShape(connection: PlayConnection, position: BlockPosition, state: BlockState): VoxelShape? {
val isTop = isTop(state, connection)
val other = connection.world[position + if (isTop) Directions.DOWN else Directions.UP]
if (other !is PropertyBlockState || other.block !is DoorBlock) return null
val top = if (isTop) state else other
val bottom = if (isTop) other else state
val hinge = top[HINGE]
val facing = bottom[FACING]
val open = bottom[OPEN]
return getShape(hinge, open, facing)
}
override fun getOutlineShape(connection: PlayConnection, position: BlockPosition, state: BlockState): AbstractVoxelShape? {
if (connection.version.flattened) return super.getOutlineShape(connection, position, state)
return getLegacyShape(connection, position, state)
}
override fun getCollisionShape(connection: PlayConnection, context: CollisionContext, position: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
if (connection.version.flattened) return super.getCollisionShape(connection, context, position, state, blockEntity)
return getLegacyShape(connection, position, state)
}
override fun bakeModel(context: RenderContext, model: DirectBlockModel) {
if (context.connection.version.flattened) return super.bakeModel(context, model)
val models: MutableMap<Map<BlockProperty<*>, Any>, BlockRender?> = hashMapOf()
for (properties in this.properties.unpack()) {
val renderer = model.choose(properties)?.bake() ?: continue
models[properties] = renderer
}
if (models.isEmpty()) return
this.model = DoorModel(models)
}
companion object {
val HALF = EnumProperty("half", Halves, EnumSet.of(Halves.UPPER, Halves.LOWER))
val HINGE = EnumProperty("hinge", Sides)
val POWERED = BlockProperties.POWERED
val FACING = BlockProperties.FACING_HORIZONTAL
val OPEN = BooleanProperty("open")
private val SHAPES = arrayOf(
VoxelShape(0.0, 0.0, 0.0, 1.0, 1.0, 0.1875),
VoxelShape(0.0, 0.0, 0.8125, 1.0, 1.0, 1.0),
VoxelShape(0.0, 0.0, 0.0, 0.1875, 1.0, 1.0),
VoxelShape(0.8125, 0.0, 0.0, 1.0, 1.0, 1.0),
)
}
private inner class DoorModel(
val models: Map<Map<BlockProperty<*>, Any>, BlockRender?>
) : PickedBlockRender {
override val default: BlockRender?
get() = null
fun pick(half: Halves, hinge: Sides, powered: Boolean, facing: Directions, open: Boolean): BlockRender? {
return models[mapOf(HALF to half, HINGE to hinge, POWERED to powered, FACING to facing, OPEN to open)]
}
override fun pick(state: BlockState, neighbours: Array<BlockState?>): BlockRender? {
if (state !is PropertyBlockState) return null
val half = state[HALF]
val other = if (half == Halves.UPPER) neighbours[Directions.O_DOWN] else neighbours[Directions.O_UP]
if (other !is PropertyBlockState || other.block !is DoorBlock) return null
val top = if (half == Halves.UPPER) state else other
val bottom = if (half == Halves.UPPER) other else state
val hinge = top[HINGE]
val powered = top[POWERED]
val facing = bottom[FACING]
val open = bottom[OPEN]
return pick(half, hinge, powered, facing, open)
}
}
abstract class WoodenDoor(identifier: ResourceLocation, settings: BlockSettings) : DoorBlock(identifier, settings), AxeRequirement {
override val hardness get() = 3.0f
override fun interact(connection: PlayConnection, target: BlockTarget, hand: Hands, stack: ItemStack?): InteractionResults {
cycleOpen(connection, target.blockPosition, target.state)
return InteractionResults.SUCCESS
}
}
open class IronDoor(identifier: ResourceLocation = Companion.identifier, settings: BlockSettings) : DoorBlock(identifier, settings), PickaxeRequirement {
override val hardness get() = 5.0f
override fun interact(connection: PlayConnection, target: BlockTarget, hand: Hands, stack: ItemStack?): InteractionResults {
return InteractionResults.FAILED
}
companion object : BlockFactory<IronDoor> {
override val identifier = minecraft("iron_door")
override fun build(registries: Registries, settings: BlockSettings) = IronDoor(settings = settings)
}
}
}

View File

@ -25,6 +25,7 @@ import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.data.registries.blocks.types.legacy.FlatteningRenamedModel
import de.bixilon.minosoft.data.registries.blocks.types.properties.ReplaceableBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.hardness.InstantBreakableBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.item.BlockWithItem
import de.bixilon.minosoft.data.registries.blocks.types.properties.offset.RandomOffsetBlock
@ -48,7 +49,7 @@ import de.bixilon.minosoft.gui.rendering.tint.tints.grass.TallGrassTintCalculato
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
abstract class DoublePlant(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), ShearsRequirement, BlockWithItem<Item>, FullOutlinedBlock, RandomOffsetBlock, InstantBreakableBlock, ModelChooser, DoubleSizeBlock {
abstract class DoublePlant(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), ShearsRequirement, BlockWithItem<Item>, FullOutlinedBlock, RandomOffsetBlock, InstantBreakableBlock, ModelChooser, DoubleSizeBlock, ReplaceableBlock {
override val randomOffset get() = RandomOffsetTypes.XYZ
override val item: Item = this::item.inject(identifier)
@ -93,7 +94,7 @@ abstract class DoublePlant(identifier: ResourceLocation, settings: BlockSettings
}
companion object {
val HALF = EnumProperty("half", Halves)
val HALF = EnumProperty("half", Halves, setOf(Halves.UPPER, Halves.LOWER))
}
open class Sunflower(identifier: ResourceLocation = Companion.identifier, settings: BlockSettings) : DoublePlant(identifier, settings) {

View File

@ -18,6 +18,7 @@ import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.data.registries.blocks.types.legacy.FlatteningRenamedModel
import de.bixilon.minosoft.data.registries.blocks.types.properties.ReplaceableBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.hardness.InstantBreakableBlock
import de.bixilon.minosoft.data.registries.blocks.types.properties.item.BlockWithItem
import de.bixilon.minosoft.data.registries.blocks.types.properties.offset.RandomOffsetBlock
@ -29,15 +30,16 @@ import de.bixilon.minosoft.data.registries.item.items.Item
import de.bixilon.minosoft.data.registries.item.items.tool.shears.ShearsRequirement
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.gui.rendering.tint.TintProvider
import de.bixilon.minosoft.gui.rendering.tint.tints.grass.GrassTinted
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
abstract class FernBlock(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), ShearsRequirement, BlockWithItem<Item>, OutlinedBlock, RandomOffsetBlock, InstantBreakableBlock {
abstract class FernBlock(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), ShearsRequirement, BlockWithItem<Item>, OutlinedBlock, RandomOffsetBlock, InstantBreakableBlock, ReplaceableBlock {
override val randomOffset get() = RandomOffsetTypes.XYZ
override val item: Item = this::item.inject(identifier)
override fun getOutlineShape(connection: PlayConnection, blockState: BlockState) = SHAPE
override fun getOutlineShape(connection: PlayConnection, position: BlockPosition, state: BlockState) = SHAPE
companion object {
private val SHAPE = VoxelShape(0.125, 0.0, 0.125, 0.875, 0.8125, 0.875)

View File

@ -33,13 +33,14 @@ import de.bixilon.minosoft.data.registries.item.items.Item
import de.bixilon.minosoft.data.registries.item.items.tool.shovel.ShovelRequirement
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape
import de.bixilon.minosoft.protocol.versions.Version
class SnowLayerBlock(identifier: ResourceLocation = Companion.identifier, settings: BlockSettings) : Block(identifier, settings), FixedCollidable, OutlinedBlock, FlatteningRenamedModel, ShovelRequirement, BlockWithItem<Item>, AbstractSnowBlock, BlockStateBuilder {
override val item: Item = this::item.inject(identifier)
override val hardness get() = 0.1f
override val legacyModelName get() = minecraft("snow_layer")
override fun buildState(settings: BlockStateSettings): BlockState {
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
val layer = settings.properties?.get(BlockProperties.SNOW_LAYERS)?.toInt() ?: return BlockState(this, settings)
settings.collisionShape = VoxelShape(0.0, 0.0, 0.0, 1.0, (layer - 1) * LAYER_HEIGHT, 1.0)

View File

@ -36,6 +36,7 @@ import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.data.registries.shapes.aabb.AABB
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
open class ScaffoldingBlock(identifier: ResourceLocation = ScaffoldingBlock.identifier, settings: BlockSettings) : Block(identifier, settings), ClimbingBlock, TransparentBlock, InstantBreakableBlock, OutlinedBlock, CollidableBlock, BlockWithItem<ClimbingItems.ScaffoldingItem> {
@ -44,20 +45,20 @@ open class ScaffoldingBlock(identifier: ResourceLocation = ScaffoldingBlock.iden
override fun canPushOut(entity: Entity) = false
override fun getOutlineShape(connection: PlayConnection, blockState: BlockState): AbstractVoxelShape? {
override fun getOutlineShape(connection: PlayConnection, position: BlockPosition, state: BlockState): AbstractVoxelShape? {
if (connection.player.items.inventory[EquipmentSlots.MAIN_HAND]?.item?.item is ClimbingItems.ScaffoldingItem) {
return AbstractVoxelShape.FULL
}
return if (blockState.isBottom()) BOTTOM_OUTLINE else OUTLINE
return if (state.isBottom()) BOTTOM_OUTLINE else OUTLINE
}
override fun getCollisionShape(context: CollisionContext, blockPosition: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
if (context.isAbove(1.0, blockPosition) && (context !is EntityCollisionContext || !context.descending)) {
override fun getCollisionShape(connection: PlayConnection, context: CollisionContext, position: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
if (context.isAbove(1.0, position) && (context !is EntityCollisionContext || !context.descending)) {
return OUTLINE
}
val distance = state[BlockProperties.DISTANCE] ?: 0
val distance = state[BlockProperties.DISTANCE]
if (distance == 0 || !state.isBottom() || !context.isAbove(0.0, blockPosition)) {
if (distance == 0 || !state.isBottom() || !context.isAbove(0.0, position)) {
return null
}
return COLLISION

View File

@ -49,8 +49,8 @@ abstract class FluidBlock(identifier: ResourceLocation, settings: BlockSettings)
fluid.nullCast<TintedBlock>()?.initTint(manager)
}
override fun getOutlineShape(connection: PlayConnection, blockState: BlockState): VoxelShape {
return VoxelShape(AABB(Vec3.EMPTY, Vec3(1.0f, fluid.getHeight(blockState), 1.0f)))
override fun getOutlineShape(connection: PlayConnection, position: BlockPosition, state: BlockState): VoxelShape {
return VoxelShape(AABB(Vec3.EMPTY, Vec3(1.0f, fluid.getHeight(state), 1.0f)))
}
override fun getLightProperties(blockState: BlockState) = LIGHT_PROPERTIES

View File

@ -39,7 +39,7 @@ open class LegacyBlock(
override val modelName: ResourceLocation? = data["model"]?.toResourceLocation() ?: identifier
override fun buildState(settings: BlockStateSettings): BlockState {
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
return AdvancedBlockState(this, settings)
}

View File

@ -1,45 +0,0 @@
/*
* 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.data.registries.blocks.types.pixlyzer
import de.bixilon.minosoft.camera.target.targets.BlockTarget
import de.bixilon.minosoft.data.container.stack.ItemStack
import de.bixilon.minosoft.data.entities.entities.player.Hands
import de.bixilon.minosoft.data.registries.blocks.factory.PixLyzerBlockFactory
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.registries.blocks.types.properties.InteractBlockHandler
import de.bixilon.minosoft.data.registries.blocks.types.properties.size.DoubleSizeBlock
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.input.interaction.InteractionResults
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
open class DoorBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : PixLyzerBlock(resourceLocation, registries, data), InteractBlockHandler, DoubleSizeBlock {
override fun interact(connection: PlayConnection, target: BlockTarget, hand: Hands, stack: ItemStack?): InteractionResults {
if (target.state.block.identifier.path.startsWith("iron")) { // TODO
return InteractionResults.FAILED
}
connection.world[target.blockPosition] = target.state.cycle(BlockProperties.DOOR_OPEN)
return InteractionResults.SUCCESS
}
companion object : PixLyzerBlockFactory<DoorBlock> {
override fun build(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>): DoorBlock {
return DoorBlock(resourceLocation, registries, data)
}
}
}

View File

@ -53,6 +53,7 @@ import de.bixilon.minosoft.gui.rendering.tint.TintedBlock
import de.bixilon.minosoft.gui.rendering.util.VecUtil.getWorldOffset
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
import de.bixilon.minosoft.protocol.versions.Versions
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
@ -87,7 +88,7 @@ open class PixLyzerBlock(
ITEM_FIELD.inject<RegistryItem>(data["item"])
}
override fun buildState(settings: BlockStateSettings): BlockState {
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
return AdvancedBlockState(this, settings)
}

View File

@ -35,13 +35,14 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.item.items.Item
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.physics.entities.EntityPhysics
import de.bixilon.minosoft.protocol.versions.Version
import kotlin.math.abs
open class SlimeBlock(identifier: ResourceLocation = SlimeBlock.identifier, settings: BlockSettings) : Block(identifier, settings), BouncingHandler, StepHandler, InstantBreakableBlock, FrictionBlock, TranslucentBlock, FullBlock, BlockWithItem<Item>, BlockStateBuilder {
override val item: Item = this::item.inject(identifier) // TODO
override val friction: Float get() = 0.8f
override fun buildState(settings: BlockStateSettings) = BlockState(this, settings)
override fun buildState(version: Version, settings: BlockStateSettings) = BlockState(this, settings)
override fun onEntityStep(entity: Entity, physics: EntityPhysics<*>, position: Vec3i, state: BlockState) {
val velocity = entity.physics.velocity

View File

@ -40,12 +40,14 @@ import de.bixilon.minosoft.data.registries.shapes.aabb.AABB
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape
import de.bixilon.minosoft.physics.entities.EntityPhysics
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
import de.bixilon.minosoft.tags.entity.MinecraftEntityTags.isIn
open class PowderSnowBlock(identifier: ResourceLocation = PowderSnowBlock.identifier, settings: BlockSettings) : Block(identifier, settings), EntityCollisionHandler, CollidableBlock, FullOutlinedBlock, OpaqueBlock, BlockStateBuilder {
override val hardness: Float get() = 0.25f
override fun buildState(settings: BlockStateSettings) = BlockState(this, settings)
override fun buildState(version: Version, settings: BlockStateSettings) = BlockState(this, settings)
override fun onEntityCollision(entity: Entity, physics: EntityPhysics<*>, position: Vec3i, state: BlockState) {
if (entity is LivingEntity && physics.positionInfo.block?.block !is PowderSnowBlock) {
@ -54,14 +56,14 @@ open class PowderSnowBlock(identifier: ResourceLocation = PowderSnowBlock.identi
physics.slowMovement(state, SLOW)
}
override fun getCollisionShape(context: CollisionContext, blockPosition: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
override fun getCollisionShape(connection: PlayConnection, context: CollisionContext, position: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
if (context !is EntityCollisionContext) {
return null
}
if (context.physics.fallDistance > 2.5f) {
return FALLING_SHAPE
}
if (context.entity is FallingBlockEntity || (context.entity.canWalkOnPowderSnow() && context.isAbove(1.0, blockPosition) && !context.descending)) {
if (context.entity is FallingBlockEntity || (context.entity.canWalkOnPowderSnow() && context.isAbove(1.0, position) && !context.descending)) {
return AbstractVoxelShape.FULL
}
return null

View File

@ -19,5 +19,5 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
interface ReplaceableBlock {
fun canReplace(connection: PlayConnection, state: BlockState, position: BlockPosition): Boolean
fun canReplace(connection: PlayConnection, state: BlockState, position: BlockPosition): Boolean = true
}

View File

@ -19,13 +19,14 @@ import de.bixilon.minosoft.data.registries.blocks.shapes.collision.context.Colli
import de.bixilon.minosoft.data.registries.blocks.state.AdvancedBlockState
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
/**
* A block with collisions (a player can not move through the shape)
*/
interface CollidableBlock {
fun getCollisionShape(context: CollisionContext, blockPosition: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
fun getCollisionShape(connection: PlayConnection, context: CollisionContext, position: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
if (state is AdvancedBlockState) {
return state.collisionShape
}

View File

@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.registries.blocks.state.AdvancedBlockState
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.types.properties.shape.collision.CollidableBlock
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
/**
* The collision box does not depend on any temporary state, it only depends on the block state
@ -31,7 +32,7 @@ interface FixedCollidable : CollidableBlock {
return state.nullCast<AdvancedBlockState>()?.collisionShape
}
override fun getCollisionShape(context: CollisionContext, blockPosition: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
override fun getCollisionShape(connection: PlayConnection, context: CollisionContext, position: Vec3i, state: BlockState, blockEntity: BlockEntity?): AbstractVoxelShape? {
return getCollisionShape(state)
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.properties.shape.outlin
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
/**
@ -22,5 +23,5 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
*/
interface FullOutlinedBlock : OutlinedBlock {
override fun getOutlineShape(connection: PlayConnection, blockState: BlockState) = AbstractVoxelShape.FULL
override fun getOutlineShape(connection: PlayConnection, position: BlockPosition, state: BlockState) = AbstractVoxelShape.FULL
}

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.properties.shape.outlin
import de.bixilon.minosoft.data.registries.blocks.state.AdvancedBlockState
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
/**
@ -23,9 +24,9 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
*/
interface OutlinedBlock {
fun getOutlineShape(connection: PlayConnection, blockState: BlockState): AbstractVoxelShape? {
if (blockState is AdvancedBlockState) {
return blockState.outlineShape
fun getOutlineShape(connection: PlayConnection, position: BlockPosition, state: BlockState): AbstractVoxelShape? {
if (state is AdvancedBlockState) {
return state.outlineShape
}
return null
}

View File

@ -27,12 +27,13 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.item.items.Item
import de.bixilon.minosoft.data.registries.item.items.tool.pickaxe.PickaxeRequirement
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.protocol.versions.Version
abstract class RockBlock(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), PickaxeRequirement, FullOpaqueBlock, BlockStateBuilder, BlockWithItem<Item> {
override val item: Item = this::item.inject(identifier)
override val hardness: Float get() = 1.5f
override fun buildState(settings: BlockStateSettings): BlockState {
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
return BlockState(this, settings.luminance)
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface Acacia {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Acacia {
companion object : BlockFactory<Door> {
override val identifier = minecraft("acacia_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface Azalea {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Azalea {
companion object : BlockFactory<Door> {
override val identifier = minecraft("azalea_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -34,4 +35,13 @@ interface Birch {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Birch {
companion object : BlockFactory<Door> {
override val identifier = minecraft("birch_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface Cherry {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Cherry {
companion object : BlockFactory<Door> {
override val identifier = minecraft("cherry_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface DarkOak {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), DarkOak {
companion object : BlockFactory<Door> {
override val identifier = minecraft("dark_oak_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface FloweringAzalea {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), FloweringAzalea {
companion object : BlockFactory<Door> {
override val identifier = minecraft("flowering_azalea_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface Jungle {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Jungle {
companion object : BlockFactory<Door> {
override val identifier = minecraft("jungle_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -39,6 +39,7 @@ import de.bixilon.minosoft.gui.rendering.tint.TintManager
import de.bixilon.minosoft.gui.rendering.tint.TintProvider
import de.bixilon.minosoft.gui.rendering.tint.TintedBlock
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.versions.Version
abstract class LeavesBlock(identifier: ResourceLocation, settings: BlockSettings) : Block(identifier, settings), CustomBlockCulling, FullBlock, BlockStateBuilder, ToolRequirement, CustomDiggingBlock, WaterloggableBlock, BlockWithItem<Item>, LightedBlock, TintedBlock {
override val hardness get() = 0.2f
@ -49,7 +50,7 @@ abstract class LeavesBlock(identifier: ResourceLocation, settings: BlockSettings
this::tintProvider.forceSet(manager.foliageTintCalculator)
}
override fun buildState(settings: BlockStateSettings): BlockState {
override fun buildState(version: Version, settings: BlockStateSettings): BlockState {
return PropertyBlockState(this, settings)
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +30,13 @@ interface Mangrove {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Mangrove {
companion object : BlockFactory<Door> {
override val identifier = minecraft("mangrove_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,8 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.blocks.types.legacy.FlatteningRenamedModel
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -29,4 +31,14 @@ interface Oak {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Oak, FlatteningRenamedModel {
override val legacyModelName get() = minecraft("wooden_door")
companion object : BlockFactory<Door> {
override val identifier = minecraft("oak_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.registries.blocks.types.wood
import de.bixilon.minosoft.data.registries.blocks.factory.BlockFactory
import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings
import de.bixilon.minosoft.data.registries.blocks.types.building.door.DoorBlock
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.data.registries.registries.Registries
@ -34,4 +35,13 @@ interface Spruce {
override fun build(registries: Registries, settings: BlockSettings) = Leaves(settings = settings)
}
}
class Door(identifier: ResourceLocation = this.identifier, settings: BlockSettings) : DoorBlock.WoodenDoor(identifier, settings), Spruce {
companion object : BlockFactory<Door> {
override val identifier = minecraft("spruce_door")
override fun build(registries: Registries, settings: BlockSettings) = Door(settings = settings)
}
}
}

View File

@ -69,7 +69,7 @@ interface PlaceableItem : ItemInteractBlockHandler {
val state: BlockState = getPlacementState(connection, target, stack)
if (state.block is CollidableBlock) {
val shape = state.block.getCollisionShape(EntityCollisionContext(player), placePosition, state, null)?.plus(placePosition)
val shape = state.block.getCollisionShape(connection, EntityCollisionContext(player), placePosition, state, null)?.plus(placePosition)
if (shape != null && connection.world.entities.isEntityIn(shape)) {
return InteractionResults.INVALID
}
@ -84,6 +84,7 @@ interface PlaceableItem : ItemInteractBlockHandler {
if (state.block is BlockPlaceHandler) {
state.block.onPlace(connection, placePosition, state, null) // TODO: block entity
}
// TODO: handle ReplaceableBlock::onDestroy
}
state.block.soundGroup?.let { group ->

View File

@ -47,7 +47,7 @@ object BlockDestroyedHandler : WorldEventHandler {
val particleRenderer = connection.world.particleRenderer ?: return
val type = connection.registries.particleType[BlockDustParticle] ?: return
if (state.block !is OutlinedBlock) return
val shape = state.block.getOutlineShape(connection, state) ?: return
val shape = state.block.getOutlineShape(connection, position, state) ?: return
val particleData = BlockParticleData(state, type)
for (aabb in shape) {

View File

@ -109,7 +109,7 @@ class WorldIterator(
if (state.block !is CollidableBlock) continue
if (predicate != null && !predicate.invoke(state)) continue
val shape = state.block.getCollisionShape(context, position, state, null) ?: continue
val shape = state.block.getCollisionShape(world.connection, context, position, state, null) ?: continue
if ((shape + position).intersect(aabb)) {
return true
}

View File

@ -281,7 +281,7 @@ class FluidSectionMesher(
if (!fluid.matches(state)) {
// TODO: this was !blockState.material.solid
if (state.block !is CollidableBlock || state.block.getCollisionShape(EmptyCollisionContext, blockPosition, state, null) == AbstractVoxelShape.EMPTY) {
if (state.block !is CollidableBlock || state.block.getCollisionShape(context.connection, EmptyCollisionContext, blockPosition, state, null) == AbstractVoxelShape.EMPTY) {
count++
}
continue

View File

@ -128,11 +128,11 @@ class BlockOutlineRenderer(
}
target.state.block.getOutlineShape(connection, target.state)?.let { mesh.drawVoxelShape(it, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, profile.outlineColor) }
target.state.block.getOutlineShape(connection, target.blockPosition, target.state)?.let { mesh.drawVoxelShape(it, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, profile.outlineColor) }
if (target.state.block is CollidableBlock && profile.collisions) { // TODO: block entity
target.state.block.getCollisionShape(EntityCollisionContext(connection.player), target.blockPosition, target.state, null)?.let { mesh.drawVoxelShape(it, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, profile.collisionColor, 0.005f) }
target.state.block.getCollisionShape(connection, EntityCollisionContext(connection.player), target.blockPosition, target.state, null)?.let { mesh.drawVoxelShape(it, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, profile.collisionColor, 0.005f) }
}
this.nextMesh = mesh

View File

@ -45,7 +45,7 @@ class WallOverlay(context: RenderContext) : SimpleOverlay(context) {
return false
}
val camera = context.connection.camera.entity
val shape = blockState.block.getCollisionShape(EntityCollisionContext(camera), position, blockState, null) ?: return false // TODO: block entity
val shape = blockState.block.getCollisionShape(context.connection, EntityCollisionContext(camera), position, blockState, null) ?: return false // TODO: block entity
if (!shape.intersect(player.physics.aabb)) {
return false
}

View File

@ -55,11 +55,11 @@ object CollisionMovementPhysics {
inChunk.x = position.x and 0x0F
inChunk.z = position.z and 0x0F
state.block.getCollisionShape(context, position, state, chunk.getBlockEntity(inChunk))
state.block.getCollisionShape(connection, context, position, state, chunk.getBlockEntity(inChunk))
}
else -> {
state.block.getCollisionShape(context, position, state, null)
state.block.getCollisionShape(connection, context, position, state, null)
}
} ?: continue
shape += position