mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
item cooldown, wip item interaction, outsource block placing
This commit is contained in:
parent
27f376110b
commit
fd9f7000bc
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.abilities
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
|
||||||
|
data class ItemCooldown(
|
||||||
|
val start: Long,
|
||||||
|
val time: Int,
|
||||||
|
) {
|
||||||
|
val end: Long = start + (time * ProtocolDefinition.TICK_TIME)
|
||||||
|
|
||||||
|
val ended: Boolean
|
||||||
|
get() = System.currentTimeMillis() >= end
|
||||||
|
}
|
@ -20,7 +20,7 @@ enum class BlockUsages {
|
|||||||
CONSUME,
|
CONSUME,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage get consumed (like pressing a button, opening a door, right clicking on block entities) with animation
|
* Usage get consumed (like pressing a button, opening a door, right clicking on block entities, placing a block, …) with animation
|
||||||
*/
|
*/
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
|
|
||||||
@ -28,10 +28,5 @@ enum class BlockUsages {
|
|||||||
* Nothing happens from block side (e.g. right clicking on dirt). You can maybe place a block, whatever
|
* Nothing happens from block side (e.g. right clicking on dirt). You can maybe place a block, whatever
|
||||||
*/
|
*/
|
||||||
PASS,
|
PASS,
|
||||||
|
|
||||||
/**
|
|
||||||
* Nothing happens, basically `CONSUME`, but a requirement was not satisfied.
|
|
||||||
*/
|
|
||||||
FAIL,
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,19 @@
|
|||||||
package de.bixilon.minosoft.data.mappings.items
|
package de.bixilon.minosoft.data.mappings.items
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
|
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||||
|
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
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.types.Block
|
import de.bixilon.minosoft.data.mappings.blocks.types.Block
|
||||||
import de.bixilon.minosoft.data.mappings.versions.Registries
|
import de.bixilon.minosoft.data.mappings.versions.Registries
|
||||||
|
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 de.bixilon.minosoft.protocol.packets.c2s.play.BlockPlaceC2SP
|
||||||
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
open class BlockItem(
|
open class BlockItem(
|
||||||
resourceLocation: ResourceLocation,
|
resourceLocation: ResourceLocation,
|
||||||
@ -24,4 +34,44 @@ open class BlockItem(
|
|||||||
data: JsonObject,
|
data: JsonObject,
|
||||||
) : Item(resourceLocation, registries, data) {
|
) : Item(resourceLocation, registries, data) {
|
||||||
val block: Block = registries.blockRegistry[data["block"].asInt]
|
val block: Block = registries.blockRegistry[data["block"].asInt]
|
||||||
|
|
||||||
|
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack): BlockUsages {
|
||||||
|
if (!connection.player.entity.gamemode.canBuild) {
|
||||||
|
return BlockUsages.PASS
|
||||||
|
}
|
||||||
|
|
||||||
|
val placePosition = raycastHit.blockPosition + raycastHit.hitDirection
|
||||||
|
val dimension = connection.world.dimension!!
|
||||||
|
if (placePosition.y < dimension.minY || placePosition.y >= dimension.height) {
|
||||||
|
return BlockUsages.PASS
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.world[placePosition]?.let {
|
||||||
|
if (!it.material.replaceable) {
|
||||||
|
return BlockUsages.PASS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val placeBlockState = block.getPlacementState(connection, raycastHit) ?: return BlockUsages.PASS
|
||||||
|
|
||||||
|
|
||||||
|
connection.world[placePosition] = placeBlockState
|
||||||
|
|
||||||
|
if (connection.player.entity.gamemode != Gamemodes.CREATIVE) {
|
||||||
|
itemStack.count--
|
||||||
|
connection.player.inventory.validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
connection.sendPacket(BlockPlaceC2SP(
|
||||||
|
position = placePosition,
|
||||||
|
direction = raycastHit.hitDirection,
|
||||||
|
cursorPosition = raycastHit.hitPosition,
|
||||||
|
item = connection.player.inventory.getHotbarSlot(),
|
||||||
|
hand = Hands.MAIN_HAND,
|
||||||
|
insideBlock = false, // ToDo
|
||||||
|
))
|
||||||
|
return BlockUsages.SUCCESS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ open class Item(
|
|||||||
return resourceLocation.toString()
|
return resourceLocation.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
|
open fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack): BlockUsages {
|
||||||
return BlockUsages.PASS
|
return BlockUsages.PASS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
*/
|
*/
|
||||||
package de.bixilon.minosoft.data.player
|
package de.bixilon.minosoft.data.player
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.abilities.ItemCooldown
|
||||||
import de.bixilon.minosoft.data.accounts.Account
|
import de.bixilon.minosoft.data.accounts.Account
|
||||||
import de.bixilon.minosoft.data.entities.EntityRotation
|
import de.bixilon.minosoft.data.entities.EntityRotation
|
||||||
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
|
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
|
||||||
|
import de.bixilon.minosoft.data.mappings.items.Item
|
||||||
import de.bixilon.minosoft.data.mappings.other.containers.Container
|
import de.bixilon.minosoft.data.mappings.other.containers.Container
|
||||||
import de.bixilon.minosoft.data.mappings.other.containers.PlayerInventory
|
import de.bixilon.minosoft.data.mappings.other.containers.PlayerInventory
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||||
@ -41,4 +43,6 @@ class Player(
|
|||||||
val containers: MutableMap<Int, Container> = synchronizedMapOf(
|
val containers: MutableMap<Int, Container> = synchronizedMapOf(
|
||||||
ProtocolDefinition.PLAYER_INVENTORY_ID to inventory)
|
ProtocolDefinition.PLAYER_INVENTORY_ID to inventory)
|
||||||
var selectedHotbarSlot: Int = 0
|
var selectedHotbarSlot: Int = 0
|
||||||
|
|
||||||
|
val itemCooldown: MutableMap<Item, ItemCooldown> = synchronizedMapOf()
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,14 @@ package de.bixilon.minosoft.gui.rendering.input
|
|||||||
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
||||||
import de.bixilon.minosoft.data.Directions
|
import de.bixilon.minosoft.data.Directions
|
||||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
|
||||||
import de.bixilon.minosoft.data.mappings.blocks.BlockUsages
|
import de.bixilon.minosoft.data.mappings.blocks.BlockUsages
|
||||||
import de.bixilon.minosoft.data.mappings.items.BlockItem
|
|
||||||
import de.bixilon.minosoft.data.player.Hands
|
import de.bixilon.minosoft.data.player.Hands
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
|
|
||||||
import de.bixilon.minosoft.protocol.packets.c2s.play.ArmSwingC2SP
|
import de.bixilon.minosoft.protocol.packets.c2s.play.ArmSwingC2SP
|
||||||
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockBreakC2SP
|
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockBreakC2SP
|
||||||
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockPlaceC2SP
|
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockPlaceC2SP
|
||||||
|
import de.bixilon.minosoft.protocol.packets.c2s.play.ItemUseC2SP
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
@ -104,8 +102,13 @@ class InteractionHandler(
|
|||||||
if (raycastHit.distance > RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) {
|
if (raycastHit.distance > RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
val itemInHand = connection.player.inventory.getHotbarSlot()
|
||||||
|
|
||||||
val usage = raycastHit.blockState.block.use(renderWindow.connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, null) // ToDo
|
val usage = if (renderWindow.inputHandler.camera.sneaking) {
|
||||||
|
BlockUsages.PASS
|
||||||
|
} else {
|
||||||
|
raycastHit.blockState.block.use(renderWindow.connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, itemInHand)
|
||||||
|
}
|
||||||
|
|
||||||
lastInteractionSent = currentTime
|
lastInteractionSent = currentTime
|
||||||
lastInteraction = currentTime
|
lastInteraction = currentTime
|
||||||
@ -128,47 +131,32 @@ class InteractionHandler(
|
|||||||
}
|
}
|
||||||
BlockUsages.PASS -> {
|
BlockUsages.PASS -> {
|
||||||
// use item or place block
|
// use item or place block
|
||||||
if (!connection.player.entity.gamemode.canBuild) {
|
itemInHand ?: return
|
||||||
return
|
|
||||||
}
|
|
||||||
val selectedItemStack = connection.player.inventory.getHotbarSlot() ?: return
|
|
||||||
val blockPosition = raycastHit.blockPosition + raycastHit.hitDirection
|
|
||||||
|
|
||||||
val dimension = connection.world.dimension!!
|
val cooldown = connection.player.itemCooldown[itemInHand.item]
|
||||||
if (blockPosition.y < dimension.minY || blockPosition.y >= dimension.height) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
renderWindow.connection.world[blockPosition]?.let {
|
cooldown?.let {
|
||||||
if (!it.material.replaceable) {
|
if (it.ended) {
|
||||||
|
connection.player.itemCooldown.remove(itemInHand.item)
|
||||||
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val blockState = if (selectedItemStack.item is BlockItem) {
|
|
||||||
selectedItemStack.item.block.getPlacementState(renderWindow.connection, raycastHit) ?: return
|
when (itemInHand.item.use(connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, itemInHand)) {
|
||||||
} else {
|
BlockUsages.SUCCESS -> {
|
||||||
return
|
connection.sendPacket(ArmSwingC2SP(Hands.MAIN_HAND))
|
||||||
|
}
|
||||||
|
BlockUsages.PASS -> {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
BlockUsages.CONSUME -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// ToDo: Before 1.9
|
||||||
renderWindow.connection.world[blockPosition] = blockState
|
connection.sendPacket(ItemUseC2SP(Hands.MAIN_HAND))
|
||||||
|
|
||||||
if (connection.player.entity.gamemode != Gamemodes.CREATIVE) {
|
|
||||||
selectedItemStack.count--
|
|
||||||
renderWindow.connection.player.inventory.validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.sendPacket(ArmSwingC2SP(Hands.MAIN_HAND))
|
|
||||||
|
|
||||||
connection.sendPacket(BlockPlaceC2SP(
|
|
||||||
position = blockPosition,
|
|
||||||
direction = raycastHit.hitDirection,
|
|
||||||
cursorPosition = raycastHit.hitPosition,
|
|
||||||
item = connection.player.inventory.getHotbarSlot(),
|
|
||||||
hand = Hands.MAIN_HAND,
|
|
||||||
insideBlock = false, // ToDo
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +94,8 @@ class Camera(
|
|||||||
var viewProjectionMatrix = projectionMatrix * viewMatrix
|
var viewProjectionMatrix = projectionMatrix * viewMatrix
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
var sneaking: Boolean = false // ToDo: Not yet implemented
|
||||||
|
|
||||||
|
|
||||||
fun mouseCallback(xPos: Double, yPos: Double) {
|
fun mouseCallback(xPos: Double, yPos: Double) {
|
||||||
var xOffset = xPos - this.lastMouseX
|
var xOffset = xPos - this.lastMouseX
|
||||||
@ -328,7 +330,7 @@ class Camera(
|
|||||||
if (distance >= 0.0f && blockState != null) {
|
if (distance >= 0.0f && blockState != null) {
|
||||||
currentPosition += direction * distance
|
currentPosition += direction * distance
|
||||||
return RaycastHit(
|
return RaycastHit(
|
||||||
currentPosition ,
|
currentPosition,
|
||||||
getTotalDistance() + distance,
|
getTotalDistance() + distance,
|
||||||
blockState = blockState,
|
blockState = blockState,
|
||||||
hitDirection = currentPosition.nearestIntegerPositionDirection,
|
hitDirection = currentPosition.nearestIntegerPositionDirection,
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
package de.bixilon.minosoft.protocol.packets.s2c.play
|
package de.bixilon.minosoft.protocol.packets.s2c.play
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.abilities.ItemCooldown
|
||||||
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
import de.bixilon.minosoft.util.logging.Log
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
@ -22,6 +24,10 @@ class ItemCooldownSetS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
val item = buffer.connection.registries.itemRegistry[buffer.readVarInt()]
|
val item = buffer.connection.registries.itemRegistry[buffer.readVarInt()]
|
||||||
val time = buffer.readVarInt()
|
val time = buffer.readVarInt()
|
||||||
|
|
||||||
|
override fun handle(connection: PlayConnection) {
|
||||||
|
connection.player.itemCooldown[item] = ItemCooldown(System.currentTimeMillis(), time)
|
||||||
|
}
|
||||||
|
|
||||||
override fun log() {
|
override fun log() {
|
||||||
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Item cooldown set (item=$item, time=$time)" }
|
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Item cooldown set (item=$item, time=$time)" }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user