feat: implemented navigator
This commit is contained in:
parent
2b007d9897
commit
b0c71740a3
@ -7,16 +7,18 @@ import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
|
||||
import net.minestom.server.event.player.PlayerDisconnectEvent;
|
||||
import net.minestom.server.event.player.PlayerSpawnEvent;
|
||||
import ru.dragonestia.msb3.api.entity.PickableItem;
|
||||
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.resource.DialogueResources;
|
||||
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
||||
import ru.dragonestia.msb3.api.ui.BlackScreen;
|
||||
import ru.dragonestia.msb3.api.ui.bossbar.KeyedBossBars;
|
||||
import ru.dragonestia.msb3.api.ui.navigator.Navigator;
|
||||
import ru.dragonestia.msb3.api.ui.navigator.Navigators;
|
||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||
import ru.dragonestia.msb3.resource.Resources;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphCharacterFactory;
|
||||
@ -103,7 +105,7 @@ public final class ServerBootstrap {
|
||||
|
||||
private void initDefaultGlyphs() {
|
||||
ClassPreLoader.preload(BlackScreen.class);
|
||||
ClassPreLoader.preload(Navigator.class);
|
||||
ClassPreLoader.preload(Navigators.class);
|
||||
ClassPreLoader.preload(KeyedBossBars.class);
|
||||
|
||||
MonologueResources.registerAvatar(MonologueResources.DEFAULT, ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/monologue/default_avatar.png"));
|
||||
@ -160,16 +162,21 @@ public final class ServerBootstrap {
|
||||
MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> {
|
||||
var player = (MsbPlayer) event.getPlayer();
|
||||
|
||||
log.info("Connected player {} (uuid: {}, address: {})", player.getUsername(), player.getUuid(), player.getPlayerConnection().getRemoteAddress());
|
||||
log.info("Connected player '{}' (uuid: {}, address: {})", player.getUsername(), player.getUuid(), player.getPlayerConnection().getRemoteAddress());
|
||||
player.initContexts();
|
||||
}).addListener(PlayerSpawnEvent.class, event -> {
|
||||
var player = (MsbPlayer) event.getPlayer();
|
||||
|
||||
player.emitSpawnSignalForContexts();
|
||||
}).addListener(PlayerDisconnectEvent.class, event -> {
|
||||
var player = (MsbPlayer) event.getPlayer();
|
||||
|
||||
log.info("Disconnected player {} (uuid: {}, address: {})", player.getUsername(), player.getUuid(), player.getPlayerConnection().getRemoteAddress());
|
||||
log.info("Disconnected player '{}' (uuid: {}, address: {})", player.getUsername(), player.getUuid(), player.getPlayerConnection().getRemoteAddress());
|
||||
player.disposeContexts();
|
||||
});
|
||||
|
||||
// Default contexts
|
||||
PlayerContextManager.registerContext(KeyedBossBarContext.class, KeyedBossBarContext::new);
|
||||
PlayerContextManager.registerContext(NavigatorContext.class, NavigatorContext::new);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,15 @@ public class MsbPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
public void emitSpawnSignalForContexts() {
|
||||
for (var entry: contexts.entrySet()) {
|
||||
var ctxKey = entry.getKey();
|
||||
var ctx = entry.getValue();
|
||||
|
||||
UncheckedRunnable.runIgnoreException(ctx::firstSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
public void disposeContexts() {
|
||||
for (var entry: contexts.entrySet()) {
|
||||
var ctxKey = entry.getKey();
|
||||
|
||||
@ -14,6 +14,8 @@ public abstract class PlayerContext {
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public void firstSpawn() {}
|
||||
|
||||
public abstract void dispose();
|
||||
|
||||
public static <T extends PlayerContext> T of(Player player, Class<T> clazz) {
|
||||
|
||||
@ -0,0 +1,129 @@
|
||||
package ru.dragonestia.msb3.api.player.defaults;
|
||||
|
||||
import lombok.Setter;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import ru.dragonestia.msb3.api.player.MsbPlayer;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||
import ru.dragonestia.msb3.api.ui.bossbar.KeyedBossBars;
|
||||
import ru.dragonestia.msb3.api.ui.navigator.Navigator;
|
||||
import ru.dragonestia.msb3.api.ui.navigator.Navigators;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphComponentBuilder;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
import ru.dragonestia.msb3.resource.glyph.MinecraftFont;
|
||||
|
||||
public class NavigatorContext extends PlayerContext implements Navigator {
|
||||
|
||||
private final static Component EMPTY = Component.text(" ");
|
||||
|
||||
private BossBar bossBar;
|
||||
private Point target;
|
||||
private String text;
|
||||
private MinecraftFont.Text cachedText;
|
||||
private boolean prevTargetEmpty = true;
|
||||
@Setter private String format = "[ %s ]";
|
||||
@Setter private TextColor textColor = TextColor.color(0xF8FF91);
|
||||
|
||||
public NavigatorContext(MsbPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {}
|
||||
|
||||
@Override
|
||||
public void firstSpawn() {
|
||||
getPlayer().eventNode().addListener(PlayerMoveEvent.class, event -> update());
|
||||
|
||||
bossBar = KeyedBossBars.showText(getPlayer(), "msb3_navigator", EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
target = null;
|
||||
text = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTarget(Point point) {
|
||||
setTarget(point, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setTarget(Point target, String text) {
|
||||
prevTargetEmpty = this.target == null;
|
||||
this.target = target;
|
||||
this.text = text;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTarget() {
|
||||
setTarget(null);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (prevTargetEmpty && target == null) return;
|
||||
|
||||
bossBar.name(render());
|
||||
}
|
||||
|
||||
private Component render() {
|
||||
if (target == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
var builder = new GlyphComponentBuilder();
|
||||
|
||||
// Text
|
||||
if (text != null) {
|
||||
builder.setColorTo(textColor);
|
||||
if (cachedText == null) {
|
||||
cachedText = MinecraftFont.translateByLineNumber(0, format.formatted(text));
|
||||
}
|
||||
builder.append((int) (cachedText.width() / -2.2), cachedText);
|
||||
builder.resetColor();
|
||||
}
|
||||
|
||||
// Arrow
|
||||
builder.append(0, getArrowGlyph());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private GlyphImage getArrowGlyph() {
|
||||
var playerPos = getPlayer().getPosition();
|
||||
var angle = computeAngle(playerPos.asVec(), playerPos.direction(), Vec.fromPoint(target));
|
||||
|
||||
if (!(angle < -2.749) && !(angle >= 2.749)) {
|
||||
if (angle < -1.963) return Navigators.GLYPH_DOWN_RIGHT;
|
||||
if (angle < -1.178) return Navigators.GLYPH_RIGHT;
|
||||
if (angle < -0.393) return Navigators.GLYPH_UP_RIGHT;
|
||||
if (angle < 0.393) return Navigators.GLYPH_UP;
|
||||
if (angle < 1.178) return Navigators.GLYPH_UP_LEFT;
|
||||
if (angle < 1.963) return Navigators.GLYPH_LEFT;
|
||||
if (angle < 2.749) return Navigators.GLYPH_DOWN_LEFT;
|
||||
}
|
||||
return Navigators.GLYPH_DOWN;
|
||||
}
|
||||
|
||||
private double computeAngle(Vec start, Vec direction, Vec destination) {
|
||||
Vec destinationDirection = destination.sub(start);
|
||||
double playerAngle = Math.atan2(direction.z(), direction.x());
|
||||
double locAngle = Math.atan2(destinationDirection.z(), destinationDirection.x());
|
||||
|
||||
double angle;
|
||||
for (angle = playerAngle - locAngle; angle > Math.PI; angle -= (Math.PI * 2D)) {}
|
||||
|
||||
while (angle < -Math.PI) {
|
||||
angle += (Math.PI * 2D);
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package ru.dragonestia.msb3.api.ui.navigator;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
|
||||
public interface Navigator {
|
||||
|
||||
void setTarget(Point target);
|
||||
|
||||
void setTarget(Point target, String text);
|
||||
|
||||
void removeTarget();
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package ru.dragonestia.msb3.api.ui.navigator;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.entity.Player;
|
||||
import ru.dragonestia.msb3.api.player.PlayerContext;
|
||||
import ru.dragonestia.msb3.api.player.defaults.NavigatorContext;
|
||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||
import ru.dragonestia.msb3.resource.Resources;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
|
||||
public class Navigators {
|
||||
|
||||
public final static GlyphImage GLYPH_UP = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/up"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/up.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_UP_RIGHT = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/up_right"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/up_right.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_RIGHT = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/right"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/right.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_DOWN_RIGHT = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/down_right"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/down_right.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_DOWN = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/down"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/down.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_DOWN_LEFT = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/down_left"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/down_left.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_LEFT = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/left"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/left.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public final static GlyphImage GLYPH_UP_LEFT = Resources.createGlyph(
|
||||
Key.key("msb3", "navigator/up_left"),
|
||||
ResourceFromJar.of("glyphs/navigator/arrow/up_left.png"),
|
||||
16,
|
||||
0);
|
||||
|
||||
public static Navigator of(Player player) {
|
||||
return PlayerContext.of(player, NavigatorContext.class);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user