Skip to content

Commit

Permalink
feat: implement server auth block breaking
Browse files Browse the repository at this point in the history
  • Loading branch information
smartcmd committed Jun 12, 2024
1 parent 7076fae commit b448493
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
import org.allaymc.api.item.ItemStack;
import org.allaymc.api.item.enchantment.type.EnchantmentAquaAffinityType;
import org.allaymc.api.item.enchantment.type.EnchantmentEfficiencyType;
import org.allaymc.api.item.tag.ItemTag;
import org.allaymc.api.item.type.ItemType;
import org.allaymc.api.world.Dimension;

import static org.allaymc.api.data.VanillaItemTags.*;
import static org.allaymc.api.data.VanillaMaterialTypes.*;
import static org.allaymc.api.item.type.ItemTypes.*;
import static org.allaymc.api.item.ItemHelper.isSword;

/**
* Allay Project 2023/4/8
Expand Down Expand Up @@ -49,14 +45,11 @@ default <DATATYPE> void updateBlockProperty(BlockPropertyType<DATATYPE> property
chunk.sendChunkPacket(Dimension.createBlockUpdatePacket(newBlockState, x, y, z, layer));
}

// TODO: 此方法为服务端权威方块破坏准备,目前不完善,等待后续完善
default double calculateBreakTime(BlockState blockState, ItemStack usedItem, Entity entity) {
checkBlockType(blockState);
double blockHardness = blockState.getBlockAttributes().hardness();
if (blockHardness == 0) return 0;
boolean isCorrectTool = isCorrectTool(blockState, usedItem);
//isAlwaysDestroyable为true时,表示方块可以被任何物品破坏并掉落物品
//部分方块(例如石头,黑曜石)不可以被徒手挖去,强行挖取它们不会掉落任何物品,且挖掘速度会受到惩罚(baseTime增大5倍,正常是1.5倍)
boolean isCorrectTool = usedItem.isCorrectToolFor(blockState);
boolean isAlwaysDestroyable = getBlockType().getMaterial().isAlwaysDestroyable();
boolean hasAquaAffinity = false;
boolean isInWater = false;
Expand Down Expand Up @@ -85,13 +78,17 @@ default double calculateBreakTime(BlockState blockState, ItemStack usedItem, Ent
}

// Calculate break time
// TODO: 需要进一步验证算法
double baseTime = ((isCorrectTool || isAlwaysDestroyable) ? 1.5 : 5.0) * blockHardness;
double speed = 1.0d / baseTime;
if (isCorrectTool) {
// 工具等级(木制,石制,铁制,etc...)加成
speed *= toolBreakTimeBonus(usedItem, blockState);
speed *= usedItem.getBreakTimeBonus(blockState);
// 工具效率附魔加成
speed += speedBonusByEfficiency(efficiencyLevel);
} else if (isSword(usedItem.getItemType())) {
// 剑挖掘方块的最低速率是1.5倍
speed *= 1.5;
}
// 实体急迫药水效果加成
speed *= 1.0d + (0.2d * hasteEffectLevel);
Expand All @@ -109,57 +106,6 @@ private static double speedBonusByEfficiency(int efficiencyLevel) {
return efficiencyLevel * efficiencyLevel + 1;
}

// TODO: toolBreakTimeBonus()和isCorrectTool()需要完善,未覆盖所有方块
private double toolBreakTimeBonus(ItemStack usedItem, BlockState blockState) {
var itemType = usedItem.getItemType();
var materialType = blockState.getBlockType().getMaterial().materialType();
// 剑破坏蜘蛛网加速
if (itemType.hasItemTag(IS_SWORD)) return materialType == WEB ? 15.0 : 1.5;
if (itemType == SHEARS_TYPE) {
// 剪刀破坏羊毛和树叶加速
if (materialType == CLOTH) {
return 5.0;
} else if (materialType == WEB || materialType == LEAVES) {
return 15.0;
}
return 1.0;
}
if (!itemType.hasItemTag(IS_TOOL)) return 1.0;
if (itemType.hasItemTag(GOLDEN_TIER)) return 12.0;
if (itemType.hasItemTag(NETHERITE_TIER)) return 9.0;
if (itemType.hasItemTag(DIAMOND_TIER)) return 8.0;
if (itemType.hasItemTag(IRON_TIER)) return 6.0;
if (itemType.hasItemTag(STONE_TIER)) return 4.0;
if (itemType.hasItemTag(WOODEN_TIER)) return 2.0;
return 1.0;
}

default boolean isCorrectTool(BlockState blockState, ItemStack usedItem) {
checkBlockType(blockState);
// TODO: 实现挖掘正确工具判断
return true;
}

private boolean isItemTierBiggerThan(ItemType<?> itemType, ItemTag tier) {
var itemTier = 0;
for (ItemTag itemTag : itemType.getItemTags()) {
var value = computeItemTier(itemTag);
if (value > itemTier) itemTier = value;
}
return itemTier > computeItemTier(tier);
}

private int computeItemTier(ItemTag itemTag) {
int itemTier = 0;
if (itemTag == WOODEN_TIER) itemTier = 1;
if (itemTag == STONE_TIER) itemTier = 2;
if (itemTag == IRON_TIER) itemTier = 3;
if (itemTag == DIAMOND_TIER) itemTier = 4;
if (itemTag == NETHERITE_TIER) itemTier = 5;
if (itemTag == GOLDEN_TIER) itemTier = 6;
return itemTier;
}

private void checkBlockType(BlockState blockState) {
if (blockState.getBlockType() != getBlockType()) throw new IllegalArgumentException("Block type is not match! Expected: " + getBlockType().getIdentifier() + ", actual: " + blockState.getBlockType().getIdentifier());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public record Material(
MaterialType materialType,
boolean canBeMovingBlock,
boolean canHavePrecipitation,
//isAlwaysDestroyable为true时,表示方块可以被任何物品破坏并掉落物品
//部分方块(例如石头,黑曜石)不可以被徒手挖去,强行挖取它们不会掉落任何物品,且挖掘速度会受到惩罚(baseTime增大5倍,正常是1.5倍)
boolean isAlwaysDestroyable,
boolean isLiquid,
boolean isSolid,
Expand Down
47 changes: 47 additions & 0 deletions Allay-API/src/main/java/org/allaymc/api/item/ItemHelper.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.allaymc.api.item;

import org.allaymc.api.data.VanillaItemTags;
import org.allaymc.api.item.init.SimpleItemStackInitInfo;
import org.allaymc.api.item.registry.ItemTypeRegistry;
import org.allaymc.api.item.type.ItemType;
import org.allaymc.api.utils.Identifier;
import org.cloudburstmc.nbt.NbtMap;

Expand All @@ -26,4 +28,49 @@ public static ItemStack fromNBT(NbtMap nbt) {
.extraTag(nbt.getCompound("tag"))
.build());
}

/**
* 获取物品的物品等级 <br>
* @return ItemTier对象, 或者null如果此物品不存在物品等级
*/
public static ItemTier getItemTier(ItemType<?> itemType) {
for (var tier : ItemTier.ORDER_OF_QUALITY) {
if (itemType.hasItemTag(tier.getItemTag())) {
return tier;
}
}
return null;
}

