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'
|
||||
}
|
||||
|
||||
version = MSB3_VERSION
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
manifest {
|
||||
@ -27,7 +29,7 @@ tasks {
|
||||
dependencies {
|
||||
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.apache.logging.log4j:log4j-slf4j2-impl:2.24.0'
|
||||
@ -48,3 +50,32 @@ dependencies {
|
||||
|
||||
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
|
||||
public void onDefaultModulesLoaded() {
|
||||
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));
|
||||
}
|
||||
|
||||
@ -33,4 +33,9 @@ public class DefaultBootstrap extends ServerInitializer {
|
||||
public void onResourcePackCompiled(ResourcePack resourcePack) {
|
||||
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.action.CloseDialogActionHandler;
|
||||
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.NeverDialogConditionHandler;
|
||||
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.player.MsbPlayer;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContextManager;
|
||||
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;
|
||||
@ -102,6 +103,7 @@ public final class ServerBootstrap {
|
||||
initDefaultDialogActionsAndConditions();
|
||||
NPCClickEvent.init();
|
||||
DebugCommands.init();
|
||||
initDefaultScripts();
|
||||
}
|
||||
|
||||
private void compileResourcePack() {
|
||||
@ -191,6 +193,8 @@ public final class ServerBootstrap {
|
||||
PlayerContextManager.registerContext(KeyedBossBarContext.class, KeyedBossBarContext::new);
|
||||
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() {
|
||||
@ -200,8 +204,13 @@ public final class ServerBootstrap {
|
||||
private void initDefaultDialogActionsAndConditions() {
|
||||
DialogRegistry.registerActionHandler("close", new CloseDialogActionHandler());
|
||||
DialogRegistry.registerActionHandler("dialog", new DialogDialogActionHandler());
|
||||
DialogRegistry.registerActionHandler("script", new ScriptDialogActionHandler());
|
||||
|
||||
DialogRegistry.registerConditionHandler("always", new AlwaysDialogConditionHandler());
|
||||
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();
|
||||
registerTeleportCommand();
|
||||
registerGameModeCommand();
|
||||
DebugRendererCommand.register();
|
||||
DebugAICommand.register();
|
||||
ScriptCommand.register();
|
||||
|
||||
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 net.kyori.adventure.sound.Sound;
|
||||
@ -11,10 +11,8 @@ import net.minestom.server.sound.SoundEvent;
|
||||
@UtilityClass
|
||||
public class DebugMessage {
|
||||
|
||||
private final boolean disabled = !Env.bool("MSB3_DEBUG").orElse(false);
|
||||
|
||||
public void send(Player player, String message) {
|
||||
if (disabled) return;
|
||||
if (!Debug.isEnabled()) return;
|
||||
|
||||
player.sendMessage(Component.text()
|
||||
.append(Component.text("[DEBUG] ", TextColor.color(0xFFC909), TextDecoration.BOLD))
|
||||
@ -23,7 +21,7 @@ public class DebugMessage {
|
||||
}
|
||||
|
||||
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);
|
||||
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.dialogue.DialogueRenderer;
|
||||
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.List;
|
||||
|
||||
@ -10,7 +10,8 @@ import net.minestom.server.entity.Player;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.TalksContext;
|
||||
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.Map;
|
||||
@ -58,7 +59,7 @@ public class DialogButton {
|
||||
boolean success;
|
||||
try {
|
||||
DebugMessage.send(player, "Выполнение действия диалога actionId=%s params=%s".formatted(actionId, params));
|
||||
action.get().handle(click, params);
|
||||
action.get().handle(click, Params.of(params));
|
||||
|
||||
success = true;
|
||||
} catch (Exception ex) {
|
||||
|
||||
@ -7,7 +7,8 @@ import lombok.Setter;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.minestom.server.entity.Player;
|
||||
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;
|
||||
|
||||
@ -33,7 +34,7 @@ public class DialogCondition {
|
||||
}
|
||||
|
||||
try {
|
||||
return condition.get().check(player, dialog, button, renderer, params);
|
||||
return condition.get().check(player, dialog, button, renderer, Params.of(params));
|
||||
} catch (Exception ex) {
|
||||
log.error(ex.getMessage(), ex);
|
||||
DebugMessage.send(player, "Во время проверки условия для кнопки произошла ошибка conditionId=%s params=%s".formatted(conditionId, params));
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
package ru.dragonestia.msb3.api.dialog.action;
|
||||
|
||||
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||
import ru.dragonestia.msb3.api.util.Params;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CloseDialogActionHandler implements DialogActionHandler {
|
||||
|
||||
@Override
|
||||
public void handle(DialogButtonClick click, Map<String, String> params) {
|
||||
public void handle(DialogButtonClick click, Params params) {
|
||||
click.renderer().close(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
package ru.dragonestia.msb3.api.dialog.action;
|
||||
|
||||
import ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||
|
||||
import java.util.Map;
|
||||
import ru.dragonestia.msb3.api.util.Params;
|
||||
|
||||
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 ru.dragonestia.msb3.api.dialog.DialogButtonClick;
|
||||
import ru.dragonestia.msb3.api.dialog.DialogRegistry;
|
||||
import ru.dragonestia.msb3.api.util.DebugMessage;
|
||||
|
||||
import java.util.Map;
|
||||
import ru.dragonestia.msb3.api.debug.DebugMessage;
|
||||
import ru.dragonestia.msb3.api.util.Params;
|
||||
|
||||
@Log4j2
|
||||
public class DialogDialogActionHandler implements DialogActionHandler {
|
||||
|
||||
@Override
|
||||
public void handle(DialogButtonClick click, Map<String, String> params) {
|
||||
public void handle(DialogButtonClick click, Params params) {
|
||||
var player = click.player();
|
||||
var dialogId = params.get("dialogId");
|
||||
if (dialogId == null) {
|
||||
|
||||
if (params.contains("dialogId")) {
|
||||
DebugMessage.sendError(player, "Отсутствует обязательный параметр dialogId для команды dialog");
|
||||
return;
|
||||
}
|
||||
|
||||
var dialogId = params.getString("dialogId");
|
||||
var dialog = DialogRegistry.findDialog(Key.key(dialogId));
|
||||
if (dialog.isEmpty()) {
|
||||
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.DialogButton;
|
||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||
|
||||
import java.util.Map;
|
||||
import ru.dragonestia.msb3.api.util.Params;
|
||||
|
||||
public class AlwaysDialogConditionHandler implements DialogConditionHandler {
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,10 +4,9 @@ import net.minestom.server.entity.Player;
|
||||
import ru.dragonestia.msb3.api.dialog.Dialog;
|
||||
import ru.dragonestia.msb3.api.dialog.DialogButton;
|
||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||
|
||||
import java.util.Map;
|
||||
import ru.dragonestia.msb3.api.util.Params;
|
||||
|
||||
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.DialogButton;
|
||||
import ru.dragonestia.msb3.api.ui.dialogue.DialogueRenderer;
|
||||
|
||||
import java.util.Map;
|
||||
import ru.dragonestia.msb3.api.util.Params;
|
||||
|
||||
public class NeverDialogConditionHandler implements DialogConditionHandler {
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.PlayerConnection;
|
||||
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 java.time.Instant;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class MsbPlayer extends Player {
|
||||
|
||||
private final Map<String, PlayerContext> contexts = new LinkedHashMap<>();
|
||||
@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) {
|
||||
super(playerConnection, gameProfile);
|
||||
updateViewerRules();
|
||||
}
|
||||
|
||||
void putContext(PlayerContext ctx) {
|
||||
@ -55,4 +59,38 @@ public class MsbPlayer extends Player {
|
||||
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.GlyphPositions;
|
||||
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.resource.glyph.GlyphComponent;
|
||||
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 lombok.extern.log4j.Log4j2;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.nbt.*;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
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.palette.Palettes;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -26,7 +25,7 @@ import java.util.*;
|
||||
public class AnvilRegionLoader {
|
||||
|
||||
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;
|
||||
|
||||
@ -178,7 +177,7 @@ public class AnvilRegionLoader {
|
||||
if (blockName.equals("minecraft:air")) {
|
||||
convertedPalette[i] = Block.AIR;
|
||||
} else {
|
||||
Block block = Objects.requireNonNull(Block.fromNamespaceId(blockName), "Unknown block " + blockName);
|
||||
Block block = Objects.requireNonNull(Block.fromKey(blockName), "Unknown block " + blockName);
|
||||
// Properties
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
CompoundBinaryTag propertiesNBT = paletteEntry.getCompound("Properties");
|
||||
@ -205,7 +204,7 @@ public class AnvilRegionLoader {
|
||||
int[] convertedPalette = new int[paletteTag.size()];
|
||||
for (int i = 0; i < convertedPalette.length; 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;
|
||||
convertedPalette[i] = biomeId;
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ subprojects {
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
group = 'ru.dragonestia.msb3'
|
||||
version = '3.0'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
|
||||
@ -33,3 +33,7 @@ dependencyManagement {
|
||||
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 {
|
||||
api 'net.kyori:adventure-api: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-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