Changed config format. Added serializers. Removed static fields from registry classes

This commit is contained in:
Nanit 2020-11-27 14:19:05 +02:00
parent fa27356bac
commit cc7009caf1
20 changed files with 661 additions and 442 deletions

View File

@ -11,13 +11,15 @@ repositories {
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile group: 'org.yaml', name: 'snakeyaml', version: '1.27'
compile files('libs/napi-configurate-yaml-1.0.jar')
compile group: 'io.netty', name: 'netty-all', version: '4.1.54.Final'
compile group: 'net.kyori', name: 'adventure-nbt', version: '4.1.1'
}
jar {
manifest {
attributes("Main-Class": "ru.nanit.limbo.NanoLimbo")
attributes('Main-Class': 'ru.nanit.limbo.NanoLimbo')
}
from {

Binary file not shown.

View File

@ -1,217 +0,0 @@
package ru.nanit.limbo;
import ru.nanit.limbo.protocol.packets.play.PacketBossBar;
import ru.nanit.limbo.util.Colors;
import ru.nanit.limbo.util.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
public final class LimboConfig {
private static String host;
private static int port;
private static int maxPlayers;
private static String dimensionType;
private static SpawnPosition spawnPosition;
private static IpForwardingType ipForwardingType;
private static long readTimeout;
private static PingData pingData;
private static int debugLevel = 3;
private static JoinMessages joinMessages;
public static void load(Path file) throws IOException {
if (!Files.exists(file)){
Files.copy(NanoLimbo.getResource("/settings.properties"), file);
}
Properties props = new Properties();
props.load(Files.newInputStream(file));
host = props.getProperty("host");
port = Integer.parseInt(props.getProperty("port"));
maxPlayers = Integer.parseInt(props.getProperty("max-players"));
dimensionType = props.getProperty("dimension");
String[] posData = props.getProperty("spawn-position").split(",");
if (posData.length != 3){
throw new IOException("Invalid spawn position. Check it in the settings.properties file");
}
spawnPosition = new SpawnPosition(Double.parseDouble(posData[0]),
Double.parseDouble(posData[1]),
Double.parseDouble(posData[2]));
ipForwardingType = IpForwardingType.valueOf(props.getProperty("ip-forwarding").toUpperCase());
readTimeout = Long.parseLong(props.getProperty("read-timeout"));
pingData = new PingData();
pingData.setVersion(props.getProperty("ping-version"));
pingData.setDescription(Colors.of(props.getProperty("ping-description")));
debugLevel = Integer.parseInt(props.getProperty("debug-level"));
joinMessages = new JoinMessages();
if(props.containsKey("join-message")){
joinMessages.setChatMessage(Colors.of(props.getProperty("join-message")));
}
if(props.containsKey("join-bossbar-text")){
joinMessages.setBossBarText(Colors.of(props.getProperty("join-bossbar-text")));
joinMessages.setBossBarHealth(Float.parseFloat(props.getProperty("join-bossbar-health")));
joinMessages.setBossBarColor(PacketBossBar.Color.valueOf(
props.getProperty("join-bossbar-color").toUpperCase()));
joinMessages.setBossBarDivision(PacketBossBar.Division.valueOf(
props.getProperty("join-bossbar-division").toUpperCase()));
}
}
public static String getHost() {
return host;
}
public static int getPort() {
return port;
}
public static int getMaxPlayers() {
return maxPlayers;
}
public static String getDimensionType() {
return dimensionType;
}
public static SpawnPosition getSpawnPosition() {
return spawnPosition;
}
public static IpForwardingType getIpForwardingType() {
return ipForwardingType;
}
public static long getReadTimeout() {
return readTimeout;
}
public static PingData getPingData() {
return pingData;
}
public static int getDebugLevel() {
return debugLevel;
}
public static JoinMessages getJoinMessages() {
return joinMessages;
}
public enum IpForwardingType {
NONE,
LEGACY,
MODERN
}
public static class SpawnPosition {
private final double x;
private final double y;
private final double z;
public SpawnPosition(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
}
public static class PingData {
private String version;
private String description;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public static class JoinMessages {
private String chatMessage;
private String bossBarText;
private float bossBarHealth;
private PacketBossBar.Color bossBarColor;
private PacketBossBar.Division bossBarDivision;
public String getChatMessage() {
return chatMessage;
}
public void setChatMessage(String chatMessage) {
this.chatMessage = chatMessage;
}
public String getBossBarText() {
return bossBarText;
}
public void setBossBarText(String bossBarText) {
this.bossBarText = bossBarText;
}
public float getBossBarHealth() {
return bossBarHealth;
}
public void setBossBarHealth(float bossBarHealth) {
this.bossBarHealth = bossBarHealth;
}
public PacketBossBar.Color getBossBarColor() {
return bossBarColor;
}
public void setBossBarColor(PacketBossBar.Color bossBarColor) {
this.bossBarColor = bossBarColor;
}
public PacketBossBar.Division getBossBarDivision() {
return bossBarDivision;
}
public void setBossBarDivision(PacketBossBar.Division bossBarDivision) {
this.bossBarDivision = bossBarDivision;
}
}
}

View File

@ -3,8 +3,6 @@ package ru.nanit.limbo;
import ru.nanit.limbo.server.LimboServer;
import ru.nanit.limbo.util.Logger;
import java.io.InputStream;
public final class NanoLimbo {
public static void main(String[] args){
@ -15,7 +13,4 @@ public final class NanoLimbo {
}
}
public static InputStream getResource(String path){
return NanoLimbo.class.getResourceAsStream(path);
}
}

View File

@ -0,0 +1,109 @@
package ru.nanit.limbo.configuration;
import napi.configurate.Configuration;
import napi.configurate.source.ConfigSources;
import napi.configurate.yaml.YamlConfiguration;
import ru.nanit.limbo.server.data.*;
import ru.nanit.limbo.util.Colors;
import java.net.SocketAddress;
import java.nio.file.Path;
public final class LimboConfig {
private final Path root;
private SocketAddress address;
private int maxPlayers;
private PingData pingData;
private String dimensionType;
private Position spawnPosition;
private boolean useJoinMessage;
private boolean useBossBar;
private String joinMessage;
private BossBar bossBar;
private InfoForwarding infoForwarding;
private long readTimeout;
private int debugLevel = 3;
public LimboConfig(Path root){
this.root = root;
}
public void load() throws Exception {
Configuration conf = YamlConfiguration.builder()
.source(ConfigSources.resource("/limbo.yml", this).copyTo(root))
.build();
conf.reload();
address = conf.getNode("bind").getValue(SocketAddress.class);
maxPlayers = conf.getNode("maxPlayers").getInt();
pingData = conf.getNode("ping").getValue(PingData.class);
dimensionType = conf.getNode("dimension").getString();
spawnPosition = conf.getNode("spawnPosition").getValue(Position.class);
useJoinMessage = conf.getNode("joinMessage", "enable").getBoolean();
useBossBar = conf.getNode("bossBar", "enable").getBoolean();
if (useJoinMessage)
joinMessage = Colors.of(conf.getNode("joinMessage", "text").getString());
if (useBossBar)
bossBar = conf.getNode("bossBar").getValue(BossBar.class);
infoForwarding = conf.getNode("infoForwarding").getValue(InfoForwarding.class);
readTimeout = conf.getNode("readTimeout").getLong();
debugLevel = conf.getNode("debugLevel").getInt();
}
public SocketAddress getAddress() {
return address;
}
public int getMaxPlayers() {
return maxPlayers;
}
public PingData getPingData() {
return pingData;
}
public String getDimensionType() {
return dimensionType;
}
public Position getSpawnPosition() {
return spawnPosition;
}
public InfoForwarding getInfoForwarding() {
return infoForwarding;
}
public long getReadTimeout() {
return readTimeout;
}
public int getDebugLevel() {
return debugLevel;
}
public boolean isUseJoinMessage() {
return useJoinMessage;
}
public boolean isUseBossBar() {
return useBossBar;
}
public String getJoinMessage() {
return joinMessage;
}
public BossBar getBossBar() {
return bossBar;
}
}

View File

@ -0,0 +1,31 @@
package ru.nanit.limbo.configuration;
import napi.configurate.data.ConfigNode;
import napi.configurate.serializing.NodeSerializer;
import napi.configurate.serializing.NodeSerializingException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
public class SocketAddressSerializer implements NodeSerializer<SocketAddress> {
@Override
public SocketAddress deserialize(ConfigNode node) {
String ip = node.getNode("ip").getString();
int port = node.getNode("port").getInt();
SocketAddress address;
if (ip == null || ip.isEmpty()){
address = new InetSocketAddress(port);
} else {
address = new InetSocketAddress(ip, port);
}
return address;
}
@Override
public void serialize(SocketAddress socketAddress, ConfigNode configNode) throws NodeSerializingException {
}
}

View File

@ -4,7 +4,7 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.timeout.ReadTimeoutHandler;
import ru.nanit.limbo.LimboConfig;
import ru.nanit.limbo.configuration.LimboConfig;
import ru.nanit.limbo.protocol.pipeline.VarIntFrameDecoder;
import ru.nanit.limbo.protocol.pipeline.PacketDecoder;
import ru.nanit.limbo.protocol.pipeline.PacketEncoder;
@ -25,7 +25,8 @@ public class ClientChannelInitializer extends ChannelInitializer<Channel> {
protected void initChannel(Channel channel) {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("timeout", new ReadTimeoutHandler(LimboConfig.getReadTimeout(), TimeUnit.MILLISECONDS));
pipeline.addLast("timeout", new ReadTimeoutHandler(server.getConfig().getReadTimeout(),
TimeUnit.MILLISECONDS));
pipeline.addLast("frame_decoder", new VarIntFrameDecoder());
pipeline.addLast("frame_encoder", new VarIntLengthEncoder());
pipeline.addLast("decoder", new PacketDecoder());

View File

@ -4,7 +4,6 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import ru.nanit.limbo.LimboConfig;
import ru.nanit.limbo.protocol.packets.login.*;
import ru.nanit.limbo.protocol.packets.play.*;
import ru.nanit.limbo.protocol.pipeline.PacketDecoder;
@ -18,7 +17,6 @@ import ru.nanit.limbo.protocol.registry.Version;
import ru.nanit.limbo.server.LimboServer;
import ru.nanit.limbo.util.Logger;
import ru.nanit.limbo.util.UuidUtil;
import ru.nanit.limbo.world.DimensionRegistry;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
@ -50,7 +48,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (state.equals(State.PLAY)){
server.removeConnection(this);
server.getConnections().removeConnection(this);
Logger.info("Player %s disconnected", this.username);
}
super.channelInactive(ctx);
@ -73,10 +71,11 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
PacketHandshake handshake = (PacketHandshake) packet;
updateState(State.getById(handshake.getNextState()));
clientVersion = handshake.getVersion();
Logger.debug("Pinged from " + handshake.getHost() + ":" + handshake.getPort());
}
if (packet instanceof PacketStatusRequest){
sendPacket(new PacketStatusResponse(server.getConnectionsCount()));
sendPacket(new PacketStatusResponse(server));
}
if (packet instanceof PacketStatusPing){
@ -84,7 +83,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
}
if (packet instanceof PacketLoginStart){
if (server.getConnectionsCount() >= LimboConfig.getMaxPlayers()){
if (server.getConnections().getCount() >= server.getConfig().getMaxPlayers()){
disconnect("Too many players connected");
return;
}
@ -105,7 +104,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
sendPacket(loginSuccess);
updateState(State.PLAY);
server.addConnection(this);
server.getConnections().addConnection(this);
Logger.info("Player %s connected (%s)", this.username, channel.remoteAddress());
sendJoinPackets();
@ -120,7 +119,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
joinGame.setFlat(false);
joinGame.setGameMode(2);
joinGame.setHardcore(false);
joinGame.setMaxPlayers(LimboConfig.getMaxPlayers());
joinGame.setMaxPlayers(server.getConfig().getMaxPlayers());
joinGame.setPreviousGameMode(-1);
joinGame.setReducedDebugInfo(false);
joinGame.setDebug(false);
@ -128,16 +127,16 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
joinGame.setWorldName("minecraft:world");
joinGame.setWorldNames("minecraft:world");
joinGame.setHashedSeed(0);
joinGame.setDimensionCodec(DimensionRegistry.getCodec());
joinGame.setDimension(DimensionRegistry.getDefaultDimension());
joinGame.setDimensionCodec(server.getDimensionRegistry().getCodec());
joinGame.setDimension(server.getDimensionRegistry().getDefaultDimension());
PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook();
positionAndLook.setX(LimboConfig.getSpawnPosition().getX());
positionAndLook.setY(LimboConfig.getSpawnPosition().getY());
positionAndLook.setZ(LimboConfig.getSpawnPosition().getZ());
positionAndLook.setYaw(90.0F);
positionAndLook.setPitch(0.0F);
positionAndLook.setX(server.getConfig().getSpawnPosition().getX());
positionAndLook.setY(server.getConfig().getSpawnPosition().getY());
positionAndLook.setZ(server.getConfig().getSpawnPosition().getZ());
positionAndLook.setYaw(server.getConfig().getSpawnPosition().getYaw());
positionAndLook.setPitch(server.getConfig().getSpawnPosition().getPitch());
positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt());
PacketPlayerInfo info = new PacketPlayerInfo();

View File

@ -2,36 +2,22 @@ package ru.nanit.limbo.protocol.packets.play;
import ru.nanit.limbo.protocol.ByteMessage;
import ru.nanit.limbo.protocol.PacketOut;
import ru.nanit.limbo.server.data.BossBar;
import java.util.UUID;
public class PacketBossBar implements PacketOut {
private UUID uuid;
private String title;
private float health;
private Color color;
private Division division;
private BossBar bossBar;
private int flags;
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public void setTitle(String title) {
this.title = title;
}
public void setHealth(float health) {
this.health = health;
}
public void setColor(Color color) {
this.color = color;
}
public void setDivision(Division division) {
this.division = division;
public void setBossBar(BossBar bossBar) {
this.bossBar = bossBar;
}
public void setFlags(int flags) {
@ -42,43 +28,11 @@ public class PacketBossBar implements PacketOut {
public void encode(ByteMessage msg) {
msg.writeUuid(uuid);
msg.writeVarInt(0); // Create bossbar
msg.writeString(title);
msg.writeFloat(health);
msg.writeVarInt(color.index);
msg.writeVarInt(division.index);
msg.writeString(bossBar.getText());
msg.writeFloat(bossBar.getHealth());
msg.writeVarInt(bossBar.getColor().getIndex());
msg.writeVarInt(bossBar.getDivision().getIndex());
msg.writeByte(flags);
}
public enum Color {
PINK(0),
BLUE(1),
RED(2),
GREEN(3),
YELLOW(4),
PURPLE(5),
WHITE(6);
private final int index;
Color(int index) {
this.index = index;
}
}
public enum Division {
SOLID(0),
DASHES_6(1),
DASHES_10(2),
DASHES_12(3),
DASHES_20(4);
private final int index;
Division(int index) {
this.index = index;
}
}
}

View File

@ -1,27 +1,28 @@
package ru.nanit.limbo.protocol.packets.status;
import ru.nanit.limbo.LimboConfig;
import ru.nanit.limbo.protocol.*;
import ru.nanit.limbo.protocol.registry.Version;
import ru.nanit.limbo.server.LimboServer;
public class PacketStatusResponse implements PacketOut {
private static final String TEMPLATE = "{ \"version\": { \"name\": \"%s\", \"protocol\": %d }, \"players\": { \"max\": %d, \"online\": %d, \"sample\": [] }, \"description\": %s }";
private int online;
private LimboServer server;
public PacketStatusResponse(){ }
public PacketStatusResponse(int online){
this.online = online;
public PacketStatusResponse(LimboServer server){
this.server = server;
}
@Override
public void encode(ByteMessage msg) {
String ver = LimboConfig.getPingData().getVersion();
String desc = LimboConfig.getPingData().getDescription();
String ver = server.getConfig().getPingData().getVersion();
String desc = server.getConfig().getPingData().getDescription();
String json = getResponseJson(ver, Version.getCurrentSupported().getProtocolNumber(),
LimboConfig.getMaxPlayers(), online, desc);
server.getConfig().getMaxPlayers(), server.getConnections().getCount(), desc);
msg.writeString(json);
}

View File

@ -0,0 +1,34 @@
package ru.nanit.limbo.server;
import ru.nanit.limbo.connection.ClientConnection;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public final class Connections {
private final Map<UUID, ClientConnection> connections;
public Connections(){
connections = new ConcurrentHashMap<>();
}
public Collection<ClientConnection> getAllConnections(){
return Collections.unmodifiableCollection(connections.values());
}
public int getCount(){
return connections.size();
}
public void addConnection(ClientConnection connection){
connections.put(connection.getUuid(), connection);
}
public void removeConnection(ClientConnection connection){
connections.remove(connection.getUuid());
}
}

View File

@ -3,40 +3,43 @@ package ru.nanit.limbo.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import ru.nanit.limbo.LimboConfig;
import napi.configurate.serializing.NodeSerializers;
import ru.nanit.limbo.configuration.LimboConfig;
import ru.nanit.limbo.configuration.SocketAddressSerializer;
import ru.nanit.limbo.connection.ClientChannelInitializer;
import ru.nanit.limbo.connection.ClientConnection;
import ru.nanit.limbo.protocol.packets.play.PacketBossBar;
import ru.nanit.limbo.protocol.packets.play.PacketChatMessage;
import ru.nanit.limbo.server.data.*;
import ru.nanit.limbo.util.Logger;
import ru.nanit.limbo.world.DimensionRegistry;
import java.net.SocketAddress;
import java.nio.file.Paths;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public final class LimboServer {
private final Map<UUID, ClientConnection> connections = new ConcurrentHashMap<>();
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private LimboConfig config;
private Connections connections;
private DimensionRegistry dimensionRegistry;
private PacketChatMessage joinMessage;
private PacketBossBar joinBossBar;
public int getConnectionsCount(){
return connections.size();
public LimboConfig getConfig(){
return config;
}
public void addConnection(ClientConnection connection){
connections.put(connection.getUuid(), connection);
public Connections getConnections(){
return connections;
}
public void removeConnection(ClientConnection connection){
connections.remove(connection.getUuid());
public DimensionRegistry getDimensionRegistry() {
return dimensionRegistry;
}
public PacketChatMessage getJoinMessage() {
@ -50,47 +53,54 @@ public final class LimboServer {
public void start() throws Exception {
Logger.info("Starting server...");
LimboConfig.load(Paths.get("./settings.properties"));
DimensionRegistry.init(LimboConfig.getDimensionType());
NodeSerializers.register(SocketAddress.class, new SocketAddressSerializer());
NodeSerializers.register(InfoForwarding.class, new InfoForwarding.Serializer());
NodeSerializers.register(PingData.class, new PingData.Serializer());
NodeSerializers.register(BossBar.class, new BossBar.Serializer());
NodeSerializers.register(Position.class, new Position.Serializer());
initializeInGameData();
config = new LimboConfig(Paths.get("./"));
config.load();
Logger.setLevel(config.getDebugLevel());
dimensionRegistry = new DimensionRegistry();
dimensionRegistry.load(config.getDimensionType());
connections = new Connections();
initInGameData();
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
ServerBootstrap bootstrap = new ServerBootstrap()
new ServerBootstrap()
.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.childHandler(new ClientChannelInitializer(this));
.childHandler(new ClientChannelInitializer(this))
.localAddress(config.getAddress())
.bind();
if (LimboConfig.getHost().isEmpty()){
bootstrap.bind(LimboConfig.getPort());
} else {
bootstrap.bind(LimboConfig.getHost(), LimboConfig.getPort());
}
Logger.info("Server started on %s:%d", LimboConfig.getHost(), LimboConfig.getPort());
Logger.info("Server started on %s", config.getAddress());
}
private void initializeInGameData(){
if (LimboConfig.getJoinMessages().getChatMessage() != null){
private void initInGameData(){
if (config.isUseJoinMessage()){
joinMessage = new PacketChatMessage();
joinMessage.setJsonData(LimboConfig.getJoinMessages().getChatMessage());
joinMessage.setJsonData(config.getJoinMessage());
joinMessage.setPosition(PacketChatMessage.Position.CHAT);
joinMessage.setSender(UUID.randomUUID());
}
if (LimboConfig.getJoinMessages().getBossBarText() != null){
if (config.isUseBossBar()){
joinBossBar = new PacketBossBar();
joinBossBar.setTitle(LimboConfig.getJoinMessages().getBossBarText());
joinBossBar.setHealth(LimboConfig.getJoinMessages().getBossBarHealth());
joinBossBar.setColor(LimboConfig.getJoinMessages().getBossBarColor());
joinBossBar.setDivision(LimboConfig.getJoinMessages().getBossBarDivision());
joinBossBar.setBossBar(config.getBossBar());
joinBossBar.setUuid(UUID.randomUUID());
}
}
private void broadcastKeepAlive(){
connections.values().forEach(ClientConnection::sendKeepAlive);
connections.getAllConnections().forEach(ClientConnection::sendKeepAlive);
}
}

View File

@ -0,0 +1,119 @@
package ru.nanit.limbo.server.data;
import napi.configurate.data.ConfigNode;
import napi.configurate.serializing.NodeSerializer;
import napi.configurate.serializing.NodeSerializingException;
import ru.nanit.limbo.util.Colors;
public class BossBar {
private String text;
private float health;
private Color color;
private Division division;
public String getText() {
return text;
}
public float getHealth() {
return health;
}
public Color getColor() {
return color;
}
public Division getDivision() {
return division;
}
public void setText(String text) {
this.text = text;
}
public void setHealth(float health) {
this.health = health;
}
public void setColor(Color color) {
this.color = color;
}
public void setDivision(Division division) {
this.division = division;
}
public enum Color {
PINK(0),
BLUE(1),
RED(2),
GREEN(3),
YELLOW(4),
PURPLE(5),
WHITE(6);
private final int index;
Color(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
}
public enum Division {
SOLID(0),
DASHES_6(1),
DASHES_10(2),
DASHES_12(3),
DASHES_20(4);
private final int index;
Division(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
}
public static class Serializer implements NodeSerializer<BossBar>{
@Override
public BossBar deserialize(ConfigNode node) throws NodeSerializingException {
BossBar bossBar = new BossBar();
bossBar.setText(Colors.of(node.getNode("text").getString()));
bossBar.setHealth(node.getNode("health").getFloat());
if (bossBar.getHealth() < 0 || bossBar.getHealth() > 1)
throw new NodeSerializingException("BossBar health value must be between 0.0 and 1.0");
try {
bossBar.setColor(Color.valueOf(node.getNode("color").getString().toUpperCase()));
} catch (IllegalArgumentException e){
throw new NodeSerializingException("Invalid bossbar color");
}
try {
bossBar.setDivision(Division.valueOf(node.getNode("division").getString().toUpperCase()));
} catch (IllegalArgumentException e){
throw new NodeSerializingException("Invalid bossbar division");
}
return bossBar;
}
@Override
public void serialize(BossBar bossBar, ConfigNode configNode) {
}
}
}

View File

@ -0,0 +1,53 @@
package ru.nanit.limbo.server.data;
import napi.configurate.data.ConfigNode;
import napi.configurate.serializing.NodeSerializer;
import napi.configurate.serializing.NodeSerializingException;
import java.util.Optional;
public class InfoForwarding {
private Type type;
private String secret;
public Type getType() {
return type;
}
public Optional<String> getSecret() {
return Optional.ofNullable(secret);
}
public enum Type {
NONE,
LEGACY,
MODERN
}
public static class Serializer implements NodeSerializer<InfoForwarding> {
@Override
public InfoForwarding deserialize(ConfigNode node) throws NodeSerializingException {
InfoForwarding forwarding = new InfoForwarding();
try {
forwarding.type = Type.valueOf(node.getNode("type").getString().toUpperCase());
} catch (IllegalArgumentException e){
throw new NodeSerializingException("Undefined info forwarding type");
}
if (forwarding.type == Type.MODERN){
forwarding.secret = node.getNode("secret").getString();
}
return forwarding;
}
@Override
public void serialize(InfoForwarding infoForwarding, ConfigNode configNode) throws NodeSerializingException {
}
}
}

View File

@ -0,0 +1,43 @@
package ru.nanit.limbo.server.data;
import napi.configurate.data.ConfigNode;
import napi.configurate.serializing.NodeSerializer;
import ru.nanit.limbo.util.Colors;
public class PingData {
private String version;
private String description;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public static class Serializer implements NodeSerializer<PingData> {
@Override
public PingData deserialize(ConfigNode node) {
PingData pingData = new PingData();
pingData.setDescription(Colors.of(node.getNode("description").getString()));
pingData.setVersion(Colors.of(node.getNode("version").getString()));
return pingData;
}
@Override
public void serialize(PingData pingData, ConfigNode configNode) {
}
}
}

View File

@ -0,0 +1,72 @@
package ru.nanit.limbo.server.data;
import napi.configurate.data.ConfigNode;
import napi.configurate.serializing.NodeSerializer;
public class Position {
private double x;
private double y;
private double z;
private float yaw;
private float pitch;
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public float getYaw() {
return yaw;
}
public float getPitch() {
return pitch;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setZ(double z) {
this.z = z;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
public static class Serializer implements NodeSerializer<Position> {
@Override
public Position deserialize(ConfigNode node) {
Position position = new Position();
position.setX(node.getNode("x").getDouble());
position.setY(node.getNode("y").getDouble());
position.setZ(node.getNode("z").getDouble());
position.setYaw(node.getNode("yaw").getFloat());
position.setPitch(node.getNode("pitch").getFloat());
return position;
}
@Override
public void serialize(Position position, ConfigNode configNode) {
}
}
}

View File

@ -1,22 +1,25 @@
package ru.nanit.limbo.util;
import ru.nanit.limbo.LimboConfig;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public final class Logger {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("hh:mm:ss");
private static int debugLevel = 3;
private Logger(){}
public static void setLevel(int level){
debugLevel = level;
}
public static void info(Object msg, Object... args){
print(Level.INFO, msg, null, args);
}
public static void info(Object msg, Throwable t, Object... args){
print(Level.INFO, msg, t, args);
public static void debug(Object msg, Object... args){
print(Level.INFO, msg, null, args);
}
public static void warning(Object msg, Object... args){
@ -36,7 +39,7 @@ public final class Logger {
}
public static void print(Level level, Object msg, Throwable t, Object... args){
if (LimboConfig.getDebugLevel() >= level.getIndex()){
if (debugLevel >= level.getIndex()){
System.out.println(String.format("%s: %s", getPrefix(level), String.format(msg.toString(), args)));
if (t != null) t.printStackTrace();
}
@ -52,7 +55,8 @@ public final class Logger {
public enum Level {
INFO ("INFO", 1),
INFO ("INFO", 0),
DEBUG ("DEBUG", 1),
WARNING("WARNING", 2),
ERROR("ERROR", 3);

View File

@ -6,11 +6,55 @@ import ru.nanit.limbo.util.Logger;
public final class DimensionRegistry {
private static CompoundBinaryTag codec;
private static CompoundBinaryTag defaultDimension;
private CompoundBinaryTag defaultDimension;
public static void init(String defaultDimensionName){
CompoundBinaryTag overworld = CompoundBinaryTag.builder()
private CompoundBinaryTag codec;
private CompoundBinaryTag overWorld;
private CompoundBinaryTag theEnd;
private CompoundBinaryTag nether;
public CompoundBinaryTag getCodec(){
return codec;
}
public CompoundBinaryTag getDefaultDimension() {
return defaultDimension;
}
public CompoundBinaryTag getOverWorld() {
return overWorld;
}
public CompoundBinaryTag getTheEnd() {
return theEnd;
}
public CompoundBinaryTag getNether() {
return nether;
}
public void load(String def){
initDimensions();
switch (def.toLowerCase()){
case "overworld":
defaultDimension = overWorld;
break;
case "nether":
defaultDimension = nether;
break;
case "the_end":
defaultDimension = theEnd;
break;
default:
defaultDimension = theEnd;
Logger.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
break;
}
}
private void initDimensions(){
overWorld = CompoundBinaryTag.builder()
.putString("name", "minecraft:overworld")
.putByte("piglin_safe", (byte) 0)
.putByte("natural", (byte) 0)
@ -28,7 +72,7 @@ public final class DimensionRegistry {
.putByte("has_ceiling", (byte) 0)
.build();
CompoundBinaryTag nether = CompoundBinaryTag.builder()
nether = CompoundBinaryTag.builder()
.putString("name", "minecraft:the_nether")
.putByte("piglin_safe", (byte) 0)
.putByte("natural", (byte) 0)
@ -46,7 +90,7 @@ public final class DimensionRegistry {
.putByte("has_ceiling", (byte) 0)
.build();
CompoundBinaryTag theEnd = CompoundBinaryTag.builder()
theEnd = CompoundBinaryTag.builder()
.putString("name", "minecraft:the_end")
.putByte("piglin_safe", (byte) 0)
.putByte("natural", (byte) 0)
@ -64,10 +108,10 @@ public final class DimensionRegistry {
.putByte("has_ceiling", (byte) 0)
.build();
CompoundBinaryTag overworldData = CompoundBinaryTag.builder()
CompoundBinaryTag overWorldData = CompoundBinaryTag.builder()
.putString("name", "minecraft:overworld")
.putInt("id", 2)
.put("element", overworld)
.put("element", overWorld)
.build();
CompoundBinaryTag netherData = CompoundBinaryTag.builder()
@ -111,7 +155,7 @@ public final class DimensionRegistry {
.put("minecraft:dimension_type", CompoundBinaryTag.builder()
.putString("type", "minecraft:dimension_type")
.put("value", ListBinaryTag.builder()
.add(overworldData)
.add(overWorldData)
.add(netherData)
.add(endData)
.build())
@ -123,29 +167,5 @@ public final class DimensionRegistry {
.build())
.build())
.build();
switch (defaultDimensionName.toLowerCase()){
case "overworld":
defaultDimension = overworld;
break;
case "nether":
defaultDimension = nether;
break;
case "the_end":
defaultDimension = theEnd;
break;
default:
defaultDimension = theEnd;
Logger.error("Undefined dimension type: '%s'. Using THE_END as default", defaultDimensionName);
break;
}
}
public static CompoundBinaryTag getCodec(){
return codec;
}
public static CompoundBinaryTag getDefaultDimension() {
return defaultDimension;
}
}

View File

@ -0,0 +1,60 @@
#
# NanoLimbo configuration
#
# Server's host address and port. Set ip empty to use public address
bind:
ip: 'localhost'
port: 65535
# Max amount of players can join to server
maxPlayers: 100
# Server's data in servers list
ping:
description: '{"text": "&9NanoLimbo"}'
version: 'NanoLimbo'
# Available dimensions: OVERWORLD, NETHER, THE_END
dimension: THE_END
# Spawn position in the world
spawnPosition:
x: 0.0
y: 0.0
z: 0.0
yaw: 0.0
pitch: 0.0
# Message sends when player join to server
joinMessage:
enable: true
text: '{"text": "&eWelcome to the Limbo!"}'
# Bossbar sends when player join to server
bossBar:
enable: true
text: '{"text": "Welcome to the Limbo!"}'
health: 1.0
# Available colors: PINK, BLUE, RED, GREEN, YELLOW, PURPLE, WHITE
color: PINK
# Available divisions: SOLID, DASHES_6, DASHES_10, DASHES_12, DASHES_20
division: SOLID
# Player info forwarding support. Available types: NONE, LEGACY, MODERN
# Don't use secret if you not use MODERN type
infoForwarding:
type: LEGACY
secret: '<YOUR_SECRET_HERE>'
# Read timeout for connections in milliseconds
readTimeout: 30000
# Define debug level. On release, i recommend to use 0 level, since
# there are many useless for release information about ping, received packets, etc.
# Levels:
# 0 - Display only useful info
# 1 - Display info and some debug
# 2 - Display info and warnings
# 3 - Display info, warnings, errors
debugLevel: 3

View File

@ -1,71 +0,0 @@
# ======= General Data ======= #
# Server's host address. Set it empty to use public address
host=localhost
# Server's port
port=65535
# Max amount of players can join to server
max-players=100
# Available dimensions: OVERWORLD, NETHER, THE_END
dimension=THE_END
# Spawn position in the world in format x,y,z
spawn-position=0.0,65.0,0.0
# Version string when client version is not compatible with server one
ping-version=NanoLimbo
# Server's description component
ping-description={"text": "&9NanoLimbo"}
# Player info forwarding support. Available types: NONE, LEGACY, MODERN
# MODERN - Velocity native forwarding type.
# LEGACY - BungeeCord forwarding type (Velocity supports it too)
ip-forwarding=LEGACY
# If you use MODERN type of forwarding, enter your secret code here
ip-forwarding-secret=<YOUR_SECRET_HERE>
# Read timeout for connections in milliseconds
read-timeout=30000
# Define debug level. On release, i recommend to use 1 level, since
# there are many useless for release warnings about undefined packets and other.
# Levels:
# 0 - Display nothing
# 1 - Display only useful info
# 2 - Display info and warnings
# 3 - Display info, warnings, errors
debug-level=3
# ======= In-game Data ======= #
# Message when player join to server. Comment this parameter to disable
join-message={"text": "&eWelcome to the Limbo!"}
# Bossbar text. Comment this parameter to disable bossbar
join-bossbar-text={"text": "Welcome to the Limbo!"}
# Bossbar percentage between 0.0 and 1.0 inclusive
join-bossbar-health=1.0
# Available bossbar colors:
# - PINK
# - BLUE
# - RED
# - GREEN
# - YELLOW
# - PURPLE
# - WHITE
join-bossbar-color=PINK
# Available bossbar divisions:
# - SOLID
# - DASHES_6
# - DASHES_10
# - DASHES_12
# - DASHES_20
join-bossbar-division=SOLID