9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-25 09:59:20 +00:00

Merge pull request #346 from Halogly/feature

增加条件,改进命令事件
This commit is contained in:
XiaoMoMi
2025-08-23 17:22:00 +08:00
committed by GitHub
18 changed files with 212 additions and 46 deletions

View File

@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.item.listener;
import io.papermc.paper.event.block.CompostItemEvent;
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent;
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
import net.momirealms.craftengine.bukkit.item.BukkitCustomItem;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
@@ -96,9 +97,10 @@ public class ItemEventListener implements Listener {
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
.withParameter(DirectContextParameters.EVENT, cancellable)
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(event.getRightClicked().getLocation()))
.withParameter(DirectContextParameters.HAND, hand)
.withParameter(DirectContextParameters.EVENT, cancellable)
.withParameter(DirectContextParameters.ENTITY, new BukkitEntity(entity))
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(event.getRightClicked().getLocation()))
);
CustomItem<ItemStack> customItem = optionalCustomItem.get();
customItem.execute(context, EventTrigger.RIGHT_CLICK);

View File

@@ -40,6 +40,7 @@ import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.block.Block;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
@@ -177,6 +178,26 @@ public class BukkitServerPlayer extends Player {
return platformPlayer().isSneaking();
}
@Override
public boolean isSwimming() {
return platformPlayer().isSwimming();
}
@Override
public boolean isClimbing() {
return platformPlayer().isClimbing();
}
@Override
public boolean isGliding() {
return platformPlayer().isGliding();
}
@Override
public boolean isFlying() {
return platformPlayer().isFlying();
}
@Override
public GameMode gameMode() {
return switch (platformPlayer().getGameMode()) {
@@ -475,7 +496,7 @@ public class BukkitServerPlayer extends Player {
ImmutableBlockState customState = optionalCustomState.get();
Item<ItemStack> tool = getItemInHand(InteractionHand.MAIN_HAND);
boolean isCorrectTool = FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(tool.getLiteralObject(), blockState);
// 如果自定义方块在服务端侧未使用正确工具,那么需要还原挖掘速度
// 如果自定义方块在服务端侧未使用正确工具,那么需要还原挖掘速度
if (!isCorrectTool) {
progress *= (10f / 3f);
}
@@ -939,6 +960,14 @@ public class BukkitServerPlayer extends Player {
platformPlayer().performCommand(command);
}
@Override
@SuppressWarnings("UnstableApiUsage")
public void performCommandAsEvent(String command) {
String formattedCommand = command.startsWith("/") ? command : "/" + command;
PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(platformPlayer(), formattedCommand);
Bukkit.getPluginManager().callEvent(event);
}
@Override
public double luck() {
if (VersionHelper.isOrAbove1_21_3()) {
@@ -948,11 +977,6 @@ public class BukkitServerPlayer extends Player {
}
}
@Override
public boolean isFlying() {
return platformPlayer().isFlying();
}
@Override
public int foodLevel() {
return platformPlayer().getFoodLevel();

View File

@@ -37,6 +37,7 @@ public final class SoundUtils {
case HOSTILE -> SoundCategory.HOSTILE;
case NEUTRAL -> SoundCategory.NEUTRAL;
case WEATHER -> SoundCategory.WEATHER;
case UI -> SoundCategory.UI;
};
}
}

View File

@@ -6,10 +6,12 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.BlockInWorld;
import net.momirealms.craftengine.core.world.World;
import org.bukkit.Location;
@@ -59,6 +61,11 @@ public class BukkitBlockInWorld implements BlockInWorld {
return this.block.getZ();
}
@Override
public Key type() {
return KeyUtils.namespacedKey2Key(this.block.getType().getKey());
}
@Override
public World world() {
return new BukkitWorld(this.block.getWorld());

View File

@@ -92,6 +92,8 @@ warning.config.condition.inverted.invalid_term_type: "<yellow>Issue found in fil
warning.config.condition.enchantment.missing_predicate: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'predicate' argument for 'enchantment' condition.</yellow>"
warning.config.condition.enchantment.invalid_predicate: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid enchantment 'predicate' argument '<arg:2>'.</yellow>"
warning.config.condition.match_block_property.missing_properties: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'properties' argument for 'match_block_property' condition.</yellow>"
warning.config.condition.match_block_type.missing_id: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'id' argument for 'match_block_type' condition.</yellow>"
warning.config.condition.match_entity_type.missing_id: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'id' argument for 'match_entity_type' condition.</yellow>"
warning.config.condition.match_item.missing_id: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'id' argument for 'match_item' condition.</yellow>"
warning.config.condition.table_bonus.missing_enchantment: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'enchantment' argument for 'table_bonus' condition.</yellow>"
warning.config.condition.table_bonus.missing_chances: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'chances' argument for 'table_bonus' condition.</yellow>"
@@ -295,7 +297,7 @@ warning.config.block.behavior.fence_gate.missing_facing: "<yellow>Issue found in
warning.config.block.behavior.fence_gate.missing_in_wall: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'in_wall' argument for 'fence_gate_block' behavior.</yellow>"
warning.config.block.behavior.fence_gate.missing_open: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'powered' argument for 'fence_gate_block' behavior.</yellow>"
warning.config.block.behavior.fence_gate.missing_powered: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'open' argument for 'fence_gate_block' behavior.</yellow>"
warning.config.block.behavior.trapdoor.missing_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'type' property for 'slab_block' behavior.</yellow>"
warning.config.block.behavior.slab.missing_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'type' property for 'slab_block' behavior.</yellow>"
warning.config.block.behavior.stairs.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'stairs_block' behavior.</yellow>"
warning.config.block.behavior.stairs.missing_half: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'half' property for 'stairs_block' behavior.</yellow>"
warning.config.block.behavior.stairs.missing_shape: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'shape' property for 'stairs_block' behavior.</yellow>"
@@ -303,9 +305,9 @@ warning.config.block.behavior.pressure_plate.missing_powered: "<yellow>Issue fou
warning.config.block.behavior.grass.missing_feature: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'feature' argument for 'grass_block' behavior.</yellow>"
warning.config.block.behavior.double_high.missing_half: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'half' property for 'double_block' behavior.</yellow>"
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
warning.config.model.generation.invalid_display_position: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid display position '<arg:2>' in 'generation.display' section. Allowed display positions: [<arg:3>]</yellow>"
warning.config.model.generation.invalid_gui_light: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid gui-light option '<arg:2>' in 'generation' section. Allowed gui light options: [<arg:3>]</yellow>"
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
warning.config.model.generation.texture.invalid: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a texture '<arg:2>' with path '<arg:3>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.model.generation.parent.invalid: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a parent argument '<arg:2>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.emoji.missing_keywords: "<yellow>Issue found in file <arg:0> - The emoji '<arg:1>' is missing the required 'keywords' argument.</yellow>"
@@ -411,14 +413,14 @@ warning.config.selector.invalid_type: "<yellow>Issue found in file <arg:0> - The
warning.config.selector.invalid_target: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector target '<arg:2>'.</yellow>"
warning.config.resource_pack.item_model.already_exist: "<yellow>Failed to generate item model for '<arg:0>' because the file '<arg:1>' already exists.</yellow>"
warning.config.resource_pack.model.generation.already_exist: "<yellow>Failed to generate model because the model file '<arg:0>' already exists.</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json file '<arg:0>' is malformatted.</yellow>"
warning.config.resource_pack.generation.missing_font_texture: "<yellow>Font '<arg:0>' is missing required texture: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.texture_not_in_atlas: "<yellow>Texture '<arg:0>' is not listed in the atlas. You need to add the texture path to the atlas or enable 'obfuscation' option in config.yml.</yellow>"
warning.config.resource_pack.generation.missing_model_texture: "<yellow>Model '<arg:0>' is missing texture '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_item_model: "<yellow>Item '<arg:0>' is missing model file: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_block_model: "<yellow>Block state '<arg:0>' is missing model file: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_parent_model: "<yellow>Model '<arg:0>' cannot find parent model: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json file '<arg:0>' is malformatted.</yellow>"
warning.config.resource_pack.generation.missing_equipment_texture: "<yellow>Equipment '<arg:0>' is missing texture '<arg:1>'</yellow>"
warning.config.resource_pack.generation.texture_not_in_atlas: "<yellow>Texture '<arg:0>' is not listed in the atlas. You need to add the texture path to the atlas or enable 'obfuscation' option in config.yml.</yellow>"
warning.config.resource_pack.invalid_overlay_format: "<yellow>Issue found in config.yml at 'resource-pack.overlay-format' - Invalid overlay format '<arg:0>'. Overlay format must contain the placeholder '{version}'.</yellow>"
warning.config.equipment.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated equipment '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
warning.config.equipment.missing_type: "<yellow>Issue found in file <arg:0> - The equipment '<arg:1>' is missing the required 'type' argument.</yellow>"

View File

@@ -92,6 +92,8 @@ warning.config.condition.inverted.invalid_term_type: "<yellow>在文件 <arg:0>
warning.config.condition.enchantment.missing_predicate: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'enchantment' 条件所需的 'predicate' 参数</yellow>"
warning.config.condition.enchantment.invalid_predicate: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 使用了无效的附魔 'predicate' 参数 '<arg:2>'</yellow>"
warning.config.condition.match_block_property.missing_properties: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_block_property' 条件所需的 'properties' 参数</yellow>"
warning.config.condition.match_block_type.missing_id: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_block_type' 条件所需的 'id' 参数</yellow>"
warning.config.condition.match_entity_type.missing_id: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_entity_type' 条件所需的 'id' 参数</yellow>"
warning.config.condition.match_item.missing_id: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_item' 条件所需的 'id' 参数</yellow>"
warning.config.condition.table_bonus.missing_enchantment: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'table_bonus' 条件所需的 'enchantment' 参数</yellow>"
warning.config.condition.table_bonus.missing_chances: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'table_bonus' 条件所需的 'chances' 参数</yellow>"
@@ -411,14 +413,14 @@ warning.config.selector.invalid_type: "<yellow>在文件 <arg:0> 中发现问题
warning.config.selector.invalid_target: "<yellow>在文件 <arg:0> 中发现问题 - 配置项 '<arg:1>' 使用了无效的选择器目标 '<arg:2>'</yellow>"
warning.config.resource_pack.item_model.already_exist: "<yellow>无法为 '<arg:0>' 生成物品模型,因为文件 '<arg:1>' 已存在</yellow>"
warning.config.resource_pack.model.generation.already_exist: "<yellow>无法生成模型,因为模型文件 '<arg:0>' 已存在</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json文件 '<arg:0>' 格式错误</yellow>"
warning.config.resource_pack.generation.missing_font_texture: "<yellow>字体'<arg:0>'缺少必要纹理: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_model_texture: "<yellow>模型'<arg:0>'缺少纹理'<arg:1>'</yellow>"
warning.config.resource_pack.generation.texture_not_in_atlas: "<yellow>纹理'<arg:0>'不在图集内. 你需要将纹理路径或文件夹前缀添加到图集内,或者启用 config.yml 中的 'obfuscation' 选项</yellow>"
warning.config.resource_pack.generation.missing_item_model: "<yellow>物品'<arg:0>'缺少模型文件: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_block_model: "<yellow>方块状态'<arg:0>'缺少模型文件: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_parent_model: "<yellow>模型'<arg:0>'找不到父级模型文件: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json文件 '<arg:0>' 格式错误</yellow>"
warning.config.resource_pack.generation.missing_equipment_texture: "<yellow>装备 '<arg:0>' 缺少纹理 '<arg:1>'</yellow>"
warning.config.resource_pack.generation.texture_not_in_atlas: "<yellow>纹理'<arg:0>'不在图集内. 你需要将纹理路径或文件夹前缀添加到图集内,或者启用 config.yml 中的 'obfuscation' 选项</yellow>"
warning.config.resource_pack.invalid_overlay_format: "<yellow>在 config.yml 的 'resource-pack.overlay-format' 处发现问题 - 无效的overlay格式 '<arg:0>'. Overlay格式必须包含占位符 '{version}'</yellow>"
warning.config.equipment.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的装备配置 '<arg:1>'。请检查其他文件中是否存在相同配置</yellow>"
warning.config.equipment.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 装备 '<arg:1>' 缺少必需的 'type' 参数</yellow>"

View File

@@ -52,6 +52,14 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract boolean isSneaking();
public abstract boolean isSwimming();
public abstract boolean isClimbing();
public abstract boolean isGliding();
public abstract boolean isFlying();
public abstract GameMode gameMode();
public abstract void setGameMode(GameMode gameMode);
@@ -106,9 +114,9 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract void performCommand(String command);
public abstract double luck();
public abstract void performCommandAsEvent(String command);
public abstract boolean isFlying();
public abstract double luck();
@Override
public Key type() {

View File

@@ -10,6 +10,8 @@ public final class CommonConditions {
public static final Key ANY_OF = Key.of("craftengine:any_of");
public static final Key INVERTED = Key.of("craftengine:inverted");
public static final Key MATCH_ITEM = Key.of("craftengine:match_item");
public static final Key MATCH_ENTITY_TYPE = Key.of("craftengine:match_entity_type");
public static final Key MATCH_BLOCK_TYPE = Key.of("craftengine:match_block_type");
public static final Key MATCH_BLOCK_PROPERTY = Key.from("craftengine:match_block_property");
public static final Key TABLE_BONUS = Key.from("craftengine:table_bonus");
public static final Key SURVIVES_EXPLOSION = Key.from("craftengine:survives_explosion");

View File

@@ -0,0 +1,50 @@
package net.momirealms.craftengine.core.plugin.context.condition;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.world.BlockInWorld;
import java.util.*;
public class MatchBlockTypeCondition<CTX extends Context> implements Condition<CTX> {
private final Set<String> ids;
private final boolean regexMatch;
public MatchBlockTypeCondition(Collection<String> ids, boolean regexMatch) {
this.ids = new HashSet<>(ids);
this.regexMatch = regexMatch;
}
@Override
public Key type() {
return CommonConditions.MATCH_ENTITY_TYPE;
}
@Override
public boolean test(CTX ctx) {
Optional<BlockInWorld> block = ctx.getOptionalParameter(DirectContextParameters.BLOCK);
if (block.isEmpty()) return false;
Optional<ImmutableBlockState> customBlock = ctx.getOptionalParameter(DirectContextParameters.CUSTOM_BLOCK_STATE);
Key key = customBlock.isPresent() ? customBlock.get().owner().value().id() : block.get().type();
return MiscUtils.matchObject(key, this.regexMatch, this.ids);
}
public static class FactoryImpl<CTX extends Context> implements ConditionFactory<CTX> {
@Override
public Condition<CTX> create(Map<String, Object> arguments) {
List<String> ids = MiscUtils.getAsStringList(arguments.get("id"));
if (ids.isEmpty()) {
throw new LocalizedResourceConfigException("warning.config.condition.match_block_type.missing_id");
}
boolean regex = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("regex", false), "regex");
return new MatchBlockTypeCondition<>(ids, regex);
}
}
}

View File

@@ -0,0 +1,48 @@
package net.momirealms.craftengine.core.plugin.context.condition;
import net.momirealms.craftengine.core.entity.Entity;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.*;
public class MatchEntityTypeCondition<CTX extends Context> implements Condition<CTX> {
private final Set<String> ids;
private final boolean regexMatch;
public MatchEntityTypeCondition(Collection<String> ids, boolean regexMatch) {
this.ids = new HashSet<>(ids);
this.regexMatch = regexMatch;
}
@Override
public Key type() {
return CommonConditions.MATCH_ENTITY_TYPE;
}
@Override
public boolean test(CTX ctx) {
Optional<Entity> entity = ctx.getOptionalParameter(DirectContextParameters.ENTITY);
if (entity.isEmpty()) return false;
Key key = entity.get().type();
return MiscUtils.matchObject(key, this.regexMatch, this.ids);
}
public static class FactoryImpl<CTX extends Context> implements ConditionFactory<CTX> {
@Override
public Condition<CTX> create(Map<String, Object> arguments) {
List<String> ids = MiscUtils.getAsStringList(arguments.get("id"));
if (ids.isEmpty()) {
throw new LocalizedResourceConfigException("warning.config.condition.match_entity_type.missing_id");
}
boolean regex = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("regex", false), "regex");
return new MatchEntityTypeCondition<>(ids, regex);
}
}
}

View File

@@ -30,17 +30,7 @@ public class MatchItemCondition<CTX extends Context> implements Condition<CTX> {
Optional<Item<?>> item = ctx.getOptionalParameter(DirectContextParameters.ITEM_IN_HAND);
if (item.isEmpty()) return false;
Key key = item.get().id();
String itemId = key.toString();
if (this.regexMatch) {
for (String regex : ids) {
if (itemId.matches(regex)) {
return true;
}
}
} else {
return this.ids.contains(itemId);
}
return false;
return MiscUtils.matchObject(key, this.regexMatch, this.ids);
}
public static class FactoryImpl<CTX extends Context> implements ConditionFactory<CTX> {

View File

@@ -17,6 +17,8 @@ public class EventConditions {
static {
register(CommonConditions.MATCH_ITEM, new MatchItemCondition.FactoryImpl<>());
register(CommonConditions.MATCH_ENTITY_TYPE, new MatchEntityTypeCondition.FactoryImpl<>());
register(CommonConditions.MATCH_BLOCK_TYPE, new MatchBlockTypeCondition.FactoryImpl<>());
register(CommonConditions.MATCH_BLOCK_PROPERTY, new MatchBlockPropertyCondition.FactoryImpl<>());
register(CommonConditions.TABLE_BONUS, new TableBonusCondition.FactoryImpl<>());
register(CommonConditions.SURVIVES_EXPLOSION, new SurvivesExplosionCondition.FactoryImpl<>());

View File

@@ -16,34 +16,34 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class CommandFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final List<TextProvider> command;
private final boolean asPlayer;
private final PlayerSelector<CTX> selector;
private final boolean asPlayer;
private final boolean asEvent;
public CommandFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, List<TextProvider> command, boolean asPlayer) {
public CommandFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, List<TextProvider> command, boolean asPlayer, boolean asEvent) {
super(predicates);
this.asPlayer = asPlayer;
this.command = command;
this.selector = selector;
this.asPlayer = asPlayer;
this.asEvent = asEvent;
}
@Override
public void runInternal(CTX ctx) {
if (this.asPlayer) {
if (this.selector == null) {
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
for (TextProvider c : this.command) {
it.performCommand(c.get(ctx));
}
});
ctx.getOptionalParameter(DirectContextParameters.PLAYER)
.ifPresent(player -> executeCommands(
ctx, this.asEvent ? player::performCommandAsEvent : player::performCommand
));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
for (TextProvider c : this.command) {
viewer.performCommand(c.get(relationalContext));
}
executeCommands(relationalContext, this.asEvent ? viewer::performCommandAsEvent : viewer::performCommand);
}
}
} else {
@@ -54,6 +54,12 @@ public class CommandFunction<CTX extends Context> extends AbstractConditionalFun
}
}
private void executeCommands(Context ctx, Consumer<String> executor) {
for (TextProvider c : this.command) {
executor.accept(c.get(ctx));
}
}
@Override
public Key type() {
return CommonFunctions.COMMAND;
@@ -70,7 +76,8 @@ public class CommandFunction<CTX extends Context> extends AbstractConditionalFun
Object command = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "command", "commands"), "warning.config.function.command.missing_command");
List<TextProvider> commands = MiscUtils.getAsStringList(command).stream().map(TextProviders::fromString).toList();
boolean asPlayer = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("as-player", false), "as-player");
return new CommandFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), commands, asPlayer);
boolean asEvent = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("as-event", false), "as-event");
return new CommandFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), commands, asPlayer, asEvent);
}
}
}

