diff --git a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerAction.java b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerAction.java index b4bf9e9eb..1d3c63373 100644 --- a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerAction.java +++ b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerAction.java @@ -22,6 +22,7 @@ public static List> getActions() actions.add(new PlayerGameModeAction()); actions.add(new PlayerAdvancementAction()); actions.add(new PlayerAnimationAction()); + actions.add(new PlayerChatAction()); actions.add(new PlayerDeathAction()); actions.add(new PlayerDropItemAction()); actions.add(new PlayerFlightAction()); diff --git a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerActionArgument.java b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerActionArgument.java index 72b0d5564..51ad637f3 100644 --- a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerActionArgument.java +++ b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/AbstractPlayerActionArgument.java @@ -5,7 +5,9 @@ import org.jetbrains.annotations.NotNull; import org.kunlab.scenamatica.action.actions.AbstractActionArgument; import org.kunlab.scenamatica.action.utils.PlayerUtils; +import org.kunlab.scenamatica.enums.ScenarioType; import org.kunlab.scenamatica.interfaces.action.ActionArgument; +import org.kunlab.scenamatica.interfaces.scenario.ScenarioEngine; import org.kunlab.scenamatica.interfaces.scenariofile.trigger.TriggerArgument; import java.util.Objects; @@ -46,6 +48,13 @@ public Player getTarget() return PlayerUtils.getPlayerOrThrow(this.target); } + @Override + public void validate(@NotNull ScenarioEngine engine, @NotNull ScenarioType type) + { + if (type == ScenarioType.ACTION_EXECUTE) + throwIfNotPresent(KEY_TARGET_PLAYER, this.target); + } + @Override public String getArgumentString() { diff --git a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/PlayerChatAction.java b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/PlayerChatAction.java new file mode 100644 index 000000000..6f62e26ca --- /dev/null +++ b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/actions/player/PlayerChatAction.java @@ -0,0 +1,125 @@ +package org.kunlab.scenamatica.action.actions.player; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerChatEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.kunlab.scenamatica.enums.ScenarioType; +import org.kunlab.scenamatica.interfaces.action.types.Executable; +import org.kunlab.scenamatica.interfaces.action.types.Watchable; +import org.kunlab.scenamatica.interfaces.scenario.ScenarioEngine; +import org.kunlab.scenamatica.interfaces.scenariofile.BeanSerializer; +import org.kunlab.scenamatica.interfaces.scenariofile.trigger.TriggerArgument; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class PlayerChatAction extends AbstractPlayerAction + implements Executable, Watchable +{ + public static final String KEY_ACTION_NAME = "player_chat"; + + @Override + public String getName() + { + return KEY_ACTION_NAME; + } + + @Override + public void execute(@NotNull ScenarioEngine engine, @Nullable Argument argument) + { + argument = this.requireArgsNonNull(argument); + + Player p = argument.getTarget(); + p.chat(argument.message); + } + + @Override + public boolean isFired(@NotNull Argument argument, @NotNull ScenarioEngine engine, @NotNull Event event) + { + if (!super.checkMatchedPlayerEvent(argument, engine, event)) + return false; + + assert event instanceof PlayerChatEvent; + PlayerChatEvent playerChatEvent = (PlayerChatEvent) event; + + return playerChatEvent.getMessage().matches(argument.message) + && playerChatEvent.getFormat().matches(argument.format); + } + + @Override + public List> getAttachingEvents() + { + //noinspection deprecation + return Collections.singletonList( + PlayerChatEvent.class + ); + } + + @Override + public Argument deserializeArgument(@NotNull Map map, @NotNull BeanSerializer serializer) + { + return new Argument( + super.deserializeTarget(map), + (String) map.get(Argument.KEY_MESSAGE), + (String) map.get(Argument.KEY_FORMAT) + ); + } + + @Value + @EqualsAndHashCode(callSuper = true) + public static class Argument extends AbstractPlayerActionArgument + { + public static final String KEY_MESSAGE = "message"; + public static final String KEY_FORMAT = "format"; + + String message; + String format; + + public Argument(@NotNull String target, String message, String format) + { + super(target); + this.message = message; + this.format = format; + } + + @Override + public boolean isSame(TriggerArgument argument) + { + if (!(argument instanceof Argument)) + return false; + + Argument arg = (Argument) argument; + + return super.isSame(arg) + && this.message.equals(arg.message) + && this.format.equals(arg.format); + } + + @Override + public void validate(@NotNull ScenarioEngine engine, @NotNull ScenarioType type) + { + super.validate(engine, type); + + if (type == ScenarioType.ACTION_EXECUTE) + { + throwIfNotPresent(KEY_MESSAGE, this.message); + throwIfPresent(KEY_FORMAT, this.format); + } + } + + @Override + public String getArgumentString() + { + return appendArgumentString( + super.getArgumentString(), + KEY_MESSAGE, this.message, + KEY_FORMAT, this.format + ); + } + } +} diff --git a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/utils/TextUtils.java b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/utils/TextUtils.java index 37f60f754..8c4a800eb 100644 --- a/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/utils/TextUtils.java +++ b/ScenamaticaActionEngine/src/main/java/org/kunlab/scenamatica/action/utils/TextUtils.java @@ -21,4 +21,15 @@ public static boolean isSameContent(net.kyori.adventure.text.Component adventure return component.content().equals(content); } + + public static boolean isContentMatches(net.kyori.adventure.text.Component component, String content) + { + net.kyori.adventure.text.TextComponent textComponent; + if (component instanceof net.kyori.adventure.text.TextComponent) + textComponent = (net.kyori.adventure.text.TextComponent) component; + else + textComponent = net.kyori.adventure.text.TextComponent.ofChildren(component); + + return textComponent.content().matches(content); + } } diff --git a/ScenamaticaPlugin/src/main/resources/scenarios/actions/player/Chat-2.yml b/ScenamaticaPlugin/src/main/resources/scenarios/actions/player/Chat-2.yml new file mode 100644 index 000000000..58e3a7853 --- /dev/null +++ b/ScenamaticaPlugin/src/main/resources/scenarios/actions/player/Chat-2.yml @@ -0,0 +1,24 @@ +# noinspection YAMLSchemaValidation +scenamatica: ${project.version} + +name: actions_player_chat_2 +description: Testing PlayerChatAction detects the message with regex or not +on: + - type: on_load + - type: manual_dispatch + +context: + actors: + - name: Actor001 + +scenario: + - type: execute + action: player_chat + with: + target: Actor001 + message: "1" + - type: execute + action: player_chat + with: + target: Actor001 + message: "^\\d$" diff --git a/ScenamaticaPlugin/src/main/resources/scenarios/actions/player/Chat.yml b/ScenamaticaPlugin/src/main/resources/scenarios/actions/player/Chat.yml new file mode 100644 index 000000000..0369ce5b5 --- /dev/null +++ b/ScenamaticaPlugin/src/main/resources/scenarios/actions/player/Chat.yml @@ -0,0 +1,24 @@ +# noinspection YAMLSchemaValidation +scenamatica: ${project.version} + +name: actions_player_chat +description: Testing PlayerChatAction works or not +on: + - type: on_load + - type: manual_dispatch + +context: + actors: + - name: Actor001 + +scenario: + - type: execute + action: player_chat + with: + target: Actor001 + message: "Hello World!" + - type: execute + action: player_chat + with: + target: Actor001 + message: "Hello World!" diff --git a/scenamatica-file.json b/scenamatica-file.json index 61d347ffa..80f3584ce 100644 --- a/scenamatica-file.json +++ b/scenamatica-file.json @@ -111,6 +111,7 @@ "inventory_open", "player_advancement", "player_animation", + "player_chat", "player_death", "player_drop_item", "player_flight", @@ -414,6 +415,26 @@ ] } }, + { + "if": { + "properties": { + "action": { + "const": "player_chat", + "description": "プレイヤーのチャットを検知します。" + } + } + }, + "then": { + "properties": { + "with": { + "$ref": "#/definitions/action/definitions/player/chat" + } + }, + "required": [ + "with" + ] + } + }, { "if": { "properties": { @@ -1477,6 +1498,20 @@ "type" ] }, + "chat": { + "$ref": "#/definitions/action/definitions/player/$base", + "properties": { + "message": { + "type": "string", + "description": "送信するメッセージまたは判定用の正規表現です。" + }, + "format": { + "type": "string", + "description": "メッセージのフォーマットです。", + "example": "<%1$s> %2$s" + } + } + }, "death": { "$ref": "#/definitions/action/definitions/player/$base", "properties": {