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,
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
||||
@ -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
|
||||
*/
|
||||
PASS,
|
||||
|
||||
/**
|
||||
* Nothing happens, basically `CONSUME`, but a requirement was not satisfied.
|
||||
*/
|
||||
FAIL,
|
||||
;
|
||||
}
|
||||
|
@ -14,9 +14,19 @@
|
||||
package de.bixilon.minosoft.data.mappings.items
|
||||
|
||||
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.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.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(
|
||||
resourceLocation: ResourceLocation,
|
||||
@ -24,4 +34,44 @@ open class BlockItem(
|
||||
data: JsonObject,
|
||||
) : Item(resourceLocation, registries, data) {
|
||||
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()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,11 @@
|
||||
*/
|
||||
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.entities.EntityRotation
|
||||
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.PlayerInventory
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||
@ -41,4 +43,6 @@ class Player(
|
||||
val containers: MutableMap<Int, Container> = synchronizedMapOf(
|
||||
ProtocolDefinition.PLAYER_INVENTORY_ID to inventory)
|
||||
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.data.Directions
|
||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||
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.gui.rendering.RenderConstants
|
||||
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.BlockBreakC2SP
|
||||
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 glm_.vec3.Vec3i
|
||||
|
||||
@ -104,8 +102,13 @@ class InteractionHandler(
|
||||
if (raycastHit.distance > RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) {
|
||||
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
|
||||
lastInteraction = currentTime
|
||||
@ -128,47 +131,32 @@ class InteractionHandler(
|
||||
}
|
||||
BlockUsages.PASS -> {
|
||||
// use item or place block
|
||||
if (!connection.player.entity.gamemode.canBuild) {
|
||||
return
|
||||
}
|
||||
val selectedItemStack = connection.player.inventory.getHotbarSlot() ?: return
|
||||
val blockPosition = raycastHit.blockPosition + raycastHit.hitDirection
|
||||
itemInHand ?: return
|
||||
|
||||
val dimension = connection.world.dimension!!
|
||||
if (blockPosition.y < dimension.minY || blockPosition.y >= dimension.height) {
|
||||
return
|
||||
}
|
||||
val cooldown = connection.player.itemCooldown[itemInHand.item]
|
||||
|
||||
renderWindow.connection.world[blockPosition]?.let {
|
||||
if (!it.material.replaceable) {
|
||||
cooldown?.let {
|
||||
if (it.ended) {
|
||||
connection.player.itemCooldown.remove(itemInHand.item)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val blockState = if (selectedItemStack.item is BlockItem) {
|
||||
selectedItemStack.item.block.getPlacementState(renderWindow.connection, raycastHit) ?: return
|
||||
} else {
|
||||
return
|
||||
|
||||
when (itemInHand.item.use(connection, raycastHit.blockState, raycastHit.blockPosition, raycastHit, Hands.MAIN_HAND, itemInHand)) {
|
||||
BlockUsages.SUCCESS -> {
|
||||
connection.sendPacket(ArmSwingC2SP(Hands.MAIN_HAND))
|
||||
}
|
||||
BlockUsages.PASS -> {
|
||||
return
|
||||
}
|
||||
BlockUsages.CONSUME -> {
|
||||
}
|
||||
}
|
||||
|
||||
renderWindow.connection.world[blockPosition] = blockState
|
||||
|
||||
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
|
||||
))
|
||||
// ToDo: Before 1.9
|
||||
connection.sendPacket(ItemUseC2SP(Hands.MAIN_HAND))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,8 @@ class Camera(
|
||||
var viewProjectionMatrix = projectionMatrix * viewMatrix
|
||||
private set
|
||||
|
||||
var sneaking: Boolean = false // ToDo: Not yet implemented
|
||||
|
||||
|
||||
fun mouseCallback(xPos: Double, yPos: Double) {
|
||||
var xOffset = xPos - this.lastMouseX
|
||||
@ -328,7 +330,7 @@ class Camera(
|
||||
if (distance >= 0.0f && blockState != null) {
|
||||
currentPosition += direction * distance
|
||||
return RaycastHit(
|
||||
currentPosition ,
|
||||
currentPosition,
|
||||
getTotalDistance() + distance,
|
||||
blockState = blockState,
|
||||
hitDirection = currentPosition.nearestIntegerPositionDirection,
|
||||
|
@ -12,6 +12,8 @@
|
||||
*/
|
||||
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.protocol.PlayInByteBuffer
|
||||
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 time = buffer.readVarInt()
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
connection.player.itemCooldown[item] = ItemCooldown(System.currentTimeMillis(), time)
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
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