forked from BLOCKFANTASY/LOOHP-Limbo
Minecraft 1.19.3
This commit is contained in:
parent
c720a0fd67
commit
50fd145d77
2
pom.xml
2
pom.xml
|
|
@ -136,7 +136,7 @@
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<finalName>${project.artifactId}-${project.version}-1.19.2</finalName>
|
<finalName>${project.artifactId}-${project.version}-1.19.3</finalName>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,8 @@ public class Limbo {
|
||||||
|
|
||||||
//===========================
|
//===========================
|
||||||
|
|
||||||
public final String SERVER_IMPLEMENTATION_VERSION = "1.19.2";
|
public final String SERVER_IMPLEMENTATION_VERSION = "1.19.3";
|
||||||
public final int SERVER_IMPLEMENTATION_PROTOCOL = 760;
|
public final int SERVER_IMPLEMENTATION_PROTOCOL = 761;
|
||||||
public final String LIMBO_IMPLEMENTATION_VERSION;
|
public final String LIMBO_IMPLEMENTATION_VERSION;
|
||||||
|
|
||||||
private AtomicBoolean isRunning;
|
private AtomicBoolean isRunning;
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,12 @@ import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.HashSet;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ServerProperties {
|
public class ServerProperties {
|
||||||
|
|
@ -77,7 +77,7 @@ public class ServerProperties {
|
||||||
private double ticksPerSecond;
|
private double ticksPerSecond;
|
||||||
private boolean handshakeVerbose;
|
private boolean handshakeVerbose;
|
||||||
private boolean enforceWhitelist;
|
private boolean enforceWhitelist;
|
||||||
private Set<UUID> whitelist;
|
private Map<UUID, String> whitelist;
|
||||||
|
|
||||||
private String resourcePackSHA1;
|
private String resourcePackSHA1;
|
||||||
private String resourcePackLink;
|
private String resourcePackLink;
|
||||||
|
|
@ -191,20 +191,26 @@ public class ServerProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceWhitelist = Boolean.parseBoolean(prop.getProperty("enforce-whitelist"));
|
enforceWhitelist = Boolean.parseBoolean(prop.getProperty("enforce-whitelist"));
|
||||||
if (enforceWhitelist) {
|
reloadWhitelist();
|
||||||
reloadWhitelist();
|
|
||||||
}
|
|
||||||
|
|
||||||
Limbo.getInstance().getConsole().sendMessage("Loaded server.properties");
|
Limbo.getInstance().getConsole().sendMessage("Loaded server.properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadWhitelist() {
|
public void reloadWhitelist() {
|
||||||
Console console = Limbo.getInstance().getConsole();
|
Console console = Limbo.getInstance().getConsole();
|
||||||
|
File whitelistFile = new File("whitelist.json");
|
||||||
whitelist = new HashSet<>();
|
if (!whitelistFile.exists()) {
|
||||||
|
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(whitelistFile.toPath())))) {
|
||||||
|
pw.println("[]");
|
||||||
|
pw.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
whitelist = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
JSONParser parser = new JSONParser();
|
JSONParser parser = new JSONParser();
|
||||||
Object obj = parser.parse(new InputStreamReader(Files.newInputStream(new File("whitelist.json").toPath()), StandardCharsets.UTF_8));
|
Object obj = parser.parse(new InputStreamReader(Files.newInputStream(whitelistFile.toPath()), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
if (!(obj instanceof JSONArray)) {
|
if (!(obj instanceof JSONArray)) {
|
||||||
console.sendMessage("whitelist: expected [] got {}");
|
console.sendMessage("whitelist: expected [] got {}");
|
||||||
|
|
@ -231,8 +237,9 @@ public class ServerProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
String uuidStr = (String) o;
|
String uuidStr = (String) o;
|
||||||
UUID allowedUuid = UUID.fromString(uuidStr);
|
UUID uuid = UUID.fromString(uuidStr);
|
||||||
whitelist.add(allowedUuid);
|
String name = element.containsKey("name") ? (String) element.get("name") : null;
|
||||||
|
whitelist.put(uuid, name);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
@ -352,7 +359,7 @@ public class ServerProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean uuidWhitelisted(UUID uuid) {
|
public boolean uuidWhitelisted(UUID uuid) {
|
||||||
return whitelist.contains(uuid);
|
return whitelist.containsKey(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getResourcePackLink() {
|
public String getResourcePackLink() {
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ public class Channel implements AutoCloseable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void close() throws Exception {
|
public synchronized void close() throws Exception {
|
||||||
if (valid.compareAndSet(false, true)) {
|
if (valid.compareAndSet(true, false)) {
|
||||||
input.close();
|
input.close();
|
||||||
output.close();
|
output.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ package com.loohp.limbo.network;
|
||||||
|
|
||||||
import com.loohp.limbo.Limbo;
|
import com.loohp.limbo.Limbo;
|
||||||
import com.loohp.limbo.events.player.PlayerJoinEvent;
|
import com.loohp.limbo.events.player.PlayerJoinEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerSpawnEvent;
|
|
||||||
import com.loohp.limbo.events.player.PlayerLoginEvent;
|
import com.loohp.limbo.events.player.PlayerLoginEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerMoveEvent;
|
import com.loohp.limbo.events.player.PlayerMoveEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerQuitEvent;
|
import com.loohp.limbo.events.player.PlayerQuitEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerResourcePackStatusEvent;
|
import com.loohp.limbo.events.player.PlayerResourcePackStatusEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent;
|
import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent;
|
||||||
|
import com.loohp.limbo.events.player.PlayerSpawnEvent;
|
||||||
import com.loohp.limbo.events.player.PluginMessageEvent;
|
import com.loohp.limbo.events.player.PluginMessageEvent;
|
||||||
import com.loohp.limbo.events.status.StatusPingEvent;
|
import com.loohp.limbo.events.status.StatusPingEvent;
|
||||||
import com.loohp.limbo.file.ServerProperties;
|
import com.loohp.limbo.file.ServerProperties;
|
||||||
|
|
@ -88,7 +88,6 @@ import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse;
|
||||||
import com.loohp.limbo.utils.NamespacedKey;
|
import com.loohp.limbo.utils.NamespacedKey;
|
||||||
import com.loohp.limbo.world.BlockPosition;
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
import com.loohp.limbo.world.World;
|
import com.loohp.limbo.world.World;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
@ -104,11 +103,14 @@ import java.io.DataInput;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
@ -121,8 +123,6 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
public class ClientConnection extends Thread {
|
public class ClientConnection extends Thread {
|
||||||
|
|
||||||
|
|
@ -429,7 +429,7 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
boolean bungeeGuardFound = false;
|
boolean bungeeGuardFound = false;
|
||||||
|
|
||||||
if (skinData != "") {
|
if (!skinData.equals("")) {
|
||||||
JSONArray skinJson = (JSONArray) new JSONParser().parse(skinData);
|
JSONArray skinJson = (JSONArray) new JSONParser().parse(skinData);
|
||||||
|
|
||||||
for (Object obj : skinJson) {
|
for (Object obj : skinJson) {
|
||||||
|
|
@ -460,10 +460,10 @@ public class ClientConnection extends Thread {
|
||||||
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
|
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int messageId = this.random.nextInt();
|
int messageId = this.random.nextInt();
|
||||||
while (clientSocket.isConnected()) {
|
while (clientSocket.isConnected()) {
|
||||||
PacketIn packetIn = channel.readPacket();
|
PacketIn packetIn = channel.readPacket();
|
||||||
|
|
||||||
if (packetIn instanceof PacketLoginInLoginStart) {
|
if (packetIn instanceof PacketLoginInLoginStart) {
|
||||||
PacketLoginInLoginStart start = (PacketLoginInLoginStart) packetIn;
|
PacketLoginInLoginStart start = (PacketLoginInLoginStart) packetIn;
|
||||||
String username = start.getUsername();
|
String username = start.getUsername();
|
||||||
|
|
@ -474,7 +474,10 @@ public class ClientConnection extends Thread {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID uuid = isBungeecord || isBungeeGuard ? bungeeUUID : UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
|
UUID uuid = isBungeecord || isBungeeGuard ? bungeeUUID : (start.hasUniqueId() ? start.getUniqueId() : null);
|
||||||
|
if (uuid == null) {
|
||||||
|
uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
if (!properties.enforceWhitelist() && properties.uuidWhitelisted(uuid)) {
|
if (!properties.enforceWhitelist() && properties.uuidWhitelisted(uuid)) {
|
||||||
disconnectDuringLogin(TextComponent.fromLegacyText("You are not whitelisted on the server"));
|
disconnectDuringLogin(TextComponent.fromLegacyText("You are not whitelisted on the server"));
|
||||||
|
|
@ -489,7 +492,6 @@ public class ClientConnection extends Thread {
|
||||||
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
||||||
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
||||||
Limbo.getInstance().addPlayer(player);
|
Limbo.getInstance().addPlayer(player);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
|
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
|
||||||
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
|
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
|
||||||
|
|
@ -546,18 +548,18 @@ public class ClientConnection extends Thread {
|
||||||
PlayerSpawnEvent spawnEvent = Limbo.getInstance().getEventsManager().callEvent(new PlayerSpawnEvent(player, worldSpawn));
|
PlayerSpawnEvent spawnEvent = Limbo.getInstance().getEventsManager().callEvent(new PlayerSpawnEvent(player, worldSpawn));
|
||||||
worldSpawn = spawnEvent.getSpawnLocation();
|
worldSpawn = spawnEvent.getSpawnLocation();
|
||||||
World world = worldSpawn.getWorld();
|
World world = worldSpawn.getWorld();
|
||||||
|
|
||||||
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, 8, properties.isReducedDebugInfo(), true, false, true);
|
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, 8, properties.isReducedDebugInfo(), true, false, true);
|
||||||
sendPacket(join);
|
sendPacket(join);
|
||||||
Limbo.getInstance().getUnsafe().setPlayerGameModeSilently(player, properties.getDefaultGamemode());
|
Limbo.getInstance().getUnsafe().setPlayerGameModeSilently(player, properties.getDefaultGamemode());
|
||||||
|
|
||||||
ByteArrayOutputStream brandOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream brandOut = new ByteArrayOutputStream();
|
||||||
DataTypeIO.writeString(new DataOutputStream(brandOut), properties.getServerModName(), StandardCharsets.UTF_8);
|
DataTypeIO.writeString(new DataOutputStream(brandOut), properties.getServerModName(), StandardCharsets.UTF_8);
|
||||||
sendPluginMessage(BRAND_ANNOUNCE_CHANNEL, brandOut.toByteArray());
|
sendPluginMessage(BRAND_ANNOUNCE_CHANNEL, brandOut.toByteArray());
|
||||||
|
|
||||||
SkinResponse skinresponce = (isVelocityModern || isBungeeGuard || isBungeecord) && forwardedSkin != null ? forwardedSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
SkinResponse skinresponce = (isVelocityModern || isBungeeGuard || isBungeecord) && forwardedSkin != null ? forwardedSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
||||||
PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null;
|
PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null;
|
||||||
PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(PlayerInfoAction.ADD_PLAYER, player.getUniqueId(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), Optional.ofNullable(skin), properties.getDefaultGamemode(), 0, false, Optional.empty()));
|
PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(EnumSet.of(PlayerInfoAction.ADD_PLAYER, PlayerInfoAction.UPDATE_GAME_MODE, PlayerInfoAction.UPDATE_LISTED, PlayerInfoAction.UPDATE_LATENCY, PlayerInfoAction.UPDATE_DISPLAY_NAME), player.getUniqueId(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), true, Optional.ofNullable(skin), properties.getDefaultGamemode(), 0, false, Optional.empty()));
|
||||||
sendPacket(info);
|
sendPacket(info);
|
||||||
|
|
||||||
Set<PlayerAbilityFlags> flags = new HashSet<>();
|
Set<PlayerAbilityFlags> flags = new HashSet<>();
|
||||||
|
|
@ -569,7 +571,7 @@ public class ClientConnection extends Thread {
|
||||||
}
|
}
|
||||||
PacketPlayOutPlayerAbilities abilities = new PacketPlayOutPlayerAbilities(0.05F, 0.1F, flags.toArray(new PlayerAbilityFlags[flags.size()]));
|
PacketPlayOutPlayerAbilities abilities = new PacketPlayOutPlayerAbilities(0.05F, 0.1F, flags.toArray(new PlayerAbilityFlags[flags.size()]));
|
||||||
sendPacket(abilities);
|
sendPacket(abilities);
|
||||||
|
|
||||||
String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "<ip address withheld>") + ":" + clientSocket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")";
|
String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "<ip address withheld>") + ":" + clientSocket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")";
|
||||||
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!");
|
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!");
|
||||||
|
|
||||||
|
|
@ -590,14 +592,14 @@ public class ClientConnection extends Thread {
|
||||||
player.getDataWatcher().update();
|
player.getDataWatcher().update();
|
||||||
PacketPlayOutEntityMetadata show = new PacketPlayOutEntityMetadata(player, false, Player.class.getDeclaredField("skinLayers"));
|
PacketPlayOutEntityMetadata show = new PacketPlayOutEntityMetadata(player, false, Player.class.getDeclaredField("skinLayers"));
|
||||||
sendPacket(show);
|
sendPacket(show);
|
||||||
|
|
||||||
Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player));
|
Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player));
|
||||||
|
|
||||||
if (properties.isAllowFlight()) {
|
if (properties.isAllowFlight()) {
|
||||||
PacketPlayOutGameState state = new PacketPlayOutGameState(3, player.getGamemode().getId());
|
PacketPlayOutGameState state = new PacketPlayOutGameState(3, player.getGamemode().getId());
|
||||||
sendPacket(state);
|
sendPacket(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RESOURCEPACK CODE CONRIBUTED BY GAMERDUCK123
|
// RESOURCEPACK CODE CONRIBUTED BY GAMERDUCK123
|
||||||
if (!properties.getResourcePackLink().equalsIgnoreCase("")) {
|
if (!properties.getResourcePackLink().equalsIgnoreCase("")) {
|
||||||
if (!properties.getResourcePackSHA1().equalsIgnoreCase("")) {
|
if (!properties.getResourcePackSHA1().equalsIgnoreCase("")) {
|
||||||
|
|
@ -610,16 +612,18 @@ public class ClientConnection extends Thread {
|
||||||
} else {
|
} else {
|
||||||
//RESOURCEPACK NOT ENABLED
|
//RESOURCEPACK NOT ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
// PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123
|
// PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123
|
||||||
player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter());
|
player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter());
|
||||||
|
|
||||||
ready = true;
|
ready = true;
|
||||||
|
|
||||||
keepAliveTask = new TimerTask() {
|
keepAliveTask = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (ready) {
|
if (state.equals(ClientState.DISCONNECTED)) {
|
||||||
|
this.cancel();
|
||||||
|
} else if (ready && state.equals(ClientState.PLAY)) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (now - getLastPacketTimestamp() > 15000) {
|
if (now - getLastPacketTimestamp() > 15000) {
|
||||||
PacketPlayOutKeepAlive keepAlivePacket = new PacketPlayOutKeepAlive(now);
|
PacketPlayOutKeepAlive keepAlivePacket = new PacketPlayOutKeepAlive(now);
|
||||||
|
|
@ -629,13 +633,11 @@ public class ClientConnection extends Thread {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.cancel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
new Timer().schedule(keepAliveTask, 5000, 10000);
|
new Timer().schedule(keepAliveTask, 5000, 10000);
|
||||||
|
|
||||||
while (clientSocket.isConnected()) {
|
while (clientSocket.isConnected()) {
|
||||||
try {
|
try {
|
||||||
CheckedBiConsumer<PlayerMoveEvent, Location, IOException> processMoveEvent = (event, originalTo) -> {
|
CheckedBiConsumer<PlayerMoveEvent, Location, IOException> processMoveEvent = (event, originalTo) -> {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
public class PacketHandshakingIn extends PacketIn {
|
public class PacketHandshakingIn extends PacketIn {
|
||||||
|
|
||||||
public static enum HandshakeType {
|
public enum HandshakeType {
|
||||||
STATUS(1),
|
STATUS(1),
|
||||||
LOGIN(2);
|
LOGIN(2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,15 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
public class PacketLoginInLoginStart extends PacketIn {
|
public class PacketLoginInLoginStart extends PacketIn {
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
|
private Optional<UUID> uuid;
|
||||||
|
|
||||||
public PacketLoginInLoginStart(String username) {
|
public PacketLoginInLoginStart(String username) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
|
@ -35,13 +38,10 @@ public class PacketLoginInLoginStart extends PacketIn {
|
||||||
|
|
||||||
public PacketLoginInLoginStart(DataInputStream in) throws IOException {
|
public PacketLoginInLoginStart(DataInputStream in) throws IOException {
|
||||||
this.username = DataTypeIO.readString(in, StandardCharsets.UTF_8);
|
this.username = DataTypeIO.readString(in, StandardCharsets.UTF_8);
|
||||||
boolean hasSigData = in.readBoolean();
|
if (in.readBoolean()) {
|
||||||
if (hasSigData) {
|
this.uuid = Optional.of(DataTypeIO.readUUID(in));
|
||||||
in.readLong();
|
} else {
|
||||||
int publicKeyLength = DataTypeIO.readVarInt(in);
|
this.uuid = Optional.empty();
|
||||||
in.readFully(new byte[publicKeyLength]);
|
|
||||||
int signatureLength = DataTypeIO.readVarInt(in);
|
|
||||||
in.readFully(new byte[signatureLength]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,4 +49,11 @@ public class PacketLoginInLoginStart extends PacketIn {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasUniqueId() {
|
||||||
|
return uuid.isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return uuid.orElse(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,10 +137,10 @@ public class PacketPlayOutLogin extends PacketOut {
|
||||||
output.writeInt(entityId);
|
output.writeInt(entityId);
|
||||||
output.writeBoolean(isHardcore);
|
output.writeBoolean(isHardcore);
|
||||||
output.writeByte((byte) gamemode.getId());
|
output.writeByte((byte) gamemode.getId());
|
||||||
output.writeByte((byte) gamemode.getId());
|
output.writeByte(-1);
|
||||||
DataTypeIO.writeVarInt(output, worlds.size());
|
DataTypeIO.writeVarInt(output, worlds.size());
|
||||||
for (int u = 0; u < worlds.size(); u++) {
|
for (World world : worlds) {
|
||||||
DataTypeIO.writeString(output, new NamespacedKey(worlds.get(u).getName()).toString(), StandardCharsets.UTF_8);
|
DataTypeIO.writeString(output, new NamespacedKey(world.getName()).toString(), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
DataTypeIO.writeCompoundTag(output, dimensionCodec);
|
DataTypeIO.writeCompoundTag(output, dimensionCodec);
|
||||||
DataTypeIO.writeString(output, world.getEnvironment().getNamespacedKey().toString(), StandardCharsets.UTF_8);
|
DataTypeIO.writeString(output, world.getEnvironment().getNamespacedKey().toString(), StandardCharsets.UTF_8);
|
||||||
|
|
@ -154,7 +154,7 @@ public class PacketPlayOutLogin extends PacketOut {
|
||||||
output.writeBoolean(isDebug);
|
output.writeBoolean(isDebug);
|
||||||
output.writeBoolean(isFlat);
|
output.writeBoolean(isFlat);
|
||||||
output.writeBoolean(false);
|
output.writeBoolean(false);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -33,31 +34,26 @@ import com.loohp.limbo.utils.GameMode;
|
||||||
public class PacketPlayOutPlayerInfo extends PacketOut {
|
public class PacketPlayOutPlayerInfo extends PacketOut {
|
||||||
|
|
||||||
public enum PlayerInfoAction {
|
public enum PlayerInfoAction {
|
||||||
ADD_PLAYER(0), UPDATE_GAMEMODE(1), UPDATE_LATENCY(2), UPDATE_DISPLAY_NAME(3), REMOVE_PLAYER(4);
|
ADD_PLAYER,
|
||||||
|
INITIALIZE_CHAT,
|
||||||
private final int id;
|
UPDATE_GAME_MODE,
|
||||||
|
UPDATE_LISTED,
|
||||||
PlayerInfoAction(int id) {
|
UPDATE_LATENCY,
|
||||||
this.id = id;
|
UPDATE_DISPLAY_NAME;
|
||||||
}
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayerInfoAction action;
|
private EnumSet<PlayerInfoAction> actions;
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private PlayerInfoData data;
|
private PlayerInfoData data;
|
||||||
|
|
||||||
public PacketPlayOutPlayerInfo(PlayerInfoAction action, UUID uuid, PlayerInfoData data) {
|
public PacketPlayOutPlayerInfo(EnumSet<PlayerInfoAction> actions, UUID uuid, PlayerInfoData data) {
|
||||||
this.action = action;
|
this.actions = actions;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerInfoAction getAction() {
|
public EnumSet<PlayerInfoAction> getActions() {
|
||||||
return action;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
|
|
@ -74,41 +70,52 @@ public class PacketPlayOutPlayerInfo extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeVarInt(output, action.getId());
|
|
||||||
|
DataTypeIO.writeEnumSet(output, actions, PlayerInfoAction.class);
|
||||||
DataTypeIO.writeVarInt(output, 1);
|
DataTypeIO.writeVarInt(output, 1);
|
||||||
DataTypeIO.writeUUID(output, uuid);
|
DataTypeIO.writeUUID(output, uuid);
|
||||||
|
|
||||||
switch (action) {
|
PlayerInfoDataAddPlayer data = (PlayerInfoDataAddPlayer) this.data;
|
||||||
case ADD_PLAYER:
|
for (PlayerInfoAction action : actions) {
|
||||||
PlayerInfoDataAddPlayer data = (PlayerInfoDataAddPlayer) this.data;
|
switch (action) {
|
||||||
DataTypeIO.writeString(output, data.getName(), StandardCharsets.UTF_8);
|
case ADD_PLAYER: {
|
||||||
if (data.getProperty().isPresent()) {
|
DataTypeIO.writeString(output, data.getName(), StandardCharsets.UTF_8);
|
||||||
DataTypeIO.writeVarInt(output, 1);
|
if (data.getProperty().isPresent()) {
|
||||||
DataTypeIO.writeString(output, "textures", StandardCharsets.UTF_8);
|
DataTypeIO.writeVarInt(output, 1);
|
||||||
DataTypeIO.writeString(output, data.getProperty().get().getSkin(), StandardCharsets.UTF_8);
|
DataTypeIO.writeString(output, "textures", StandardCharsets.UTF_8);
|
||||||
output.writeBoolean(true);
|
DataTypeIO.writeString(output, data.getProperty().get().getSkin(), StandardCharsets.UTF_8);
|
||||||
DataTypeIO.writeString(output, data.getProperty().get().getSignature(), StandardCharsets.UTF_8);
|
output.writeBoolean(true);
|
||||||
} else {
|
DataTypeIO.writeString(output, data.getProperty().get().getSignature(), StandardCharsets.UTF_8);
|
||||||
DataTypeIO.writeVarInt(output, 0);
|
} else {
|
||||||
|
DataTypeIO.writeVarInt(output, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INITIALIZE_CHAT: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UPDATE_GAME_MODE: {
|
||||||
|
DataTypeIO.writeVarInt(output, data.getGamemode().getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UPDATE_LISTED: {
|
||||||
|
output.writeBoolean(data.isListed());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UPDATE_LATENCY: {
|
||||||
|
DataTypeIO.writeVarInt(output, data.getPing());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UPDATE_DISPLAY_NAME: {
|
||||||
|
if (data.getDisplayNameJson().isPresent()) {
|
||||||
|
output.writeBoolean(true);
|
||||||
|
DataTypeIO.writeString(output, data.getDisplayNameJson().get(), StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
|
output.writeBoolean(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DataTypeIO.writeVarInt(output, data.getGamemode().getId());
|
|
||||||
DataTypeIO.writeVarInt(output, data.getPing());
|
|
||||||
if (data.getDisplayNameJson().isPresent()) {
|
|
||||||
output.writeBoolean(true);
|
|
||||||
DataTypeIO.writeString(output, data.getDisplayNameJson().get(), StandardCharsets.UTF_8);
|
|
||||||
} else {
|
|
||||||
output.writeBoolean(false);
|
|
||||||
}
|
|
||||||
output.writeBoolean(false);
|
|
||||||
break;
|
|
||||||
case REMOVE_PLAYER:
|
|
||||||
break;
|
|
||||||
case UPDATE_DISPLAY_NAME:
|
|
||||||
break;
|
|
||||||
case UPDATE_GAMEMODE:
|
|
||||||
break;
|
|
||||||
case UPDATE_LATENCY:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
|
|
@ -121,15 +128,16 @@ public class PacketPlayOutPlayerInfo extends PacketOut {
|
||||||
public static class PlayerInfoDataAddPlayer extends PlayerInfoData {
|
public static class PlayerInfoDataAddPlayer extends PlayerInfoData {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
private boolean listed;
|
||||||
private Optional<PlayerSkinProperty> skin;
|
private Optional<PlayerSkinProperty> skin;
|
||||||
private GameMode gamemode;
|
private GameMode gamemode;
|
||||||
private int ping;
|
private int ping;
|
||||||
private boolean hasDisplayName;
|
private boolean hasDisplayName;
|
||||||
private Optional<String> displayNameJson;
|
private Optional<String> displayNameJson;
|
||||||
|
|
||||||
public PlayerInfoDataAddPlayer(String name, Optional<PlayerSkinProperty> skin, GameMode gamemode, int ping,
|
public PlayerInfoDataAddPlayer(String name, boolean listed, Optional<PlayerSkinProperty> skin, GameMode gamemode, int ping, boolean hasDisplayName, Optional<String> displayNameJson) {
|
||||||
boolean hasDisplayName, Optional<String> displayNameJson) {
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.listed = listed;
|
||||||
this.skin = skin;
|
this.skin = skin;
|
||||||
this.gamemode = gamemode;
|
this.gamemode = gamemode;
|
||||||
this.ping = ping;
|
this.ping = ping;
|
||||||
|
|
@ -141,6 +149,10 @@ public class PacketPlayOutPlayerInfo extends PacketOut {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isListed() {
|
||||||
|
return listed;
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<PlayerSkinProperty> getProperty() {
|
public Optional<PlayerSkinProperty> getProperty() {
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.loohp.limbo.world.BlockPosition;
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
|
|
@ -33,6 +36,47 @@ import net.querz.nbt.tag.CompoundTag;
|
||||||
import net.querz.nbt.tag.Tag;
|
import net.querz.nbt.tag.Tag;
|
||||||
|
|
||||||
public class DataTypeIO {
|
public class DataTypeIO {
|
||||||
|
|
||||||
|
public static <E extends Enum<E>> void writeEnumSet(DataOutputStream out, EnumSet<E> enumset, Class<E> oclass) throws IOException {
|
||||||
|
E[] ae = oclass.getEnumConstants();
|
||||||
|
BitSet bitset = new BitSet(ae.length);
|
||||||
|
|
||||||
|
for (int i = 0; i < ae.length; ++i) {
|
||||||
|
bitset.set(i, enumset.contains(ae[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFixedBitSet(out, bitset, ae.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E extends Enum<E>> EnumSet<E> readEnumSet(DataInputStream in, Class<E> oclass) throws IOException {
|
||||||
|
E[] ae = oclass.getEnumConstants();
|
||||||
|
BitSet bitset = readFixedBitSet(in, ae.length);
|
||||||
|
EnumSet<E> enumset = EnumSet.noneOf(oclass);
|
||||||
|
|
||||||
|
for (int i = 0; i < ae.length; ++i) {
|
||||||
|
if (bitset.get(i)) {
|
||||||
|
enumset.add(ae[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeFixedBitSet(DataOutputStream out, BitSet bitset, int i) throws IOException {
|
||||||
|
if (bitset.length() > i) {
|
||||||
|
int j = bitset.length();
|
||||||
|
throw new RuntimeException("BitSet is larger than expected size (" + j + ">" + i + ")");
|
||||||
|
} else {
|
||||||
|
byte[] abyte = bitset.toByteArray();
|
||||||
|
out.write(Arrays.copyOf(abyte, -Math.floorDiv(-i, 8)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitSet readFixedBitSet(DataInputStream in, int i) throws IOException {
|
||||||
|
byte[] abyte = new byte[-Math.floorDiv(-i, 8)];
|
||||||
|
in.readFully(abyte);
|
||||||
|
return BitSet.valueOf(abyte);
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeBlockPosition(DataOutputStream out, BlockPosition position) throws IOException {
|
public static void writeBlockPosition(DataOutputStream out, BlockPosition position) throws IOException {
|
||||||
out.writeLong(((position.getX() & 0x3FFFFFF) << 38) | ((position.getZ() & 0x3FFFFFF) << 12) | (position.getY() & 0xFFF));
|
out.writeLong(((position.getX() & 0x3FFFFFF) << 38) | ((position.getZ() & 0x3FFFFFF) << 12) | (position.getY() & 0xFFF));
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -12,44 +12,44 @@
|
||||||
"PacketLoginOutPluginMessaging": "0x04"
|
"PacketLoginOutPluginMessaging": "0x04"
|
||||||
},
|
},
|
||||||
"PlayIn": {
|
"PlayIn": {
|
||||||
"0x12": "PacketPlayInKeepAlive",
|
"0x11": "PacketPlayInKeepAlive",
|
||||||
"0x04": "ServerboundChatCommandPacket",
|
"0x04": "ServerboundChatCommandPacket",
|
||||||
"0x05": "PacketPlayInChat",
|
"0x05": "PacketPlayInChat",
|
||||||
"0x15": "PacketPlayInPositionAndLook",
|
"0x14": "PacketPlayInPositionAndLook",
|
||||||
"0x14": "PacketPlayInPosition",
|
"0x13": "PacketPlayInPosition",
|
||||||
"0x16": "PacketPlayInRotation",
|
"0x15": "PacketPlayInRotation",
|
||||||
"0x0D": "PacketPlayInPluginMessaging",
|
"0x0C": "PacketPlayInPluginMessaging",
|
||||||
"0x09": "PacketPlayInTabComplete",
|
"0x08": "PacketPlayInTabComplete",
|
||||||
"0x28": "PacketPlayInHeldItemChange",
|
"0x28": "PacketPlayInHeldItemChange",
|
||||||
"0x24": "PacketPlayInResourcePackStatus"
|
"0x24": "PacketPlayInResourcePackStatus"
|
||||||
},
|
},
|
||||||
"PlayOut": {
|
"PlayOut": {
|
||||||
"PacketPlayOutLogin": "0x25",
|
"PacketPlayOutLogin": "0x24",
|
||||||
"PacketPlayOutPositionAndLook": "0x39",
|
"PacketPlayOutPositionAndLook": "0x38",
|
||||||
"PacketPlayOutSpawnPosition": "0x4D",
|
"PacketPlayOutSpawnPosition": "0x4C",
|
||||||
"ClientboundSystemChatPacket": "0x62",
|
"ClientboundSystemChatPacket": "0x60",
|
||||||
"PacketPlayOutPlayerAbilities": "0x31",
|
"PacketPlayOutPlayerAbilities": "0x30",
|
||||||
"ClientboundLevelChunkWithLightPacket": "0x21",
|
"ClientboundLevelChunkWithLightPacket": "0x20",
|
||||||
"PacketPlayOutUnloadChunk": "0x1C",
|
"PacketPlayOutUnloadChunk": "0x1B",
|
||||||
"PacketPlayOutKeepAlive": "0x20",
|
"PacketPlayOutKeepAlive": "0x1F",
|
||||||
"PacketPlayOutPlayerInfo": "0x37",
|
"PacketPlayOutPlayerInfo": "0x36",
|
||||||
"PacketPlayOutUpdateViewPosition": "0x4B",
|
"PacketPlayOutUpdateViewPosition": "0x4A",
|
||||||
"PacketPlayOutDisconnect": "0x19",
|
"PacketPlayOutDisconnect": "0x17",
|
||||||
"PacketPlayOutPluginMessaging": "0x16",
|
"PacketPlayOutPluginMessaging": "0x15",
|
||||||
"PacketPlayOutTabComplete": "0x0E",
|
"PacketPlayOutTabComplete": "0x0D",
|
||||||
"PacketPlayOutDeclareCommands": "0x0F",
|
"PacketPlayOutDeclareCommands": "0x0E",
|
||||||
"PacketPlayOutRespawn": "0x3E",
|
"PacketPlayOutRespawn": "0x3E",
|
||||||
"PacketPlayOutGameState": "0x1D",
|
"PacketPlayOutGameState": "0x1C",
|
||||||
"PacketPlayOutEntityDestroy": "0x3B",
|
"PacketPlayOutEntityDestroy": "0x3A",
|
||||||
"PacketPlayOutEntityMetadata": "0x50",
|
"PacketPlayOutEntityMetadata": "0x4E",
|
||||||
"PacketPlayOutSpawnEntity": "0x00",
|
"PacketPlayOutSpawnEntity": "0x00",
|
||||||
"PacketPlayOutHeldItemChange": "0x4A",
|
"PacketPlayOutHeldItemChange": "0x49",
|
||||||
"PacketPlayOutPlayerListHeaderFooter": "0x63",
|
"PacketPlayOutPlayerListHeaderFooter": "0x61",
|
||||||
"PacketPlayOutResourcePackSend": "0x3D",
|
"PacketPlayOutResourcePackSend": "0x3C",
|
||||||
"ClientboundSetTitlesAnimationPacket": "0x5E",
|
"ClientboundSetTitlesAnimationPacket": "0x5C",
|
||||||
"ClientboundSetTitleTextPacket": "0x5D",
|
"ClientboundSetTitleTextPacket": "0x5B",
|
||||||
"ClientboundSetSubtitleTextPacket": "0x5B",
|
"ClientboundSetSubtitleTextPacket": "0x59",
|
||||||
"ClientboundClearTitlesPacket": "0x0D"
|
"ClientboundClearTitlesPacket": "0x0C"
|
||||||
},
|
},
|
||||||
"StatusIn": {
|
"StatusIn": {
|
||||||
"0x01": "PacketStatusInPing",
|
"0x01": "PacketStatusInPing",
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,6 @@ required-resource-pack=false
|
||||||
#JSON formatted text to show when prompting the player to install the resource pack (May be left blank)
|
#JSON formatted text to show when prompting the player to install the resource pack (May be left blank)
|
||||||
resource-pack-prompt={"text":"","extra":[{"text":"Install server resource pack!","color":"yellow"}]}
|
resource-pack-prompt={"text":"","extra":[{"text":"Install server resource pack!","color":"yellow"}]}
|
||||||
|
|
||||||
#Whether to enforce the player allowlist. If true, loads and enforces the allowlist from 'allowlist.json'
|
#Whether to enforce the player whitelist. If true, enforces the whitelist from 'whitelist.json'
|
||||||
#in the same format as vanilla minecraft servers
|
#in the same format as vanilla minecraft servers
|
||||||
enforce-allowlist=false
|
enforce-whitelist=false
|
||||||
Loading…
Reference in New Issue