Merge pull request 'Feat: Implemented degub tools' (#1) from feat/debug-render into master
Reviewed-on: http://git.dragonestia.ru/MSB/msb3/pulls/1
This commit is contained in:
commit
fc04f223a4
@ -2,6 +2,8 @@ plugins {
|
|||||||
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version = MSB3_VERSION
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
shadowJar {
|
shadowJar {
|
||||||
manifest {
|
manifest {
|
||||||
@ -27,7 +29,7 @@ tasks {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api project(":resource-compiler")
|
api project(":resource-compiler")
|
||||||
|
|
||||||
api 'net.minestom:minestom-snapshots:1_21_4-6490538291'
|
api 'net.minestom:minestom-snapshots:8209a1d1e9' // stableVersion: 1_21_4-6490538291
|
||||||
|
|
||||||
api 'org.slf4j:slf4j-api:2.0.16'
|
api 'org.slf4j:slf4j-api:2.0.16'
|
||||||
api 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.0'
|
api 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.0'
|
||||||
@ -48,3 +50,32 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
implementation 'org.apache.commons:commons-text:1.10.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
maven(MavenPublication) {
|
||||||
|
groupId = 'ru.dragonestia.msb3'
|
||||||
|
artifactId = 'msb-api'
|
||||||
|
version = MSB3_VERSION
|
||||||
|
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "Gitea"
|
||||||
|
url = uri(MSB3_MAVEN_REPOSITORY)
|
||||||
|
allowInsecureProtocol = true
|
||||||
|
|
||||||
|
credentials(HttpHeaderCredentials) {
|
||||||
|
name = "Authorization"
|
||||||
|
value = "token ${dragonestiaGiteaToken}"
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication {
|
||||||
|
header(HttpHeaderAuthentication)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ public class DefaultBootstrap extends ServerInitializer {
|
|||||||
@Override
|
@Override
|
||||||
public void onDefaultModulesLoaded() {
|
public void onDefaultModulesLoaded() {
|
||||||
MotdModule.init("logo.png", "<gradient:#ff0059:#e06806><bold>msb3 server</bold></gradient>");
|
MotdModule.init("logo.png", "<gradient:#ff0059:#e06806><bold>msb3 server</bold></gradient>");
|
||||||
FlatWorldModule.init(GameMode.ADVENTURE);
|
FlatWorldModule.init(GameMode.CREATIVE);
|
||||||
PrometheusMetricsModule.init(new InetSocketAddress("0.0.0.0", 7500));
|
PrometheusMetricsModule.init(new InetSocketAddress("0.0.0.0", 7500));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,4 +33,9 @@ public class DefaultBootstrap extends ServerInitializer {
|
|||||||
public void onResourcePackCompiled(ResourcePack resourcePack) {
|
public void onResourcePackCompiled(ResourcePack resourcePack) {
|
||||||
ResourcePackRepositoryModule.init("0.0.0.0", 7270);
|
ResourcePackRepositoryModule.init("0.0.0.0", 7270);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServerStarted() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import ru.dragonestia.msb3.api.command.DebugCommands;
|
|||||||
import ru.dragonestia.msb3.api.dialog.DialogRegistry;
|
import ru.dragonestia.msb3.api.dialog.DialogRegistry;
|
||||||
import ru.dragonestia.msb3.api.dialog.action.CloseDialogActionHandler;
|
import ru.dragonestia.msb3.api.dialog.action.CloseDialogActionHandler;
|
||||||
import ru.dragonestia.msb3.api.dialog.action.DialogDialogActionHandler;
|
import ru.dragonestia.msb3.api.dialog.action.DialogDialogActionHandler;
|
||||||
|
import ru.dragonestia.msb3.api.dialog.action.ScriptDialogActionHandler;
|
||||||
import ru.dragonestia.msb3.api.dialog.condition.AlwaysDialogConditionHandler;
|
import ru.dragonestia.msb3.api.dialog.condition.AlwaysDialogConditionHandler;
|
||||||
import ru.dragonestia.msb3.api.dialog.condition.NeverDialogConditionHandler;
|
import ru.dragonestia.msb3.api.dialog.condition.NeverDialogConditionHandler;
|
||||||
import ru.dragonestia.msb3.api.entity.PickableItem;
|
import ru.dragonestia.msb3.api.entity.PickableItem;
|
||||||
@ -19,11 +20,11 @@ import ru.dragonestia.msb3.api.event.NPCClickEvent;
|
|||||||
import ru.dragonestia.msb3.api.item.ItemUtil;
|
import ru.dragonestia.msb3.api.item.ItemUtil;
|
||||||
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
import ru.dragonestia.msb3.api.player.PlayerContextManager;
|
import ru.dragonestia.msb3.api.player.PlayerContextManager;
|
||||||
import ru.dragonestia.msb3.api.player.defaults.KeyedBossBarContext;
|
import ru.dragonestia.msb3.api.player.defaults.*;
|
||||||
import ru.dragonestia.msb3.api.player.defaults.NavigatorContext;
|
|
||||||
import ru.dragonestia.msb3.api.player.defaults.TalksContext;
|
|
||||||
import ru.dragonestia.msb3.api.resource.DialogueResources;
|
import ru.dragonestia.msb3.api.resource.DialogueResources;
|
||||||
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
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.skin.SkinStorage;
|
||||||
import ru.dragonestia.msb3.api.ui.BlackScreen;
|
import ru.dragonestia.msb3.api.ui.BlackScreen;
|
||||||
import ru.dragonestia.msb3.api.ui.bossbar.KeyedBossBars;
|
import ru.dragonestia.msb3.api.ui.bossbar.KeyedBossBars;
|
||||||
@ -102,6 +103,7 @@ public final class ServerBootstrap {
|
|||||||
initDefaultDialogActionsAndConditions();
|
initDefaultDialogActionsAndConditions();
|
||||||
NPCClickEvent.init();
|
NPCClickEvent.init();
|
||||||
DebugCommands.init();
|
DebugCommands.init();
|
||||||
|
initDefaultScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compileResourcePack() {
|
private void compileResourcePack() {
|
||||||
@ -191,6 +193,8 @@ public final class ServerBootstrap {
|
|||||||
PlayerContextManager.registerContext(KeyedBossBarContext.class, KeyedBossBarContext::new);
|
PlayerContextManager.registerContext(KeyedBossBarContext.class, KeyedBossBarContext::new);
|
||||||
PlayerContextManager.registerContext(NavigatorContext.class, NavigatorContext::new);
|
PlayerContextManager.registerContext(NavigatorContext.class, NavigatorContext::new);
|
||||||
PlayerContextManager.registerContext(TalksContext.class, TalksContext::new);
|
PlayerContextManager.registerContext(TalksContext.class, TalksContext::new);
|
||||||
|
PlayerContextManager.registerContext(DebugParamsContext.class, DebugParamsContext::new);
|
||||||
|
PlayerContextManager.registerContext(PlayerScriptContext.class, PlayerScriptContext::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDefaultSkins() {
|
private void initDefaultSkins() {
|
||||||
@ -200,8 +204,13 @@ public final class ServerBootstrap {
|
|||||||
private void initDefaultDialogActionsAndConditions() {
|
private void initDefaultDialogActionsAndConditions() {
|
||||||
DialogRegistry.registerActionHandler("close", new CloseDialogActionHandler());
|
DialogRegistry.registerActionHandler("close", new CloseDialogActionHandler());
|
||||||
DialogRegistry.registerActionHandler("dialog", new DialogDialogActionHandler());
|
DialogRegistry.registerActionHandler("dialog", new DialogDialogActionHandler());
|
||||||
|
DialogRegistry.registerActionHandler("script", new ScriptDialogActionHandler());
|
||||||
|
|
||||||
DialogRegistry.registerConditionHandler("always", new AlwaysDialogConditionHandler());
|
DialogRegistry.registerConditionHandler("always", new AlwaysDialogConditionHandler());
|
||||||
DialogRegistry.registerConditionHandler("never", new NeverDialogConditionHandler());
|
DialogRegistry.registerConditionHandler("never", new NeverDialogConditionHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initDefaultScripts() {
|
||||||
|
ScriptRegistry.register(HelloWorldScript::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package ru.dragonestia.msb3.api.command;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
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.ArgumentBoolean;
|
||||||
|
import net.minestom.server.command.builder.arguments.ArgumentType;
|
||||||
|
import net.minestom.server.entity.Player;
|
||||||
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
|
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||||
|
import ru.dragonestia.msb3.api.player.defaults.DebugParamsContext;
|
||||||
|
|
||||||
|
public class DebugAICommand extends Command {
|
||||||
|
|
||||||
|
private final ArgumentBoolean argShowPathValue = ArgumentType.Boolean("show");
|
||||||
|
|
||||||
|
public DebugAICommand() {
|
||||||
|
super("debug_ai");
|
||||||
|
setDefaultExecutor(this::defaultExecutor);
|
||||||
|
|
||||||
|
addSyntax(this::executeShowPath, ArgumentType.Literal("show_path"), argShowPathValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register() {
|
||||||
|
MinecraftServer.getCommandManager().register(new DebugAICommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void defaultExecutor(CommandSender sender, CommandContext ctx) {
|
||||||
|
var player = (Player) sender;
|
||||||
|
|
||||||
|
player.sendMessage("Debug Render commands:");
|
||||||
|
player.sendMessage("/debug_ai show_path <true/false> - Change debug renderer for path finder");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeShowPath(CommandSender sender, CommandContext ctx) {
|
||||||
|
var player = (MsbPlayer) sender;
|
||||||
|
var show = ctx.get(argShowPathValue);
|
||||||
|
|
||||||
|
PlayerContext.of(player, DebugParamsContext.class).setShowDebugRendererAiPathFinder(show);
|
||||||
|
if (show) {
|
||||||
|
player.sendMessage(Component.text("Enabled debug renderer for path finder", NamedTextColor.YELLOW));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Component.text("Disabled debug renderer for path finder", NamedTextColor.YELLOW));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,6 +29,9 @@ public class DebugCommands {
|
|||||||
registerPosCommand();
|
registerPosCommand();
|
||||||
registerTeleportCommand();
|
registerTeleportCommand();
|
||||||
registerGameModeCommand();
|
registerGameModeCommand();
|
||||||
|
DebugRendererCommand.register();
|
||||||
|
DebugAICommand.register();
|
||||||
|
ScriptCommand.register();
|
||||||
|
|
||||||
log.info("Registered debug commands");
|
log.info("Registered debug commands");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
package ru.dragonestia.msb3.api.command;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
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.ArgumentEnum;
|
||||||
|
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.player.MsbPlayer;
|
||||||
|
|
||||||
|
public class DebugRendererCommand extends Command {
|
||||||
|
|
||||||
|
private final ArgumentEnum<Option> argOption = ArgumentType.Enum("option", Option.class).setFormat(ArgumentEnum.Format.LOWER_CASED);
|
||||||
|
private final ArgumentString argLayerName = ArgumentType.String("layer");
|
||||||
|
|
||||||
|
public DebugRendererCommand() {
|
||||||
|
super("debug_render");
|
||||||
|
setDefaultExecutor(this::defaultExecutor);
|
||||||
|
|
||||||
|
argOption.setCallback((sender, ex) -> {
|
||||||
|
sender.sendMessage(Component.text("Invalid option", NamedTextColor.RED));
|
||||||
|
});
|
||||||
|
|
||||||
|
addSyntax(this::execute, argOption, argLayerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register() {
|
||||||
|
MinecraftServer.getCommandManager().register(new DebugRendererCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void defaultExecutor(CommandSender sender, CommandContext ctx) {
|
||||||
|
var player = (Player) sender;
|
||||||
|
|
||||||
|
player.sendMessage("Debug Render commands:");
|
||||||
|
player.sendMessage("/debug_render show <layer> - Show debug layer");
|
||||||
|
player.sendMessage("/debug_render hide <layer> - Hide debug layer");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void execute(CommandSender sender, CommandContext ctx) {
|
||||||
|
var player = (MsbPlayer) sender;
|
||||||
|
var option = ctx.get(argOption);
|
||||||
|
var layerName = ctx.get(argLayerName);
|
||||||
|
|
||||||
|
if (option == Option.SHOW) {
|
||||||
|
player.addDebugRenderLayer(layerName);
|
||||||
|
player.sendMessage(Component.text("Debug layer '%s' was showed for you".formatted(layerName), NamedTextColor.YELLOW));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.removeDebugRenderLayer(layerName);
|
||||||
|
player.sendMessage(Component.text("Debug layer '%s' was hidden for you".formatted(layerName), NamedTextColor.YELLOW));
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Option {
|
||||||
|
SHOW,
|
||||||
|
HIDE,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
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.kyori.adventure.text.format.Style;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
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.ContinuousScript;
|
||||||
|
import ru.dragonestia.msb3.api.script.ScriptRegistry;
|
||||||
|
import ru.dragonestia.msb3.api.script.ScriptService;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
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'(%s)...".formatted(scriptId, script.get().getClass().getSimpleName()), NamedTextColor.YELLOW));
|
||||||
|
scriptService.start(script.get(), Params.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 continuous script '%s'(%s)...".formatted(scriptId, script.get().getClass().getSimpleName()), 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(ContinuousScript::getId).toList();
|
||||||
|
|
||||||
|
player.sendMessage(Component.text("Active continuous 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()
|
||||||
|
.append(Component.text("Click to copy", Style.style().color(NamedTextColor.YELLOW).decoration(TextDecoration.UNDERLINED, true).build()))
|
||||||
|
.appendNewline()
|
||||||
|
.appendNewline()
|
||||||
|
.append(Component.text(ScriptRegistry.findAndCreateScript(id).orElseThrow().getClass().getName()))
|
||||||
|
.build()
|
||||||
|
)).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, id)))
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
api/src/main/java/ru/dragonestia/msb3/api/debug/Debug.java
Normal file
11
api/src/main/java/ru/dragonestia/msb3/api/debug/Debug.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package ru.dragonestia.msb3.api.debug;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import ru.dragonestia.msb3.api.util.Env;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class Debug {
|
||||||
|
|
||||||
|
@Getter private final boolean enabled = Env.bool("MSB3_DEBUG").orElse(false);
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.dragonestia.msb3.api.util;
|
package ru.dragonestia.msb3.api.debug;
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import net.kyori.adventure.sound.Sound;
|
import net.kyori.adventure.sound.Sound;
|
||||||
@ -11,10 +11,8 @@ import net.minestom.server.sound.SoundEvent;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class DebugMessage {
|
public class DebugMessage {
|
||||||
|
|
||||||
private final boolean disabled = !Env.bool("MSB3_DEBUG").orElse(false);
|
|
||||||
|
|
||||||
public void send(Player player, String message) {
|
public void send(Player player, String message) {
|
||||||
if (disabled) return;
|
if (!Debug.isEnabled()) return;
|
||||||
|
|
||||||
player.sendMessage(Component.text()
|
player.sendMessage(Component.text()
|
||||||
.append(Component.text("[DEBUG] ", TextColor.color(0xFFC909), TextDecoration.BOLD))
|
.append(Component.text("[DEBUG] ", TextColor.color(0xFFC909), TextDecoration.BOLD))
|
||||||
@ -23,7 +21,7 @@ public class DebugMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendError(Player player, String message) {
|
public void sendError(Player player, String message) {
|
||||||
if (disabled) return;
|
if (!Debug.isEnabled()) return;
|
||||||
|
|
||||||
var sound = Sound.sound(SoundEvent.BLOCK_NOTE_BLOCK_BIT, Sound.Source.NEUTRAL, 1f, 0f);
|
var sound = Sound.sound(SoundEvent.BLOCK_NOTE_BLOCK_BIT, Sound.Source.NEUTRAL, 1f, 0f);
|
||||||
player.playSound(sound);
|
player.playSound(sound);
|
||||||
129
api/src/main/java/ru/dragonestia/msb3/api/debug/Graph.java
Normal file
129
api/src/main/java/ru/dragonestia/msb3/api/debug/Graph.java
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package ru.dragonestia.msb3.api.debug;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class Graph {
|
||||||
|
|
||||||
|
private final static AtomicInteger freeId = new AtomicInteger(1);
|
||||||
|
|
||||||
|
private final Map<Integer, Node> nodes = new HashMap<>();
|
||||||
|
|
||||||
|
public Node addNode(Vec pos) {
|
||||||
|
var node = new Node(pos);
|
||||||
|
nodes.put(node.getId(), node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addNodeLink(Node from, Node to) {
|
||||||
|
return from.addLink(to) && to.addLink(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeLink(Node from, Node to) {
|
||||||
|
from.removeLink(to);
|
||||||
|
to.removeLink(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNode(Node node) {
|
||||||
|
nodes.remove(node.getId());
|
||||||
|
node.getLinks().forEach(other -> removeLink(other, node));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Node> getNodes() {
|
||||||
|
return nodes.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Node> findNode(int id) {
|
||||||
|
return Optional.ofNullable(nodes.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializedGraph serialize() {
|
||||||
|
var nodes = new ArrayList<SerializedNode>();
|
||||||
|
var links = new HashSet<IntPair>();
|
||||||
|
|
||||||
|
for (var node: getNodes()) {
|
||||||
|
nodes.add(new SerializedNode(node.id, node.position.x(), node.position.y(), node.position.z()));
|
||||||
|
|
||||||
|
for (var otherNode: node.getLinks()) {
|
||||||
|
if (links.contains(new IntPair(otherNode.getId(), node.getId()))) continue;
|
||||||
|
links.add(new IntPair(node.getId(), otherNode.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new SerializedGraph(nodes, links);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Graph deserialize(SerializedGraph serializedGraph) {
|
||||||
|
var graph = new Graph();
|
||||||
|
for (var node: serializedGraph.nodes) {
|
||||||
|
graph.addNode(new Vec(node.x(), node.y(), node.z()));
|
||||||
|
}
|
||||||
|
for (var link: serializedGraph.links) {
|
||||||
|
graph.addNodeLink(graph.findNode(link.a).orElseThrow(), graph.findNode(link.b).orElseThrow());
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static class Node {
|
||||||
|
|
||||||
|
@Getter private final int id = freeId.getAndIncrement();
|
||||||
|
@Getter private final Vec position;
|
||||||
|
private final Map<Node, Double> links = new HashMap<>();
|
||||||
|
|
||||||
|
private boolean addLink(Node node) {
|
||||||
|
if (id == node.getId()) return false;
|
||||||
|
return links.put(node, position.distance(node.position)) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeLink(Node node) {
|
||||||
|
links.remove(node);
|
||||||
|
node.links.remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasLink(Node node) {
|
||||||
|
if (id == node.getId()) return true;
|
||||||
|
return links.containsKey(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Node> getLinks() {
|
||||||
|
return links.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<DistancePair> getLinksWithDistance() {
|
||||||
|
return links.entrySet().stream()
|
||||||
|
.map(entry -> new DistancePair(entry.getKey(), entry.getValue()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDistanceTo(Node node) {
|
||||||
|
return links.getOrDefault(node, Double.NaN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) return true;
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (obj instanceof Node other) {
|
||||||
|
return id == other.id;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record SerializedGraph(List<SerializedNode> nodes, Set<IntPair> links) {}
|
||||||
|
|
||||||
|
public record SerializedNode(int id, double x, double y, double z) {}
|
||||||
|
|
||||||
|
public record IntPair(int a, int b) {}
|
||||||
|
|
||||||
|
public record DistancePair(Node node, double distance) {}
|
||||||
|
}
|
||||||
@ -14,7 +14,7 @@ import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber;
|
|||||||
import ru.dragonestia.msb3.api.ui.TalksThemes;
|
import ru.dragonestia.msb3.api.ui.TalksThemes;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueTheme;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueTheme;
|
||||||
import ru.dragonestia.msb3.api.util.DebugMessage;
|
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import net.minestom.server.entity.Player;
|
|||||||
import ru.dragonestia.msb3.api.player.PlayerContext;
|
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||||
import ru.dragonestia.msb3.api.player.defaults.TalksContext;
|
import ru.dragonestia.msb3.api.player.defaults.TalksContext;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||||
import ru.dragonestia.msb3.api.util.DebugMessage;
|
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -58,7 +59,7 @@ public class DialogButton {
|
|||||||
boolean success;
|
boolean success;
|
||||||
try {
|
try {
|
||||||
DebugMessage.send(player, "Выполнение действия диалога actionId=%s params=%s".formatted(actionId, params));
|
DebugMessage.send(player, "Выполнение действия диалога actionId=%s params=%s".formatted(actionId, params));
|
||||||
action.get().handle(click, params);
|
action.get().handle(click, Params.of(params));
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import lombok.Setter;
|
|||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||||
import ru.dragonestia.msb3.api.util.DebugMessage;
|
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ public class DialogCondition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return condition.get().check(player, dialog, button, renderer, params);
|
return condition.get().check(player, dialog, button, renderer, Params.of(params));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.error(ex.getMessage(), ex);
|
log.error(ex.getMessage(), ex);
|
||||||
DebugMessage.send(player, "Во время проверки условия для кнопки произошла ошибка conditionId=%s params=%s".formatted(conditionId, params));
|
DebugMessage.send(player, "Во время проверки условия для кнопки произошла ошибка conditionId=%s params=%s".formatted(conditionId, params));
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
package ru.dragonestia.msb3.api.dialog.action;
|
package ru.dragonestia.msb3.api.dialog.action;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class CloseDialogActionHandler implements DialogActionHandler {
|
public class CloseDialogActionHandler implements DialogActionHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(DialogButtonClick click, Map<String, String> params) {
|
public void handle(DialogButtonClick click, Params params) {
|
||||||
click.renderer().close(false);
|
click.renderer().close(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
package ru.dragonestia.msb3.api.dialog.action;
|
package ru.dragonestia.msb3.api.dialog.action;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface DialogActionHandler {
|
public interface DialogActionHandler {
|
||||||
|
|
||||||
void handle(DialogButtonClick click, Map<String, String> params);
|
void handle(DialogButtonClick click, Params params);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,22 +4,22 @@ import lombok.extern.log4j.Log4j2;
|
|||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogRegistry;
|
import ru.dragonestia.msb3.api.dialog.DialogRegistry;
|
||||||
import ru.dragonestia.msb3.api.util.DebugMessage;
|
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
public class DialogDialogActionHandler implements DialogActionHandler {
|
public class DialogDialogActionHandler implements DialogActionHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(DialogButtonClick click, Map<String, String> params) {
|
public void handle(DialogButtonClick click, Params params) {
|
||||||
var player = click.player();
|
var player = click.player();
|
||||||
var dialogId = params.get("dialogId");
|
|
||||||
if (dialogId == null) {
|
if (params.contains("dialogId")) {
|
||||||
DebugMessage.sendError(player, "Отсутствует обязательный параметр dialogId для команды dialog");
|
DebugMessage.sendError(player, "Отсутствует обязательный параметр dialogId для команды dialog");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dialogId = params.getString("dialogId");
|
||||||
var dialog = DialogRegistry.findDialog(Key.key(dialogId));
|
var dialog = DialogRegistry.findDialog(Key.key(dialogId));
|
||||||
if (dialog.isEmpty()) {
|
if (dialog.isEmpty()) {
|
||||||
log.error("Dialog {} not found", dialogId);
|
log.error("Dialog {} not found", dialogId);
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
package ru.dragonestia.msb3.api.dialog.action;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||||
|
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||||
|
import ru.dragonestia.msb3.api.script.ScriptRegistry;
|
||||||
|
import ru.dragonestia.msb3.api.script.ScriptService;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
public class ScriptDialogActionHandler implements DialogActionHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(DialogButtonClick click, Params params) {
|
||||||
|
var player = click.player();
|
||||||
|
|
||||||
|
if (params.contains("scriptId")) {
|
||||||
|
DebugMessage.sendError(player, "Отсутствует обязательный параметр scriptId для команды script");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scriptId = params.getString("scriptId");
|
||||||
|
var script = ScriptRegistry.findAndCreateScript(scriptId);
|
||||||
|
if (script.isEmpty()) {
|
||||||
|
log.error("Script {} not found", scriptId);
|
||||||
|
DebugMessage.sendError(player, "Скрипт с идентификатором %s не найден".formatted(scriptId));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptService.ofPlayer(player).start(script.get(), params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,13 +4,12 @@ import net.minestom.server.entity.Player;
|
|||||||
import ru.dragonestia.msb3.api.dialog.Dialog;
|
import ru.dragonestia.msb3.api.dialog.Dialog;
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class AlwaysDialogConditionHandler implements DialogConditionHandler {
|
public class AlwaysDialogConditionHandler implements DialogConditionHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check(Player player, Dialog dialog, DialogButton button, DialogueRenderer renderer, Map<String, String> params) {
|
public boolean check(Player player, Dialog dialog, DialogButton button, DialogueRenderer renderer, Params params) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,9 @@ import net.minestom.server.entity.Player;
|
|||||||
import ru.dragonestia.msb3.api.dialog.Dialog;
|
import ru.dragonestia.msb3.api.dialog.Dialog;
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface DialogConditionHandler {
|
public interface DialogConditionHandler {
|
||||||
|
|
||||||
boolean check(Player player, Dialog dialog, DialogButton button, DialogueRenderer renderer, Map<String, String> params);
|
boolean check(Player player, Dialog dialog, DialogButton button, DialogueRenderer renderer, Params params);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,13 +4,12 @@ import net.minestom.server.entity.Player;
|
|||||||
import ru.dragonestia.msb3.api.dialog.Dialog;
|
import ru.dragonestia.msb3.api.dialog.Dialog;
|
||||||
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
||||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class NeverDialogConditionHandler implements DialogConditionHandler {
|
public class NeverDialogConditionHandler implements DialogConditionHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check(Player player, Dialog dialog, DialogButton button, DialogueRenderer renderer, Map<String, String> params) {
|
public boolean check(Player player, Dialog dialog, DialogButton button, DialogueRenderer renderer, Params params) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity;
|
||||||
|
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
|
||||||
|
public interface OffsetPosition {
|
||||||
|
|
||||||
|
void setOffsetPosition(Point offset);
|
||||||
|
|
||||||
|
Point getOffsetPosition();
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity.debug;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
|
import net.minestom.server.entity.metadata.display.BlockDisplayMeta;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
|
||||||
|
public class DebugCollider extends DebugRendererEntity {
|
||||||
|
|
||||||
|
private DebugHologram hologram;
|
||||||
|
|
||||||
|
public DebugCollider(String layerName, Block block, Point size) {
|
||||||
|
super(EntityType.BLOCK_DISPLAY, layerName);
|
||||||
|
|
||||||
|
var meta = (BlockDisplayMeta) getEntityMeta();
|
||||||
|
meta.setScale(Vec.fromPoint(size));
|
||||||
|
meta.setBlockState(block);
|
||||||
|
meta.setScale(Vec.fromPoint(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DebugCollider(String layerName, Block block, Point size, Component text) {
|
||||||
|
this(layerName, block, size);
|
||||||
|
|
||||||
|
var meta = (BlockDisplayMeta) getEntityMeta();
|
||||||
|
addNestedEntity(hologram = new DebugHologram(layerName, text), meta.getScale().div(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity.debug;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
|
import net.minestom.server.entity.metadata.display.AbstractDisplayMeta;
|
||||||
|
import net.minestom.server.entity.metadata.display.TextDisplayMeta;
|
||||||
|
|
||||||
|
public class DebugHologram extends DebugRendererEntity {
|
||||||
|
|
||||||
|
public DebugHologram(String layerName, Component text) {
|
||||||
|
super(EntityType.TEXT_DISPLAY, layerName);
|
||||||
|
|
||||||
|
var meta = (TextDisplayMeta) getEntityMeta();
|
||||||
|
meta.setText(text);
|
||||||
|
meta.setBillboardRenderConstraints(AbstractDisplayMeta.BillboardConstraints.CENTER);
|
||||||
|
meta.setSeeThrough(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity.debug;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
|
import net.minestom.server.entity.metadata.display.BlockDisplayMeta;
|
||||||
|
import net.minestom.server.instance.Instance;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
import ru.dragonestia.msb3.api.math.Quaternion;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Log4j2
|
||||||
|
public class DebugLine extends DebugRendererEntity {
|
||||||
|
|
||||||
|
private Vec normalWithLength;
|
||||||
|
private Block block;
|
||||||
|
|
||||||
|
protected DebugLine(String layerName, Vec normalWithLength, Block block) {
|
||||||
|
super(EntityType.BLOCK_DISPLAY, layerName);
|
||||||
|
|
||||||
|
var meta = getMeta();
|
||||||
|
meta.setBrightnessOverride(15);
|
||||||
|
meta.setBrightness(15, 15);
|
||||||
|
|
||||||
|
updateNormalWithLength(normalWithLength);
|
||||||
|
updateBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateNormalWithLength(Vec newValue) {
|
||||||
|
normalWithLength = newValue;
|
||||||
|
var meta = getMeta();
|
||||||
|
meta.setScale(new Vec(0.1, normalWithLength.length(), 0.1));
|
||||||
|
meta.setLeftRotation(Quaternion.DEFAULT
|
||||||
|
.rotate(newValue.normalize())
|
||||||
|
.toFloatArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBlock(Block block) {
|
||||||
|
getMeta().setBlockState(this.block = block);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockDisplayMeta getMeta() {
|
||||||
|
return (BlockDisplayMeta) getEntityMeta();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DebugLine spawn(Instance instance, Point start, Point end, Block block, String layerName) {
|
||||||
|
var entity = new DebugLine(layerName, Vec.fromPoint(end.sub(start)), block);
|
||||||
|
entity.setInstance(instance, start);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity.debug;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.coordinate.Pos;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
|
import net.minestom.server.entity.metadata.display.AbstractDisplayMeta;
|
||||||
|
import net.minestom.server.entity.metadata.display.BlockDisplayMeta;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
|
||||||
|
public class DebugMarker extends DebugRendererEntity {
|
||||||
|
|
||||||
|
public DebugMarker(String layerName, Block block) {
|
||||||
|
super(EntityType.BLOCK_DISPLAY, layerName);
|
||||||
|
|
||||||
|
var meta = (BlockDisplayMeta) getEntityMeta();
|
||||||
|
meta.setBlockState(block);
|
||||||
|
meta.setBillboardRenderConstraints(AbstractDisplayMeta.BillboardConstraints.CENTER);
|
||||||
|
meta.setTranslation(new Pos(-0.5, -0.5, -0.5));
|
||||||
|
meta.setLeftRotation(new float[] { 0.33333f, 0.33333f, 0.33333f, 0.8f });
|
||||||
|
}
|
||||||
|
|
||||||
|
public DebugMarker(String layerName, Block block, Component text) {
|
||||||
|
this(layerName, block);
|
||||||
|
|
||||||
|
addNestedEntity(new DebugHologram(layerName, text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScale(double x, double y, double z) {
|
||||||
|
var meta = (BlockDisplayMeta) getEntityMeta();
|
||||||
|
meta.setScale(new Vec(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity.debug;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
import net.minestom.server.coordinate.Pos;
|
||||||
|
import net.minestom.server.entity.Entity;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
|
import net.minestom.server.entity.metadata.display.AbstractDisplayMeta;
|
||||||
|
import net.minestom.server.instance.Instance;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import ru.dragonestia.msb3.api.debug.Debug;
|
||||||
|
import ru.dragonestia.msb3.api.entity.OffsetPosition;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class DebugRendererEntity extends Entity implements OffsetPosition {
|
||||||
|
|
||||||
|
private final String layerName;
|
||||||
|
private final List<Entity> nestedEntities = new ArrayList<>();
|
||||||
|
private Point offsetPosition = Pos.ZERO;
|
||||||
|
|
||||||
|
public DebugRendererEntity(@NotNull EntityType entityType, String layerName) {
|
||||||
|
super(entityType);
|
||||||
|
this.layerName = layerName;
|
||||||
|
|
||||||
|
setNoGravity(true);
|
||||||
|
if (getEntityMeta() instanceof AbstractDisplayMeta meta) {
|
||||||
|
meta.setBrightnessOverride(1);
|
||||||
|
meta.setBrightness(15, 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNestedEntity(Entity entity) {
|
||||||
|
nestedEntities.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNestedEntity(Entity entity, Point offset) {
|
||||||
|
if (entity instanceof OffsetPosition target) target.setOffsetPosition(offset);
|
||||||
|
nestedEntities.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> setInstance(@NotNull Instance instance, @NotNull Pos spawnPosition) {
|
||||||
|
return super.setInstance(instance, spawnPosition)
|
||||||
|
.thenRun(() -> {
|
||||||
|
if (!Debug.isEnabled()) {
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var entity: nestedEntities) {
|
||||||
|
if (entity instanceof OffsetPosition offsetPosition) {
|
||||||
|
entity.setInstance(instance, spawnPosition.add(offsetPosition.getOffsetPosition()));
|
||||||
|
} else {
|
||||||
|
entity.setInstance(instance, spawnPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull CompletableFuture<Void> teleport(@NotNull Pos position, long @Nullable [] chunks, int flags, boolean shouldConfirm) {
|
||||||
|
return super.teleport(position, chunks, flags, shouldConfirm)
|
||||||
|
.thenRun(() -> {
|
||||||
|
for (var entity: nestedEntities) {
|
||||||
|
if (entity instanceof OffsetPosition offsetPosition) {
|
||||||
|
entity.teleport(position.add(offsetPosition.getOffsetPosition()), chunks, flags, shouldConfirm);
|
||||||
|
} else {
|
||||||
|
entity.teleport(position, chunks, flags, shouldConfirm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
super.remove();
|
||||||
|
for (var entity: nestedEntities) {
|
||||||
|
entity.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOffsetPosition(Point offset) {
|
||||||
|
offsetPosition = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Point getOffsetPosition() {
|
||||||
|
return offsetPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity.rule;
|
||||||
|
|
||||||
|
import net.minestom.server.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public abstract class PlayerViewerRule {
|
||||||
|
|
||||||
|
private final UUID id = UUID.randomUUID();
|
||||||
|
|
||||||
|
public final UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean canView(Entity entity);
|
||||||
|
|
||||||
|
@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 PlayerViewerRule other) {
|
||||||
|
return this.id.equals(other.id);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package ru.dragonestia.msb3.api.math;
|
||||||
|
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
|
||||||
|
public record Quaternion(double x, double y, double z, double w) {
|
||||||
|
|
||||||
|
public static final Quaternion DEFAULT = new Quaternion(0, 0, 0, 1);
|
||||||
|
|
||||||
|
public static Quaternion fromVec (Vec vec, double realPart) {
|
||||||
|
return new Quaternion(vec.x(), vec.y(), vec.z(), realPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] toFloatArray() {
|
||||||
|
return new float[] { (float) x, (float) y, (float) z, (float) w };
|
||||||
|
}
|
||||||
|
|
||||||
|
public double length() {
|
||||||
|
return Math.sqrt(x * x + y * y + z * z + w * w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion normalize() {
|
||||||
|
var length = length();
|
||||||
|
return new Quaternion(x / length, y / length, z / length, w / length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion conjugate() {
|
||||||
|
return new Quaternion(-x, -y, -z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double dotProduct(Quaternion target) {
|
||||||
|
return (x * target.x + y * target.y + z * target.z + w * target.w
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion mul(Quaternion target) {
|
||||||
|
return new Quaternion(
|
||||||
|
w() * target.x() + x() * target.w() + y() * target.z() - z() * target.y(),
|
||||||
|
w() * target.y() - x() * target.z() + y() * target.w() + z() * target.x(),
|
||||||
|
w() * target.z() + x() * target.y() - y() * target.x() + z() * target.w(),
|
||||||
|
w() * target.w() - x() * target.x() - y() * target.y() - z() * target.z()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion add(Quaternion target) {
|
||||||
|
return new Quaternion(
|
||||||
|
x + target.x,
|
||||||
|
y + target.y,
|
||||||
|
z + target.z,
|
||||||
|
w + target.w
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion sub(Quaternion target) {
|
||||||
|
return new Quaternion(
|
||||||
|
x - target.x,
|
||||||
|
y - target.y,
|
||||||
|
z - target.z,
|
||||||
|
w - target.w
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion rotate(Vec normal) {
|
||||||
|
var defaultQuaternion = new Quaternion(0, 0, 0, 1);
|
||||||
|
var defaultVector = new Vec(0, 1, 0);
|
||||||
|
|
||||||
|
var feta = Math.acos(defaultVector.dot(normal));
|
||||||
|
var r = defaultVector.cross(normal);
|
||||||
|
if (r.isZero()){
|
||||||
|
r = new Vec(0, 0, 1);
|
||||||
|
}
|
||||||
|
var rotation = fromVec(r.normalize().mul(Math.sin(feta / 2)), Math.cos(feta / 2));
|
||||||
|
return defaultQuaternion.mul(rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,19 +5,23 @@ import net.minestom.server.entity.Player;
|
|||||||
import net.minestom.server.network.player.GameProfile;
|
import net.minestom.server.network.player.GameProfile;
|
||||||
import net.minestom.server.network.player.PlayerConnection;
|
import net.minestom.server.network.player.PlayerConnection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import ru.dragonestia.msb3.api.entity.debug.DebugRendererEntity;
|
||||||
|
import ru.dragonestia.msb3.api.entity.rule.PlayerViewerRule;
|
||||||
import ru.dragonestia.msb3.api.util.UncheckedRunnable;
|
import ru.dragonestia.msb3.api.util.UncheckedRunnable;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class MsbPlayer extends Player {
|
public class MsbPlayer extends Player {
|
||||||
|
|
||||||
private final Map<String, PlayerContext> contexts = new LinkedHashMap<>();
|
private final Map<String, PlayerContext> contexts = new LinkedHashMap<>();
|
||||||
@Getter private final Instant startSessionTime = Instant.now();
|
@Getter private final Instant startSessionTime = Instant.now();
|
||||||
|
private final Set<PlayerViewerRule> viewerRules = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
private final Set<String> debugRenderLayers = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
public MsbPlayer(@NotNull PlayerConnection playerConnection, @NotNull GameProfile gameProfile) {
|
public MsbPlayer(@NotNull PlayerConnection playerConnection, @NotNull GameProfile gameProfile) {
|
||||||
super(playerConnection, gameProfile);
|
super(playerConnection, gameProfile);
|
||||||
|
updateViewerRules();
|
||||||
}
|
}
|
||||||
|
|
||||||
void putContext(PlayerContext ctx) {
|
void putContext(PlayerContext ctx) {
|
||||||
@ -55,4 +59,38 @@ public class MsbPlayer extends Player {
|
|||||||
UncheckedRunnable.runIgnoreException(ctx::dispose);
|
UncheckedRunnable.runIgnoreException(ctx::dispose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDebugRenderLayer(String layerName) {
|
||||||
|
debugRenderLayers.add(layerName);
|
||||||
|
updateViewerRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeDebugRenderLayer(String layerName) {
|
||||||
|
debugRenderLayers.remove(layerName);
|
||||||
|
updateViewerRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendViewRule(PlayerViewerRule rule) {
|
||||||
|
viewerRules.add(rule);
|
||||||
|
updateViewerRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeViewRule(PlayerViewerRule rule) {
|
||||||
|
viewerRules.remove(rule);
|
||||||
|
updateViewerRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateViewerRules() {
|
||||||
|
updateViewerRule(entity -> {
|
||||||
|
if (entity instanceof DebugRendererEntity debugRenderer) {
|
||||||
|
return debugRenderLayers.contains(debugRenderer.getLayerName());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var rule: viewerRules) {
|
||||||
|
if (!rule.canView(entity)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,59 @@
|
|||||||
|
package ru.dragonestia.msb3.api.player.defaults;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.minestom.server.entity.EntityCreature;
|
||||||
|
import net.minestom.server.network.packet.server.play.ParticlePacket;
|
||||||
|
import net.minestom.server.particle.Particle;
|
||||||
|
import net.minestom.server.timer.Task;
|
||||||
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
|
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||||
|
import ru.dragonestia.msb3.api.scheduler.Scheduler;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
public class DebugParamsContext extends PlayerContext {
|
||||||
|
|
||||||
|
private final static Particle PARTICLE_AI_PATH = Particle.DUST
|
||||||
|
.withScale(2f)
|
||||||
|
.withColor(NamedTextColor.GREEN);
|
||||||
|
|
||||||
|
private Task taskDebugRendererAiPathFinder;
|
||||||
|
|
||||||
|
public DebugParamsContext(MsbPlayer player) {
|
||||||
|
super(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setShowDebugRendererAiPathFinder(boolean value) {
|
||||||
|
if (value) {
|
||||||
|
if (taskDebugRendererAiPathFinder != null) return;
|
||||||
|
|
||||||
|
taskDebugRendererAiPathFinder = Scheduler.ofPlayer(getPlayer()).repeatingTask(() -> {
|
||||||
|
for (var entity: getPlayer().getInstance().getNearbyEntities(getPlayer().getPosition(), 32)) {
|
||||||
|
if (entity instanceof EntityCreature creature) {
|
||||||
|
var nodes = creature.getNavigator().getNodes();
|
||||||
|
if (nodes == null) continue;
|
||||||
|
for (var point: nodes) {
|
||||||
|
var packet = new ParticlePacket(PARTICLE_AI_PATH, point.x(), point.y() + 0.5, point.z(), 0, 0, 0, 0, 1);
|
||||||
|
entity.sendPacketToViewers(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, Duration.ofMillis(500));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskDebugRendererAiPathFinder == null) return;
|
||||||
|
taskDebugRendererAiPathFinder.cancel();
|
||||||
|
taskDebugRendererAiPathFinder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
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.ContinuousScript;
|
||||||
|
import ru.dragonestia.msb3.api.script.Script;
|
||||||
|
import ru.dragonestia.msb3.api.script.ScriptService;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
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, ContinuousScript> 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, Params params) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (script instanceof ContinuousScript continuousScript) startContinuousScript(continuousScript, params);
|
||||||
|
else startScript(script, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startContinuousScript(ContinuousScript script, Params params) {
|
||||||
|
var opt = findScript(script.getId());
|
||||||
|
if (opt.isPresent()) {
|
||||||
|
DebugMessage.send(getPlayer(), "Script '%s' already running".formatted(script.getId()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startScript(script, params);
|
||||||
|
scripts.put(script.getId(), script);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startScript(Script script, Params params) {
|
||||||
|
try {
|
||||||
|
script.start(getPlayer(), params);
|
||||||
|
DebugMessage.send(getPlayer(), "Script '%s' was started!".formatted(script.getId()));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
DebugMessage.sendError(getPlayer(), "Script '%s' was started with error %s: %s".formatted(script.getId(), ex.getClass().getSimpleName(), ex.getMessage()));
|
||||||
|
log.error(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(ContinuousScript 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<ContinuousScript> getActiveScripts() {
|
||||||
|
return scripts.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ContinuousScript> findScript(String id) {
|
||||||
|
return Optional.ofNullable(scripts.get(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package ru.dragonestia.msb3.api.script;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public abstract class ContinuousScript implements Script {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public ContinuousScript(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void start(MsbPlayer player, Params params);
|
||||||
|
|
||||||
|
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 ContinuousScript other) {
|
||||||
|
return id.equals(other.id);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package ru.dragonestia.msb3.api.script;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public abstract class InstantScript implements Script {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public InstantScript(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void start(MsbPlayer player, Params params);
|
||||||
|
}
|
||||||
11
api/src/main/java/ru/dragonestia/msb3/api/script/Script.java
Normal file
11
api/src/main/java/ru/dragonestia/msb3/api/script/Script.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package ru.dragonestia.msb3.api.script;
|
||||||
|
|
||||||
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
public interface Script {
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
void start(MsbPlayer player, Params params);
|
||||||
|
}
|
||||||
@ -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,28 @@
|
|||||||
|
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 ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface ScriptService {
|
||||||
|
|
||||||
|
default void start(Script script) {
|
||||||
|
start(script, Params.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void start(Script script, Params params);
|
||||||
|
|
||||||
|
void stop(ContinuousScript script);
|
||||||
|
|
||||||
|
Collection<ContinuousScript> getActiveScripts();
|
||||||
|
|
||||||
|
Optional<ContinuousScript> findScript(String id);
|
||||||
|
|
||||||
|
static ScriptService ofPlayer(Player player) {
|
||||||
|
return PlayerContext.of(player, PlayerScriptContext.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package ru.dragonestia.msb3.api.script.defaults;
|
||||||
|
|
||||||
|
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||||
|
import ru.dragonestia.msb3.api.script.InstantScript;
|
||||||
|
import ru.dragonestia.msb3.api.util.Params;
|
||||||
|
|
||||||
|
public class HelloWorldScript extends InstantScript {
|
||||||
|
|
||||||
|
public HelloWorldScript() {
|
||||||
|
super("hello_world");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(MsbPlayer player, Params params) {
|
||||||
|
player.sendMessage("Hello World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,7 +24,7 @@ import ru.dragonestia.msb3.api.item.ItemUtil;
|
|||||||
import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber;
|
import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber;
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.GlyphPositions;
|
import ru.dragonestia.msb3.api.resource.dialog.GlyphPositions;
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.TextureProperties;
|
import ru.dragonestia.msb3.api.resource.dialog.TextureProperties;
|
||||||
import ru.dragonestia.msb3.api.util.DebugMessage;
|
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||||
import ru.dragonestia.msb3.api.util.StringUtil;
|
import ru.dragonestia.msb3.api.util.StringUtil;
|
||||||
import ru.dragonestia.msb3.resource.glyph.GlyphComponent;
|
import ru.dragonestia.msb3.resource.glyph.GlyphComponent;
|
||||||
import ru.dragonestia.msb3.resource.glyph.GlyphComponentBuilder;
|
import ru.dragonestia.msb3.resource.glyph.GlyphComponentBuilder;
|
||||||
|
|||||||
57
api/src/main/java/ru/dragonestia/msb3/api/util/Params.java
Normal file
57
api/src/main/java/ru/dragonestia/msb3/api/util/Params.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package ru.dragonestia.msb3.api.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class Params {
|
||||||
|
|
||||||
|
public static final Params EMPTY = of(new HashMap<>());
|
||||||
|
|
||||||
|
private final Map<String, String> params;
|
||||||
|
|
||||||
|
private Params(Map<String, String> params) {
|
||||||
|
this.params = new HashMap<>(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Params of(Map<String, String> params) {
|
||||||
|
return new Params(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String key) {
|
||||||
|
return params.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> keys() {
|
||||||
|
return params.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return params.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString(String key) {
|
||||||
|
return params.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String key) {
|
||||||
|
return Boolean.parseBoolean(getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt(String key) {
|
||||||
|
return Integer.parseInt(getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong(String key) {
|
||||||
|
return Long.parseLong(getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDouble(String key) {
|
||||||
|
return Double.parseDouble(getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloat(String key) {
|
||||||
|
return Float.parseFloat(getString(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package ru.dragonestia.msb3.api.world.loader.anvil;
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
import net.kyori.adventure.nbt.*;
|
import net.kyori.adventure.nbt.*;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.instance.DynamicChunk;
|
import net.minestom.server.instance.DynamicChunk;
|
||||||
@ -11,9 +12,7 @@ import net.minestom.server.instance.block.Block;
|
|||||||
import net.minestom.server.instance.block.BlockHandler;
|
import net.minestom.server.instance.block.BlockHandler;
|
||||||
import net.minestom.server.instance.palette.Palettes;
|
import net.minestom.server.instance.palette.Palettes;
|
||||||
import net.minestom.server.registry.DynamicRegistry;
|
import net.minestom.server.registry.DynamicRegistry;
|
||||||
import net.minestom.server.utils.ArrayUtils;
|
|
||||||
import net.minestom.server.utils.MathUtils;
|
import net.minestom.server.utils.MathUtils;
|
||||||
import net.minestom.server.utils.NamespaceID;
|
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import net.minestom.server.world.biome.Biome;
|
import net.minestom.server.world.biome.Biome;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -26,7 +25,7 @@ import java.util.*;
|
|||||||
public class AnvilRegionLoader {
|
public class AnvilRegionLoader {
|
||||||
|
|
||||||
private static final DynamicRegistry<Biome> BIOME_REGISTRY = MinecraftServer.getBiomeRegistry();
|
private static final DynamicRegistry<Biome> BIOME_REGISTRY = MinecraftServer.getBiomeRegistry();
|
||||||
private final static int PLAINS_ID = BIOME_REGISTRY.getId(NamespaceID.from("minecraft:plains"));
|
private final static int PLAINS_ID = BIOME_REGISTRY.getId(Key.key("minecraft:plains"));
|
||||||
|
|
||||||
private final File worldDir;
|
private final File worldDir;
|
||||||
|
|
||||||
@ -178,7 +177,7 @@ public class AnvilRegionLoader {
|
|||||||
if (blockName.equals("minecraft:air")) {
|
if (blockName.equals("minecraft:air")) {
|
||||||
convertedPalette[i] = Block.AIR;
|
convertedPalette[i] = Block.AIR;
|
||||||
} else {
|
} else {
|
||||||
Block block = Objects.requireNonNull(Block.fromNamespaceId(blockName), "Unknown block " + blockName);
|
Block block = Objects.requireNonNull(Block.fromKey(blockName), "Unknown block " + blockName);
|
||||||
// Properties
|
// Properties
|
||||||
final Map<String, String> properties = new HashMap<>();
|
final Map<String, String> properties = new HashMap<>();
|
||||||
CompoundBinaryTag propertiesNBT = paletteEntry.getCompound("Properties");
|
CompoundBinaryTag propertiesNBT = paletteEntry.getCompound("Properties");
|
||||||
@ -205,7 +204,7 @@ public class AnvilRegionLoader {
|
|||||||
int[] convertedPalette = new int[paletteTag.size()];
|
int[] convertedPalette = new int[paletteTag.size()];
|
||||||
for (int i = 0; i < convertedPalette.length; i++) {
|
for (int i = 0; i < convertedPalette.length; i++) {
|
||||||
final String name = paletteTag.getString(i);
|
final String name = paletteTag.getString(i);
|
||||||
int biomeId = BIOME_REGISTRY.getId(NamespaceID.from(name));
|
int biomeId = BIOME_REGISTRY.getId(Key.key(name));
|
||||||
if (biomeId == -1) biomeId = PLAINS_ID;
|
if (biomeId == -1) biomeId = PLAINS_ID;
|
||||||
convertedPalette[i] = biomeId;
|
convertedPalette[i] = biomeId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ subprojects {
|
|||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
group = 'ru.dragonestia.msb3'
|
group = 'ru.dragonestia.msb3'
|
||||||
version = '3.0'
|
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
|
|||||||
@ -33,3 +33,7 @@ dependencyManagement {
|
|||||||
mavenBom "com.vaadin:vaadin-bom:${vaadinVersion}"
|
mavenBom "com.vaadin:vaadin-bom:${vaadinVersion}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourcesJar.dependsOn({
|
||||||
|
vaadinPrepareFrontend
|
||||||
|
})
|
||||||
|
|||||||
2
gradle.properties
Normal file
2
gradle.properties
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
MSB3_MAVEN_REPOSITORY=http://git.dragonestia.ru/api/packages/MSB/maven
|
||||||
|
MSB3_VERSION=3.0.1
|
||||||
@ -1,3 +1,9 @@
|
|||||||
|
ext {
|
||||||
|
ext.set("VERSION", '1.0.0')
|
||||||
|
}
|
||||||
|
|
||||||
|
version = ext.get("VERSION")
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'net.kyori:adventure-api:4.17.0'
|
api 'net.kyori:adventure-api:4.17.0'
|
||||||
api 'net.kyori:adventure-text-minimessage:4.17.0'
|
api 'net.kyori:adventure-text-minimessage:4.17.0'
|
||||||
@ -5,3 +11,32 @@ dependencies {
|
|||||||
api 'team.unnamed:creative-serializer-minecraft:1.7.3'
|
api 'team.unnamed:creative-serializer-minecraft:1.7.3'
|
||||||
api 'team.unnamed:creative-server:1.7.3'
|
api 'team.unnamed:creative-server:1.7.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
maven(MavenPublication) {
|
||||||
|
groupId = 'ru.dragonestia.msb3'
|
||||||
|
artifactId = 'resource-compiler'
|
||||||
|
version = project.ext.get("VERSION")
|
||||||
|
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "Gitea"
|
||||||
|
url = uri(MSB3_MAVEN_REPOSITORY)
|
||||||
|
allowInsecureProtocol = true
|
||||||
|
|
||||||
|
credentials(HttpHeaderCredentials) {
|
||||||
|
name = "Authorization"
|
||||||
|
value = "token ${dragonestiaGiteaToken}"
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication {
|
||||||
|
header(HttpHeaderAuthentication)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user