Skip to content

Commit

Permalink
Merge pull request BetonQuest#2563 from J0B10/feature/log-event
Browse files Browse the repository at this point in the history
Add `log` event
  • Loading branch information
seyfahni authored Oct 27, 2023
2 parents 529bfb9 + 98b8b02 commit 19cc6b3
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- `numbercompare` condition
- `cancelOnLogout` argument for `folder` event
- `npcinteract` objective - now supports the argument `interaction` to choose between left, right or both clicks
- `log` event
- Things that are also added in 1.12.X:
- new line support for `journal_lore` in `messages.yml`
- FastAsyncWorldEdit compatibility
Expand Down
17 changes: 17 additions & 0 deletions docs/Documentation/Scripting/Building-Blocks/Events-List.md
Original file line number Diff line number Diff line change
Expand Up @@ -738,3 +738,20 @@ events:
events:
cancel: "cancelconversation"
```
## Log message to console: `log`

**persistent**, **static**

Prints a provided message to the server log. Any variables used in the message will be resolved.
Note that when used in static context (by schedules) replacing player dependent variables won't work as the event is player independent.

| Parameter | Syntax | Default Value | Explanation |
|-----------|------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| _level_ | `level:logLevel` | `INFO` | Optionally the log level can be specified but only **before** the message. <br>There are 4 levels: `debug`, `info`, `warning` and `error` |

```YAML title="Example"
events:
logPlayer: "log %player% completed first quest."
debug: "log level:DEBUG daily quests have been reset"
```

2 changes: 2 additions & 0 deletions src/main/java/org/betonquest/betonquest/BetonQuest.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@
import org.betonquest.betonquest.quest.event.legacy.QuestEventFactoryAdapter;
import org.betonquest.betonquest.quest.event.lever.LeverEventFactory;
import org.betonquest.betonquest.quest.event.lightning.LightningEventFactory;
import org.betonquest.betonquest.quest.event.log.LogEventFactory;
import org.betonquest.betonquest.quest.event.logic.IfElseEventFactory;
import org.betonquest.betonquest.quest.event.notify.NotifyAllEventFactory;
import org.betonquest.betonquest.quest.event.notify.NotifyEventFactory;
Expand Down Expand Up @@ -953,6 +954,7 @@ public void onEnable() {
registerEvent("deleteglobalpoint", new DeleteGlobalPointEventFactory());
registerEvent("drop", new DropEventFactory(getServer(), getServer().getScheduler(), this));
registerNonStaticEvent("itemdurability", new ItemDurabilityEventFactory(loggerFactory, getServer(), getServer().getScheduler(), this));
registerEvent("log", new LogEventFactory(loggerFactory));

registerObjectives("location", LocationObjective.class);
registerObjectives("block", BlockObjective.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.betonquest.betonquest.quest.event.log;

import org.betonquest.betonquest.VariableString;
import org.betonquest.betonquest.api.logger.BetonQuestLogger;
import org.betonquest.betonquest.api.profiles.Profile;
import org.betonquest.betonquest.api.quest.event.Event;
import org.betonquest.betonquest.exceptions.QuestRuntimeException;

/**
* Prints a simple message to the server log.
*/
public class LogEvent implements Event {

/**
* Message to log.
*/
private final VariableString message;

/**
* Logger to use.
*/
private final BetonQuestLogger logger;

/**
* Level to log the message at.
*/
private final LogEventLevel level;

/**
* Create a new {@link LogEvent}.
*
* @param logger logger used for logging messages.
* @param level level to log the message at.
* @param message message that should be printed to the server log.
*/
public LogEvent(final BetonQuestLogger logger, final LogEventLevel level, final VariableString message) {
this.logger = logger;
this.message = message;
this.level = level;
}

@Override
public void execute(final Profile profile) throws QuestRuntimeException {
level.log(logger, message.getString(profile));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.betonquest.betonquest.quest.event.log;

import org.betonquest.betonquest.Instruction;
import org.betonquest.betonquest.VariableString;
import org.betonquest.betonquest.api.logger.BetonQuestLogger;
import org.betonquest.betonquest.api.logger.BetonQuestLoggerFactory;
import org.betonquest.betonquest.api.quest.event.Event;
import org.betonquest.betonquest.api.quest.event.EventFactory;
import org.betonquest.betonquest.api.quest.event.StaticEvent;
import org.betonquest.betonquest.api.quest.event.StaticEventFactory;
import org.betonquest.betonquest.exceptions.InstructionParseException;
import org.betonquest.betonquest.quest.event.NullStaticEventAdapter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Factory to parse new {@link LogEvent}s.
*/
public class LogEventFactory implements EventFactory, StaticEventFactory {

/**
* Regex used to detect a conditions statement at the end of the instruction.
*/
private static final Pattern CONDITIONS_REGEX = Pattern.compile("conditions?:\\S*\\s*$");

/**
* Regex used to detect a level statement at the beginning of the instruction.
*/
private static final Pattern LEVEL_REGEX = Pattern.compile("^\\s*level:\\S*\\s");

/**
* Logger factory to create a logger for events.
*/
private final BetonQuestLoggerFactory loggerFactory;

/**
* Create a new log event factory.
*
* @param loggerFactory BetonQuest logger factory used to retrieve the {@link BetonQuestLogger} for new events.
*/
public LogEventFactory(final BetonQuestLoggerFactory loggerFactory) {
this.loggerFactory = loggerFactory;
}

@Override
public Event parseEvent(final Instruction instruction) throws InstructionParseException {
final LogEventLevel level = instruction.getEnum("level", LogEventLevel.class, LogEventLevel.INFO);
final String raw = instruction.getInstruction();
final Matcher conditionsMatcher = CONDITIONS_REGEX.matcher(raw);
final Matcher levelMatcher = LEVEL_REGEX.matcher(raw);
final int msgStart = levelMatcher.find() ? levelMatcher.end() : 0;
final int msgEnd = conditionsMatcher.find() ? conditionsMatcher.start() : raw.length();
final VariableString message = new VariableString(instruction.getPackage(), raw.substring(msgStart, msgEnd));
return new LogEvent(loggerFactory.create(LogEvent.class), level, message);
}

@Override
public StaticEvent parseStaticEvent(final Instruction instruction) throws InstructionParseException {
return new NullStaticEventAdapter(parseEvent(instruction));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.betonquest.betonquest.quest.event.log;

import org.betonquest.betonquest.api.logger.BetonQuestLogger;

import java.util.function.BiConsumer;

/**
* Human-readable log level used by the {@link LogEvent}.
* <p>
* While there is already a ton of similar enums for log levels,
* they are all not really suitable for this use case for multiple reasons.
* Some of them use different names for the levels, some have different levels (e.g. TRACE, ALL),
* some are not direct dependencies of BetonQuest and most of them are not compatible with the {@link BetonQuestLogger}.
*/
public enum LogEventLevel {
/**
* Level used for normal messages, default level.
*/
INFO(BetonQuestLogger::info),

/**
* Level used for debug messages.
*/
DEBUG(BetonQuestLogger::debug),

/**
* Level used for warnings.
*/
WARNING(BetonQuestLogger::warn),

/**
* Level used for errors.
*/
ERROR(BetonQuestLogger::error);

/**
* Method of the {@link BetonQuestLogger} used to log the message.
*/
private final BiConsumer<BetonQuestLogger, String> logFunction;

/**
* Create a new {@link LogEventLevel}.
*
* @param logFunction method of the {@link BetonQuestLogger} used to log the message.
*/
LogEventLevel(final BiConsumer<BetonQuestLogger, String> logFunction) {
this.logFunction = logFunction;
}

/**
* Log the message with the given logger at this level.
*
* @param logger logger used to log the message.
* @param message message to log.
*/
public void log(final BetonQuestLogger logger, final String message) {
logFunction.accept(logger, message);
}

}

0 comments on commit 19cc6b3

Please sign in to comment.