public static boolean isTool(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_TOOL);
}

public static boolean isSword(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_SWORD);
}

public static boolean isPickaxe(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_PICKAXE);
}

public static boolean isHoe(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_HOE);
}

public static boolean isAxe(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_AXE);
}

public static boolean isShovel(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_SHOVEL);
}

public static boolean isArmor(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.IS_ARMOR);
}

public static boolean isTrimmableArmor(ItemType<?> itemType) {
return itemType.hasItemTag(VanillaItemTags.TRIMMABLE_ARMORS);
}
}
34 changes: 34 additions & 0 deletions Allay-API/src/main/java/org/allaymc/api/item/ItemTier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.allaymc.api.item;

import lombok.Getter;
import org.allaymc.api.item.tag.ItemTag;

import static org.allaymc.api.data.VanillaItemTags.*;

/**
* Allay Project 2024/6/12
*
* @author daoge_cmd
*/
public enum ItemTier {
WOODEN(WOODEN_TIER),
STONE(STONE_TIER),
IRON(IRON_TIER),
DIAMOND(DIAMOND_TIER),
NETHERITE(NETHERITE_TIER),
GOLD(GOLDEN_TIER);

public static final ItemTier[] ORDER_OF_QUALITY =
{GOLD, NETHERITE, DIAMOND, IRON, STONE, WOODEN};

@Getter
private final ItemTag itemTag;

ItemTier(ItemTag itemTag) {
this.itemTag = itemTag;
}

public boolean isBetterThan(ItemTier tier) {
return this.ordinal() > tier.ordinal();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import org.allaymc.api.block.data.BlockFace;
import org.allaymc.api.block.type.BlockState;
import org.allaymc.api.data.VanillaBlockId;
import org.allaymc.api.data.VanillaItemId;
import org.allaymc.api.entity.interfaces.EntityPlayer;
import org.allaymc.api.item.ItemHelper;
import org.allaymc.api.item.ItemStack;
import org.allaymc.api.item.component.ItemComponent;
import org.allaymc.api.item.enchantment.EnchantmentType;
Expand All @@ -13,8 +16,16 @@
import org.joml.Vector3fc;
import org.joml.Vector3ic;

import java.util.EnumMap;
import java.util.List;

import static org.allaymc.api.block.type.BlockTypes.BAMBOO_BLOCK_TYPE;
import static org.allaymc.api.data.VanillaItemTags.*;
import static org.allaymc.api.data.VanillaItemTags.WOODEN_TIER;
import static org.allaymc.api.data.VanillaMaterialTypes.*;
import static org.allaymc.api.item.type.ItemTypes.BAMBOO_TYPE;
import static org.allaymc.api.item.type.ItemTypes.SHEARS_TYPE;

/**
* Allay Project 2023/5/19
*
Expand Down Expand Up @@ -116,4 +127,44 @@ default NbtMap saveNBT() {
short getEnchantmentLevel(EnchantmentType enchantmentType);

void addEnchantment(EnchantmentType enchantmentType, short level);

/**
* 获取破坏方块的加速倍数 <br>
* @param blockState 要破坏的方块
* @return 加速倍速
*/
default double getBreakTimeBonus(BlockState blockState) {
var itemType = getItemType();
var materialType = blockState.getBlockType().getMaterial().materialType();
// 剑破坏蜘蛛网加速
if (itemType.hasItemTag(IS_SWORD)) {
if (materialType == WEB) return 15.0;
if (blockState.getBlockType() == BAMBOO_BLOCK_TYPE) return Integer.MAX_VALUE;
}
if (itemType == SHEARS_TYPE) {
// 剪刀破坏羊毛和树叶加速
if (materialType == CLOTH) {
return 5.0;
} else if (materialType == WEB || materialType == LEAVES) {
return 15.0;
}
return 1.0;
}
if (!itemType.hasItemTag(IS_TOOL)) return 1.0;
if (itemType.hasItemTag(GOLDEN_TIER)) return 12.0;
if (itemType.hasItemTag(NETHERITE_TIER)) return 9.0;
if (itemType.hasItemTag(DIAMOND_TIER)) return 8.0;
if (itemType.hasItemTag(IRON_TIER)) return 6.0;
if (itemType.hasItemTag(STONE_TIER)) return 4.0;
if (itemType.hasItemTag(WOODEN_TIER)) return 2.0;
return 1.0;
}

/**
* 判断是否是指定方块的正确破坏工具 <br>
* 若不是正确破坏工具,使用此物品破坏方块时将获得速度惩罚,且不会产生掉落物 <br>
* @param blockState 要破坏的方块
* @return 是否是正确工具
*/
boolean isCorrectToolFor(BlockState blockState);
}
Binary file not shown.
Loading

0 comments on commit b448493

Please sign in to comment.