View File

@@ -57,8 +57,11 @@ public final class DirectContextParameters {
public static final ContextKey<AnchorType> ANCHOR_TYPE = ContextKey.direct("anchor_type");
public static final ContextKey<InteractionHand> HAND = ContextKey.direct("hand");
public static final ContextKey<Cancellable> EVENT = ContextKey.direct("event");
public static final ContextKey<Boolean> IS_FLYING = ContextKey.direct("is_flying");
public static final ContextKey<Boolean> IS_SNEAKING = ContextKey.direct("is_sneaking");
public static final ContextKey<Boolean> IS_SWIMMING = ContextKey.direct("is_swimming");
public static final ContextKey<Boolean> IS_CLIMBING = ContextKey.direct("is_climbing");
public static final ContextKey<Boolean> IS_GLIDING = ContextKey.direct("is_gliding");
public static final ContextKey<Boolean> IS_FLYING = ContextKey.direct("is_flying");
public static final ContextKey<Boolean> IS_CUSTOM = ContextKey.direct("is_custom");
public static final ContextKey<Boolean> IS_BLOCK_ITEM = ContextKey.direct("is_block_item");
public static final ContextKey<GameMode> GAMEMODE = ContextKey.direct("gamemode");

View File

@@ -29,8 +29,11 @@ public class PlayerParameterProvider implements ChainParameterProvider<Player> {
CONTEXT_FUNCTIONS.put(DirectContextParameters.NAME, Player::name);
CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Player::uuid);
CONTEXT_FUNCTIONS.put(DirectContextParameters.WORLD, Entity::world);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_FLYING, Player::isFlying);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_SNEAKING, Player::isSneaking);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_SWIMMING, Player::isSwimming);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_CLIMBING, Player::isClimbing);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_GLIDING, Player::isGliding);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_FLYING, Player::isFlying);
CONTEXT_FUNCTIONS.put(DirectContextParameters.GAMEMODE, Player::gameMode);
CONTEXT_FUNCTIONS.put(DirectContextParameters.MAIN_HAND_ITEM, p -> p.getItemInHand(InteractionHand.MAIN_HAND));
CONTEXT_FUNCTIONS.put(DirectContextParameters.OFF_HAND_ITEM, p -> p.getItemInHand(InteractionHand.OFF_HAND));

View File

@@ -12,7 +12,8 @@ public enum SoundSource {
NEUTRAL("neutral"),
PLAYER("player"),
AMBIENT("ambient"),
VOICE("voice");
VOICE("voice"),
UI("ui");
private final String id;

View File

@@ -4,10 +4,7 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
public class MiscUtils {
@@ -153,4 +150,18 @@ public class MiscUtils {
return o;
}
}
public static boolean matchObject(Key key, boolean regexMatch, Set<String> ids) {
String id = key.toString();
if (regexMatch) {
for (String regex : ids) {
if (id.matches(regex)) {
return true;
}
}
} else {
return ids.contains(id);
}
return false;
}
}

View File

@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.world;
import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.Nullable;
public interface BlockInWorld {
@@ -27,6 +28,8 @@ public interface BlockInWorld {
World world();
Key type();
int x();
int y();