Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement exposed actions #1102

Merged
merged 1 commit into from
Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion core/src/main/java/tc/oc/pgm/action/ActionMatchModule.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tc.oc.pgm.action;

import com.google.common.collect.ImmutableList;
import tc.oc.pgm.action.actions.ExposedAction;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.match.MatchModule;
import tc.oc.pgm.api.module.exception.ModuleLoadException;
Expand All @@ -10,10 +11,15 @@
public class ActionMatchModule implements MatchModule {
private final Match match;
private final ImmutableList<Trigger<?>> triggers;
private final ImmutableList<ExposedAction> exposedActions;

public ActionMatchModule(Match match, ImmutableList<Trigger<?>> triggers) {
public ActionMatchModule(
Match match,
ImmutableList<Trigger<?>> triggers,
ImmutableList<ExposedAction> exposedActions) {
this.match = match;
this.triggers = triggers;
this.exposedActions = exposedActions;
}

@Override
Expand All @@ -34,4 +40,8 @@ private <T extends Filterable<?>> void setupTrigger(Trigger<T> rule, FilterMatch
else rule.getAction().untrigger(filterable);
});
}

public ImmutableList<ExposedAction> getExposedActions() {
return exposedActions;
}
}
10 changes: 9 additions & 1 deletion core/src/main/java/tc/oc/pgm/action/ActionModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.jdom2.Document;
import org.jdom2.Element;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.action.actions.ExposedAction;
import tc.oc.pgm.api.map.MapModule;
import tc.oc.pgm.api.map.factory.MapFactory;
import tc.oc.pgm.api.map.factory.MapModuleFactory;
Expand All @@ -19,11 +20,18 @@
public class ActionModule implements MapModule<ActionMatchModule> {

private final ImmutableList<Trigger<?>> triggers;
private ImmutableList<ExposedAction> actions;

public ActionModule(ImmutableList<Trigger<?>> triggers) {
this.triggers = triggers;
}

@Override
public void postParse(MapFactory factory, Logger logger, Document doc) {
// Must be post-parsed, as other parts of the XML may create other actions
this.actions = ImmutableList.copyOf(factory.getFeatures().getAll(ExposedAction.class));
}

@Nullable
@Override
public Collection<Class<? extends MatchModule>> getHardDependencies() {
Expand All @@ -33,7 +41,7 @@ public Collection<Class<? extends MatchModule>> getHardDependencies() {
@Nullable
@Override
public ActionMatchModule createMatchModule(Match match) throws ModuleLoadException {
return new ActionMatchModule(match, triggers);
return new ActionMatchModule(match, triggers, actions);
}

public static class Factory implements MapModuleFactory<ActionModule> {
Expand Down
18 changes: 17 additions & 1 deletion core/src/main/java/tc/oc/pgm/action/ActionParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.action.actions.ActionNode;
import tc.oc.pgm.action.actions.ExposedAction;
import tc.oc.pgm.action.actions.KillEntitiesAction;
import tc.oc.pgm.action.actions.MessageAction;
import tc.oc.pgm.action.actions.ReplaceItemAction;
Expand All @@ -21,6 +22,7 @@
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.filter.Filterables;
import tc.oc.pgm.api.map.factory.MapFactory;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.features.FeatureDefinitionContext;
import tc.oc.pgm.features.XMLFeatureReference;
import tc.oc.pgm.filters.Filterable;
Expand Down Expand Up @@ -65,8 +67,22 @@ public <B extends Filterable<?>> Action<? super B> parse(Element el, @Nullable C

Action<? super B> result = parseDynamic(el, bound);
if (bound != null) validate(result, ActionScopeValidation.of(bound), node);
if (result instanceof ActionDefinition)
if (result instanceof ActionDefinition) {
if (XMLUtils.parseBoolean(Node.fromAttr(el, "expose"), false)) {

if (id == null)
throw new InvalidXMLException("Attribute 'id' is required for exposed actions", el);

if (!result.getScope().isAssignableFrom(Match.class))
throw new InvalidXMLException("Match scope is required for exposed actions", el);

result =
(ActionDefinition<? super B>)
new ExposedAction(id, (ActionDefinition<? super Match>) result);
}

features.addFeature(el, (ActionDefinition<? super B>) result);
}
return result;
}

Expand Down
41 changes: 41 additions & 0 deletions core/src/main/java/tc/oc/pgm/action/actions/ExposedAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package tc.oc.pgm.action.actions;

import tc.oc.pgm.action.ActionDefinition;
import tc.oc.pgm.api.feature.Feature;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.features.SelfIdentifyingFeatureDefinition;

/**
* Wraps an action definition to consider it exposed. This is an easy way to avoid needing each
* specialized action to implement a way to expose itself or not.
*/
public class ExposedAction extends SelfIdentifyingFeatureDefinition
implements ActionDefinition<Match>, Feature<ActionDefinition<? super Match>> {

private final ActionDefinition<? super Match> delegate;

public ExposedAction(String id, ActionDefinition<? super Match> delegate) {
super(id);
this.delegate = delegate;
}

@Override
public ActionDefinition<? super Match> getDefinition() {
return delegate;
}

@Override
public Class<Match> getScope() {
return Match.class;
}

@Override
public void trigger(Match m) {
delegate.trigger(m);
}

@Override
public void untrigger(Match m) {
delegate.untrigger(m);
}
}
79 changes: 79 additions & 0 deletions core/src/main/java/tc/oc/pgm/command/ActionCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package tc.oc.pgm.command;

import static net.kyori.adventure.text.Component.text;

import cloud.commandframework.annotations.Argument;
import cloud.commandframework.annotations.CommandDescription;
import cloud.commandframework.annotations.CommandMethod;
import cloud.commandframework.annotations.CommandPermission;
import cloud.commandframework.annotations.Flag;
import cloud.commandframework.annotations.specifier.Greedy;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender;
import tc.oc.pgm.action.ActionMatchModule;
import tc.oc.pgm.action.actions.ExposedAction;
import tc.oc.pgm.api.Permissions;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.util.Audience;
import tc.oc.pgm.util.PrettyPaginatedComponentResults;
import tc.oc.pgm.util.text.TextFormatter;

@CommandMethod("action|actions")
public class ActionCommand {

@CommandMethod("list|page [page]")
@CommandDescription("Inspect variables for a player")
@CommandPermission(Permissions.GAMEPLAY)
public void showActions(
Audience audience,
CommandSender sender,
ActionMatchModule amm,
@Argument(value = "page", defaultValue = "1") int page,
@Flag(value = "query", aliases = "q") String query,
@Flag(value = "all", aliases = "a") boolean all) {

List<ExposedAction> actions =
amm.getExposedActions().stream()
.filter(a -> query == null || a.getId().contains(query))
.sorted(Comparator.comparing(ExposedAction::getId))
.collect(Collectors.toList());

int resultsPerPage = all ? actions.size() : 8;
int pages = all ? 1 : (actions.size() + resultsPerPage - 1) / resultsPerPage;

Component title =
TextFormatter.paginate(
text("Actions"), page, pages, NamedTextColor.DARK_AQUA, NamedTextColor.AQUA, true);
Component header = TextFormatter.horizontalLineHeading(sender, title, NamedTextColor.BLUE);

PrettyPaginatedComponentResults.display(
audience,
actions,
page,
resultsPerPage,
header,
(v, i) -> text((i + 1) + ". ").append(text(v.getId(), NamedTextColor.AQUA)));
}

@CommandMethod("trigger [action]")
@CommandDescription("Trigger a specific action")
@CommandPermission(Permissions.GAMEPLAY)
public void triggerAction(
Audience audience, Match match, @Argument("action") @Greedy ExposedAction action) {
action.trigger(match);
audience.sendMessage(text("Triggered " + action.getId()));
}

@CommandMethod("untrigger [action]")
@CommandDescription("Untrigger a specific action")
@CommandPermission(Permissions.GAMEPLAY)
public void untriggerAction(
Audience audience, Match match, @Argument("action") @Greedy ExposedAction action) {
action.untrigger(match);
audience.sendMessage(text("Untriggered " + action.getId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package tc.oc.pgm.command.parsers;

import cloud.commandframework.arguments.parser.ParserParameters;
import cloud.commandframework.paper.PaperCommandManager;
import java.util.Collection;
import org.bukkit.command.CommandSender;
import tc.oc.pgm.action.ActionMatchModule;
import tc.oc.pgm.action.actions.ExposedAction;

public class ExposedActionParser extends MatchObjectParser<ExposedAction, ActionMatchModule> {

public ExposedActionParser(PaperCommandManager<CommandSender> manager, ParserParameters options) {
super(manager, options, ExposedAction.class, ActionMatchModule.class, "actions");
}

@Override
protected Collection<ExposedAction> objects(ActionMatchModule module) {
return module.getExposedActions();
}

@Override
protected String getName(ExposedAction obj) {
return obj.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import net.kyori.adventure.util.ComponentMessageThrowable;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.action.actions.ExposedAction;
import tc.oc.pgm.api.Config;
import tc.oc.pgm.api.PGM;
import tc.oc.pgm.api.map.MapInfo;
Expand All @@ -53,6 +54,7 @@
import tc.oc.pgm.api.setting.SettingKey;
import tc.oc.pgm.api.setting.SettingValue;
import tc.oc.pgm.classes.PlayerClass;
import tc.oc.pgm.command.ActionCommand;
import tc.oc.pgm.command.AdminCommand;
import tc.oc.pgm.command.CancelCommand;
import tc.oc.pgm.command.ClassCommand;
Expand Down Expand Up @@ -84,6 +86,7 @@
import tc.oc.pgm.command.injectors.TeamMatchModuleProvider;
import tc.oc.pgm.command.parsers.DurationParser;
import tc.oc.pgm.command.parsers.EnumParser;
import tc.oc.pgm.command.parsers.ExposedActionParser;
import tc.oc.pgm.command.parsers.MapInfoParser;
import tc.oc.pgm.command.parsers.MapPoolParser;
import tc.oc.pgm.command.parsers.MatchPlayerParser;
Expand Down Expand Up @@ -200,6 +203,7 @@ public CommandGraph(PGM pgm) throws Exception {

// Commands
public void registerCommands() {
register(new ActionCommand());
register(new AdminCommand());
register(new CancelCommand());
register(new ClassCommand());
Expand All @@ -210,6 +214,7 @@ public void registerCommands() {
register(new JoinCommand());
register(new ListCommand());
register(new MapCommand());
register(new MapDevCommand());
register(new MapOrderCommand());
register(new MapPoolCommand());
register(new MatchCommand());
Expand All @@ -222,7 +227,6 @@ public void registerCommands() {
register(new TeamCommand());
register(new TimeLimitCommand());
register(new VotingCommand());
register(new MapDevCommand());

if (pgm.getConfiguration().isCommunityMode()) {
register(new ReportCommand());
Expand Down Expand Up @@ -284,6 +288,7 @@ protected void setupParsers() {
registerParser(TypeFactory.parameterizedClass(Collection.class, Team.class), TeamsParser::new);
registerParser(PlayerClass.class, PlayerClassParser::new);
registerParser(Mode.class, ModeParser::new);
registerParser(ExposedAction.class, ExposedActionParser::new);
registerParser(
TypeFactory.parameterizedClass(Optional.class, VictoryCondition.class),
new VictoryConditionParser());
Expand Down