-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: rework block breaking system (#84)
* feat: use attributes for custom-block-breaking system * feat: implement BlockyModifiers * feat: create datapack to disable * fix: handle break modifier when breaking vanilla noteblock due to datapack * refactor: code cleanup of old system code * refactor: more code cleanup * fix: workflow java version
- Loading branch information
Showing
15 changed files
with
304 additions
and
425 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.mineinabyss.blocky | ||
|
||
import com.mineinabyss.idofront.messaging.broadcast | ||
import com.mineinabyss.idofront.messaging.broadcastVal | ||
import com.mineinabyss.idofront.messaging.logVal | ||
import io.papermc.paper.datapack.Datapack | ||
import io.papermc.paper.datapack.DatapackManager | ||
import io.papermc.paper.datapack.PaperDatapack | ||
import kotlinx.serialization.json.* | ||
import net.minecraft.core.registries.BuiltInRegistries | ||
import net.minecraft.tags.BlockTags | ||
import net.minecraft.world.level.block.NoteBlock | ||
import org.bukkit.Bukkit | ||
import org.bukkit.Tag | ||
|
||
object BlockyDatapacks { | ||
|
||
private val defaultWorld = Bukkit.getWorlds().first() | ||
private val blockyDatapack = defaultWorld.worldFolder.resolve("datapacks/blocky") | ||
|
||
fun generateDatapack() { | ||
blockyDatapack.resolve("data").mkdirs() | ||
writeMcMeta() | ||
generateMineableTag() | ||
|
||
Bukkit.getDatapackManager().packs.firstOrNull { it.name == "file/blocky" }?.isEnabled = true | ||
} | ||
|
||
fun writeMcMeta() { | ||
runCatching { | ||
val packMeta = blockyDatapack.resolve("pack.mcmeta") | ||
packMeta.writeText(buildJsonObject { | ||
putJsonObject("pack") { | ||
put("description", "Datapack for Blocky") | ||
put("pack_format", 26) | ||
} | ||
}.toString()) | ||
}.onFailure { it.printStackTrace() } | ||
} | ||
|
||
private fun generateMineableTag() { | ||
runCatching { | ||
val tagFile = blockyDatapack.resolve("data/minecraft/tags/blocks/mineable/axe.json") | ||
tagFile.parentFile.mkdirs() | ||
tagFile.createNewFile() | ||
|
||
val tagObject = buildJsonObject { | ||
put("replace", true) | ||
putJsonArray("values") { | ||
BuiltInRegistries.BLOCK.tags.toList().find { it.first == BlockTags.MINEABLE_WITH_AXE }?.second?.forEach { | ||
if (it.registeredName != "minecraft:note_block") add(it.registeredName) | ||
} | ||
} | ||
} | ||
|
||
tagFile.writeText(tagObject.toString()) | ||
}.onFailure { it.printStackTrace() } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 47 additions & 40 deletions
87
src/main/kotlin/com/mineinabyss/blocky/components/features/BlockyBreaking.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,81 @@ | ||
package com.mineinabyss.blocky.components.features | ||
|
||
import com.mineinabyss.blocky.components.core.BlockyInfo | ||
import com.mineinabyss.blocky.components.features.mining.BlockyMining | ||
import com.mineinabyss.blocky.api.BlockyFurnitures.prefabKey | ||
import com.mineinabyss.blocky.components.features.mining.ToolType | ||
import com.mineinabyss.blocky.helpers.GenericHelpers | ||
import com.mineinabyss.blocky.helpers.gearyInventory | ||
import com.mineinabyss.geary.papermc.tracking.blocks.helpers.toGearyOrNull | ||
import com.mineinabyss.geary.prefabs.PrefabKey | ||
import com.mineinabyss.idofront.messaging.broadcastVal | ||
import com.mineinabyss.idofront.serialization.DurationSerializer | ||
import com.mineinabyss.idofront.serialization.SerializableItemStack | ||
import com.mineinabyss.idofront.serialization.toSerializable | ||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
import org.bukkit.Material | ||
import org.bukkit.attribute.AttributeModifier | ||
import org.bukkit.block.Block | ||
import org.bukkit.entity.Player | ||
import org.bukkit.inventory.EquipmentSlot | ||
import org.bukkit.inventory.ItemStack | ||
import org.bukkit.inventory.EquipmentSlotGroup | ||
import java.util.UUID | ||
import kotlin.time.Duration | ||
import kotlin.time.Duration.Companion.seconds | ||
|
||
@Serializable | ||
@SerialName("blocky:breaking") | ||
data class BlockyBreaking( | ||
val baseDuration: @Serializable(DurationSerializer::class) Duration = 3.seconds, | ||
val hardness: Double, | ||
val modifiers: BlockyModifiers = BlockyModifiers() | ||
) { | ||
private fun defaultBlockHardness(block: Block): Double { | ||
return when (block.type) { | ||
Material.NOTE_BLOCK -> 0.8 | ||
else -> 1.0 | ||
} | ||
} | ||
|
||
fun calculateBreakTime(block: Block, player: Player, hand: EquipmentSlot, heldItem: ItemStack?): Duration { | ||
val itemInHand = heldItem ?: ItemStack(Material.AIR) | ||
var duration = baseDuration | ||
if (block.toGearyOrNull()?.get<BlockyInfo>()?.isUnbreakable == true) return Duration.INFINITE | ||
/** | ||
* Calculates the AttributeModifier that would correctly change the breaking-speed based on the BlockyBreaking-hardness | ||
* This method takes into account the base-value of the PLAYER_BLOCK_BREAKING_SPEED attribute, as well as any existing modifiers | ||
* It then handles it based on the default hardness of the block | ||
*/ | ||
fun createBreakingModifier(player: Player, block: Block): AttributeModifier { | ||
return AttributeModifier.deserialize( | ||
mapOf( | ||
"slot" to EquipmentSlotGroup.HAND, | ||
"uuid" to UUID.nameUUIDFromBytes(block.toString().toByteArray()).toString(), | ||
"name" to "blocky:custom_break_speed", | ||
"operation" to AttributeModifier.Operation.MULTIPLY_SCALAR_1.ordinal, | ||
"amount" to (defaultBlockHardness(block) / hardness) - 1 + player.blockStateModifiers() | ||
) | ||
) | ||
} | ||
|
||
if (modifiers.heldItems.isNotEmpty()) { | ||
val heldPrefab = player.gearyInventory?.get(hand)?.prefabs?.first()?.get<PrefabKey>() | ||
val modifier = modifiers.heldItems.firstOrNull { | ||
it.item.prefab?.let { p -> p == heldPrefab?.full } ?: false | ||
//TODO This could be improved. isSimilar cares about durability which we don't want though | ||
|| (it.item.type == itemInHand.type) | ||
} | ||
if (modifier != null) duration = maxOf(duration - modifier.value, Duration.ZERO) | ||
} else if (modifiers.heldTypes.isNotEmpty()) { | ||
val heldTypes = player.gearyInventory?.get(hand)?.get<BlockyMining>()?.toolTypes ?: setOf(GenericHelpers.vanillaToolTypes(itemInHand)) | ||
val modifier = modifiers.heldTypes.firstOrNull { it.toolType in heldTypes } | ||
if (modifier != null) duration = maxOf(duration - modifier.value, Duration.ZERO) | ||
} | ||
private fun Player.blockStateModifiers(): Double { | ||
var modifier = 0.0 | ||
|
||
//TODO: state modifiers | ||
/*if (player.activePotionEffects.any { it.type == PotionEffectType.FAST_DIGGING }) | ||
duration = duration.times(0.2 * (player.activePotionEffects.first { it.type == PotionEffectType.FAST_DIGGING }.amplifier)) | ||
if (player.isInWater && player.)*/ | ||
modifier += modifiers.heldTypes.find { it.toolType.contains(inventory.itemInMainHand) }?.value ?: 0.0 | ||
modifier += modifiers.heldItems.find { | ||
if (it.item.prefab != null) it.item.prefab == inventory.itemInMainHand.toSerializable().prefab | ||
else it.item.type == inventory.itemInMainHand.type | ||
}?.value ?: 0.0 | ||
|
||
return duration | ||
return modifier | ||
} | ||
|
||
@Serializable | ||
@SerialName("blocky:modifier") | ||
data class BlockyModifiers( | ||
val heldItems: Set<BlockySerializableItemModifier> = setOf(), | ||
val heldTypes: Set<BlockyToolModifier> = setOf(), | ||
val states: Set<BlockyStateModifier> = setOf(), | ||
) { | ||
@Serializable data class BlockySerializableItemModifier(val item: SerializableItemStack, val value: @Serializable(DurationSerializer::class) Duration) | ||
@Serializable data class BlockyToolModifier(val toolType: ToolType, val value: @Serializable(DurationSerializer::class) Duration) | ||
@Serializable data class BlockyStateModifier(val state: BlockyStateType, val value: @Serializable(DurationSerializer::class) Duration, val operation: Operation = Operation.SUBTRACT) | ||
@Serializable | ||
data class BlockySerializableItemModifier( | ||
val item: SerializableItemStack, | ||
val value: Double | ||
) | ||
|
||
enum class Operation { | ||
ADD, SUBTRACT, MULTIPLY, DIVIDE | ||
} | ||
enum class BlockyStateType { | ||
HASTE, MINING_FATIGUE, IN_WATER, IN_WATER_NO_AFFINITY, NOT_ON_GROUND, IS_SNEAKING | ||
} | ||
@Serializable | ||
data class BlockyToolModifier( | ||
val toolType: ToolType, | ||
val value: Double | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 0 additions & 7 deletions
7
src/main/kotlin/com/mineinabyss/blocky/components/features/mining/PlayerIsMining.kt
This file was deleted.
Oops, something went wrong.
23 changes: 23 additions & 0 deletions
23
src/main/kotlin/com/mineinabyss/blocky/components/features/mining/PlayerMiningAttribute.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.mineinabyss.blocky.components.features.mining | ||
|
||
import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull | ||
import com.mineinabyss.idofront.messaging.broadcastVal | ||
import com.mineinabyss.idofront.serialization.AttributeModifierSerializer | ||
import kotlinx.serialization.Serializable | ||
import org.bukkit.attribute.Attribute | ||
import org.bukkit.attribute.AttributeModifier | ||
import org.bukkit.entity.Player | ||
|
||
@Serializable | ||
data class PlayerMiningAttribute(val modifier: @Serializable(AttributeModifierSerializer::class) AttributeModifier) { | ||
fun addTransientModifier(player: Player) { | ||
player.getAttribute(Attribute.PLAYER_BLOCK_BREAK_SPEED)?.addTransientModifier(modifier) | ||
} | ||
|
||
fun removeModifier(player: Player) { | ||
player.getAttribute(Attribute.PLAYER_BLOCK_BREAK_SPEED)?.removeModifier(modifier) | ||
player.toGearyOrNull()?.remove<PlayerMiningAttribute>() | ||
} | ||
} | ||
|
||
val Player.miningAttribute get() = toGearyOrNull()?.get<PlayerMiningAttribute>() |
Oops, something went wrong.