diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index e8dca66a7..ac1084288 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -90,7 +90,10 @@ warning.config.condition.match_block_property.missing_properties: "Issue warning.config.condition.match_item.missing_id: "Issue found in file - The config '' is missing the required 'id' argument for 'match_item' condition." warning.config.condition.table_bonus.missing_enchantment: "Issue found in file - The config '' is missing the required 'enchantment' argument for 'table_bonus' condition." warning.config.condition.table_bonus.missing_chances: "Issue found in file - The config '' is missing the required 'chances' argument for 'table_bonus' condition." -warning.config.condition.click_type.missing_click_type: "Issue found in file - The config '' is missing the required 'click-type' argument for 'click_type' condition." +warning.config.condition.permission.missing_permission: "Issue found in file - The config '' is missing the required 'permission' argument for 'permission' condition." +warning.config.condition.equals.missing_value1: "Issue found in file - The config '' is missing the required 'value1' argument for 'equals' condition." +warning.config.condition.equals.missing_value2: "Issue found in file - The config '' is missing the required 'value2' argument for 'equals' condition." +warning.config.condition.expression.missing_expression: "Issue found in file - The config '' is missing the required 'expression' argument for 'expression' condition." warning.config.structure.not_section: "Issue found in file - The config '' is expected to be a config section while it's actually a(n) ''." warning.config.image.duplicate: "Issue found in file - Duplicated image ''. Please check if there is the same configuration in other files." warning.config.image.missing_height: "Issue found in file - The image '' is missing the required 'height' argument." @@ -302,4 +305,9 @@ warning.config.event.condition.missing_type: "Issue found in file Issue found in file - The config '' is using an invalid 'type' argument '' for event condition." warning.config.function.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for function." warning.config.function.invalid_type: "Issue found in file - The config '' is using an invalid function type ''." -warning.config.function.command.missing_command: "Issue found in file - The config '' is missing the required 'command' argument for 'command' function." \ No newline at end of file +warning.config.function.command.missing_command: "Issue found in file - The config '' is missing the required 'command' argument for 'command' function." +warning.config.function.actionbar.missing_actionbar: "Issue found in file - The config '' is missing the required 'actionbar' argument for 'actionbar' function." +warning.config.function.message.missing_message: "Issue found in file - The config '' is missing the required 'message' argument for 'message' function." +warning.config.selector.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for selector." +warning.config.selector.invalid_type: "Issue found in file - The config '' is using an invalid selector type ''." +warning.config.selector.invalid_target: "Issue found in file - The config '' is using an invalid selector target ''." \ No newline at end of file diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index a8c511c27..f0f71519f 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -90,7 +90,8 @@ warning.config.condition.match_block_property.missing_properties: "在 warning.config.condition.match_item.missing_id: "在文件 发现问题 - 配置项 '' 缺少 'match_item' 条件所需的 'id' 参数" warning.config.condition.table_bonus.missing_enchantment: "在文件 发现问题 - 配置项 '' 缺少 'table_bonus' 条件所需的 'enchantment' 参数" warning.config.condition.table_bonus.missing_chances: "在文件 发现问题 - 配置项 '' 缺少 'table_bonus' 条件所需的 'chances' 参数" -warning.config.condition.click_type.missing_click_type: "Issue found in file - The config '' is missing the required 'click-type' argument for 'click_type' condition." + + warning.config.structure.not_section: "在文件 发现问题 - 配置项 '' 应为配置段落 但实际类型为 ''" warning.config.image.duplicate: "在文件 发现问题 - 重复的图片配置 '' 请检查其他文件中是否存在相同配置" warning.config.image.missing_height: "在文件 发现问题 - 图片 '' 缺少必需的 'height' 参数" diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index 21e0ebc39..070c400b4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -11,6 +11,7 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.config.Config; @@ -42,6 +43,7 @@ import org.bukkit.event.world.GenericGameEvent; import org.bukkit.inventory.ItemStack; import java.util.List; +import java.util.Optional; public class BlockEventListener implements Listener { private final BukkitCraftEngine plugin; @@ -121,11 +123,35 @@ public class BlockEventListener implements Listener { Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData()); int stateId = BlockStateUtils.blockStateToId(blockState); Player player = event.getPlayer(); + Location location = block.getLocation(); + BukkitServerPlayer serverPlayer = this.plugin.adapt(player); + net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld()); + WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5); + Item itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND); + + if (itemInHand != null) { + Optional> optionalCustomItem = itemInHand.getCustomItem(); + if (optionalCustomItem.isPresent()) { + Cancellable dummy = Cancellable.dummy(); + optionalCustomItem.get().execute( + PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() + .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)) + .withParameter(DirectContextParameters.POSITION, position) + .withParameter(DirectContextParameters.PLAYER, serverPlayer) + .withParameter(DirectContextParameters.EVENT, dummy) + .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand) + ), EventTrigger.BREAK + ); + if (dummy.isCancelled()) { + event.setCancelled(true); + return; + } + } + } + if (!BlockStateUtils.isVanillaBlock(stateId)) { ImmutableBlockState state = manager.getImmutableBlockStateUnsafe(stateId); if (!state.isEmpty()) { - Location location = block.getLocation(); - BukkitServerPlayer serverPlayer = this.plugin.adapt(player); // double check adventure mode to prevent dupe if (!FastNMS.INSTANCE.mayBuild(serverPlayer.serverPlayer()) && !serverPlayer.canBreak(LocationUtils.toBlockPos(location), null)) { return; @@ -139,10 +165,6 @@ public class BlockEventListener implements Listener { return; } - Item itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(location.getWorld()); - WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5); - // execute functions Cancellable cancellable = Cancellable.dummy(); PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() @@ -180,12 +202,12 @@ public class BlockEventListener implements Listener { } // drop items - ContextHolder.Builder builder = ContextHolder.builder() + ContextHolder.Builder lootContext = ContextHolder.builder() .withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.PLAYER, serverPlayer) .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)) .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand); - for (Item item : state.getDrops(builder, world, serverPlayer)) { + for (Item item : state.getDrops(lootContext, world, serverPlayer)) { world.dropItemNaturally(position, item); } } @@ -197,23 +219,19 @@ public class BlockEventListener implements Listener { event.setDropItems(false); event.setExpToDrop(0); } - Location location = block.getLocation(); - BukkitServerPlayer serverPlayer = this.plugin.adapt(player); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld()); - WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5); - ContextHolder.Builder builder = ContextHolder.builder() + ContextHolder lootContext = ContextHolder.builder() .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)) .withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.PLAYER, serverPlayer) - .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND)); - ContextHolder contextHolder = builder.build(); + .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand).build(); for (LootTable lootTable : it.lootTables()) { - for (Item item : lootTable.getRandomItems(contextHolder, world, serverPlayer)) { + for (Item item : lootTable.getRandomItems(lootContext, world, serverPlayer)) { world.dropItemNaturally(position, item); } } }); } + // sound system if (Config.enableSoundSystem()) { Object ownerBlock = BlockStateUtils.getBlockOwner(blockState); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java index 536217d46..ffe08c8fd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java @@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.world.World; import java.lang.ref.WeakReference; +import java.util.UUID; public class BukkitEntity extends AbstractEntity { private final WeakReference entity; @@ -69,4 +70,14 @@ public class BukkitEntity extends AbstractEntity { public Key type() { return KeyUtils.namespacedKey2Key(literalObject().getType().getKey()); } + + @Override + public String name() { + return literalObject().getName(); + } + + @Override + public UUID uuid() { + return literalObject().getUniqueId(); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 1d4086b39..5e045570f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -13,6 +13,7 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.BlockSettings; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.PackedBlockState; +import net.momirealms.craftengine.core.entity.player.GameMode; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.Item; @@ -27,7 +28,10 @@ import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldEvents; -import org.bukkit.*; +import org.bukkit.FluidCollisionMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.SoundCategory; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.block.Block; @@ -145,18 +149,18 @@ public class BukkitServerPlayer extends Player { } @Override - public boolean isCreativeMode() { - return platformPlayer().getGameMode() == GameMode.CREATIVE; + public GameMode gameMode() { + return switch (platformPlayer().getGameMode()) { + case CREATIVE -> GameMode.CREATIVE; + case SPECTATOR -> GameMode.SPECTATOR; + case ADVENTURE -> GameMode.ADVENTURE; + case SURVIVAL -> GameMode.SURVIVAL; + }; } @Override - public boolean isSpectatorMode() { - return platformPlayer().getGameMode() == GameMode.SPECTATOR; - } - - @Override - public boolean isAdventureMode() { - return platformPlayer().getGameMode() == GameMode.ADVENTURE; + public void setGameMode(GameMode gameMode) { + platformPlayer().setGameMode(Objects.requireNonNull(org.bukkit.GameMode.getByValue(gameMode.id()))); } @Override @@ -175,6 +179,14 @@ public class BukkitServerPlayer extends Player { sendPacket(packet, false); } + @Override + public void sendTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) { + Object titlePacket = FastNMS.INSTANCE.constructor$ClientboundSetTitleTextPacket(ComponentUtils.adventureToMinecraft(title)); + Object subtitlePacket = FastNMS.INSTANCE.constructor$ClientboundSetSubtitleTextPacket(ComponentUtils.adventureToMinecraft(subtitle)); + Object timePacket = FastNMS.INSTANCE.constructor$ClientboundSetTitlesAnimationPacket(fadeIn, stay, fadeOut); + sendPackets(List.of(titlePacket, subtitlePacket, timePacket), false); + } + @Override public void sendMessage(Component text, boolean overlay) { Object packet = FastNMS.INSTANCE.constructor$ClientboundSystemChatPacket(ComponentUtils.adventureToMinecraft(text), overlay); @@ -816,4 +828,9 @@ public class BukkitServerPlayer extends Player { return LegacyAttributeUtils.getLuck(platformPlayer()); } } + + @Override + public boolean isFlying() { + return platformPlayer().isFlying(); + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java index 8c9958a36..15720fa5c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java @@ -5,6 +5,8 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; +import java.util.UUID; + public interface Entity { Key type(); @@ -29,4 +31,8 @@ public interface Entity { Direction getDirection(); Object literalObject(); + + String name(); + + UUID uuid(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/GameMode.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/GameMode.java new file mode 100644 index 000000000..716ce0ba3 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/GameMode.java @@ -0,0 +1,18 @@ +package net.momirealms.craftengine.core.entity.player; + +public enum GameMode { + SURVIVAL(0), + CREATIVE(1), + ADVENTURE(2), + SPECTATOR(3); + + private final int id; + + GameMode(int id) { + this.id = id; + } + + public int id() { + return id; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index 81a9b77c3..bb50aec7d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -46,11 +46,9 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract boolean isSneaking(); - public abstract boolean isCreativeMode(); + public abstract GameMode gameMode(); - public abstract boolean isSpectatorMode(); - - public abstract boolean isAdventureMode(); + public abstract void setGameMode(GameMode gameMode); public abstract boolean canBreak(BlockPos pos, Object state); @@ -60,6 +58,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract void sendMessage(Component text, boolean overlay); + public abstract void sendTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut); + public abstract boolean updateLastSuccessfulInteractionTick(int tick); public abstract int lastSuccessfulInteractionTick(); @@ -75,7 +75,7 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract String name(); public void playSound(Key sound) { - playSound(sound, 1, 1); + playSound(sound, 1f, 1f); } public abstract void playSound(Key sound, float volume, float pitch); @@ -92,8 +92,26 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract double luck(); + public abstract boolean isFlying(); + @Override public Key type() { return TYPE; } + + public boolean isCreativeMode() { + return gameMode() == GameMode.CREATIVE; + } + + public boolean isSpectatorMode() { + return gameMode() == GameMode.SPECTATOR; + } + + public boolean isSurvivalMode() { + return gameMode() == GameMode.SURVIVAL; + } + + public boolean isAdventureMode() { + return gameMode() == GameMode.ADVENTURE; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java index 0dc4c9a32..43ca9b0aa 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java @@ -30,6 +30,9 @@ public class LootConditions { register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>()); register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>()); register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>()); + register(CommonConditions.PERMISSION, new PermissionCondition.FactoryImpl<>()); + register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>()); + register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/AbstractChainParameterContext.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/AbstractChainParameterContext.java index 14bde9ccb..9eed4f51b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/AbstractChainParameterContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/AbstractChainParameterContext.java @@ -14,6 +14,8 @@ public abstract class AbstractChainParameterContext extends AbstractCommonContex CHAIN_PARAMETERS.put(DirectContextParameters.WORLD, new WorldParameterProvider()); CHAIN_PARAMETERS.put(DirectContextParameters.BLOCK, new BlockParameterProvider()); CHAIN_PARAMETERS.put(DirectContextParameters.POSITION, new PositionParameterProvider()); + CHAIN_PARAMETERS.put(DirectContextParameters.FURNITURE, new FurnitureParameterProvider()); + CHAIN_PARAMETERS.put(DirectContextParameters.ENTITY, new EntityParameterProvider()); ItemParameterProvider itemProvider = new ItemParameterProvider(); CHAIN_PARAMETERS.put(DirectContextParameters.MAIN_HAND_ITEM, itemProvider); CHAIN_PARAMETERS.put(DirectContextParameters.OFF_HAND_ITEM, itemProvider); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java index 7c6f06c33..600d204c8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java @@ -10,7 +10,6 @@ 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 CLICK_TYPE = Key.of("craftengine:click_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"); @@ -19,4 +18,6 @@ public final class CommonConditions { public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block"); public static final Key DISTANCE = Key.from("craftengine:distance"); public static final Key PERMISSION = Key.from("craftengine:permission"); + public static final Key EQUALS = Key.from("craftengine:equals"); + public static final Key EXPRESSION = Key.from("craftengine:expression"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java new file mode 100644 index 000000000..bc48c0a1a --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java @@ -0,0 +1,40 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.text.TextProvider; +import net.momirealms.craftengine.core.plugin.context.text.TextProviders; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.Map; + +public class EqualsCondition implements Condition { + private final TextProvider value1; + private final TextProvider value2; + + public EqualsCondition(TextProvider value1, TextProvider value2) { + this.value1 = value1; + this.value2 = value2; + } + + @Override + public Key type() { + return CommonConditions.EQUALS; + } + + @Override + public boolean test(CTX ctx) { + return this.value1.get(ctx).equals(this.value2.get(ctx)); + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + String value1 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value1"), "warning.config.condition.equals.missing_value1"); + String value2 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value1"), "warning.config.condition.equals.missing_value2"); + return new EqualsCondition<>(TextProviders.fromString(value1), TextProviders.fromString(value2)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java new file mode 100644 index 000000000..7ae158e1f --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java @@ -0,0 +1,48 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import com.ezylang.evalex.EvaluationException; +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.parser.ParseException; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.text.TextProvider; +import net.momirealms.craftengine.core.plugin.context.text.TextProviders; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.Map; + +public class ExpressionCondition implements Condition { + private final TextProvider expression; + + public ExpressionCondition(TextProvider expression) { + this.expression = expression; + } + + @Override + public Key type() { + return CommonConditions.EXPRESSION; + } + + @Override + public boolean test(CTX ctx) { + String exp = expression.get(ctx); + Expression expr = new Expression(exp); + try { + return expr.evaluate().getBooleanValue(); + } catch (ParseException | EvaluationException e) { + CraftEngine.instance().logger().warn("Invalid expression " + exp, e); + return false; + } + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + String value = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("expression"), "warning.config.condition.expression.missing_expression"); + return new ExpressionCondition<>(TextProviders.fromString(value)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/PermissionCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/PermissionCondition.java new file mode 100644 index 000000000..2a7a7f829 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/PermissionCondition.java @@ -0,0 +1,39 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import net.momirealms.craftengine.core.entity.player.Player; +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.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.Map; +import java.util.Optional; + +public class PermissionCondition implements Condition { + private final String permission; + + public PermissionCondition(String permission) { + this.permission = permission; + } + + @Override + public Key type() { + return CommonConditions.PERMISSION; + } + + @Override + public boolean test(CTX ctx) { + Optional player = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + return player.map(value -> value.hasPermission(this.permission)).orElse(false); + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + String permission = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("permission"), "warning.config.condition.permission.missing_permission"); + return new PermissionCondition<>(permission); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java new file mode 100644 index 000000000..1db327924 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java @@ -0,0 +1,61 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.*; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors; +import net.momirealms.craftengine.core.plugin.context.text.TextProvider; +import net.momirealms.craftengine.core.plugin.context.text.TextProviders; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class ActionBarFunction extends AbstractConditionalFunction { + private final TextProvider message; + private final PlayerSelector selector; + + public ActionBarFunction(List> predicates, @Nullable PlayerSelector selector, TextProvider messages) { + super(predicates); + this.message = messages; + this.selector = selector; + } + + @Override + public void runInternal(CTX ctx) { + Optional owner = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + if (this.selector == null) { + owner.ifPresent(it -> { + it.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(ctx), ctx.tagResolvers())); + }); + } else { + for (Player viewer : this.selector.get(ctx)) { + RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY)); + viewer.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(relationalContext), relationalContext.tagResolvers())); + } + } + } + + @Override + public Key type() { + return CommonFunctions.ACTIONBAR; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + String message = ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "actionbar", "message"), "warning.config.function.actionbar.missing_actionbar"); + return new ActionBarFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), TextProviders.fromString(message)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CancelEventFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CancelEventFunction.java new file mode 100644 index 000000000..4c75c7eb9 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CancelEventFunction.java @@ -0,0 +1,41 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +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.util.Cancellable; +import net.momirealms.craftengine.core.util.Key; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class CancelEventFunction extends AbstractConditionalFunction { + + public CancelEventFunction(List> predicates) { + super(predicates); + } + + @Override + public void runInternal(CTX ctx) { + Optional cancellable = ctx.getOptionalParameter(DirectContextParameters.EVENT); + cancellable.ifPresent(value -> value.setCancelled(true)); + } + + @Override + public Key type() { + return CommonFunctions.CANCEL_EVENT; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + return new CancelEventFunction<>(getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java index 98c69097e..0b203a447 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java @@ -23,7 +23,7 @@ public class CommandFunction extends AbstractConditionalFun private final boolean asPlayer; private final PlayerSelector selector; - public CommandFunction(List> predicates, List command, boolean asPlayer, @Nullable PlayerSelector selector) { + public CommandFunction(List> predicates, @Nullable PlayerSelector selector, List command, boolean asPlayer) { super(predicates); this.asPlayer = asPlayer; this.command = command; @@ -72,7 +72,7 @@ public class CommandFunction extends AbstractConditionalFun Object command = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "command", "commands"), "warning.config.function.command.missing_command"); List commands = MiscUtils.getAsStringList(command).stream().map(TextProviders::fromString).toList(); boolean asPlayer = (boolean) arguments.getOrDefault("as-player", false); - return new CommandFunction<>(getPredicates(arguments), commands, asPlayer, PlayerSelectors.fromObject(arguments.get("target"), conditionFactory())); + return new CommandFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), commands, asPlayer); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java index 541774050..1b4f2ddbd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java @@ -22,7 +22,7 @@ public class MessageFunction extends AbstractConditionalFun private final PlayerSelector selector; private final boolean overlay; - public MessageFunction(List> predicates, List messages, @Nullable PlayerSelector selector, boolean overlay) { + public MessageFunction(List> predicates, @Nullable PlayerSelector selector, List messages, boolean overlay) { super(predicates); this.messages = messages; this.selector = selector; @@ -64,7 +64,7 @@ public class MessageFunction extends AbstractConditionalFun Object message = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "messages", "message"), "warning.config.function.command.missing_message"); List messages = MiscUtils.getAsStringList(message).stream().map(TextProviders::fromString).toList(); boolean overlay = (boolean) arguments.getOrDefault("overlay", false); - return new MessageFunction<>(getPredicates(arguments), messages, PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), overlay); + return new MessageFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), messages, overlay); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java new file mode 100644 index 000000000..6d55589ae --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java @@ -0,0 +1,82 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.*; +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.plugin.context.selector.PlayerSelector; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors; +import net.momirealms.craftengine.core.plugin.context.text.TextProvider; +import net.momirealms.craftengine.core.plugin.context.text.TextProviders; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.Key; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class TitleFunction extends AbstractConditionalFunction { + private final PlayerSelector selector; + private final TextProvider main; + private final TextProvider sub; + private final NumberProvider fadeIn; + private final NumberProvider stay; + private final NumberProvider fadeOut; + + public TitleFunction(List> predicates, @Nullable PlayerSelector selector, + TextProvider main, TextProvider sub, NumberProvider fadeIn, NumberProvider stay, NumberProvider fadeOut) { + super(predicates); + this.selector = selector; + this.main = main; + this.sub = sub; + this.fadeIn = fadeIn; + this.stay = stay; + this.fadeOut = fadeOut; + } + + @Override + public void runInternal(CTX ctx) { + Optional owner = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + if (this.selector == null) { + owner.ifPresent(it -> it.sendTitle( + AdventureHelper.miniMessage().deserialize(this.main.get(ctx), ctx.tagResolvers()), + AdventureHelper.miniMessage().deserialize(this.sub.get(ctx), ctx.tagResolvers()), + this.fadeIn.getInt(ctx), this.stay.getInt(ctx), this.fadeOut.getInt(ctx) + )); + } else { + for (Player viewer : this.selector.get(ctx)) { + RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY)); + viewer.sendTitle( + AdventureHelper.miniMessage().deserialize(this.main.get(relationalContext), relationalContext.tagResolvers()), + AdventureHelper.miniMessage().deserialize(this.sub.get(relationalContext), relationalContext.tagResolvers()), + this.fadeIn.getInt(relationalContext), this.stay.getInt(relationalContext), this.fadeOut.getInt(relationalContext) + ); + } + } + } + + @Override + public Key type() { + return CommonFunctions.TITLE; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + String title = arguments.getOrDefault("title", "").toString(); + String subtitle = arguments.getOrDefault("subtitle", "").toString(); + NumberProvider fadeIn = NumberProviders.fromObject(arguments.getOrDefault("fade-in", 10)); + NumberProvider stay = NumberProviders.fromObject(arguments.getOrDefault("stay", 20)); + NumberProvider fadeOut = NumberProviders.fromObject(arguments.getOrDefault("fade-out", 5)); + return new TitleFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), + TextProviders.fromString(title), TextProviders.fromString(subtitle), fadeIn, stay, fadeOut); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java index 5fcee23b8..151b69866 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java @@ -2,8 +2,10 @@ package net.momirealms.craftengine.core.plugin.context.parameter; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.entity.Entity; import net.momirealms.craftengine.core.entity.furniture.AnchorType; import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.player.GameMode; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.Item; @@ -29,6 +31,7 @@ public final class DirectContextParameters { public static final ContextKey FALLING_BLOCK = ContextKey.direct("falling_block"); public static final ContextKey EXPLOSION_RADIUS = ContextKey.direct("explosion_radius"); public static final ContextKey PLAYER = ContextKey.direct("player"); + public static final ContextKey ENTITY = ContextKey.direct("entity"); public static final ContextKey BLOCK_STATE = ContextKey.direct("custom_block_state"); public static final ContextKey COORDINATE = ContextKey.direct("coordinate"); public static final ContextKey POSITION = ContextKey.direct("position"); @@ -51,4 +54,8 @@ public final class DirectContextParameters { public static final ContextKey ANCHOR_TYPE = ContextKey.direct("anchor_type"); public static final ContextKey HAND = ContextKey.direct("hand"); public static final ContextKey EVENT = ContextKey.direct("event"); + public static final ContextKey IS_FLYING = ContextKey.direct("is_flying"); + public static final ContextKey IS_SNEAKING = ContextKey.direct("is_sneaking"); + public static final ContextKey IS_CUSTOM = ContextKey.direct("is_custom"); + public static final ContextKey GAMEMODE = ContextKey.direct("gamemode"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java new file mode 100644 index 000000000..b36225670 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java @@ -0,0 +1,33 @@ +package net.momirealms.craftengine.core.plugin.context.parameter; + +import net.momirealms.craftengine.core.entity.Entity; +import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider; +import net.momirealms.craftengine.core.plugin.context.ContextKey; +import net.momirealms.craftengine.core.util.MCUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +public class EntityParameterProvider implements ChainParameterProvider { + private static final Map, Function> CONTEXT_FUNCTIONS = new HashMap<>(); + static { + CONTEXT_FUNCTIONS.put(DirectContextParameters.X, Entity::x); + CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, Entity::y); + CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, Entity::z); + CONTEXT_FUNCTIONS.put(DirectContextParameters.POSITION, Entity::position); + CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_X, p -> MCUtils.fastFloor(p.x())); + CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Y, p -> MCUtils.fastFloor(p.y())); + CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Z, p -> MCUtils.fastFloor(p.z())); + CONTEXT_FUNCTIONS.put(DirectContextParameters.NAME, Entity::name); + CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Entity::uuid); + CONTEXT_FUNCTIONS.put(DirectContextParameters.WORLD, Entity::world); + } + + @SuppressWarnings("unchecked") + @Override + public Optional getOptionalParameter(ContextKey parameter, Entity entity) { + return (Optional) Optional.ofNullable(CONTEXT_FUNCTIONS.get(parameter)).map(f -> f.apply(entity)); + } +} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/FurnitureParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/FurnitureParameterProvider.java new file mode 100644 index 000000000..2f49aca37 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/FurnitureParameterProvider.java @@ -0,0 +1,25 @@ +package net.momirealms.craftengine.core.plugin.context.parameter; + +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider; +import net.momirealms.craftengine.core.plugin.context.ContextKey; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +public class FurnitureParameterProvider implements ChainParameterProvider { + private static final Map, Function> CONTEXT_FUNCTIONS = new HashMap<>(); + static { + CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Furniture::id); + CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Furniture::uuid); + CONTEXT_FUNCTIONS.put(DirectContextParameters.ANCHOR_TYPE, Furniture::anchorType); + } + + @SuppressWarnings("unchecked") + @Override + public Optional getOptionalParameter(ContextKey parameter, Furniture world) { + return (Optional) Optional.ofNullable(CONTEXT_FUNCTIONS.get(parameter)).map(f -> f.apply(world)); + } +} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/ItemParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/ItemParameterProvider.java index b933a6eba..a4709072f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/ItemParameterProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/ItemParameterProvider.java @@ -14,6 +14,7 @@ public class ItemParameterProvider implements ChainParameterProvider> { static { CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Item::id); CONTEXT_FUNCTIONS.put(DirectContextParameters.CUSTOM_MODEL_DATA, i -> i.customModelData().orElse(null)); + CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_CUSTOM, Item::isCustomItem); } @SuppressWarnings("unchecked") diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java index efeca907e..4075c6ff8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java @@ -26,6 +26,9 @@ public class PlayerParameterProvider implements ChainParameterProvider { 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.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)); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/AllPlayerSelector.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/AllPlayerSelector.java index 5b075bd98..edd33b388 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/AllPlayerSelector.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/AllPlayerSelector.java @@ -13,6 +13,8 @@ import net.momirealms.craftengine.core.util.MCUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.function.Function; import java.util.function.Predicate; public class AllPlayerSelector implements PlayerSelector { @@ -50,4 +52,14 @@ public class AllPlayerSelector implements PlayerSelector implements PlayerSelectorFactory { + + @Override + public PlayerSelector create(Map args, Function, Condition> conditionFactory) { + + + return null; + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectorFactory.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectorFactory.java new file mode 100644 index 000000000..c286c38e4 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectorFactory.java @@ -0,0 +1,12 @@ +package net.momirealms.craftengine.core.plugin.context.selector; + +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; + +import java.util.Map; +import java.util.function.Function; + +public interface PlayerSelectorFactory { + + PlayerSelector create(Map args, Function, Condition> conditionFactory); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectors.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectors.java index 2887faa49..c1198e8d9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectors.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/PlayerSelectors.java @@ -2,12 +2,17 @@ package net.momirealms.craftengine.core.plugin.context.selector; import net.momirealms.craftengine.core.plugin.context.Condition; import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; 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.util.ResourceKey; +import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.function.Function; @@ -15,37 +20,41 @@ public class PlayerSelectors { public static final Key ALL = Key.of("craftengine:all"); public static final Key SELF = Key.of("craftengine:self"); + static { + register(ALL, new AllPlayerSelector.FactoryImpl<>()); + register(SELF, new SelfPlayerSelector.FactoryImpl<>()); + } + + public static void register(Key key, PlayerSelectorFactory factory) { + Holder.Reference> holder = ((WritableRegistry>) BuiltInRegistries.PLAYER_SELECTOR_FACTORY) + .registerForHolder(new ResourceKey<>(Registries.PLAYER_SELECTOR_FACTORY.location(), key)); + holder.bindValue(factory); + } + + @Nullable public static PlayerSelector fromObject(Object object, Function, Condition> conditionFactory) { if (object == null) return null; - if (object instanceof String string) { - if (string.equals("self") || string.equals("@self") || string.equals("@s")) { - return new SelfPlayerSelector<>(); - } else if (string.equals("all") || string.equals("@all") || string.equals("@a")) { - return new AllPlayerSelector<>(); - } - } else if (object instanceof Map map) { + if (object instanceof Map map) { Map selectorMap = MiscUtils.castToMap(map, false); - Object typeObj = selectorMap.get("type"); - Object conditionObj = ResourceConfigUtils.get(selectorMap, "conditions"); - if (!(typeObj instanceof String typeString)) { - throw new UnsupportedOperationException("Not supported yet."); - } - if (typeString.equals("all") || typeString.equals("@all") || typeString.equals("@a")) { - List> conditions = new ArrayList<>(); - if (conditionObj instanceof List list) { - @SuppressWarnings("unchecked") - List> conditionList = (List>) list; - for (Map condition : conditionList) { - conditions.add(conditionFactory.apply(condition)); - } - } else if (conditionObj instanceof Map) { - conditions.add(conditionFactory.apply(MiscUtils.castToMap(conditionObj, false))); - } else { - return new AllPlayerSelector<>(); - } - return new AllPlayerSelector<>(conditions); + return fromMap(selectorMap, conditionFactory); + } else if (object instanceof String target) { + if (target.equals("all") || target.equals("@a")) { + return new AllPlayerSelector<>(); + } else if (target.equals("self") || target.equals("@s")) { + return new SelfPlayerSelector<>(); } } - throw new UnsupportedOperationException("Not supported yet."); + throw new LocalizedResourceConfigException("warning.config.selector.invalid_target", object.toString()); + } + + public static PlayerSelector fromMap(Map map, Function, Condition> conditionFactory) { + String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.selector.missing_type"); + Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE); + @SuppressWarnings("unchecked") + PlayerSelectorFactory factory = (PlayerSelectorFactory) BuiltInRegistries.PLAYER_SELECTOR_FACTORY.getValue(key); + if (factory == null) { + throw new LocalizedResourceConfigException("warning.config.selector.invalid_type", type); + } + return factory.create(map, conditionFactory); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/SelfPlayerSelector.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/SelfPlayerSelector.java index 978c8ccfd..64024828c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/SelfPlayerSelector.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/selector/SelfPlayerSelector.java @@ -1,11 +1,14 @@ package net.momirealms.craftengine.core.plugin.context.selector; import net.momirealms.craftengine.core.entity.player.Player; +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.util.Key; import java.util.List; +import java.util.Map; +import java.util.function.Function; public class SelfPlayerSelector implements PlayerSelector { @@ -18,4 +21,11 @@ public class SelfPlayerSelector implements PlayerSelector implements PlayerSelectorFactory { + @Override + public PlayerSelector create(Map args, Function, Condition> conditionFactory) { + return new SelfPlayerSelector<>(); + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java index d2d6d7c4c..b1c578046 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java @@ -28,6 +28,9 @@ public class EventConditions { register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>()); register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>()); register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>()); + register(CommonConditions.PERMISSION, new PermissionCondition.FactoryImpl<>()); + register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>()); + register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java index 91dc5df2a..91d28760f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java @@ -1,10 +1,7 @@ package net.momirealms.craftengine.core.plugin.event; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.function.CommandFunction; -import net.momirealms.craftengine.core.plugin.context.function.CommonFunctions; -import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory; +import net.momirealms.craftengine.core.plugin.context.function.*; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; @@ -24,6 +21,10 @@ public class EventFunctions { static { register(CommonFunctions.COMMAND, new CommandFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.MESSAGE, new MessageFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.ACTIONBAR, new ActionBarFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.TITLE, new TitleFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.CANCEL_EVENT, new CancelEventFunction.FactoryImpl<>(EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java index 708f00d80..a28c42fe9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java @@ -25,6 +25,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory; import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory; import net.momirealms.craftengine.core.plugin.context.number.NumberProviderFactory; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectorFactory; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; @@ -54,6 +55,7 @@ public class BuiltInRegistries { public static final Registry RESOURCE_PACK_HOST_FACTORY = createRegistry(Registries.RESOURCE_PACK_HOST_FACTORY); public static final Registry> EVENT_FUNCTION_FACTORY = createRegistry(Registries.EVENT_FUNCTION_FACTORY); public static final Registry> EVENT_CONDITION_FACTORY = createRegistry(Registries.EVENT_CONDITION_FACTORY); + public static final Registry> PLAYER_SELECTOR_FACTORY = createRegistry(Registries.PLAYER_SELECTOR_FACTORY); private static Registry createRegistry(ResourceKey> key) { return new MappedRegistry<>(key); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java index 5d0ab47b6..5d8ed2868 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java @@ -25,6 +25,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory; import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory; import net.momirealms.craftengine.core.plugin.context.number.NumberProviderFactory; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectorFactory; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; @@ -53,6 +54,7 @@ public class Registries { public static final ResourceKey> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory")); public static final ResourceKey> HITBOX_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("hitbox_factory")); public static final ResourceKey> RESOURCE_PACK_HOST_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resource_pack_host_factory")); - public static final ResourceKey>> EVENT_FUNCTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_block_function_factory")); - public static final ResourceKey>> EVENT_CONDITION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_block_condition_factory")); + public static final ResourceKey>> EVENT_FUNCTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_function_factory")); + public static final ResourceKey>> EVENT_CONDITION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_condition_factory")); + public static final ResourceKey>> PLAYER_SELECTOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_selector")); }