mirror of
https://github.com/Nan1t/NanoLimbo.git
synced 2025-07-14 13:20:12 +02:00
Send keep alive frequently. Removed unused packets. Moved initialization in server class
This commit is contained in:
parent
7eb6f75908
commit
bc05228da3
18
settings.properties
Normal file
18
settings.properties
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# NanoLimbo configuration
|
||||
#
|
||||
|
||||
host=localhost
|
||||
port=65535
|
||||
max-players=100
|
||||
ping-version=NanoLimbo
|
||||
ping-description={"text": "NanoLimbo"}
|
||||
|
||||
# Player info forwarding support. Available types: NONE, LEGACY, MODERN
|
||||
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
|
@ -17,7 +17,7 @@ public final class LimboConfig {
|
||||
|
||||
public static void load(Path file) throws IOException {
|
||||
if (!Files.exists(file)){
|
||||
Files.copy(LimboConfig.class.getResourceAsStream("/settings.properties"), file);
|
||||
Files.copy(NanoLimbo.getResource("/settings.properties"), file);
|
||||
}
|
||||
|
||||
Properties properties = new Properties();
|
||||
|
@ -2,28 +2,14 @@ package ru.nanit.limbo;
|
||||
|
||||
import ru.nanit.limbo.server.LimboServer;
|
||||
import ru.nanit.limbo.util.Logger;
|
||||
import ru.nanit.limbo.world.DefaultDimension;
|
||||
import ru.nanit.limbo.world.DefaultWorld;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public final class NanoLimbo {
|
||||
|
||||
private LimboServer server;
|
||||
|
||||
public void start() throws Exception {
|
||||
LimboConfig.load(Paths.get("./settings.properties"));
|
||||
DefaultDimension.init();
|
||||
DefaultWorld.init();
|
||||
|
||||
server = new LimboServer();
|
||||
server.start();
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
try {
|
||||
new NanoLimbo().start();
|
||||
new LimboServer().start();
|
||||
} catch (Exception e){
|
||||
Logger.error("Cannot start server: ", e);
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import ru.nanit.limbo.server.LimboServer;
|
||||
import ru.nanit.limbo.util.Logger;
|
||||
import ru.nanit.limbo.util.UuidUtil;
|
||||
import ru.nanit.limbo.world.DefaultDimension;
|
||||
import ru.nanit.limbo.world.DefaultWorld;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
@ -30,8 +30,18 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
private final Channel channel;
|
||||
|
||||
private State state;
|
||||
|
||||
private UUID uuid;
|
||||
private String username;
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public ClientConnection(Channel channel, LimboServer server){
|
||||
this.server = server;
|
||||
this.channel = channel;
|
||||
@ -40,14 +50,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
if (state.equals(State.PLAY)){
|
||||
server.decrementPlayers();
|
||||
server.removeConnection(this);
|
||||
Logger.info("Player %s disconnected", this.username);
|
||||
}
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
if (channel.isActive()){
|
||||
Logger.error("Unhandled exception: %s", cause.getMessage());
|
||||
}
|
||||
@ -74,12 +84,13 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
if (packet instanceof PacketLoginStart){
|
||||
if (server.getPlayersCount() >= LimboConfig.getMaxPlayers()){
|
||||
if (server.getConnectionsCount() >= LimboConfig.getMaxPlayers()){
|
||||
disconnect("Too many players connected");
|
||||
return;
|
||||
}
|
||||
|
||||
this.username = ((PacketLoginStart) packet).getUsername();
|
||||
this.uuid = UuidUtil.getOfflineModeUuid(this.username);
|
||||
|
||||
PacketLoginSuccess loginSuccess = new PacketLoginSuccess();
|
||||
|
||||
@ -89,7 +100,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
sendPacket(loginSuccess);
|
||||
updateState(State.PLAY);
|
||||
|
||||
server.incrementPlayers();
|
||||
server.addConnection(this);
|
||||
Logger.info("Player %s connected", this.username);
|
||||
|
||||
startJoinProcess();
|
||||
@ -122,34 +133,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook();
|
||||
|
||||
positionAndLook.setX(0.0);
|
||||
positionAndLook.setY(2.0);
|
||||
positionAndLook.setY(0.0);
|
||||
positionAndLook.setZ(0.0);
|
||||
positionAndLook.setYaw(90.0F);
|
||||
positionAndLook.setPitch(0.0F);
|
||||
positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt());
|
||||
|
||||
PacketUpdateViewPos updateViewPos = new PacketUpdateViewPos();
|
||||
|
||||
updateViewPos.setChunkX(0);
|
||||
updateViewPos.setChunkY(0);
|
||||
|
||||
PacketChunkData chunkData = new PacketChunkData();
|
||||
|
||||
chunkData.setChunkX(0);
|
||||
chunkData.setChunkZ(0);
|
||||
chunkData.setFullChunk(false);
|
||||
chunkData.setPrimaryBitMask(1);
|
||||
chunkData.setHeightMaps(DefaultWorld.getHeightMaps());
|
||||
chunkData.setData(new byte[0]);
|
||||
chunkData.setBlockEntities(new CompoundBinaryTag[]{CompoundBinaryTag.empty()});
|
||||
|
||||
sendPacket(joinGame);
|
||||
sendPacket(positionAndLook);
|
||||
sendPacket(updateViewPos);
|
||||
sendPacket(chunkData);
|
||||
sendPacket(updateViewPos);
|
||||
sendPacket(positionAndLook);
|
||||
|
||||
sendKeepAlive();
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,12 @@ public class ByteMessage extends ByteBuf {
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
public byte[] toByteArray(){
|
||||
byte[] bytes = new byte[buf.readableBytes()];
|
||||
buf.readBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* Minecraft protocol methods */
|
||||
|
||||
public int readVarInt() {
|
||||
@ -127,6 +133,13 @@ public class ByteMessage extends ByteBuf {
|
||||
}
|
||||
}
|
||||
|
||||
public void writeLongArray(long[] array) {
|
||||
writeVarInt(array.length);
|
||||
for (long i : array) {
|
||||
writeLong(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeCompoundTagArray(CompoundBinaryTag[] compoundTags) {
|
||||
try {
|
||||
ByteBufOutputStream stream = new ByteBufOutputStream(buf);
|
||||
@ -1125,4 +1138,8 @@ public class ByteMessage extends ByteBuf {
|
||||
public boolean release(int decrement) {
|
||||
return buf.release(decrement);
|
||||
}
|
||||
|
||||
public static ByteMessage create(){
|
||||
return new ByteMessage(Unpooled.buffer());
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
package ru.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import ru.nanit.limbo.protocol.ByteMessage;
|
||||
import ru.nanit.limbo.protocol.PacketOut;
|
||||
import ru.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketChunkData implements PacketOut {
|
||||
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
private boolean fullChunk;
|
||||
private int primaryBitMask;
|
||||
private CompoundBinaryTag heightMaps;
|
||||
private int[] biomes;
|
||||
private byte[] data;
|
||||
private CompoundBinaryTag[] blockEntities;
|
||||
|
||||
public void setChunkX(int chunkX) {
|
||||
this.chunkX = chunkX;
|
||||
}
|
||||
|
||||
public void setChunkZ(int chunkZ) {
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
public void setFullChunk(boolean fullChunk) {
|
||||
this.fullChunk = fullChunk;
|
||||
}
|
||||
|
||||
public void setPrimaryBitMask(int primaryBitMask) {
|
||||
this.primaryBitMask = primaryBitMask;
|
||||
}
|
||||
|
||||
public void setHeightMaps(CompoundBinaryTag heightMaps) {
|
||||
this.heightMaps = heightMaps;
|
||||
}
|
||||
|
||||
public void setBiomes(int[] biomes) {
|
||||
this.biomes = biomes;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setBlockEntities(CompoundBinaryTag[] blockEntities) {
|
||||
this.blockEntities = blockEntities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeInt(chunkX);
|
||||
msg.writeInt(chunkZ);
|
||||
msg.writeBoolean(fullChunk);
|
||||
msg.writeVarInt(primaryBitMask);
|
||||
msg.writeCompoundTag(heightMaps);
|
||||
|
||||
if (fullChunk){
|
||||
msg.writeVarIntArray(biomes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
msg.writeBytesArray(data);
|
||||
msg.writeCompoundTagArray(blockEntities);
|
||||
}
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package ru.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ru.nanit.limbo.protocol.ByteMessage;
|
||||
import ru.nanit.limbo.protocol.PacketOut;
|
||||
import ru.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketUpdateViewPos implements PacketOut {
|
||||
|
||||
private int chunkX;
|
||||
private int chunkY;
|
||||
|
||||
public void setChunkX(int chunkX) {
|
||||
this.chunkX = chunkX;
|
||||
}
|
||||
|
||||
public void setChunkY(int chunkY) {
|
||||
this.chunkY = chunkY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeVarInt(chunkX);
|
||||
msg.writeVarInt(chunkY);
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,8 @@ public enum State {
|
||||
HANDSHAKING(0){
|
||||
{
|
||||
serverBound.register(Version.getMinimal(), 0x00, PacketHandshake::new);
|
||||
|
||||
int[] i = new int[16 * 16 * 16];
|
||||
}
|
||||
},
|
||||
STATUS(1){
|
||||
@ -36,12 +38,10 @@ public enum State {
|
||||
},
|
||||
PLAY(3){
|
||||
{
|
||||
clientBound.register(Version.V1_16_4, 0x20, PacketChunkData::new);
|
||||
clientBound.register(Version.V1_16_4, 0x24, PacketJoinGame::new);
|
||||
clientBound.register(Version.V1_16_4, 0x34, PacketPlayerPositionAndLook::new);
|
||||
clientBound.register(Version.V1_16_4, 0x40, PacketUpdateViewPos::new);
|
||||
clientBound.register(Version.V1_16_4, 0x1F, PacketKeepAlive::new);
|
||||
serverBound.register(Version.V1_16_4, 0x1F, PacketKeepAlive::new);
|
||||
serverBound.register(Version.V1_16_4, 0x10, PacketKeepAlive::new);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,30 +5,42 @@ import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import ru.nanit.limbo.LimboConfig;
|
||||
import ru.nanit.limbo.connection.ClientChannelInitializer;
|
||||
import ru.nanit.limbo.connection.ClientConnection;
|
||||
import ru.nanit.limbo.util.Logger;
|
||||
import ru.nanit.limbo.world.DefaultDimension;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
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 AtomicInteger playersCount;
|
||||
private final Map<UUID, ClientConnection> connections = new ConcurrentHashMap<>();
|
||||
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
public int getPlayersCount(){
|
||||
return playersCount.get();
|
||||
public int getConnectionsCount(){
|
||||
return connections.size();
|
||||
}
|
||||
|
||||
public void incrementPlayers(){
|
||||
playersCount.incrementAndGet();
|
||||
public void addConnection(ClientConnection connection){
|
||||
connections.put(connection.getUuid(), connection);
|
||||
}
|
||||
|
||||
public void decrementPlayers(){
|
||||
playersCount.decrementAndGet();
|
||||
public void removeConnection(ClientConnection connection){
|
||||
connections.remove(connection.getUuid());
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
Logger.info("Starting server...");
|
||||
|
||||
playersCount = new AtomicInteger();
|
||||
LimboConfig.load(Paths.get("./settings.properties"));
|
||||
DefaultDimension.init();
|
||||
|
||||
executor.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
|
||||
|
||||
ServerBootstrap bootstrap = new ServerBootstrap()
|
||||
.group(new NioEventLoopGroup(), new NioEventLoopGroup())
|
||||
@ -36,7 +48,12 @@ public final class LimboServer {
|
||||
.childHandler(new ClientChannelInitializer(this));
|
||||
|
||||
bootstrap.bind(LimboConfig.getHost(), LimboConfig.getPort());
|
||||
|
||||
Logger.info("Server started on %s:%d", LimboConfig.getHost(), LimboConfig.getPort());
|
||||
}
|
||||
|
||||
private void broadcastKeepAlive(){
|
||||
connections.values().forEach(ClientConnection::sendKeepAlive);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
package ru.nanit.limbo.world;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
|
||||
public final class DefaultWorld {
|
||||
|
||||
private static CompoundBinaryTag heightMaps;
|
||||
|
||||
private DefaultWorld(){}
|
||||
|
||||
public static void init(){
|
||||
heightMaps = CompoundBinaryTag.builder()
|
||||
.putLongArray("MOTION_BLOCKING", new long[]{
|
||||
1371773531765642314L, 1389823183635651148L, 1371738278539598925L,
|
||||
1389823183635388492L, 1353688558756731469L, 1389823114781694027L, 1317765589597723213L,
|
||||
1371773531899860042L, 1389823183635651149L, 1371773462911685197L, 1389823183635650636L,
|
||||
1353688626805119565L, 1371773531900123211L, 1335639250618849869L, 1371738278674077258L,
|
||||
1389823114781694028L, 1353723811310638154L, 1371738278674077259L, 1335674228429068364L,
|
||||
1335674228429067338L, 1335674228698027594L, 1317624576693539402L, 1335709481520370249L,
|
||||
1299610178184057417L, 1335638906349064264L, 1299574993811968586L, 1299574924958011464L,
|
||||
1299610178184056904L, 1299574924958011464L, 1299610109330100296L, 1299574924958011464L,
|
||||
1299574924823793736L, 1299574924958011465L, 1281525273222484040L, 1299574924958011464L,
|
||||
1281525273222484040L, 9548107335L
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
public static CompoundBinaryTag getHeightMaps(){
|
||||
return heightMaps;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user