wip block interactions

This commit is contained in:
Bixilon 2021-05-16 21:41:04 +02:00
parent fc04dc9235
commit 88c38c68bb
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
27 changed files with 382 additions and 67 deletions

View File

@ -47,6 +47,9 @@ object KeyBindingsNames {
val CLOSE = ResourceLocation("minosoft:close")
val BLOCK_INTERACT = ResourceLocation("minosoft:interact_block")
val SELECT_HOTBAR_SLOTS = arrayOf(
ResourceLocation("minosoft:select_hotbar_slot_1"),
ResourceLocation("minosoft:select_hotbar_slot_2"),
@ -200,5 +203,10 @@ object KeyBindingsNames {
),
ignoreConsumer = true
),
BLOCK_INTERACT to KeyBinding(
mutableMapOf(
KeyAction.CHANGE to mutableSetOf(KeyCodes.MOUSE_BUTTON_RIGHT)
)
)
)
}

View File

@ -19,6 +19,7 @@ import com.google.gson.JsonPrimitive
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.data.mappings.materials.Material
import de.bixilon.minosoft.data.mappings.versions.VersionMapping
import de.bixilon.minosoft.data.text.RGBColor
@ -28,10 +29,12 @@ import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockLikeRenderer
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockRenderer
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.MultipartRenderer
import de.bixilon.minosoft.util.enum.ValuesEnum
import glm_.vec3.Vec3i
import java.util.*
import kotlin.math.abs
import kotlin.random.Random
import kotlin.reflect.full.companionObjectInstance
data class BlockState(
val block: Block,
@ -111,7 +114,6 @@ data class BlockState(
return renderers[abs(random.nextLong().toInt() % renderers.size)]
}
companion object {
fun deserialize(owner: Block, versionMapping: VersionMapping, data: JsonObject, models: Map<ResourceLocation, BlockModel>): BlockState {
@ -225,10 +227,43 @@ data class BlockState(
}
}
// properties
fun isPowered(): Boolean? {
return properties[BlockProperties.POWERED] as Boolean?
fun withProperties(vararg properties: Pair<BlockProperties, Any>): BlockState {
val newProperties = this.properties.toMutableMap()
for ((key, value) in properties) {
newProperties[key] = value
}
val wannabe = WannabeBlockState(resourceLocation = this.block.resourceLocation, properties = newProperties)
for (blockState in this.block.states) {
if (blockState.equals(wannabe)) {
return blockState
}
}
throw IllegalArgumentException("Can not find ${this.block.resourceLocation}, with properties: $properties")
}
fun cycle(property: BlockProperties): BlockState {
val currentValue = properties[property] ?: throw IllegalArgumentException("$this has no property $property")
when (currentValue) {
is Boolean -> {
return withProperties(property to !currentValue)
}
is Number -> {
return try {
withProperties(property to (currentValue.toInt() + 1))
} catch (exception: IllegalArgumentException) {
withProperties(property to 0)
}
}
is Enum<*> -> {
val values = currentValue::class.companionObjectInstance as ValuesEnum<Enum<*>>
return withProperties(property to values.next(currentValue))
}
else -> {
return this
}
}
}
// ToDo
}

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.data.mappings.blocks
enum class BlockUsages {
/**
* Usage get consumed (like trying to open an iron door) without animation
*/
CONSUME,
/**
* Usage get consumed (like pressing a button, opening a door, right clicking on block entities) with animation
*/
SUCCESS,
/**
* Nothing happens from block side (e.g. right clicking on dirt). You can maybe place a block, whatever
*/
PASS,
/**
* Nothing happens, basically `CONSUME`, but a requirement was not satisfied.
*/
FAIL,
;
}

View File

@ -18,7 +18,7 @@ import de.bixilon.minosoft.data.entities.block.BlockEntity
import de.bixilon.minosoft.data.entities.block.BlockEntityFactory
import de.bixilon.minosoft.data.entities.block.DefaultBlockEntityMetaDataFactory
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.data.mappings.registry.RegistryItem
import de.bixilon.minosoft.data.mappings.registry.ResourceLocationDeserializer
import de.bixilon.minosoft.data.mappings.versions.VersionMapping

View File

@ -13,25 +13,20 @@
package de.bixilon.minosoft.data.mappings.blocks.entites
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.data.mappings.registry.Registry
import de.bixilon.minosoft.data.mappings.versions.VersionMapping
class BlockEntityTypeRegistry(
private val versionMapping: VersionMapping,
private var parentRegistry: BlockEntityTypeRegistry? = null,
) : Registry<BlockEntityType>() {
parentRegistry: BlockEntityTypeRegistry? = null,
) : Registry<BlockEntityType>(parentRegistry) {
private lateinit var blockTypeMap: MutableMap<Block, BlockEntityType>
fun getByBlock(block: Block): BlockEntityType? {
val parentRegistry = super.parentRegistry as BlockEntityTypeRegistry?
return blockTypeMap[block] ?: parentRegistry?.getByBlock(block)
}
fun setParent(parent: BlockEntityTypeRegistry?) {
super.setParent(parent)
this.parentRegistry = parent
}
override fun postInit(versionMapping: VersionMapping) {
super.postInit(versionMapping)
blockTypeMap = mutableMapOf()

View File

@ -16,35 +16,35 @@ package de.bixilon.minosoft.data.mappings.blocks.properties
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.mappings.blocks.properties.serializer.BlockPropertiesSerializer
import de.bixilon.minosoft.data.mappings.blocks.properties.serializer.BooleanBlocKPropertiesSerializer
import de.bixilon.minosoft.data.mappings.blocks.properties.serializer.BooleanBlockPropertiesSerializer
import de.bixilon.minosoft.data.mappings.blocks.properties.serializer.IntBlockPropertiesSerializer
import java.util.*
enum class BlockProperties {
POWERED(BooleanBlocKPropertiesSerializer),
TRIGGERED(BooleanBlocKPropertiesSerializer),
INVERTED(BooleanBlocKPropertiesSerializer),
LIT(BooleanBlocKPropertiesSerializer),
WATERLOGGED(BooleanBlocKPropertiesSerializer),
POWERED(BooleanBlockPropertiesSerializer),
TRIGGERED(BooleanBlockPropertiesSerializer),
INVERTED(BooleanBlockPropertiesSerializer),
LIT(BooleanBlockPropertiesSerializer),
WATERLOGGED(BooleanBlockPropertiesSerializer),
STAIR_DIRECTIONAL("shape", Shapes),
STAIR_HALF("half", Halves),
SLAB_TYPE("type", Halves),
MOISTURE_LEVEL("moisture", IntBlockPropertiesSerializer),
FLUID_LEVEL("level", IntBlockPropertiesSerializer),
HONEY_LEVEL("honey_level", IntBlockPropertiesSerializer),
PISTON_EXTENDED("extended", BooleanBlocKPropertiesSerializer),
PISTON_EXTENDED("extended", BooleanBlockPropertiesSerializer),
PISTON_TYPE("type", PistonTypes),
PISTON_SHORT("short", BooleanBlocKPropertiesSerializer),
PISTON_SHORT("short", BooleanBlockPropertiesSerializer),
RAILS_SHAPE("shape", Shapes),
SNOWY(BooleanBlocKPropertiesSerializer),
SNOWY(BooleanBlockPropertiesSerializer),
STAGE(IntBlockPropertiesSerializer),
DISTANCE(IntBlockPropertiesSerializer),
LEAVES_PERSISTENT("persistent", BooleanBlocKPropertiesSerializer),
LEAVES_PERSISTENT("persistent", BooleanBlockPropertiesSerializer),
BED_PART("part", BedParts),
BED_OCCUPIED("occupied", BooleanBlocKPropertiesSerializer),
TNT_UNSTABLE("unstable", BooleanBlocKPropertiesSerializer),
BED_OCCUPIED("occupied", BooleanBlockPropertiesSerializer),
TNT_UNSTABLE("unstable", BooleanBlockPropertiesSerializer),
DOOR_HINGE("hinge", Sides),
DOOR_OPEN("open", BooleanBlocKPropertiesSerializer),
DOOR_OPEN("open", BooleanBlockPropertiesSerializer),
AGE(IntBlockPropertiesSerializer),
INSTRUMENT(Instruments),
NOTE(IntBlockPropertiesSerializer),
@ -58,55 +58,55 @@ enum class BlockProperties {
MULTIPART_DOWN("down", MultipartDirectionParser),
SNOW_LAYERS("layers", IntBlockPropertiesSerializer),
FENCE_IN_WALL("in_wall", BooleanBlocKPropertiesSerializer),
SCAFFOLDING_BOTTOM("bottom", BooleanBlocKPropertiesSerializer),
TRIPWIRE_DISARMED("disarmed", BooleanBlocKPropertiesSerializer),
TRIPWIRE_IN_AIR("in_air", BooleanBlocKPropertiesSerializer),
TRIPWIRE_ATTACHED("attached", BooleanBlocKPropertiesSerializer),
FENCE_IN_WALL("in_wall", BooleanBlockPropertiesSerializer),
SCAFFOLDING_BOTTOM("bottom", BooleanBlockPropertiesSerializer),
TRIPWIRE_DISARMED("disarmed", BooleanBlockPropertiesSerializer),
TRIPWIRE_IN_AIR("in_air", BooleanBlockPropertiesSerializer),
TRIPWIRE_ATTACHED("attached", BooleanBlockPropertiesSerializer),
STRUCTURE_BLOCK_MODE("mode", StructureBlockModes),
COMMAND_BLOCK_CONDITIONAL("conditional", BooleanBlocKPropertiesSerializer),
BUBBLE_COLUMN_DRAG("drag", BooleanBlocKPropertiesSerializer),
COMMAND_BLOCK_CONDITIONAL("conditional", BooleanBlockPropertiesSerializer),
BUBBLE_COLUMN_DRAG("drag", BooleanBlockPropertiesSerializer),
BELL_ATTACHMENT("attachment", Attachments),
LANTERN_HANGING("hanging", BooleanBlocKPropertiesSerializer),
LANTERN_HANGING("hanging", BooleanBlockPropertiesSerializer),
SEA_PICKLE_PICKLES("pickles", IntBlockPropertiesSerializer),
LECTERN_BOOK("has_book", BooleanBlocKPropertiesSerializer),
LECTERN_BOOK("has_book", BooleanBlockPropertiesSerializer),
BREWING_STAND_BOTTLE_0("has_bottle_0", BooleanBlocKPropertiesSerializer),
BREWING_STAND_BOTTLE_1("has_bottle_1", BooleanBlocKPropertiesSerializer),
BREWING_STAND_BOTTLE_2("has_bottle_2", BooleanBlocKPropertiesSerializer),
BREWING_STAND_BOTTLE_0("has_bottle_0", BooleanBlockPropertiesSerializer),
BREWING_STAND_BOTTLE_1("has_bottle_1", BooleanBlockPropertiesSerializer),
BREWING_STAND_BOTTLE_2("has_bottle_2", BooleanBlockPropertiesSerializer),
CHEST_TYPE("type", ChestTypes),
CAKE_BITES("bites", IntBlockPropertiesSerializer),
BAMBOO_LEAVES("leaves", BambooLeaves),
REPEATER_LOCKED("locked", BooleanBlocKPropertiesSerializer),
REPEATER_LOCKED("locked", BooleanBlockPropertiesSerializer),
REPEATER_DELAY("delay", IntBlockPropertiesSerializer),
PORTA_FRAME_EYE("eye", BooleanBlocKPropertiesSerializer),
JUKEBOX_HAS_RECORD("has_record", BooleanBlocKPropertiesSerializer),
CAMPFIRE_SIGNAL_FIRE("signal_fire", BooleanBlocKPropertiesSerializer),
PORTA_FRAME_EYE("eye", BooleanBlockPropertiesSerializer),
JUKEBOX_HAS_RECORD("has_record", BooleanBlockPropertiesSerializer),
CAMPFIRE_SIGNAL_FIRE("signal_fire", BooleanBlockPropertiesSerializer),
TURTLE_EGS_EGGS("eggs", IntBlockPropertiesSerializer),
TURTLE_EGGS_HATCH("hatch", IntBlockPropertiesSerializer),
RESPAWN_ANCHOR_CHARGES("charges", IntBlockPropertiesSerializer),
CANDLES(IntBlockPropertiesSerializer),
FACE("face", Attachments),
HOPPER_ENABLED("enabled", BooleanBlocKPropertiesSerializer),
HOPPER_ENABLED("enabled", BooleanBlockPropertiesSerializer),
DRIPSTONE_THICKNESS("thickness", Thicknesses),
LEGACY_BLOCK_UPDATE("block_update", BooleanBlocKPropertiesSerializer),
LEGACY_SMOOTH("smooth", BooleanBlocKPropertiesSerializer),
LEGACY_BLOCK_UPDATE("block_update", BooleanBlockPropertiesSerializer),
LEGACY_SMOOTH("smooth", BooleanBlockPropertiesSerializer),
SCULK_SENSOR_PHASE("sculk_sensor_phase", SensorPhases),
DRIPSTONE_TILT("tilt", Tilts),
CAVE_VINES_BERRIES("berries", BooleanBlocKPropertiesSerializer),
CAVE_VINES_BERRIES("berries", BooleanBlockPropertiesSerializer),
VERTICAL_DIRECTION("vertical_direction", VerticalDirections),
LEGACY_CHECK_DECAY("check_decay", BooleanBlocKPropertiesSerializer),
LEGAVY_DECAYABLE("decayable", BooleanBlocKPropertiesSerializer),
LEGAVY_NODROP("nodrop", BooleanBlocKPropertiesSerializer),
LEGACY_CHECK_DECAY("check_decay", BooleanBlockPropertiesSerializer),
LEGAVY_DECAYABLE("decayable", BooleanBlockPropertiesSerializer),
LEGAVY_NODROP("nodrop", BooleanBlockPropertiesSerializer),
AXIS("axis", Axes),
FACING("facing", Directions),
@ -128,6 +128,7 @@ enum class BlockProperties {
this.serializer = serializer
}
companion object {
private val PROPERTIES: Map<String, List<BlockProperties>> = run {
val map: MutableMap<String, MutableList<BlockProperties>> = mutableMapOf()

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.data.mappings.blocks.properties.serializer
object BooleanBlocKPropertiesSerializer : BlockPropertiesSerializer {
object BooleanBlockPropertiesSerializer : BlockPropertiesSerializer {
override fun deserialize(value: Any): Boolean {
if (value is Boolean) {

View File

@ -10,18 +10,28 @@
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.mappings.blocks
package de.bixilon.minosoft.data.mappings.blocks.types
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.entities.block.BlockEntity
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.blocks.BlockUsages
import de.bixilon.minosoft.data.mappings.blocks.RandomOffsetTypes
import de.bixilon.minosoft.data.mappings.blocks.entites.BlockEntityType
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.mappings.items.Item
import de.bixilon.minosoft.data.mappings.registry.RegistryItem
import de.bixilon.minosoft.data.mappings.registry.ResourceLocationDeserializer
import de.bixilon.minosoft.data.mappings.versions.VersionMapping
import de.bixilon.minosoft.data.player.Hands
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.TintColorCalculator
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockLikeRenderer
import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import glm_.vec3.Vec3i
open class Block(final override val resourceLocation: ResourceLocation, mappings: VersionMapping, data: JsonObject) : RegistryItem {
open val explosionResistance: Float = data["explosion_resistance"]?.asFloat ?: 0.0f
@ -50,12 +60,40 @@ open class Block(final override val resourceLocation: ResourceLocation, mappings
return resourceLocation.full
}
open fun getPlacementState(connection: PlayConnection, raycastHit: RaycastHit): BlockState {
return defaultState
}
open fun onBreak(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState, blockEntity: BlockEntity?) {
}
open fun onPlace(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState) {
}
open fun canPlaceAt(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState): Boolean {
return true
}
open fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
if (blockEntityType == null) {
return BlockUsages.PASS
}
return BlockUsages.SUCCESS
}
fun withProperties(vararg properties: Pair<BlockProperties, Any>): BlockState {
return this.defaultState.withProperties(*properties)
}
companion object : ResourceLocationDeserializer<Block> {
override fun deserialize(mappings: VersionMapping?, resourceLocation: ResourceLocation, data: JsonObject): Block {
check(mappings != null) { "VersionMapping is null!" }
val block = when (data["class"].asString) {
"FluidBlock" -> FluidBlock(resourceLocation, mappings, data)
"DoorBlock" -> DoorBlock(resourceLocation, mappings, data)
else -> Block(resourceLocation, mappings, data)
}

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.data.mappings.blocks.types
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.entities.block.BlockEntity
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.blocks.BlockUsages
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.mappings.blocks.properties.Halves
import de.bixilon.minosoft.data.mappings.materials.DefaultMaterials
import de.bixilon.minosoft.data.mappings.versions.VersionMapping
import de.bixilon.minosoft.data.player.Hands
import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import glm_.vec3.Vec3i
open class DoorBlock(resourceLocation: ResourceLocation, mappings: VersionMapping, data: JsonObject) : Block(resourceLocation, mappings, data) {
override fun getPlacementState(connection: PlayConnection, raycastHit: RaycastHit): BlockState {
TODO()
}
override fun onBreak(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState, blockEntity: BlockEntity?) {
if (blockState.properties[BlockProperties.STAIR_HALF] == Halves.LOWER) {
connection.world.forceSetBlock(blockPosition + Directions.UP, null)
} else {
connection.world.forceSetBlock(blockPosition + Directions.DOWN, null)
}
}
override fun onPlace(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState) {
if (blockState.properties[BlockProperties.STAIR_HALF] == Halves.LOWER) {
connection.world.forceSetBlock(blockPosition + Directions.UP, blockState.withProperties(BlockProperties.STAIR_HALF to Halves.UPPER))
} else {
connection.world.forceSetBlock(blockPosition + Directions.DOWN, blockState.withProperties(BlockProperties.STAIR_HALF to Halves.LOWER))
}
}
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
if (blockState.material.resourceLocation == DefaultMaterials.METAL) {
return BlockUsages.CONSUME
}
val nextBlockState = blockState.cycle(BlockProperties.DOOR_OPEN)
connection.world.setBlock(blockPosition, nextBlockState)
return BlockUsages.SUCCESS
}
}

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.mappings.blocks
package de.bixilon.minosoft.data.mappings.blocks.types
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.mappings.ResourceLocation

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.data.mappings.items
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.data.mappings.versions.VersionMapping
open class BlockItem(

View File

@ -0,0 +1,20 @@
/*
* 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.data.mappings.materials
import de.bixilon.minosoft.util.KUtil.asResourceLocation
object DefaultMaterials {
val METAL = "minecraft:metal".asResourceLocation()
}

View File

@ -20,7 +20,7 @@ import de.bixilon.minosoft.util.collections.Clearable
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
open class Registry<T : RegistryItem>(
private var parentRegistry: Registry<T>? = null,
protected var parentRegistry: Registry<T>? = null,
) : Iterable<T>, Clearable, Parentable<Registry<T>> {
private var initialized = false
protected val idValueMap: MutableMap<Int, T> = mutableMapOf()

View File

@ -23,10 +23,10 @@ import de.bixilon.minosoft.data.mappings.*
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.mappings.biomes.BiomeCategory
import de.bixilon.minosoft.data.mappings.biomes.BiomePrecipitation
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.blocks.entites.BlockEntityType
import de.bixilon.minosoft.data.mappings.blocks.entites.BlockEntityTypeRegistry
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.data.mappings.effects.StatusEffect
import de.bixilon.minosoft.data.mappings.entities.EntityType
import de.bixilon.minosoft.data.mappings.entities.villagers.VillagerProfession
@ -93,7 +93,7 @@ class VersionMapping {
val entityMetaIndexMap: MutableMap<EntityMetaDataFields, Int> = mutableMapOf()
val entityRegistry: Registry<EntityType> = Registry()
val blockEntityTypeRegistry = BlockEntityTypeRegistry(this)
val blockEntityTypeRegistry = BlockEntityTypeRegistry()
val blockEntityMetaDataTypeRegistry: Registry<BlockEntityMetaType> = Registry()
val containerTypeRegistry: Registry<ContainerType> = Registry()

View File

@ -80,6 +80,11 @@ class World(
} else {
VersionTweaker.transformBlock(blockState, sections, blockPosition.inChunkSectionPosition, blockPosition.sectionHeight)
}
val inChunkPosition = blockPosition.inChunkPosition
it.getBlockState(inChunkPosition)?.let { oldBlockState ->
oldBlockState.block.onBreak(connection, blockPosition, oldBlockState, it.getBlockEntity(inChunkPosition))
}
blockState?.block?.onPlace(connection, blockPosition, blockState)
it.setBlockState(blockPosition.inChunkPosition, transformedBlockState)
connection.fireEvent(BlockSetEvent(
connection = connection,
@ -89,6 +94,10 @@ class World(
}
}
fun forceSetBlock(blockPosition: Vec3i, blockState: BlockState?) {
chunks[blockPosition.chunkPosition]?.setBlockState(blockPosition.inChunkPosition, blockState)
}
fun unloadChunk(chunkPosition: Vec2i) {
chunks.remove(chunkPosition)?.let {
connection.fireEvent(ChunkUnloadEvent(connection, chunkPosition))

View File

@ -260,8 +260,10 @@ class RenderWindow(
glfwSetCursorPosCallback(windowId, inputHandler::mouseMove)
inputHandler.init()
registerGlobalKeyCombinations()
connection.fireEvent(ScreenResizeEvent(previousScreenDimensions = Vec2i(0, 0), screenDimensions = screenDimensions))
@ -327,7 +329,7 @@ class RenderWindow(
glfwSwapBuffers(windowId)
glfwPollEvents()
inputHandler.camera.draw()
inputHandler.draw()
inputHandler.camera.handleInput(deltaFrameTime)
// handle opengl context tasks, but limit it per frame

View File

@ -18,8 +18,8 @@ import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.blocks.FluidBlock
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.mappings.blocks.types.FluidBlock
import de.bixilon.minosoft.data.mappings.versions.VersionMapping
import de.bixilon.minosoft.data.world.Chunk
import de.bixilon.minosoft.data.world.ChunkSection

View File

@ -2,9 +2,9 @@ package de.bixilon.minosoft.gui.rendering.chunk.models.renderable
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.data.mappings.fluid.Fluid
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.data.world.World

View File

@ -0,0 +1,82 @@
/*
* 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.input
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.mappings.blocks.BlockUsages
import de.bixilon.minosoft.data.player.Hands
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.protocol.packets.c2s.play.ArmSwingC2SP
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockPlaceC2SP
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
class InteractionHandler(
val renderWindow: RenderWindow,
) {
private var lastInteraction = 0L
private var lastInteractionSent = 0L
fun init() {
renderWindow.inputHandler.registerCheckCallback(KeyBindingsNames.BLOCK_INTERACT)
}
private fun checkInteraction(isKeyDown: Boolean) {
val currentTime = System.currentTimeMillis()
if (!isKeyDown) {
lastInteraction = 0L
return
}
if (currentTime - lastInteraction < ProtocolDefinition.TICK_TIME * 5) {
return
}
val raycastHit = renderWindow.inputHandler.camera.getTargetBlock() ?: return
if (raycastHit.distance > RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) {
return
}
val usage = raycastHit.blockState.block.use(renderWindow.connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, null) // ToDo
when (usage) {
BlockUsages.SUCCESS -> {
if (currentTime - lastInteractionSent < ProtocolDefinition.TICK_TIME) {
return
}
renderWindow.connection.sendPacket(ArmSwingC2SP(Hands.MAIN_HAND))
renderWindow.connection.sendPacket(BlockPlaceC2SP(
position = raycastHit.blockPosition,
direction = Directions.NORTH, // ToDo
cursorPosition = raycastHit.hitPosition,
item = null, // ToDo
hand = Hands.MAIN_HAND,
insideBlock = false, // ToDo
))
lastInteractionSent = currentTime
lastInteraction = currentTime
}
BlockUsages.PASS -> {
// use item or place block
}
}
}
fun draw() {
checkInteraction(renderWindow.inputHandler.isKeyBindingDown(KeyBindingsNames.BLOCK_INTERACT))
}
}

View File

@ -24,4 +24,5 @@ data class RaycastHit(
val steps: Int,
) {
val blockPosition = position.floor
val hitPosition = position.minus(blockPosition)
}

View File

@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.hud.elements.input.KeyConsumer
import de.bixilon.minosoft.gui.rendering.input.InteractionHandler
import de.bixilon.minosoft.gui.rendering.input.camera.Camera
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.logging.Log
@ -41,6 +42,7 @@ class RenderWindowInputHandler(
private var skipNextCharPress = false
private val interactionHandler = InteractionHandler(renderWindow)
init {
registerKeyCallback(KeyBindingsNames.DEBUG_MOUSE_CATCH) {
@ -54,6 +56,10 @@ class RenderWindowInputHandler(
}
}
fun init() {
interactionHandler.init()
}
var currentKeyConsumer: KeyConsumer? = null
@ -266,4 +272,9 @@ class RenderWindowInputHandler(
}
return false
}
fun draw() {
camera.draw()
interactionHandler.draw()
}
}

View File

@ -19,8 +19,8 @@ import com.google.gson.JsonObject
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.RandomOffsetTypes
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.func.common.clamp

View File

@ -39,7 +39,7 @@ class BlockBreakC2SP(
} else {
buffer.writePosition(position)
}
buffer.writeByte(direction?.ordinal ?: 0xFF)
buffer.writeByte(direction?.ordinal ?: 0x00)
}
override fun log() {

View File

@ -27,7 +27,7 @@ class BlockPlaceC2SP(
val position: Vec3i,
val direction: Directions,
val cursorPosition: Vec3,
val item: ItemStack,
val item: ItemStack?,
val hand: Hands,
val insideBlock: Boolean,
) : PlayC2SPacket {

View File

@ -14,7 +14,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play
import de.bixilon.minosoft.data.entities.block.BlockActionEntity
import de.bixilon.minosoft.data.entities.block.DefaultBlockEntityMetaDataFactory
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.mappings.blocks.types.Block
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer

View File

@ -26,9 +26,9 @@ import de.bixilon.minosoft.util.logging.LogMessageType
class ContainerOpenS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
val containerId: Byte = buffer.readByte()
val containerType: ContainerType = if (buffer.versionId < V_14W03B) {
buffer.connection.mapping.containerTypeRegistry.get(buffer.readUnsignedByte())
buffer.connection.mapping.containerTypeRegistry[buffer.readUnsignedByte()]
} else {
buffer.connection.mapping.containerTypeRegistry.get(buffer.readResourceLocation())!!
buffer.connection.mapping.containerTypeRegistry[buffer.readResourceLocation()]!!
}
val title: ChatComponent = buffer.readChatComponent()
val slotCount: Int = if (buffer.versionId < V_19W02A || buffer.versionId >= V_19W11A) {

View File

@ -24,4 +24,12 @@ interface ValuesEnum<T : Enum<*>> {
operator fun get(name: String): T {
return NAME_MAP[name]!!
}
fun next(current: T): T {
val ordinal = current.ordinal
if (ordinal + 1 > VALUES.size) {
return VALUES[0]
}
return VALUES[ordinal + 1]
}
}