feat: implemented ScriptService
This commit is contained in:
parent
65a784a1ef
commit
7ebcad5fa7
@ -19,12 +19,11 @@ import ru.dragonestia.msb3.api.event.NPCClickEvent;
|
||||
import ru.dragonestia.msb3.api.item.ItemUtil;
|
||||
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContextManager;
|
||||
import ru.dragonestia.msb3.api.player.defaults.DebugParamsContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.KeyedBossBarContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.NavigatorContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.TalksContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.*;
|
||||
import ru.dragonestia.msb3.api.resource.DialogueResources;
|
||||
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
||||
import ru.dragonestia.msb3.api.script.ScriptRegistry;
|
||||
import ru.dragonestia.msb3.api.script.defaults.HelloWorldScript;
|
||||
import ru.dragonestia.msb3.api.skin.SkinStorage;
|
||||
import ru.dragonestia.msb3.api.ui.BlackScreen;
|
||||
import ru.dragonestia.msb3.api.ui.bossbar.KeyedBossBars;
|
||||
@ -103,6 +102,7 @@ public final class ServerBootstrap {
|
||||
initDefaultDialogActionsAndConditions();
|
||||
NPCClickEvent.init();
|
||||
DebugCommands.init();
|
||||
initDefaultScripts();
|
||||
}
|
||||
|
||||
private void compileResourcePack() {
|
||||
@ -193,6 +193,7 @@ public final class ServerBootstrap {
|
||||
PlayerContextManager.registerContext(NavigatorContext.class, NavigatorContext::new);
|
||||
PlayerContextManager.registerContext(TalksContext.class, TalksContext::new);
|
||||
PlayerContextManager.registerContext(DebugParamsContext.class, DebugParamsContext::new);
|
||||
PlayerContextManager.registerContext(PlayerScriptContext.class, PlayerScriptContext::new);
|
||||
}
|
||||
|
||||
private void initDefaultSkins() {
|
||||
@ -206,4 +207,8 @@ public final class ServerBootstrap {
|
||||
DialogRegistry.registerConditionHandler("always", new AlwaysDialogConditionHandler());
|
||||
DialogRegistry.registerConditionHandler("never", new NeverDialogConditionHandler());
|
||||
}
|
||||
|
||||
private void initDefaultScripts() {
|
||||
ScriptRegistry.register(HelloWorldScript::new);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ public class DebugCommands {
|
||||
registerGameModeCommand();
|
||||
DebugRendererCommand.register();
|
||||
DebugAICommand.register();
|
||||
ScriptCommand.register();
|
||||
|
||||
log.info("Registered debug commands");
|
||||
}
|
||||
|
||||
@ -0,0 +1,105 @@
|
||||
package ru.dragonestia.msb3.api.command;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandContext;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentString;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentType;
|
||||
import net.minestom.server.entity.Player;
|
||||
import ru.dragonestia.msb3.api.script.Script;
|
||||
import ru.dragonestia.msb3.api.script.ScriptRegistry;
|
||||
import ru.dragonestia.msb3.api.script.ScriptService;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ScriptCommand extends Command {
|
||||
|
||||
private final ArgumentString argScriptId = ArgumentType.String("scriptId");
|
||||
|
||||
public ScriptCommand() {
|
||||
super("script");
|
||||
setDefaultExecutor(this::defaultExecutor);
|
||||
|
||||
addSyntax(this::executeStartScript, ArgumentType.Literal("start"), argScriptId);
|
||||
addSyntax(this::executeStopScript, ArgumentType.Literal("stop"), argScriptId);
|
||||
addSyntax(this::executeListActiveScripts, ArgumentType.Literal("active"));
|
||||
addSyntax(this::executeListRegisteredScripts, ArgumentType.Literal("registered"));
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
MinecraftServer.getCommandManager().register(new ScriptCommand());
|
||||
}
|
||||
|
||||
private void defaultExecutor(CommandSender sender, CommandContext ctx) {
|
||||
var player = (Player) sender;
|
||||
|
||||
player.sendMessage("Script commands:");
|
||||
player.sendMessage("/script start <scriptId> - Start script");
|
||||
player.sendMessage("/script stop <scriptId> - Stop script");
|
||||
player.sendMessage("/script active - List active scripts");
|
||||
player.sendMessage("/script registered - List registered scripts");
|
||||
}
|
||||
|
||||
private void executeStartScript(CommandSender sender, CommandContext ctx) {
|
||||
var player = (Player) sender;
|
||||
var scriptService = ScriptService.ofPlayer(player);
|
||||
var scriptId = ctx.get(argScriptId);
|
||||
var script = ScriptRegistry.findAndCreateScript(scriptId);
|
||||
|
||||
if (script.isEmpty()) {
|
||||
player.sendMessage(Component.text("Script '%s' is not registered".formatted(scriptId), NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendMessage(Component.text("Staring script '%s'...".formatted(scriptId), NamedTextColor.YELLOW));
|
||||
scriptService.start(script.get());
|
||||
}
|
||||
|
||||
private void executeStopScript(CommandSender sender, CommandContext ctx) {
|
||||
var player = (Player) sender;
|
||||
var scriptService = ScriptService.ofPlayer(player);
|
||||
var scriptId = ctx.get(argScriptId);
|
||||
var script = scriptService.findScript(scriptId);
|
||||
|
||||
if (script.isEmpty()) {
|
||||
player.sendMessage(Component.text("Active script '%s' not found".formatted(scriptId), NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendMessage(Component.text("Stopping script '%s'...".formatted(scriptId), NamedTextColor.YELLOW));
|
||||
scriptService.stop(script.get());
|
||||
}
|
||||
|
||||
private void executeListActiveScripts(CommandSender sender, CommandContext ctx) {
|
||||
var player = (Player) sender;
|
||||
var scriptService = ScriptService.ofPlayer(player);
|
||||
var scripts = scriptService.getActiveScripts().stream().map(Script::getId).toList();
|
||||
|
||||
player.sendMessage(Component.text("Active scripts(%s): ".formatted(scripts.size()))
|
||||
.append(listScriptIds(scripts)));
|
||||
}
|
||||
|
||||
private void executeListRegisteredScripts(CommandSender sender, CommandContext ctx) {
|
||||
var player = (Player) sender;
|
||||
var scripts = ScriptRegistry.listRegisteredScripts();
|
||||
|
||||
player.sendMessage(Component.text("Registered scripts(%s): ".formatted(scripts.size()))
|
||||
.append(listScriptIds(scripts)));
|
||||
}
|
||||
|
||||
private Component listScriptIds(Collection<String> scriptIds) {
|
||||
return Component.join(
|
||||
JoinConfiguration.builder().separator(Component.text(", ")).build(),
|
||||
scriptIds.stream().map(id -> Component.text(id, NamedTextColor.GOLD)
|
||||
.hoverEvent(HoverEvent.showText(Component.text("Click to copy")))
|
||||
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, id)))
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
package ru.dragonestia.msb3.api.player.defaults;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||
import ru.dragonestia.msb3.api.script.Script;
|
||||
import ru.dragonestia.msb3.api.script.ScriptService;
|
||||
import ru.dragonestia.msb3.api.util.UncheckedRunnable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Log4j2
|
||||
public class PlayerScriptContext extends PlayerContext implements ScriptService {
|
||||
|
||||
private final Map<String, Script> scripts = new ConcurrentHashMap<>();
|
||||
|
||||
public PlayerScriptContext(MsbPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
synchronized (this) {
|
||||
for (var script : scripts.values()) {
|
||||
UncheckedRunnable.runIgnoreException(() -> script.end(getPlayer()));
|
||||
}
|
||||
scripts.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Script script) {
|
||||
synchronized (this) {
|
||||
var opt = findScript(script.getId());
|
||||
if (opt.isPresent()) {
|
||||
DebugMessage.send(getPlayer(), "Script '%s' already started".formatted(script.getId()));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
script.start(getPlayer());
|
||||
DebugMessage.send(getPlayer(), "Script '%s' started!".formatted(script.getId()));
|
||||
} catch (Exception ex) {
|
||||
DebugMessage.sendError(getPlayer(), "Script '%s' started with error %s: %s".formatted(script.getId(), ex.getClass().getSimpleName(), ex.getMessage()));
|
||||
log.error(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
scripts.put(script.getId(), script);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(Script script) {
|
||||
synchronized (this) {
|
||||
if (!scripts.containsKey(script.getId())) {
|
||||
DebugMessage.send(getPlayer(), "Script '%s' not started".formatted(script.getId()));
|
||||
return;
|
||||
}
|
||||
|
||||
scripts.remove(script.getId());
|
||||
|
||||
try {
|
||||
script.end(getPlayer());
|
||||
DebugMessage.send(getPlayer(), "Script '%s' stopped".formatted(script.getId()));
|
||||
} catch (Exception ex) {
|
||||
DebugMessage.sendError(getPlayer(), "Script '%s' stopped with error %s: %s".formatted(script.getId(), ex.getClass().getSimpleName(), ex.getMessage()));
|
||||
log.error(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Script> getActiveScripts() {
|
||||
return scripts.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Script> findScript(String id) {
|
||||
return Optional.ofNullable(scripts.get(id));
|
||||
}
|
||||
}
|
||||
33
api/src/main/java/ru/dragonestia/msb3/api/script/Script.java
Normal file
33
api/src/main/java/ru/dragonestia/msb3/api/script/Script.java
Normal file
@ -0,0 +1,33 @@
|
||||
package ru.dragonestia.msb3.api.script;
|
||||
|
||||
import lombok.Getter;
|
||||
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||
|
||||
@Getter
|
||||
public abstract class Script {
|
||||
|
||||
private final String id;
|
||||
|
||||
public Script(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public abstract void start(MsbPlayer player);
|
||||
|
||||
public abstract void end(MsbPlayer player);
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null) return false;
|
||||
if (obj instanceof Script other) {
|
||||
return id.equals(other.id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package ru.dragonestia.msb3.api.script;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@UtilityClass
|
||||
public class ScriptRegistry {
|
||||
|
||||
private final Map<String, Supplier<Script>> scripts = new ConcurrentHashMap<>();
|
||||
|
||||
public void register(Supplier<Script> scriptSupplier) {
|
||||
var prev = scripts.put(scriptSupplier.get().getId(), scriptSupplier);
|
||||
if (prev != null) {
|
||||
throw new IllegalStateException("Script already registered: " + scriptSupplier.get().getId());
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Script> findAndCreateScript(String id) {
|
||||
return Optional.ofNullable(scripts.get(id)).map(Supplier::get);
|
||||
}
|
||||
|
||||
public Collection<String> listRegisteredScripts() {
|
||||
return scripts.keySet();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package ru.dragonestia.msb3.api.script;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.PlayerScriptContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ScriptService {
|
||||
|
||||
void start(Script script);
|
||||
|
||||
void stop(Script script);
|
||||
|
||||
Collection<Script> getActiveScripts();
|
||||
|
||||
Optional<Script> findScript(String id);
|
||||
|
||||
static ScriptService ofPlayer(Player player) {
|
||||
return PlayerContext.of(player, PlayerScriptContext.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package ru.dragonestia.msb3.api.script.defaults;
|
||||
|
||||
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||
import ru.dragonestia.msb3.api.script.Script;
|
||||
|
||||
public class HelloWorldScript extends Script {
|
||||
|
||||
public HelloWorldScript() {
|
||||
super("hello_world");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(MsbPlayer player) {
|
||||
player.sendMessage("Hello World!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(MsbPlayer player) {
|
||||
player.sendMessage("Goodbye my dear friend!");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user