option to disable tool interaction, almost finished mining math

This commit is contained in:
Bixilon 2021-05-22 23:43:23 +02:00
parent bf66039ca0
commit 9edda894fd
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
18 changed files with 210 additions and 130 deletions

View File

@ -17,4 +17,7 @@ import com.squareup.moshi.Json
data class ControlsGameConfig(
@Json(name = "key_bindings") var keyBindings: KeyBindingsGameConfig = KeyBindingsGameConfig(),
@Json(name = "enable_flattening") var enableFlattening: Boolean = true,
@Json(name = "enable_stripping") var enableStripping: Boolean = true,
@Json(name = "enable_tilling") var enableTilling: Boolean = true,
)

View File

@ -18,26 +18,31 @@ import de.bixilon.minosoft.util.enum.ValuesEnum
enum class Gamemodes(
val canBuild: Boolean,
val canBreak: Boolean,
val useTools: Boolean,
val canInteract: InteractionAbilities,
) {
SURVIVAL(
canBuild = true,
canBreak = true,
useTools = true,
canInteract = InteractionAbilities.EVERYTHING,
),
CREATIVE(
canBuild = true,
canBreak = true,
useTools = true,
canInteract = InteractionAbilities.EVERYTHING,
),
ADVENTURE(
canBuild = false,
canBreak = false,
useTools = false,
canInteract = InteractionAbilities.ONLY_ENTITIES,
),
SPECTATOR(
canBuild = false,
canBreak = false,
useTools = false,
canInteract = InteractionAbilities.ONLY_ENTITIES,
),
;

View File

@ -1,67 +0,0 @@
/*
* Minosoft
* Copyright (C) 2020 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.inventory;
import java.util.HashMap;
public class Inventory {
private final InventoryProperties properties;
private final HashMap<Integer, ItemStack> slots;
public Inventory(InventoryProperties properties, HashMap<Integer, ItemStack> slots) {
this.properties = properties;
this.slots = slots;
}
public Inventory(InventoryProperties properties) {
this.properties = properties;
this.slots = new HashMap<>();
}
public Inventory(InventoryProperties properties, ItemStack[] itemStacks) {
this.properties = properties;
this.slots = new HashMap<>();
for (int i = 0; i < itemStacks.length; i++) {
this.slots.put(i, itemStacks[i]);
}
}
public ItemStack getSlot(int slotId, int versionId) {
return getSlot(slotId);
}
public ItemStack getSlot(int slot) {
return this.slots.get(slot);
}
public void setSlot(int slot, ItemStack data) {
this.slots.put(slot, data);
}
public void setSlot(int slotId, int versionId, ItemStack data) {
this.slots.put(slotId, data);
}
public void clear() {
this.slots.clear();
}
public HashMap<Integer, ItemStack> getSlots() {
return this.slots;
}
public InventoryProperties getProperties() {
return this.properties;
}
}

View File

@ -23,8 +23,8 @@ import de.bixilon.minosoft.data.inventory.ItemNBTValues.ENCHANTMENT_PRE_FLATTENI
import de.bixilon.minosoft.data.inventory.ItemNBTValues.HIDE_FLAGS_TAG
import de.bixilon.minosoft.data.inventory.ItemNBTValues.REPAIR_COST_TAG
import de.bixilon.minosoft.data.inventory.ItemNBTValues.UNBREAKABLE_TAG
import de.bixilon.minosoft.data.mappings.Enchantment
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.enchantment.Enchantment
import de.bixilon.minosoft.data.mappings.items.Item
import de.bixilon.minosoft.data.mappings.versions.Version
import de.bixilon.minosoft.data.text.ChatComponent

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.blocks
import de.bixilon.minosoft.util.KUtil.asResourceLocation
object DefaultBlocks {
val COBWEB = "minecraft:cobweb".asResourceLocation()
}

View File

@ -0,0 +1,21 @@
/*
* 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.effects
import de.bixilon.minosoft.util.KUtil.asResourceLocation
object DefaultStatusEffects {
val HASTE = "minecraft:haste".asResourceLocation()
val MINING_FATIGUE = "minecraft:mining_fatigue".asResourceLocation()
}

View File

@ -11,17 +11,10 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.player
package de.bixilon.minosoft.data.mappings.enchantment
import de.bixilon.minosoft.data.inventory.Inventory
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.asResourceLocation
class PlayerInventoryManager {
val inventories: MutableMap<Int, Inventory> = mutableMapOf()
var selectedHotbarSlot: Int = 0
init {
// create our own inventory without any properties
inventories[ProtocolDefinition.PLAYER_INVENTORY_ID] = Inventory(null)
}
object DefaultEnchantments {
val EFFICIENCY = "minecraft:efficiency".asResourceLocation()
}

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020 Moritz Zwerger
* 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.
*
@ -10,9 +10,10 @@
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.mappings
package de.bixilon.minosoft.data.mappings.enchantment
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.registry.RegistryItem
import de.bixilon.minosoft.data.mappings.registry.ResourceLocationDeserializer
import de.bixilon.minosoft.data.mappings.versions.Registries

View File

@ -47,7 +47,7 @@ open class Item(
return resourceLocation.toString()
}
open fun getMiningSpeedMultiplier(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, itemStack: ItemStack): Float {
open fun getMiningSpeedMultiplier(connection: PlayConnection, blockState: BlockState, itemStack: ItemStack): Float {
return 1.0f
}
@ -73,6 +73,7 @@ open class Item(
"SpawnEggItem" -> SpawnEggItem(resourceLocation, mappings, data)
"MusicDiscItem" -> MusicDiscItem(resourceLocation, mappings, data)
"ShovelItem" -> ShovelItem(resourceLocation, mappings, data)
"PickaxeItem" -> PickaxeItem(resourceLocation, mappings, data)
"HoeItem" -> HoeItem(resourceLocation, mappings, data)
// "Item" -> Item(resourceLocation, data)
// else -> TODO("Can not find item class: ${data["class"].asString}")

View File

@ -14,7 +14,7 @@
package de.bixilon.minosoft.data.mappings.items.tools
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.blocks.BlockState
@ -23,7 +23,6 @@ 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 glm_.vec3.Vec3i
@ -33,23 +32,20 @@ open class AxeItem(
data: JsonObject,
) : MiningToolItem(resourceLocation, registries, data) {
val strippableBlocks: Map<Block, Block>? = data["strippables_blocks"]?.asJsonObject?.let {
val items: MutableMap<Block, Block> = mutableMapOf()
val entries: MutableMap<Block, Block> = mutableMapOf()
for ((origin, target) in it.entrySet()) {
items[registries.blockRegistry[origin.toInt()]] = registries.blockRegistry[target.asInt]
entries[registries.blockRegistry[origin.toInt()]] = registries.blockRegistry[target]
}
items.toMap()
entries.toMap()
}
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack): BlockUsages {
// ToDo: Check tags (21w19a+)
val target = strippableBlocks?.get(blockState.block) ?: return BlockUsages.PASS
if (connection.world[blockPosition + Directions.UP] != null) {
return BlockUsages.PASS
if (!Minosoft.config.config.game.controls.enableStripping) {
return BlockUsages.CONSUME
}
connection.world[blockPosition] = target.withProperties(blockState.properties)
return BlockUsages.SUCCESS
return super.interactWithTool(connection, blockPosition, strippableBlocks?.get(blockState.block)?.withProperties(blockState.properties))
}
}

View File

@ -14,6 +14,7 @@
package de.bixilon.minosoft.data.mappings.items.tools
import com.google.gson.JsonObject
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.mappings.ResourceLocation
@ -33,23 +34,24 @@ open class HoeItem(
data: JsonObject,
) : MiningToolItem(resourceLocation, registries, data) {
val tillableBlockStates: Map<Block, BlockState>? = data["tillables_block_states"]?.asJsonObject?.let {
val items: MutableMap<Block, BlockState> = mutableMapOf()
val entries: MutableMap<Block, BlockState> = mutableMapOf()
for ((origin, target) in it.entrySet()) {
items[registries.blockRegistry[origin.toInt()]] = registries.getBlockState(target.asInt)!!
entries[registries.blockRegistry[origin.toInt()]] = registries.getBlockState(target.asInt)!!
}
items.toMap()
entries.toMap()
}
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack): BlockUsages {
// ToDo: Check tags (21w19a+)
val nextState = tillableBlockStates?.get(blockState.block) ?: return BlockUsages.PASS
if (!Minosoft.config.config.game.controls.enableTilling) {
return BlockUsages.CONSUME
}
if (connection.world[blockPosition + Directions.UP] != null) {
return BlockUsages.PASS
}
connection.world[blockPosition] = nextState
return BlockUsages.SUCCESS
return super.interactWithTool(connection, blockPosition, tillableBlockStates?.get(blockState.block))
}
}

View File

@ -17,6 +17,7 @@ import com.google.gson.JsonObject
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.protocol.network.connection.PlayConnection
@ -27,23 +28,38 @@ open class MiningToolItem(
registries: Registries,
data: JsonObject,
) : ToolItem(resourceLocation, registries, data) {
val diggableBlocks: List<Block>? = data["diggable_blocks"]?.asJsonArray?.let {
val diggableBlocks: MutableList<Block> = mutableListOf()
val diggableBlocks: Set<Block>? = data["diggable_blocks"]?.asJsonArray?.let {
val entries: MutableList<Block> = mutableListOf()
for (id in it) {
diggableBlocks += registries.blockRegistry[id.asInt]
entries += registries.blockRegistry[id]
}
diggableBlocks.toList()
entries.toSet()
}
override val attackDamage: Float = data["attack_damage"]?.asFloat ?: 1.0f
val miningSpeed: Float = data["mining_speed"]?.asFloat ?: 1.0f
override fun getMiningSpeedMultiplier(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, itemStack: ItemStack): Float {
// ToDo: Calculate correct, Tags (21w19a)
if (diggableBlocks?.contains(blockState.block) == true) {
return 10.0f * miningSpeed
open fun isEffectiveOn(blockState: BlockState): Boolean {
return diggableBlocks?.contains(blockState.block) == true
}
protected fun interactWithTool(connection: PlayConnection, blockPosition: Vec3i, replace: BlockState?): BlockUsages {
if (!connection.player.entity.gamemode.useTools) {
return BlockUsages.PASS
}
return super.getMiningSpeedMultiplier(connection, blockState, blockPosition, itemStack)
replace ?: return BlockUsages.PASS
connection.world[blockPosition] = replace
return BlockUsages.SUCCESS
}
override fun getMiningSpeedMultiplier(connection: PlayConnection, blockState: BlockState, itemStack: ItemStack): Float {
// ToDo: Calculate correct, Tags (21w19a)
if (isEffectiveOn(blockState)) {
return speed
}
return super.getMiningSpeedMultiplier(connection, blockState, itemStack)
}
}

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.mappings.items.tools
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.versions.Registries
open class PickaxeItem(
resourceLocation: ResourceLocation,
registries: Registries,
data: JsonObject,
) : MiningToolItem(resourceLocation, registries, data)

View File

@ -14,6 +14,7 @@
package de.bixilon.minosoft.data.mappings.items.tools
import com.google.gson.JsonObject
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.mappings.ResourceLocation
@ -33,24 +34,26 @@ open class ShovelItem(
data: JsonObject,
) : MiningToolItem(resourceLocation, registries, data) {
val flattenableBlockStates: Map<Block, BlockState>? = data["flattenables_block_states"]?.asJsonObject?.let {
val items: MutableMap<Block, BlockState> = mutableMapOf()
val entries: MutableMap<Block, BlockState> = mutableMapOf()
for ((origin, target) in it.entrySet()) {
items[registries.blockRegistry[origin.toInt()]] = registries.getBlockState(target.asInt)!!
entries[registries.blockRegistry[origin.toInt()]] = registries.getBlockState(target.asInt)!!
}
items.toMap()
entries.toMap()
}
override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack): BlockUsages {
// ToDo: Check tags (21w19a+)
val nextState = flattenableBlockStates?.get(blockState.block) ?: return BlockUsages.PASS
if (!Minosoft.config.config.game.controls.enableFlattening) {
return BlockUsages.CONSUME
}
if (connection.world[blockPosition + Directions.UP] != null) {
return BlockUsages.PASS
}
connection.world[blockPosition] = nextState
return BlockUsages.SUCCESS
return super.interactWithTool(connection, blockPosition, flattenableBlockStates?.get(blockState.block))
}
}

View File

@ -17,10 +17,9 @@ import com.google.gson.JsonObject
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.DefaultBlocks
import de.bixilon.minosoft.data.mappings.versions.Registries
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import glm_.vec3.Vec3i
open class SwordItem(
@ -30,15 +29,10 @@ open class SwordItem(
) : ToolItem(resourceLocation, registries, data) {
override val attackDamage = data["attack_damage"]?.asFloat ?: -1.0f
override fun getMiningSpeedMultiplier(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, itemStack: ItemStack): Float {
if (blockState.block.resourceLocation == COBWEB_BLOCK) {
override fun getMiningSpeedMultiplier(connection: PlayConnection, blockState: BlockState, itemStack: ItemStack): Float {
if (blockState.block.resourceLocation == DefaultBlocks.COBWEB) {
return 15.0f
}
return super.getMiningSpeedMultiplier(connection, blockState, blockPosition, itemStack)
}
companion object {
val COBWEB_BLOCK = "minecraft:cobweb".asResourceLocation()
return super.getMiningSpeedMultiplier(connection, blockState, itemStack)
}
}

View File

@ -13,9 +13,12 @@
package de.bixilon.minosoft.data.mappings.registry
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.versions.Registries
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import de.bixilon.minosoft.util.collections.Clearable
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
@ -27,6 +30,18 @@ open class Registry<T : RegistryItem>(
protected val valueIdMap: MutableMap<T, Int> = mutableMapOf()
protected val resourceLocationMap: MutableMap<ResourceLocation, T> = mutableMapOf()
open operator fun get(json: JsonElement): T {
return when (json) {
is JsonPrimitive -> {
when {
json.isString -> get(json.asString.asResourceLocation())!!
json.isNumber -> get(json.asInt)
else -> TODO()
}
}
else -> TODO()
}
}
open operator fun get(resourceLocation: ResourceLocation): T? {
return resourceLocationMap[resourceLocation] ?: parentRegistry?.get(resourceLocation)

View File

@ -19,7 +19,10 @@ import de.bixilon.minosoft.data.entities.EntityMetaDataFields
import de.bixilon.minosoft.data.entities.block.BlockEntityMetaType
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
import de.bixilon.minosoft.data.inventory.InventorySlots
import de.bixilon.minosoft.data.mappings.*
import de.bixilon.minosoft.data.mappings.DefaultRegistries
import de.bixilon.minosoft.data.mappings.Dimension
import de.bixilon.minosoft.data.mappings.Motive
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.mappings.biomes.BiomeCategory
import de.bixilon.minosoft.data.mappings.biomes.BiomePrecipitation
@ -28,6 +31,7 @@ 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.enchantment.Enchantment
import de.bixilon.minosoft.data.mappings.entities.EntityType
import de.bixilon.minosoft.data.mappings.entities.villagers.VillagerProfession
import de.bixilon.minosoft.data.mappings.fluid.Fluid

View File

@ -18,12 +18,16 @@ import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.mappings.effects.DefaultStatusEffects
import de.bixilon.minosoft.data.mappings.enchantment.DefaultEnchantments
import de.bixilon.minosoft.data.mappings.items.tools.MiningToolItem
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.BlockBreakC2SP
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.pow
import glm_.vec3.Vec3i
class LeftClickHandler(
@ -42,6 +46,10 @@ class LeftClickHandler(
private var lastSwing = 0L
private var creativeLastHoldBreakTime = 0L
private val efficiencyEnchantment = connection.registries.enchantmentRegistry[DefaultEnchantments.EFFICIENCY]
private val hasteStatusEffect = connection.registries.statusEffectRegistry[DefaultStatusEffects.HASTE]
private val miningFatigueStatusEffect = connection.registries.statusEffectRegistry[DefaultStatusEffects.MINING_FATIGUE]
private fun clearDigging() {
breakPosition = null
breakBlockState = null
@ -116,6 +124,11 @@ class LeftClickHandler(
connection.sendPacket(BlockBreakC2SP(BlockBreakC2SP.BreakType.FINISHED_DIGGING, raycastHit.blockPosition, raycastHit.hitDirection))
clearDigging()
connection.world.setBlockState(raycastHit.blockPosition, null)
if (connection.player.entity.gamemode != Gamemodes.CREATIVE) {
// decrease durability
// ToDo
}
}
val canStartBreaking = currentTime - breakSent >= ProtocolDefinition.TICK_TIME
@ -149,15 +162,51 @@ class LeftClickHandler(
swingArm()
// thanks to https://minecraft.fandom.com/wiki/Breaking#Calculation
var speedMultiplier = 1.0f
val breakItemInHand = breakItemInHand
val isBestTool = !raycastHit.blockState.requiresTool || breakItemInHand?.item?.let {
return@let if (it is MiningToolItem) {
it.isEffectiveOn(raycastHit.blockState)
} else {
false
}
} ?: false
var speedMultiplier = breakItemInHand?.let { it.item.getMiningSpeedMultiplier(connection, raycastHit.blockState, it) } ?: 1.0f
if (isBestTool) {
breakItemInHand?.enchantments?.get(efficiencyEnchantment)?.let {
speedMultiplier += it.pow(2) + 1.0f
}
}
connection.player.entity.activeStatusEffects[hasteStatusEffect]?.let {
speedMultiplier *= (0.2f * it.amplifier) + 1.0f
}
connection.player.entity.activeStatusEffects[miningFatigueStatusEffect]?.let {
speedMultiplier *= when (it.amplifier) {
0 -> 0.3f
1 -> 0.09f
2 -> 0.0027f
else -> 0.00081f
}
}
// ToDp: Check if is in water
if (!connection.player.entity.onGround) {
speedMultiplier /= 5.0f
}
var damage = speedMultiplier / raycastHit.blockState.hardness
damage /= if (raycastHit.blockState.requiresTool) {
100
} else {
damage /= if (isBestTool) {
30
} else {
100
}
when {