Skip to content

Commit

Permalink
core impl of new event couldMatching engine
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Nov 14, 2021
1 parent b2159ad commit ebf31bd
Show file tree
Hide file tree
Showing 13 changed files with 401 additions and 164 deletions.
301 changes: 218 additions & 83 deletions src/main/java/com/denizenscript/denizencore/events/ScriptEvent.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package com.denizenscript.denizencore.events;

import com.denizenscript.denizencore.utilities.CoreUtilities;
import com.denizenscript.denizencore.utilities.debugging.Debug;

import java.util.*;

/**
* Helper to generate automatic logic for ScriptEvent#couldMatch.
*/
public class ScriptEventCouldMatcher {

/**
* Registry of validators, as a map from name to instance object.
*/
public static HashMap<String, PathArgumentValidator> knownValidatorTypes = new HashMap<>();

/**
* The raw format string used to construct this couldMatcher.
*/
public String format;

/**
* The array of validator objects for this couldMatcher.
* The path length should equal the array length, and each argument match the validator.
*/
public PathArgumentValidator[] validators;

/**
* Special optimization trick: an array of argument indices to control testing order.
* The simplest tests are run first.
*/
public int[] argOrder;

public ScriptEventCouldMatcher(String format) {
this.format = format;
ArrayList<PathArgumentValidator> validatorList = new ArrayList<>();
List<String> args = CoreUtilities.split(format, ' ');
for (String arg : args) {
if (arg.isEmpty()) {
Debug.echoError("Event matcher format error: '" + format + "' has a double space?");
continue;
}
if (arg.startsWith("<")) {
if (!arg.endsWith(">")) {
Debug.echoError("Event matcher format error: '" + format + "' has an unclosed fill-in part.");
continue;
}
String toUse = arg.substring(1, arg.length() - 1);
if (toUse.startsWith("'") && toUse.endsWith("'")) {
validatorList.add(new StringBasedValidator(arg));
}
else {
PathArgumentValidator validator = knownValidatorTypes.get(toUse);
if (validator == null) {
Debug.echoError("Event matcher format error: '" + format + "' has an unrecognized input type '" + toUse + "'");
continue;
}
validatorList.add(validator);
}
}
else if (CoreUtilities.contains(arg, '|')) {
validatorList.add(new StringSetBasedValidator(CoreUtilities.split(arg, '|')));
}
else {
validatorList.add(new StringBasedValidator(arg));
}
}
validators = validatorList.toArray(new PathArgumentValidator[0]);
argOrder = new int[validators.length];
int index = 0;
for (int i = 0; i < validators.length; i++) {
if (shouldPrioritize(validators[i])) {
argOrder[index++] = i;
}
}
for (int i = 0; i < validators.length; i++) {
if (!shouldPrioritize(validators[i])) {
argOrder[index++] = i;
}
}
}

private static boolean shouldPrioritize(PathArgumentValidator valid) {
return valid instanceof StringBasedValidator || valid instanceof StringSetBasedValidator;
}

/**
* Returns true if the path could-match this event.
*/
public boolean doesMatch(ScriptEvent.ScriptPath path) {
if (path.eventArgsLower.length != validators.length) {
return false;
}
for (int i : argOrder) {
if (!validators[i].doesMatch(path.eventArgsLower[i])) {
return false;
}
}
return true;
}

/**
* Interface for validating a single argument of a script path in a couldMatch call.
*/
@FunctionalInterface
public interface PathArgumentValidator {
boolean doesMatch(String arg);
}

/**
* The simplest possible PathArgumentValidator: a string equality comparison.
*/
public static class StringBasedValidator implements PathArgumentValidator {

public String word;

public StringBasedValidator(String word) {
this.word = word;
}

@Override
public final boolean doesMatch(String arg) {
return arg.equals(word);
}
}

/**
* The second-simplest possible PathArgumentValidator: a set of possible exact strings.
*/
public static class StringSetBasedValidator implements PathArgumentValidator {

public HashSet<String> words;

public StringSetBasedValidator(Collection<String> words) {
this.words = new HashSet<>(words);
}

@Override
public final boolean doesMatch(String arg) {
return words.contains(arg);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public class ConsoleOutputScriptEvent extends ScriptEvent {

public static ConsoleOutputScriptEvent instance;

public ConsoleOutputScriptEvent() {
instance = this;
registerCouldMatcher("console output");
}

public String message = null;

public ScriptEntryData data = DenizenCore.implementation.getEmptyScriptEntryData();
Expand All @@ -44,15 +49,6 @@ public ObjectTag getContext(String name) {
return super.getContext(name);
}

public ConsoleOutputScriptEvent() {
instance = this;
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("console output");
}

@Override
public String getName() {
return "ConsoleOutput";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,8 @@ public class CustomScriptEvent extends ScriptEvent {

public CustomScriptEvent() {
instance = this;
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("custom event");
registerCouldMatcher("custom event");
registerSwitches("id", "data");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ public class DeltaTimeScriptEvent extends ScriptEvent {

// <--[event]
// @Events
// delta time [hourly/minutely/secondly]
// delta time hourly|minutely|secondly
//
// @Switch every:<count> to only run the event every *count* times (like "on delta time secondly every:5" for every 5 seconds).
//
// @Regex ^on delta time (hourly|minutely|secondly)$
//
// @Group Core
//
// @Triggers every <count> seconds, minutes, or hours of game calculation time. Default repetitions count of 1.
Expand All @@ -33,11 +31,8 @@ public class DeltaTimeScriptEvent extends ScriptEvent {

public DeltaTimeScriptEvent() {
instance = this;
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("delta time");
registerCouldMatcher("delta time hourly|minutely|secondly");
registerSwitches("every");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,14 @@ public class PreScriptReloadScriptEvent extends ScriptEvent {

public static PreScriptReloadScriptEvent instance;

@Override
public ScriptEntryData getScriptEntryData() {
return DenizenCore.implementation.getEmptyScriptEntryData();
}

public PreScriptReloadScriptEvent() {
instance = this;
registerCouldMatcher("pre script reload");
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("pre script reload");
public ScriptEntryData getScriptEntryData() {
return DenizenCore.implementation.getEmptyScriptEntryData();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public class ReloadScriptsScriptEvent extends ScriptEvent {

public static ReloadScriptsScriptEvent instance;

public ReloadScriptsScriptEvent() {
instance = this;
registerCouldMatcher("reload scripts");
registerCouldMatcher("script reload");
registerSwitches("had_error");
}

public boolean hadError = false;

@Override
Expand All @@ -44,15 +51,6 @@ public ObjectTag getContext(String name) {
return super.getContext(name);
}

public ReloadScriptsScriptEvent() {
instance = this;
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("reload scripts") || path.eventLower.startsWith("script reload");
}

@Override
public boolean matches(ScriptPath path) {
if (!path.checkSwitch("had_error", hadError ? "true" : "false")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class ScriptGeneratesErrorScriptEvent extends ScriptEvent {

public ScriptGeneratesErrorScriptEvent() {
instance = this;
registerCouldMatcher("script generates error");
}

public ScriptQueue queue;
Expand Down Expand Up @@ -72,14 +73,6 @@ public ObjectTag getContext(String name) {
return super.getContext(name);
}

@Override
public boolean couldMatch(ScriptPath path) {
if (!path.eventLower.startsWith("script generates error")) {
return false;
}
return true;
}

@Override
public void cancellationChanged() {
cancelledTracker = cancelled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class ServerGeneratesExceptionScriptEvent extends ScriptEvent {

public ServerGeneratesExceptionScriptEvent() {
instance = this;
registerCouldMatcher("server generates exception");
}

public Throwable exception;
Expand Down Expand Up @@ -65,14 +66,6 @@ public ObjectTag getContext(String name) {
return super.getContext(name);
}

@Override
public boolean couldMatch(ScriptPath path) {
if (!path.eventLower.startsWith("server generates exception")) {
return false;
}
return true;
}

@Override
public void cancellationChanged() {
cancelledTracker = cancelled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,11 @@ public class ShutdownScriptEvent extends ScriptEvent {
//
// -->

public ShutdownScriptEvent() {
instance = this;
}

public static ShutdownScriptEvent instance;

@Override
public boolean couldMatch(ScriptPath path) {
if (!path.eventLower.startsWith("shutdown")) {
return false;
}
return true;
public ShutdownScriptEvent() {
instance = this;
registerCouldMatcher("shutdown");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ public class SystemTimeScriptEvent extends ScriptEvent {

// <--[event]
// @Events
// system time [<HH:MM>/hourly/minutely/secondly]
// system time HH:MM
// system time hourly|minutely|secondly
//
// @Switch every:<count> to only run the event every *count* times (like "on system time secondly every:5" for every 5 seconds).
//
// @Regex ^on system time( (\d\d\:\d\d|hourly|minutely|secondly))?$
//
// @Synonyms cron
//
// @Group Core
Expand All @@ -37,11 +36,9 @@ public class SystemTimeScriptEvent extends ScriptEvent {

public SystemTimeScriptEvent() {
instance = this;
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("system time");
registerCouldMatcher("system time");
registerCouldMatcher("system time hourly|minutely|secondly");
registerSwitches("every");
}

public ElementTag hour;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ public class TickScriptEvent extends ScriptEvent {

public static TickScriptEvent instance;

public TickScriptEvent() {
instance = this;
registerCouldMatcher("tick");
registerSwitches("every");
}

public long ticks = 0;

public ScriptEntryData data = DenizenCore.implementation.getEmptyScriptEntryData();
Expand All @@ -46,15 +52,6 @@ public ObjectTag getContext(String name) {
return super.getContext(name);
}

public TickScriptEvent() {
instance = this;
}

@Override
public boolean couldMatch(ScriptPath path) {
return path.eventLower.startsWith("tick");
}

@Override
public boolean matches(ScriptPath path) {
String countString = path.switches.get("every");
Expand Down
Loading

0 comments on commit ebf31bd

Please sign in to comment.