mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
Merge branch 'dev' of https://github.com/Xiao-MoMi/craft-engine into dev
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,9 @@ public class SimpleStorageBlockEntity extends BlockEntity {
|
||||
public void updateOpenBlockState(boolean open) {
|
||||
ImmutableBlockState state = super.world.getBlockStateAtIfLoaded(this.pos);
|
||||
if (state == null || state.behavior() != this.behavior) return;
|
||||
Property<Boolean> property = this.behavior.openProperty();
|
||||
SimpleStorageBlockBehavior behavior = state.behavior().getAs(SimpleStorageBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) return;
|
||||
Property<Boolean> property = behavior.openProperty();
|
||||
if (property == null) return;
|
||||
super.world.world().setBlockState(this.pos.x(), this.pos.y(), this.pos.z(), state.with(property, open), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -162,6 +162,7 @@ warning.config.recipe.smithing_transform.post_processor.missing_type: "<yellow>I
|
||||
warning.config.recipe.smithing_transform.post_processor.invalid_type: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is using an invalid post processor type '<arg:2>'.</yellow>"
|
||||
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is missing the required argument 'components' for post-processors 'keep_components'.</yellow>"
|
||||
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is missing the required argument 'tags' for post-processors 'keep_tags'.</yellow>"
|
||||
warning.config.recipe.smithing_transform.post_processor.keep_custom_data.missing_paths: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is missing the required argument 'paths' for post-processors 'keep_custom_data'.</yellow>"
|
||||
warning.config.recipe.smithing_transform.missing_base: "<yellow>Issue found in file <arg:0> - The smithing transform recipe '<arg:1>' is missing the required 'base' argument.</yellow>"
|
||||
warning.config.recipe.smithing_trim.missing_base: "<yellow>Issue found in file <arg:0> - The smithing trim recipe '<arg:1>' is missing the required 'base' argument.</yellow>"
|
||||
warning.config.recipe.smithing_trim.missing_template_type: "<yellow>Issue found in file <arg:0> - The smithing trim recipe '<arg:1>' is missing the required 'template-type' argument.</yellow>"
|
||||
|
||||
@@ -159,6 +159,7 @@ warning.config.recipe.smithing_transform.post_processor.missing_type: "<yellow>
|
||||
warning.config.recipe.smithing_transform.post_processor.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 锻造升级配方 '<arg:1>' 使用了无效的后处理器类型 '<arg:2>'</yellow>"
|
||||
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "<yellow>在文件 <arg:0> 发现问题 - 锻造升级配方 '<arg:1>' 的 'keep_components' 后处理器缺少必需的 'components' 参数</yellow>"
|
||||
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "<yellow>在文件 <arg:0> 发现问题 - 锻造升级配方 '<arg:1>' 的 'keep_tags' 后处理器缺少必需的 'tags' 参数</yellow>"
|
||||
warning.config.recipe.smithing_transform.post_processor.keep_custom_data.missing_paths: "<yellow>在文件 <arg:0> 发现问题 - 锻造升级配方 '<arg:1>' 的 'keep_custom_data' 后处理器缺少必需的 'paths' 参数</yellow>"
|
||||
warning.config.recipe.smithing_transform.missing_base: "<yellow>在文件 <arg:0> 发现问题 - 锻造升级配方 '<arg:1>' 缺少必需的 'base' 参数</yellow>"
|
||||
warning.config.recipe.smithing_trim.missing_base: "<yellow>在文件 <arg:0> 发现问题 - 锻造纹饰配方 '<arg:1>' 缺少必需的 'base' 参数</yellow>"
|
||||
warning.config.recipe.smithing_trim.missing_template_type: "<yellow>在文件 <arg:0> 发现问题 - 锻造纹饰配方 '<arg:1>' 缺少必需的 'template-type' 参数</yellow>"
|
||||
|
||||
@@ -19,10 +19,7 @@ import net.momirealms.craftengine.core.util.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -232,10 +229,12 @@ public class CustomSmithingTransformRecipe<T> extends AbstractedFixedResultRecip
|
||||
public static final Key KEEP_COMPONENTS = Key.of("craftengine:keep_components");
|
||||
public static final Key KEEP_TAGS = Key.of("craftengine:keep_tags");
|
||||
public static final Key MERGE_ENCHANTMENTS = Key.of("craftengine:merge_enchantments");
|
||||
public static final Key KEEP_CUSTOM_DATA = Key.of("craftengine:keep_custom_data");
|
||||
|
||||
static {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
register(KEEP_COMPONENTS, KeepComponents.FACTORY);
|
||||
register(KEEP_CUSTOM_DATA, KeepCustomData.FACTORY);
|
||||
} else {
|
||||
register(KEEP_TAGS, KeepTags.FACTORY);
|
||||
}
|
||||
@@ -315,6 +314,42 @@ public class CustomSmithingTransformRecipe<T> extends AbstractedFixedResultRecip
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeepCustomData implements ItemDataProcessor {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final List<String[]> paths;
|
||||
|
||||
public KeepCustomData(List<String[]> data) {
|
||||
this.paths = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Item<?> item1, Item<?> item2, Item<?> item3) {
|
||||
for (String[] path : this.paths) {
|
||||
Object dataObj = item1.getJavaTag((Object[]) path);
|
||||
if (dataObj != null) {
|
||||
item3.setTag(dataObj, (Object[]) path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return ItemDataProcessors.KEEP_CUSTOM_DATA;
|
||||
}
|
||||
|
||||
public static class Factory implements ProcessorFactory {
|
||||
|
||||
@Override
|
||||
public ItemDataProcessor create(Map<String, Object> arguments) {
|
||||
List<String> paths = MiscUtils.getAsStringList(ResourceConfigUtils.requireNonNullOrThrow(
|
||||
arguments.get("paths"),
|
||||
"warning.config.recipe.smithing_transform.post_processor.keep_custom_data.missing_paths")
|
||||
);
|
||||
return new KeepCustomData(paths.stream().map(it -> it.split("\\.")).toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeepComponents implements ItemDataProcessor {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final List<Key> components;
|
||||
@@ -339,6 +374,7 @@ public class CustomSmithingTransformRecipe<T> extends AbstractedFixedResultRecip
|
||||
}
|
||||
|
||||
public static class Factory implements ProcessorFactory {
|
||||
private static final Key CUSTOM_DATA = Key.of("minecraft", "custom_data");
|
||||
|
||||
@Override
|
||||
public ItemDataProcessor create(Map<String, Object> arguments) {
|
||||
@@ -347,7 +383,7 @@ public class CustomSmithingTransformRecipe<T> extends AbstractedFixedResultRecip
|
||||
throw new LocalizedResourceConfigException("warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components");
|
||||
}
|
||||
List<String> components = MiscUtils.getAsStringList(componentsObj);
|
||||
return new KeepComponents(components.stream().map(Key::of).toList());
|
||||
return new KeepComponents(components.stream().map(Key::of).filter(it -> !CUSTOM_DATA.equals(it)).toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user