mirror of
https://github.com/Nan1t/NanoLimbo.git
synced 2025-07-13 21:20:12 +02:00
Added spawn position and dimension in condifgration. Added color codes conversion. PlayerInfo packet
This commit is contained in:
parent
e029336cf0
commit
8da830503a
@ -1,6 +1,8 @@
|
|||||||
package ru.nanit.limbo;
|
package ru.nanit.limbo;
|
||||||
|
|
||||||
import ru.nanit.limbo.protocol.packets.play.PacketBossBar;
|
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.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -12,6 +14,8 @@ public final class LimboConfig {
|
|||||||
private static String host;
|
private static String host;
|
||||||
private static int port;
|
private static int port;
|
||||||
private static int maxPlayers;
|
private static int maxPlayers;
|
||||||
|
private static String dimensionType;
|
||||||
|
private static SpawnPosition spawnPosition;
|
||||||
private static IpForwardingType ipForwardingType;
|
private static IpForwardingType ipForwardingType;
|
||||||
private static long readTimeout;
|
private static long readTimeout;
|
||||||
private static PingData pingData;
|
private static PingData pingData;
|
||||||
@ -30,23 +34,36 @@ public final class LimboConfig {
|
|||||||
port = Integer.parseInt(props.getProperty("port"));
|
port = Integer.parseInt(props.getProperty("port"));
|
||||||
|
|
||||||
maxPlayers = Integer.parseInt(props.getProperty("max-players"));
|
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());
|
ipForwardingType = IpForwardingType.valueOf(props.getProperty("ip-forwarding").toUpperCase());
|
||||||
readTimeout = Long.parseLong(props.getProperty("read-timeout"));
|
readTimeout = Long.parseLong(props.getProperty("read-timeout"));
|
||||||
|
|
||||||
pingData = new PingData();
|
pingData = new PingData();
|
||||||
pingData.setVersion(props.getProperty("ping-version"));
|
pingData.setVersion(props.getProperty("ping-version"));
|
||||||
pingData.setDescription(props.getProperty("ping-description"));
|
pingData.setDescription(Colors.of(props.getProperty("ping-description")));
|
||||||
|
|
||||||
debugLevel = Integer.parseInt(props.getProperty("debug-level"));
|
debugLevel = Integer.parseInt(props.getProperty("debug-level"));
|
||||||
|
|
||||||
joinMessages = new JoinMessages();
|
joinMessages = new JoinMessages();
|
||||||
|
|
||||||
if(props.containsKey("join-message")){
|
if(props.containsKey("join-message")){
|
||||||
joinMessages.setChatMessage(props.getProperty("join-message"));
|
joinMessages.setChatMessage(Colors.of(props.getProperty("join-message")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(props.containsKey("join-bossbar-text")){
|
if(props.containsKey("join-bossbar-text")){
|
||||||
joinMessages.setBossBarText(props.getProperty("join-bossbar-text"));
|
joinMessages.setBossBarText(Colors.of(props.getProperty("join-bossbar-text")));
|
||||||
joinMessages.setBossBarHealth(Float.parseFloat(props.getProperty("join-bossbar-health")));
|
joinMessages.setBossBarHealth(Float.parseFloat(props.getProperty("join-bossbar-health")));
|
||||||
joinMessages.setBossBarColor(PacketBossBar.Color.valueOf(
|
joinMessages.setBossBarColor(PacketBossBar.Color.valueOf(
|
||||||
props.getProperty("join-bossbar-color").toUpperCase()));
|
props.getProperty("join-bossbar-color").toUpperCase()));
|
||||||
@ -67,6 +84,14 @@ public final class LimboConfig {
|
|||||||
return maxPlayers;
|
return maxPlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getDimensionType() {
|
||||||
|
return dimensionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpawnPosition getSpawnPosition() {
|
||||||
|
return spawnPosition;
|
||||||
|
}
|
||||||
|
|
||||||
public static IpForwardingType getIpForwardingType() {
|
public static IpForwardingType getIpForwardingType() {
|
||||||
return ipForwardingType;
|
return ipForwardingType;
|
||||||
}
|
}
|
||||||
@ -93,6 +118,31 @@ public final class LimboConfig {
|
|||||||
MODERN
|
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 {
|
public static class PingData {
|
||||||
|
|
||||||
private String version;
|
private String version;
|
||||||
|
@ -38,6 +38,10 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
public ClientConnection(Channel channel, LimboServer server){
|
public ClientConnection(Channel channel, LimboServer server){
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
@ -125,19 +129,26 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
|||||||
joinGame.setWorldNames("minecraft:world");
|
joinGame.setWorldNames("minecraft:world");
|
||||||
joinGame.setHashedSeed(0);
|
joinGame.setHashedSeed(0);
|
||||||
joinGame.setDimensionCodec(DimensionRegistry.getCodec());
|
joinGame.setDimensionCodec(DimensionRegistry.getCodec());
|
||||||
joinGame.setDimension(DimensionRegistry.getDimension());
|
joinGame.setDimension(DimensionRegistry.getDefaultDimension());
|
||||||
|
|
||||||
PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook();
|
PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook();
|
||||||
|
|
||||||
positionAndLook.setX(0.0);
|
positionAndLook.setX(LimboConfig.getSpawnPosition().getX());
|
||||||
positionAndLook.setY(0.0);
|
positionAndLook.setY(LimboConfig.getSpawnPosition().getY());
|
||||||
positionAndLook.setZ(0.0);
|
positionAndLook.setZ(LimboConfig.getSpawnPosition().getZ());
|
||||||
positionAndLook.setYaw(90.0F);
|
positionAndLook.setYaw(90.0F);
|
||||||
positionAndLook.setPitch(0.0F);
|
positionAndLook.setPitch(0.0F);
|
||||||
positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt());
|
positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt());
|
||||||
|
|
||||||
|
PacketPlayerInfo info = new PacketPlayerInfo();
|
||||||
|
|
||||||
|
info.setConnection(this);
|
||||||
|
info.setGameMode(2);
|
||||||
|
|
||||||
sendPacket(joinGame);
|
sendPacket(joinGame);
|
||||||
sendPacket(positionAndLook);
|
sendPacket(positionAndLook);
|
||||||
|
sendPacket(info);
|
||||||
|
|
||||||
sendKeepAlive();
|
sendKeepAlive();
|
||||||
|
|
||||||
if (server.getJoinMessage() != null){
|
if (server.getJoinMessage() != null){
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package ru.nanit.limbo.protocol.packets.play;
|
||||||
|
|
||||||
|
import ru.nanit.limbo.connection.ClientConnection;
|
||||||
|
import ru.nanit.limbo.protocol.ByteMessage;
|
||||||
|
import ru.nanit.limbo.protocol.PacketOut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This packet wrapper used only for ADD_PLAYER action
|
||||||
|
*/
|
||||||
|
public class PacketPlayerInfo implements PacketOut {
|
||||||
|
|
||||||
|
private int gameMode;
|
||||||
|
private ClientConnection connection;
|
||||||
|
|
||||||
|
public void setConnection(ClientConnection connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGameMode(int gameMode) {
|
||||||
|
this.gameMode = gameMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ByteMessage msg) {
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
msg.writeVarInt(1);
|
||||||
|
msg.writeUuid(connection.getUuid());
|
||||||
|
msg.writeString(connection.getUsername());
|
||||||
|
msg.writeVarInt(0);
|
||||||
|
msg.writeVarInt(gameMode);
|
||||||
|
msg.writeVarInt(60);
|
||||||
|
msg.writeBoolean(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -42,6 +42,7 @@ public enum State {
|
|||||||
clientBound.register(0x1F, PacketKeepAlive::new);
|
clientBound.register(0x1F, PacketKeepAlive::new);
|
||||||
clientBound.register(0x0E, PacketChatMessage::new);
|
clientBound.register(0x0E, PacketChatMessage::new);
|
||||||
clientBound.register(0x0C, PacketBossBar::new);
|
clientBound.register(0x0C, PacketBossBar::new);
|
||||||
|
clientBound.register(0x32, PacketPlayerInfo::new);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,54 +87,4 @@ public enum State {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Temporary don't needed
|
|
||||||
|
|
||||||
public static class PacketVersionRegistry {
|
|
||||||
|
|
||||||
private final Map<Version, PacketIdRegistry<?>> MAPPINGS = new HashMap<>();
|
|
||||||
|
|
||||||
public PacketIdRegistry<?> getRegistry(Version version){
|
|
||||||
PacketIdRegistry<?> registry = MAPPINGS.get(version);
|
|
||||||
return registry != null ? registry : MAPPINGS.get(version.getClosest(MAPPINGS.keySet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Packet> void register(Version version, int packetId, Supplier<T> supplier){
|
|
||||||
PacketIdRegistry<T> registry = (PacketIdRegistry<T>) MAPPINGS.computeIfAbsent(version, PacketIdRegistry::new);
|
|
||||||
registry.register(packetId, supplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PacketIdRegistry<T extends Packet> {
|
|
||||||
|
|
||||||
private final Version version;
|
|
||||||
private final Map<Integer, Supplier<T>> packetsById = new HashMap<>();
|
|
||||||
private final Map<Class<?>, Integer> packetIdByClass = new HashMap<>();
|
|
||||||
|
|
||||||
public PacketIdRegistry(Version version){
|
|
||||||
this.version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Version getVersion(){
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Packet getPacket(int packetId){
|
|
||||||
Supplier<T> supplier = packetsById.get(packetId);
|
|
||||||
return supplier == null ? null : supplier.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPacketId(Class<?> packetClass){
|
|
||||||
return packetIdByClass.getOrDefault(packetClass, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(int packetId, Supplier<T> supplier){
|
|
||||||
packetsById.put(packetId, supplier);
|
|
||||||
packetIdByClass.put(supplier.get().getClass(), packetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public final class LimboServer {
|
|||||||
Logger.info("Starting server...");
|
Logger.info("Starting server...");
|
||||||
|
|
||||||
LimboConfig.load(Paths.get("./settings.properties"));
|
LimboConfig.load(Paths.get("./settings.properties"));
|
||||||
DimensionRegistry.init();
|
DimensionRegistry.init(LimboConfig.getDimensionType());
|
||||||
|
|
||||||
initializeInGameData();
|
initializeInGameData();
|
||||||
|
|
||||||
|
14
src/main/java/ru/nanit/limbo/util/Colors.java
Normal file
14
src/main/java/ru/nanit/limbo/util/Colors.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package ru.nanit.limbo.util;
|
||||||
|
|
||||||
|
public final class Colors {
|
||||||
|
|
||||||
|
private static final char CHAR_FROM = '\u0026';
|
||||||
|
private static final char CHAR_TO = '\u00A7';
|
||||||
|
|
||||||
|
private Colors(){}
|
||||||
|
|
||||||
|
public static String of(String text){
|
||||||
|
return text.replace(CHAR_FROM, CHAR_TO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,14 +2,51 @@ package ru.nanit.limbo.world;
|
|||||||
|
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.nbt.ListBinaryTag;
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
|
import ru.nanit.limbo.util.Logger;
|
||||||
|
|
||||||
public final class DimensionRegistry {
|
public final class DimensionRegistry {
|
||||||
|
|
||||||
private static CompoundBinaryTag CODEC;
|
private static CompoundBinaryTag codec;
|
||||||
private static CompoundBinaryTag DIMENSION;
|
private static CompoundBinaryTag defaultDimension;
|
||||||
|
|
||||||
public static void init(){
|
public static void init(String defaultDimensionName){
|
||||||
DIMENSION = CompoundBinaryTag.builder()
|
CompoundBinaryTag overworld = CompoundBinaryTag.builder()
|
||||||
|
.putString("name", "minecraft:overworld")
|
||||||
|
.putByte("piglin_safe", (byte) 0)
|
||||||
|
.putByte("natural", (byte) 0)
|
||||||
|
.putFloat("ambient_light", 0.0F)
|
||||||
|
.putString("infiniburn", "minecraft:infiniburn_overworld")
|
||||||
|
.putByte("respawn_anchor_works", (byte) 0)
|
||||||
|
.putByte("has_skylight", (byte) 0)
|
||||||
|
.putByte("bed_works", (byte) 0)
|
||||||
|
.putString("effects", "minecraft:overworld")
|
||||||
|
.putLong("fixed_time", 6000L)
|
||||||
|
.putByte("has_raids", (byte) 1)
|
||||||
|
.putInt("logical_height", 256)
|
||||||
|
.putDouble("coordinate_scale", 1.0)
|
||||||
|
.putByte("ultrawarm", (byte) 0)
|
||||||
|
.putByte("has_ceiling", (byte) 0)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CompoundBinaryTag nether = CompoundBinaryTag.builder()
|
||||||
|
.putString("name", "minecraft:the_nether")
|
||||||
|
.putByte("piglin_safe", (byte) 0)
|
||||||
|
.putByte("natural", (byte) 0)
|
||||||
|
.putFloat("ambient_light", 0.0F)
|
||||||
|
.putString("infiniburn", "minecraft:infiniburn_nether")
|
||||||
|
.putByte("respawn_anchor_works", (byte) 0)
|
||||||
|
.putByte("has_skylight", (byte) 0)
|
||||||
|
.putByte("bed_works", (byte) 0)
|
||||||
|
.putString("effects", "minecraft:the_nether")
|
||||||
|
.putLong("fixed_time", 18000L)
|
||||||
|
.putByte("has_raids", (byte) 1)
|
||||||
|
.putInt("logical_height", 128)
|
||||||
|
.putDouble("coordinate_scale", 1.0)
|
||||||
|
.putByte("ultrawarm", (byte) 0)
|
||||||
|
.putByte("has_ceiling", (byte) 0)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CompoundBinaryTag theEnd = CompoundBinaryTag.builder()
|
||||||
.putString("name", "minecraft:the_end")
|
.putString("name", "minecraft:the_end")
|
||||||
.putByte("piglin_safe", (byte) 0)
|
.putByte("piglin_safe", (byte) 0)
|
||||||
.putByte("natural", (byte) 0)
|
.putByte("natural", (byte) 0)
|
||||||
@ -27,10 +64,22 @@ public final class DimensionRegistry {
|
|||||||
.putByte("has_ceiling", (byte) 0)
|
.putByte("has_ceiling", (byte) 0)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
CompoundBinaryTag dimensionData = CompoundBinaryTag.builder()
|
CompoundBinaryTag overworldData = CompoundBinaryTag.builder()
|
||||||
|
.putString("name", "minecraft:overworld")
|
||||||
|
.putInt("id", 2)
|
||||||
|
.put("element", overworld)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CompoundBinaryTag netherData = CompoundBinaryTag.builder()
|
||||||
|
.putString("name", "minecraft:the_nether")
|
||||||
|
.putInt("id", 2)
|
||||||
|
.put("element", nether)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CompoundBinaryTag endData = CompoundBinaryTag.builder()
|
||||||
.putString("name", "minecraft:the_end")
|
.putString("name", "minecraft:the_end")
|
||||||
.putInt("id", 2)
|
.putInt("id", 2)
|
||||||
.put("element", DIMENSION)
|
.put("element", theEnd)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
CompoundBinaryTag plains = CompoundBinaryTag.builder()
|
CompoundBinaryTag plains = CompoundBinaryTag.builder()
|
||||||
@ -58,11 +107,13 @@ public final class DimensionRegistry {
|
|||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
CODEC = CompoundBinaryTag.builder()
|
codec = CompoundBinaryTag.builder()
|
||||||
.put("minecraft:dimension_type", CompoundBinaryTag.builder()
|
.put("minecraft:dimension_type", CompoundBinaryTag.builder()
|
||||||
.putString("type", "minecraft:dimension_type")
|
.putString("type", "minecraft:dimension_type")
|
||||||
.put("value", ListBinaryTag.builder()
|
.put("value", ListBinaryTag.builder()
|
||||||
.add(dimensionData)
|
.add(overworldData)
|
||||||
|
.add(netherData)
|
||||||
|
.add(endData)
|
||||||
.build())
|
.build())
|
||||||
.build())
|
.build())
|
||||||
.put("minecraft:worldgen/biome", CompoundBinaryTag.builder()
|
.put("minecraft:worldgen/biome", CompoundBinaryTag.builder()
|
||||||
@ -72,14 +123,29 @@ public final class DimensionRegistry {
|
|||||||
.build())
|
.build())
|
||||||
.build())
|
.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(){
|
public static CompoundBinaryTag getCodec(){
|
||||||
return CODEC;
|
return codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompoundBinaryTag getDimension(){
|
public static CompoundBinaryTag getDefaultDimension() {
|
||||||
return DIMENSION;
|
return defaultDimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,17 @@ port=65535
|
|||||||
# Max amount of players can join to server
|
# Max amount of players can join to server
|
||||||
max-players=100
|
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
|
# Version string when client version is not compatible with server one
|
||||||
ping-version=NanoLimbo
|
ping-version=NanoLimbo
|
||||||
|
|
||||||
# Server's description component
|
# Server's description component
|
||||||
ping-description={"text": "NanoLimbo"}
|
ping-description={"text": "&9NanoLimbo"}
|
||||||
|
|
||||||
# Player info forwarding support. Available types: NONE, LEGACY, MODERN
|
# Player info forwarding support. Available types: NONE, LEGACY, MODERN
|
||||||
# MODERN - Velocity native forwarding type.
|
# MODERN - Velocity native forwarding type.
|
||||||
@ -40,7 +46,7 @@ debug-level=3
|
|||||||
# ======= In-game Data ======= #
|
# ======= In-game Data ======= #
|
||||||
|
|
||||||
# Message when player join to server. Comment this parameter to disable
|
# Message when player join to server. Comment this parameter to disable
|
||||||
join-message={"text": "Welcome to the Limbo!"}
|
join-message={"text": "&eWelcome to the Limbo!"}
|
||||||
|
|
||||||
# Bossbar text. Comment this parameter to disable bossbar
|
# Bossbar text. Comment this parameter to disable bossbar
|
||||||
join-bossbar-text={"text": "Welcome to the Limbo!"}
|
join-bossbar-text={"text": "Welcome to the Limbo!"}
|
||||||
@ -56,7 +62,7 @@ join-bossbar-health=1.0
|
|||||||
# - YELLOW
|
# - YELLOW
|
||||||
# - PURPLE
|
# - PURPLE
|
||||||
# - WHITE
|
# - WHITE
|
||||||
join-bossbar-color=RED
|
join-bossbar-color=PINK
|
||||||
|
|
||||||
# Available bossbar divisions:
|
# Available bossbar divisions:
|
||||||
# - SOLID
|
# - SOLID
|
||||||
|
Loading…
x
Reference in New Issue
Block a user