Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make CommandFilter more extendable + fix AsyncTeleport not applying command cooldown
  • Loading branch information
FrankHeijden committed Dec 31, 2020
1 parent 76e45fd commit dfda202
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,17 @@ private void teleport(final IUser teleportee, final ITarget target, final Trade
delay = event.getDelay();

Trade cashCharge = chargeFor;
String cooldownCommand = null;

if (chargeFor != null) {
chargeFor.isAffordableFor(teleportOwner, future);
if (future.isCompletedExceptionally()) {
return;
}

// When cashCharge is being reassigned below, ensure the charge knows the command we should apply cooldown on
cooldownCommand = chargeFor.getCommand();

//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleportOwner).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
Expand All @@ -281,7 +285,7 @@ private void teleport(final IUser teleportee, final ITarget target, final Trade
}
nowAsync(teleportee, target, cause, future);
if (cashCharge != null) {
cashCharge.charge(teleportOwner, future);
cashCharge.charge(teleportOwner, cooldownCommand, future);
if (future.isCompletedExceptionally()) {
return;
}
Expand All @@ -305,13 +309,17 @@ private void teleportOther(final IUser teleporter, final IUser teleportee, final
delay = event.getDelay();

Trade cashCharge = chargeFor;
String cooldownCommand = null;

if (teleporter != null && chargeFor != null) {
chargeFor.isAffordableFor(teleporter, future);
if (future.isCompletedExceptionally()) {
return;
}

// When cashCharge is being reassigned below, ensure the charge knows the command we should apply cooldown on
cooldownCommand = chargeFor.getCommand();

//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
if (!chargeFor.getCommandCost(teleporter).equals(BigDecimal.ZERO)) {
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
Expand All @@ -332,7 +340,7 @@ private void teleportOther(final IUser teleporter, final IUser teleportee, final

nowAsync(teleportee, target, cause, future);
if (teleporter != null && cashCharge != null) {
cashCharge.charge(teleporter, future);
cashCharge.charge(teleporter, cooldownCommand, future);
if (future.isCompletedExceptionally()) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package com.earth2me.essentials;

import com.google.common.base.Preconditions;
import net.ess3.api.IUser;

import java.math.BigDecimal;
import java.util.Date;
import java.util.regex.Pattern;

public class CommandFilter {
public abstract class CommandFilter {

public enum Type {
REGEX,
ESS
}

private final String name;
private final String command;
private final Pattern pattern;
private final Integer cooldown;
private final boolean persistentCooldown;
private final BigDecimal cost;

public CommandFilter(String name, String command, Pattern pattern, Integer cooldown, boolean persistentCooldown, BigDecimal cost) {
public CommandFilter(String name, Pattern pattern, Integer cooldown, boolean persistentCooldown, BigDecimal cost) {
Preconditions.checkNotNull(pattern);
this.name = name;
this.command = command;
this.pattern = pattern;
this.cooldown = cooldown;
this.persistentCooldown = persistentCooldown;
Expand All @@ -28,14 +33,6 @@ public String getName() {
return name;
}

public String getCommand() {
return command;
}

public boolean hasCommand() {
return command != null;
}

public Pattern getPattern() {
return pattern;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

import java.io.File;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
Expand All @@ -19,7 +21,7 @@ public class CommandFilters implements IConf {
private final IEssentials essentials;
private final EssentialsConf config;
private ConfigurationSection filters;
private Map<String, CommandFilter> commandFilters;
private Map<CommandFilter.Type, List<CommandFilter>> commandFilters;

public CommandFilters(final IEssentials essentials) {
this.essentials = essentials;
Expand Down Expand Up @@ -50,16 +52,16 @@ private ConfigurationSection _getCommandFilterSection() {
return null;
}

private Map<String, CommandFilter> _getCommandFilters() {
final Map<String, CommandFilter> commandFilters = new HashMap<>();
private Map<CommandFilter.Type, List<CommandFilter>> _getCommandFilters() {
final Map<CommandFilter.Type, List<CommandFilter>> commandFilters = new EnumMap<>(CommandFilter.Type.class);
for (final String name : filters.getKeys(false)) {
if (!filters.isConfigurationSection(name)) {
EssentialsConf.LOGGER.warning("Invalid command filter '" + name + "'");
continue;
}

final ConfigurationSection section = Objects.requireNonNull(filters.getConfigurationSection(name));
Pattern pattern = section.isString("pattern") ? compileRegex(section.getString("pattern")) : null;
final Pattern pattern = section.isString("pattern") ? compileRegex(section.getString("pattern")) : null;
final String command = section.getString("command");

if (pattern == null && command == null) {
Expand All @@ -72,11 +74,6 @@ private Map<String, CommandFilter> _getCommandFilters() {
continue;
}

// Compile the command as a regex if the pattern hasn't been set, so pattern is always available.
if (pattern == null) {
pattern = compileRegex(command);
}

Integer cooldown = section.getInt("cooldown", -1);
if (cooldown < 0) {
cooldown = null;
Expand All @@ -88,7 +85,12 @@ private Map<String, CommandFilter> _getCommandFilters() {
final BigDecimal cost = EssentialsConf.toBigDecimal(section.getString("cost"), null);

final String lowerName = name.toLowerCase(Locale.ENGLISH);
commandFilters.put(lowerName, new CommandFilter(lowerName, command, pattern, cooldown, persistentCooldown, cost));

if (pattern == null) {
commandFilters.computeIfAbsent(CommandFilter.Type.ESS, k -> new ArrayList<>()).add(new EssCommandFilter(lowerName, command, compileRegex(command), cooldown, persistentCooldown, cost));
} else {
commandFilters.computeIfAbsent(CommandFilter.Type.REGEX, k -> new ArrayList<>()).add(new RegexCommandFilter(lowerName, pattern, cooldown, persistentCooldown, cost));
}
}
config.save();
return commandFilters;
Expand Down Expand Up @@ -116,28 +118,18 @@ public EssentialsConf getConfig() {
return config;
}

public CommandFilter getFilterByName(final String name) {
return commandFilters.get(name.toLowerCase(Locale.ENGLISH));
}

public CommandFilter getCommandCooldown(final IUser user, final String label, boolean essCommand) {
public CommandFilter getCommandCooldown(final IUser user, final String label, CommandFilter.Type type) {
if (user.isAuthorized("essentials.commandcooldowns.bypass")) return null;
return getFilter(label, essCommand, filter -> filter.hasCooldown() && !user.isAuthorized("essentials.commandcooldowns.bypass." + filter.getName()));
return getFilter(label, type, filter -> filter.hasCooldown() && !user.isAuthorized("essentials.commandcooldowns.bypass." + filter.getName()));
}

public CommandFilter getCommandCost(final IUser user, final String label, boolean essCommand) {
public CommandFilter getCommandCost(final IUser user, final String label, CommandFilter.Type type) {
if (user.isAuthorized("essentials.nocommandcost.all")) return null;
return getFilter(label, essCommand, filter -> filter.hasCost() && !user.isAuthorized("essentials.nocommandcost." + filter.getName()));
return getFilter(label, type, filter -> filter.hasCost() && !user.isAuthorized("essentials.nocommandcost." + filter.getName()));
}

private CommandFilter getFilter(final String label, boolean essCommand, Predicate<CommandFilter> filterPredicate) {
for (CommandFilter filter : commandFilters.values()) {
// When the label is an ess command, the filter must define a command entry.
if (essCommand && !filter.hasCommand()) continue;

// Same vice versa.
if (!essCommand && filter.hasCommand()) continue;

private CommandFilter getFilter(final String label, CommandFilter.Type type, Predicate<CommandFilter> filterPredicate) {
for (CommandFilter filter : commandFilters.get(type)) {
if (!filterPredicate.test(filter)) continue;

final boolean matches = filter.getPattern().matcher(label).matches();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.earth2me.essentials;

import java.math.BigDecimal;
import java.util.regex.Pattern;

public class EssCommandFilter extends CommandFilter {

private final String command;

public EssCommandFilter(String name, String command, Pattern pattern, Integer cooldown, boolean persistentCooldown, BigDecimal cost) {
super(name, pattern, cooldown, persistentCooldown, cost);
this.command = command;
}

public String getCommand() {
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -603,18 +603,18 @@ public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event)
}

if (!cooldownFound) {
final CommandFilter cooldownFilter = ess.getCommandFilters().getCommandCooldown(user, fullCommand, false);
final CommandFilter cooldownFilter = ess.getCommandFilters().getCommandCooldown(user, fullCommand, CommandFilter.Type.REGEX);
if (cooldownFilter != null) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Applying " + cooldownFilter.getCooldown() + "ms cooldown on /" + fullCommand + " for" + user.getName() + ".");
ess.getLogger().info("Applying " + cooldownFilter.getCooldown() + "ms cooldown on /" + fullCommand + " for " + user.getName() + ".");
}
cooldownFilter.applyCooldownTo(user);
}

final CommandFilter costFilter = ess.getCommandFilters().getCommandCost(user, fullCommand, false);
final CommandFilter costFilter = ess.getCommandFilters().getCommandCost(user, fullCommand, CommandFilter.Type.REGEX);
if (costFilter != null) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Applying a cost of " + costFilter.getCost() + " on /" + fullCommand + " for" + user.getName() + ".");
ess.getLogger().info("Applying a cost of " + costFilter.getCost() + " on /" + fullCommand + " for " + user.getName() + ".");
}

final BigDecimal cost = costFilter.getCost();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.earth2me.essentials;

import java.math.BigDecimal;
import java.util.regex.Pattern;

public class RegexCommandFilter extends CommandFilter {

public RegexCommandFilter(String name, Pattern pattern, Integer cooldown, boolean persistentCooldown, BigDecimal cost) {
super(name, pattern, cooldown, persistentCooldown, cost);
}
}
27 changes: 19 additions & 8 deletions Essentials/src/main/java/com/earth2me/essentials/Trade.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,17 +283,14 @@ public void charge(final IUser user) throws ChargeException {
} catch (final ExecutionException e) {
throw (ChargeException) e.getCause();
}
} else {
if (command != null && !command.isEmpty()) {
final CommandFilter cooldownFilter = ess.getCommandFilters().getCommandCooldown(user, command, true);
if (cooldownFilter != null) {
cooldownFilter.applyCooldownTo(user);
}
}
}
}

public void charge(final IUser user, final CompletableFuture<Boolean> future) {
charge(user, this.command, future);
}

public void charge(final IUser user, final String cooldownCommand, final CompletableFuture<Boolean> future) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "attempting to charge user " + user.getName());
}
Expand Down Expand Up @@ -340,6 +337,20 @@ public void charge(final IUser user, final CompletableFuture<Boolean> future) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "charge user " + user.getName() + " completed");
}

if (cooldownCommand != null && !cooldownCommand.isEmpty()) {
final CommandFilter cooldownFilter = ess.getCommandFilters().getCommandCooldown(user, cooldownCommand, CommandFilter.Type.ESS);
if (cooldownFilter != null) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info("Applying " + cooldownFilter.getCooldown() + "ms cooldown on /" + cooldownCommand + " for " + user.getName() + ".");
}
cooldownFilter.applyCooldownTo(user);
}
}
}

public String getCommand() {
return command;
}

public BigDecimal getMoney() {
Expand Down Expand Up @@ -369,7 +380,7 @@ public TradeType getType() {
public BigDecimal getCommandCost(final IUser user) {
BigDecimal cost = BigDecimal.ZERO;
if (command != null && !command.isEmpty()) {
final CommandFilter filter = ess.getCommandFilters().getCommandCost(user, command.charAt(0) == '/' ? command.substring(1) : command, true);
final CommandFilter filter = ess.getCommandFilters().getCommandCost(user, command.charAt(0) == '/' ? command.substring(1) : command, CommandFilter.Type.ESS);
if (filter != null && filter.getCost().signum() != 0) {
cost = filter.getCost();
} else if (fallbackTrade != null) {
Expand Down

0 comments on commit dfda202

Please sign in to comment.