mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
Merge pull request #486 from jhqwqmc/feat/drop-experience-block
添加掉落经验方块
This commit is contained in:
@@ -47,6 +47,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key SURFACE_SPREADING_BLOCK = Key.from("craftengine:surface_spreading_block");
|
||||
public static final Key SNOWY_BLOCK = Key.from("craftengine:snowy_block");
|
||||
public static final Key HANGABLE_BLOCK = Key.from("craftengine:hangable_block");
|
||||
public static final Key DROP_EXPERIENCE_BLOCK = Key.from("craftengine:drop_experience_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -92,5 +93,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(SURFACE_SPREADING_BLOCK, SurfaceSpreadingBlockBehavior.FACTORY);
|
||||
register(SNOWY_BLOCK, SnowyBlockBehavior.FACTORY);
|
||||
register(HANGABLE_BLOCK, HangableBlockBehavior.FACTORY);
|
||||
register(DROP_EXPERIENCE_BLOCK, DropExperienceBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.BlockSettings;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.condition.AllOfCondition;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventConditions;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class DropExperienceBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final NumberProvider amount;
|
||||
private final Condition<Context> conditions;
|
||||
|
||||
public DropExperienceBlockBehavior(CustomBlock customBlock, NumberProvider amount, Condition<Context> conditions) {
|
||||
super(customBlock);
|
||||
this.amount = amount;
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnAfterBreak(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
boolean dropExperience = (boolean) args[4]; // 通常来说是 false
|
||||
Item<ItemStack> item = BukkitItemManager.instance().wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(args[3]));
|
||||
if (!dropExperience) {
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(args[0]).orElse(null);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
BlockSettings settings = state.settings();
|
||||
if (settings.requireCorrectTool()) {
|
||||
if (item.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
boolean cannotBreak = !settings.isCorrectTool(item.id())
|
||||
&& (!settings.respectToolComponent()
|
||||
|| !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(args[3], state.customBlockState().literalObject()));
|
||||
if (cannotBreak) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
World world = BukkitWorldManager.instance().wrap(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1]));
|
||||
BlockPos pos = LocationUtils.fromBlockPos(args[2]);
|
||||
tryDropExperience(world, pos, item);
|
||||
}
|
||||
|
||||
private void tryDropExperience(World world, BlockPos pos, Item<ItemStack> item) {
|
||||
Vec3d dropPos = Vec3d.atCenterOf(pos);
|
||||
ContextHolder holder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, new WorldPosition(world, dropPos))
|
||||
.withParameter(DirectContextParameters.ITEM_IN_HAND, item)
|
||||
.build();
|
||||
LootContext context = new LootContext(world, null, 1.0f, holder);
|
||||
if (this.conditions != null && !this.conditions.test(context)) {
|
||||
return;
|
||||
}
|
||||
int finalAmount = this.amount.getInt(context);
|
||||
if (finalAmount <= 0) {
|
||||
return;
|
||||
}
|
||||
world.dropExp(dropPos, finalAmount);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
NumberProvider amount = NumberProviders.fromObject(arguments.getOrDefault("amount", 0));
|
||||
Condition<Context> conditions = null;
|
||||
List<Condition<Context>> conditionList = ResourceConfigUtils.parseConfigAsList(ResourceConfigUtils.get(arguments, "conditions", "condition"), EventConditions::fromMap);
|
||||
if (conditionList.size() == 1) {
|
||||
conditions = conditionList.getFirst();
|
||||
} else if (!conditionList.isEmpty()) {
|
||||
conditions = new AllOfCondition<>(conditionList);
|
||||
}
|
||||
return new DropExperienceBlockBehavior(block, amount, conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,13 +27,17 @@ items:
|
||||
texture: minecraft:item/custom/topaz
|
||||
blocks:
|
||||
default:topaz_ore:
|
||||
behavior:
|
||||
type: drop_experience_block
|
||||
amount: 3~7
|
||||
condition:
|
||||
type: enchantment
|
||||
predicate: minecraft:silk_touch<=0
|
||||
loot:
|
||||
template: default:loot_table/ore
|
||||
arguments:
|
||||
ore_drop: default:topaz
|
||||
ore_block: default:topaz_ore
|
||||
min_exp: 3
|
||||
max_exp: 7
|
||||
settings:
|
||||
template: default:settings/ore
|
||||
arguments:
|
||||
@@ -45,13 +49,17 @@ blocks:
|
||||
arguments:
|
||||
path: minecraft:block/custom/topaz_ore
|
||||
default:deepslate_topaz_ore:
|
||||
behavior:
|
||||
type: drop_experience_block
|
||||
amount: 3~7
|
||||
condition:
|
||||
type: enchantment
|
||||
predicate: minecraft:silk_touch<=0
|
||||
loot:
|
||||
template: default:loot_table/ore
|
||||
arguments:
|
||||
ore_drop: default:topaz
|
||||
ore_block: default:deepslate_topaz_ore
|
||||
min_exp: 3
|
||||
max_exp: 7
|
||||
settings:
|
||||
template: default:settings/deepslate_ore
|
||||
arguments:
|
||||
|
||||
@@ -180,7 +180,6 @@ templates:
|
||||
# ore_block: the ore block
|
||||
# ore_drop: the drops of the ore material
|
||||
# ore_drop_count: the amount of the ore materials
|
||||
# exp: the exp to drop
|
||||
default:loot_table/ore:
|
||||
pools:
|
||||
- rolls: 1
|
||||
@@ -203,8 +202,6 @@ templates:
|
||||
formula:
|
||||
type: ore_drops
|
||||
- type: explosion_decay
|
||||
- type: drop_exp
|
||||
count: ${exp:-2~4}
|
||||
|
||||
# Using Silk Touch or shears will cause the leaves block itself to drop.
|
||||
# Using Fortune, however, increases the drop rates of sticks and saplings.
|
||||
|
||||
Reference in New Issue
Block a user