Compare commits
2 Commits
master
...
dev/open-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
2b3d45a389
|
|||
|
abac6e8491
|
@@ -1,13 +1,12 @@
|
|||||||
# MC-SERVER
|
# MC-SERVER
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
Написанный с нуля сервер **Minecraft 1.12.2**.
|
Написанный с нуля сервер **Minecraft 1.12.2**.
|
||||||
|
|
||||||
На данный момент сервер может показывать о себе информацию в списке серверов (motd, онлайн, иконка) и позволять
|
На данный момент может только показывать информацию о себе. Подключение к серверу не возможно.
|
||||||
игрокам подключиться к себе. Загружается пустой мир.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
project.group=mc-project
|
project.group=mc-project
|
||||||
project.name=mc-server
|
project.name=mc-server
|
||||||
project.version=1.1
|
project.version=1.1-SNAPSHOT
|
||||||
@@ -2,16 +2,12 @@ package mc.protocol;
|
|||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import mc.protocol.api.ConnectionContext;
|
import mc.protocol.api.ConnectionContext;
|
||||||
import mc.protocol.packets.ServerSidePacket;
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
import mc.protocol.pool.Passivable;
|
import mc.protocol.pool.Passivable;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
public class NettyConnectionContext implements ConnectionContext, Passivable {
|
public class NettyConnectionContext implements ConnectionContext, Passivable {
|
||||||
|
|
||||||
@@ -19,14 +15,6 @@ public class NettyConnectionContext implements ConnectionContext, Passivable {
|
|||||||
@Setter
|
@Setter
|
||||||
private ChannelHandlerContext ctx;
|
private ChannelHandlerContext ctx;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private boolean usedContext;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public State getState() {
|
public State getState() {
|
||||||
return ctx.channel().attr(NetworkAttributes.STATE).get();
|
return ctx.channel().attr(NetworkAttributes.STATE).get();
|
||||||
@@ -37,27 +25,6 @@ public class NettyConnectionContext implements ConnectionContext, Passivable {
|
|||||||
ctx.channel().attr(NetworkAttributes.STATE).set(state);
|
ctx.channel().attr(NetworkAttributes.STATE).set(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public <T> void setCustomProperty(String key, T value) {
|
|
||||||
Map<String, Object> map = ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get();
|
|
||||||
map.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public <T> Optional<T> getCustomProperty(String key, Class<T> classResult) {
|
|
||||||
Map<String, Object> map = ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get();
|
|
||||||
return (Optional<T>) Optional.ofNullable(map.getOrDefault(key, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(ServerSidePacket packet) {
|
public void send(ServerSidePacket packet) {
|
||||||
ctx.write(packet);
|
ctx.write(packet);
|
||||||
|
|||||||
@@ -3,16 +3,8 @@ package mc.protocol;
|
|||||||
import io.netty.util.AttributeKey;
|
import io.netty.util.AttributeKey;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class NetworkAttributes {
|
public class NetworkAttributes {
|
||||||
|
|
||||||
public static final AttributeKey<State> STATE = AttributeKey.newInstance("STATE");
|
public static final AttributeKey<State> STATE = AttributeKey.newInstance("STATE");
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final AttributeKey<Map<String, Object>> CUSTOM_PROPERTIES = AttributeKey.newInstance("CUSTOM_PROPERTIES");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,20 +3,14 @@ package mc.protocol;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import mc.protocol.packets.ClientSidePacket;
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
import mc.protocol.event.EventBus;
|
import mc.protocol.event.EventBus;
|
||||||
import mc.protocol.pool.PacketPool;
|
import mc.protocol.pool.PacketPool;
|
||||||
import org.apache.commons.pool2.ObjectPool;
|
import org.apache.commons.pool2.ObjectPool;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PacketInboundHandler extends SimpleChannelInboundHandler<ClientSidePacket> {
|
public class PacketInboundHandler extends SimpleChannelInboundHandler<ClientSidePacket> {
|
||||||
|
|
||||||
private static final String CLIENT_FORCE_DISCONNECTED_IOEXCEPTION_MESSAGE_RU = "Программа на вашем хост-компьютере разорвала установленное подключение";
|
|
||||||
|
|
||||||
private final ObjectPool<NettyConnectionContext> poolNettyConnectionContext;
|
private final ObjectPool<NettyConnectionContext> poolNettyConnectionContext;
|
||||||
private final PacketPool poolPackets;
|
private final PacketPool poolPackets;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
@@ -28,21 +22,7 @@ public class PacketInboundHandler extends SimpleChannelInboundHandler<ClientSide
|
|||||||
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
||||||
eventBus.emit(state, context, packet);
|
eventBus.emit(state, context, packet);
|
||||||
|
|
||||||
if (!context.isUsedContext()) {
|
poolNettyConnectionContext.returnObject(context);
|
||||||
poolNettyConnectionContext.returnObject(context);
|
|
||||||
}
|
|
||||||
poolPackets.returnObject(packet);
|
poolPackets.returnObject(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
|
||||||
if (cause instanceof IOException && cause.getLocalizedMessage().equalsIgnoreCase(CLIENT_FORCE_DISCONNECTED_IOEXCEPTION_MESSAGE_RU)) {
|
|
||||||
log.warn("Client '{}' force disconnected", ctx.channel().remoteAddress());
|
|
||||||
if (log.isTraceEnabled()) {
|
|
||||||
log.trace("", cause);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.error("{}", cause.getMessage(), cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import lombok.Getter;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import mc.protocol.packets.ClientSidePacket;
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
import mc.protocol.packets.Packet;
|
import mc.protocol.packets.Packet;
|
||||||
import mc.protocol.packets.KeepAlivePacket;
|
import mc.protocol.packets.PingPacket;
|
||||||
import mc.protocol.packets.ServerSidePacket;
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
import mc.protocol.packets.client.*;
|
import mc.protocol.packets.client.*;
|
||||||
import mc.protocol.packets.server.*;
|
import mc.protocol.packets.server.*;
|
||||||
@@ -24,12 +24,12 @@ public enum State {
|
|||||||
// client side
|
// client side
|
||||||
Map.of(
|
Map.of(
|
||||||
0x00, StatusServerRequestPacket.class,
|
0x00, StatusServerRequestPacket.class,
|
||||||
0x01, KeepAlivePacket.class
|
0x01, PingPacket.class
|
||||||
),
|
),
|
||||||
// server side
|
// server side
|
||||||
Map.of(
|
Map.of(
|
||||||
StatusServerResponse.class, 0x00,
|
StatusServerResponse.class, 0x00,
|
||||||
KeepAlivePacket.class, 0x01
|
PingPacket.class, 0x01
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
LOGIN(2,
|
LOGIN(2,
|
||||||
@@ -47,17 +47,19 @@ public enum State {
|
|||||||
0x00, TeleportConfirmPacket.class,
|
0x00, TeleportConfirmPacket.class,
|
||||||
0x04, ClientSettingsPacket.class,
|
0x04, ClientSettingsPacket.class,
|
||||||
0x09, PluginMessagePacket.class,
|
0x09, PluginMessagePacket.class,
|
||||||
0x0B, KeepAlivePacket.class,
|
0x0B, PingPacket.class,
|
||||||
0x0D, PlayerPositionPacket.class,
|
0x0D, PlayerPositionPacket.class,
|
||||||
0x0E, CPlayerPositionAndLookPacket.class,
|
0x0E, CPlayerPositionAndLookPacket.class,
|
||||||
0x0F, PlayerLookPacket.class,
|
0x0F, PlayerLookPacket.class,
|
||||||
0x15, EntityActionPacket.class
|
0x15, EntityActionPacket.class,
|
||||||
|
0x1C, UpdateSignPacket.class
|
||||||
),
|
),
|
||||||
// client bound
|
// client bound
|
||||||
Map.of(
|
Map.of(
|
||||||
KeepAlivePacket.class, 0x1F,
|
PingPacket.class, 0x1F,
|
||||||
ChunkDataPacket.class, 0x20,
|
ChunkDataPacket.class, 0x20,
|
||||||
JoinGamePacket.class, 0x23,
|
JoinGamePacket.class, 0x23,
|
||||||
|
OpenSignEditorPacket.class, 0x2A,
|
||||||
PlayerAbilitiesPacket.class,0x2C,
|
PlayerAbilitiesPacket.class,0x2C,
|
||||||
SPlayerPositionAndLookPacket.class, 0x2F,
|
SPlayerPositionAndLookPacket.class, 0x2F,
|
||||||
SpawnPositionPacket.class, 0x46
|
SpawnPositionPacket.class, 0x46
|
||||||
|
|||||||
@@ -3,37 +3,11 @@ package mc.protocol.api;
|
|||||||
import mc.protocol.State;
|
import mc.protocol.State;
|
||||||
import mc.protocol.packets.ServerSidePacket;
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public interface ConnectionContext {
|
public interface ConnectionContext {
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
void setUsedContext(boolean value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
boolean isUsedContext();
|
|
||||||
|
|
||||||
State getState();
|
State getState();
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
<T> void setCustomProperty(String key, T value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated костыль
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
<T> Optional<T> getCustomProperty(String key, Class<T> classResult);
|
|
||||||
|
|
||||||
void send(ServerSidePacket packet);
|
void send(ServerSidePacket packet);
|
||||||
void sendNow(ServerSidePacket packet);
|
void sendNow(ServerSidePacket packet);
|
||||||
void flushSending();
|
void flushSending();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import mc.protocol.pool.PacketPool;
|
|||||||
import org.apache.commons.pool2.ObjectPool;
|
import org.apache.commons.pool2.ObjectPool;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -37,8 +36,6 @@ public class ProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(@Nonnull ChannelHandlerContext ctx) throws Exception {
|
public void channelActive(@Nonnull ChannelHandlerContext ctx) throws Exception {
|
||||||
ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).set(new HashMap<>());
|
|
||||||
|
|
||||||
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
||||||
consumerNewConnection.accept(context);
|
consumerNewConnection.accept(context);
|
||||||
|
|
||||||
@@ -51,9 +48,6 @@ public class ProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
||||||
consumerDisconnect.accept(context);
|
consumerDisconnect.accept(context);
|
||||||
|
|
||||||
ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get().clear();
|
|
||||||
ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).set(null);
|
|
||||||
|
|
||||||
poolNettyConnectionContext.returnObject(context);
|
poolNettyConnectionContext.returnObject(context);
|
||||||
super.channelInactive(ctx);
|
super.channelInactive(ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,16 +9,4 @@ public class Location {
|
|||||||
private double x;
|
private double x;
|
||||||
private double y;
|
private double y;
|
||||||
private double z;
|
private double z;
|
||||||
|
|
||||||
public int getIntX() {
|
|
||||||
return (int) x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIntZ() {
|
|
||||||
return (int) z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location toChunkXZ() {
|
|
||||||
return new Location(this.getIntX() >> 4, 0d, this.getIntZ() >> 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import mc.protocol.io.NetByteBuf;
|
|||||||
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Keep_Alive">Keep Alive</a>
|
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Keep_Alive">Keep Alive</a>
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class KeepAlivePacket implements ClientSidePacket, ServerSidePacket {
|
public class PingPacket implements ClientSidePacket, ServerSidePacket {
|
||||||
|
|
||||||
private Long payload;
|
private Long payload;
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package mc.protocol.packets.client;
|
||||||
|
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import mc.protocol.io.NetByteBuf;
|
||||||
|
import mc.protocol.model.Location;
|
||||||
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
|
import mc.protocol.packets.server.OpenSignEditorPacket;
|
||||||
|
import mc.protocol.serializer.LocationSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update Sign packet.
|
||||||
|
*
|
||||||
|
* <p>Отправляется клиентом, когда нажата кнопка "Done" в окне редактирования таблички.</p>
|
||||||
|
*
|
||||||
|
* <p>Структура пакета</p>
|
||||||
|
* <pre>
|
||||||
|
* | FIELD | TYPE | NOTES |
|
||||||
|
* |----------|--------------|--------------------------------|
|
||||||
|
* | Location | Location | Позиция редактируемой табилчки |
|
||||||
|
* | Line 1 | String (384) | Строка таблички |
|
||||||
|
* | Line 2 | String (384) | Строка таблички |
|
||||||
|
* | Line 3 | String (384) | Строка таблички |
|
||||||
|
* | Line 4 | String (384) | Строка таблички |
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Update_Sign" target="_top">Update Sign</a>
|
||||||
|
* @see OpenSignEditorPacket
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@ToString
|
||||||
|
public class UpdateSignPacket implements ClientSidePacket {
|
||||||
|
|
||||||
|
private Location location;
|
||||||
|
@SuppressWarnings("MismatchedReadAndWriteOfArray")
|
||||||
|
private String[] lines;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readSelf(NetByteBuf netByteBuf) {
|
||||||
|
this.location = LocationSerializer.fromLongValue(netByteBuf.readLong());
|
||||||
|
this.lines = new String[4];
|
||||||
|
this.lines[0] = netByteBuf.readString(384);
|
||||||
|
this.lines[1] = netByteBuf.readString(384);
|
||||||
|
this.lines[2] = netByteBuf.readString(384);
|
||||||
|
this.lines[3] = netByteBuf.readString(384);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void passivate() {
|
||||||
|
this.location = null;
|
||||||
|
this.lines = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,17 +28,13 @@ import mc.protocol.packets.ServerSidePacket;
|
|||||||
@Data
|
@Data
|
||||||
public class ChunkDataPacket implements ServerSidePacket {
|
public class ChunkDataPacket implements ServerSidePacket {
|
||||||
|
|
||||||
private static NetByteBuf voidData;
|
|
||||||
|
|
||||||
private int x;
|
private int x;
|
||||||
private int z;
|
private int z;
|
||||||
|
|
||||||
@SuppressWarnings("java:S125")
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSelf(NetByteBuf netByteBuf) {
|
public void writeSelf(NetByteBuf netByteBuf) {
|
||||||
netByteBuf.writeInt(x);
|
netByteBuf.writeInt(x);
|
||||||
netByteBuf.writeInt(z);
|
netByteBuf.writeInt(z);
|
||||||
/* Временное отключение кода
|
|
||||||
netByteBuf.writeBoolean(true); // Is Full chunk
|
netByteBuf.writeBoolean(true); // Is Full chunk
|
||||||
netByteBuf.writeVarInt(0b11111111); // Available Sections
|
netByteBuf.writeVarInt(0b11111111); // Available Sections
|
||||||
|
|
||||||
@@ -68,41 +64,6 @@ public class ChunkDataPacket implements ServerSidePacket {
|
|||||||
netByteBuf.writeVarInt(data.readableBytes()); // Size of Data
|
netByteBuf.writeVarInt(data.readableBytes()); // Size of Data
|
||||||
netByteBuf.writeBytes(data); // Data
|
netByteBuf.writeBytes(data); // Data
|
||||||
netByteBuf.writeVarInt(0); // Number of block entities
|
netByteBuf.writeVarInt(0); // Number of block entities
|
||||||
// write NBT's
|
/* write NBT's */
|
||||||
*/
|
|
||||||
|
|
||||||
netByteBuf.writeBytes(voidData);
|
|
||||||
|
|
||||||
voidData.resetReaderIndex();
|
|
||||||
voidData.resetWriterIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
voidData = new NetByteBuf(Unpooled.buffer());
|
|
||||||
voidData.writeBoolean(true); // Is Full chunk
|
|
||||||
voidData.writeVarInt(0b11111111); // Available Sections
|
|
||||||
|
|
||||||
NetByteBuf data = new NetByteBuf(Unpooled.buffer());
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
NetByteBuf dataBuff = new NetByteBuf(Unpooled.wrappedBuffer(new byte[4096]));
|
|
||||||
NetByteBuf blockLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048]));
|
|
||||||
NetByteBuf skyLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048]));
|
|
||||||
NetByteBuf biomes = new NetByteBuf(Unpooled.wrappedBuffer(new byte[256]));
|
|
||||||
|
|
||||||
data.writeUnsignedByte(13);
|
|
||||||
data.writeUnsignedByte(0);
|
|
||||||
data.writeVarInt(dataBuff.readableBytes());
|
|
||||||
data.writeBytes(dataBuff);
|
|
||||||
data.writeBytes(blockLight);
|
|
||||||
data.writeBytes(skyLight);
|
|
||||||
data.writeBytes(biomes);
|
|
||||||
}
|
|
||||||
|
|
||||||
voidData.writeVarInt(data.readableBytes());
|
|
||||||
voidData.writeBytes(data);
|
|
||||||
voidData.writeVarInt(0);
|
|
||||||
|
|
||||||
voidData.markReaderIndex();
|
|
||||||
voidData.markWriterIndex();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package mc.protocol.packets.server;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import mc.protocol.io.NetByteBuf;
|
||||||
|
import mc.protocol.model.Location;
|
||||||
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
|
import mc.protocol.packets.client.UpdateSignPacket;
|
||||||
|
import mc.protocol.serializer.LocationSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Открыть окно редактирования таблички.
|
||||||
|
*
|
||||||
|
* <p>Структура пакета</p>
|
||||||
|
* <pre>
|
||||||
|
* | FIELD | TYPE | NOTES |
|
||||||
|
* |----------|----------|-------|
|
||||||
|
* | Location | Location | |
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Open_Sign_Editor">Open Sign Editor</a>
|
||||||
|
* @see UpdateSignPacket
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OpenSignEditorPacket implements ServerSidePacket {
|
||||||
|
|
||||||
|
private Location location;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeSelf(NetByteBuf netByteBuf) {
|
||||||
|
long value = LocationSerializer.toLongValue(this.location);
|
||||||
|
netByteBuf.writeLong(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import lombok.Data;
|
|||||||
import mc.protocol.io.NetByteBuf;
|
import mc.protocol.io.NetByteBuf;
|
||||||
import mc.protocol.model.Location;
|
import mc.protocol.model.Location;
|
||||||
import mc.protocol.packets.ServerSidePacket;
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
|
import mc.protocol.serializer.LocationSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Спавн позиция игрока.
|
* Спавн позиция игрока.
|
||||||
@@ -14,7 +15,7 @@ import mc.protocol.packets.ServerSidePacket;
|
|||||||
* <pre>
|
* <pre>
|
||||||
* | FIELD | TYPE | NOTES |
|
* | FIELD | TYPE | NOTES |
|
||||||
* |----------|----------|-----------------------|
|
* |----------|----------|-----------------------|
|
||||||
* | Location | Position | Локация спавна игрока |
|
* | Location | Location | Локация спавна игрока |
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Spawn_Position">Spawn Position</a>
|
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Spawn_Position">Spawn Position</a>
|
||||||
@@ -26,16 +27,7 @@ public class SpawnPositionPacket implements ServerSidePacket {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSelf(NetByteBuf netByteBuf) {
|
public void writeSelf(NetByteBuf netByteBuf) {
|
||||||
long spawnSerialized =
|
long spawnSerialized = LocationSerializer.toLongValue(this.spawn);
|
||||||
((long) (floorDouble(spawn.getX()) & 0x3FFFFFF) << 38)
|
|
||||||
| ((long) (floorDouble(spawn.getY()) & 0xFFF) << 26)
|
|
||||||
| (floorDouble(spawn.getZ()) & 0x3FFFFFF);
|
|
||||||
netByteBuf.writeLong(spawnSerialized);
|
netByteBuf.writeLong(spawnSerialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int floorDouble(double value) {
|
|
||||||
int i = (int) value;
|
|
||||||
return value < (double) i ? i - 1 : i;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package mc.protocol.serializer;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import mc.protocol.model.Location;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class LocationSerializer {
|
||||||
|
|
||||||
|
public long toLongValue(Location location) {
|
||||||
|
return ((long) (floorDouble(location.getX()) & 0x3FFFFFF) << 38)
|
||||||
|
| ((long) (floorDouble(location.getY()) & 0xFFF) << 26)
|
||||||
|
| (floorDouble(location.getZ()) & 0x3FFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location fromLongValue(long value) {
|
||||||
|
return new Location(
|
||||||
|
value >> 38,
|
||||||
|
(value >> 26) & 0xFFF,
|
||||||
|
value << 38 >> 38);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int floorDouble(double value) {
|
||||||
|
int i = (int) value;
|
||||||
|
return value < (double) i ? i - 1 : i;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package mc.protocol.world;
|
|
||||||
|
|
||||||
public interface Chunk {
|
|
||||||
|
|
||||||
int getX();
|
|
||||||
int getZ();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package mc.protocol.world;
|
|
||||||
|
|
||||||
import mc.protocol.model.Location;
|
|
||||||
import mc.protocol.utils.LevelType;
|
|
||||||
|
|
||||||
public interface World {
|
|
||||||
|
|
||||||
LevelType getLevelType();
|
|
||||||
|
|
||||||
Location getSpawn();
|
|
||||||
|
|
||||||
Chunk getChunk(int x, int z);
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ import mc.protocol.api.Server;
|
|||||||
import mc.protocol.di.DaggerProtocolComponent;
|
import mc.protocol.di.DaggerProtocolComponent;
|
||||||
import mc.protocol.di.ProtocolComponent;
|
import mc.protocol.di.ProtocolComponent;
|
||||||
import mc.protocol.di.ProtocolModule;
|
import mc.protocol.di.ProtocolModule;
|
||||||
import mc.protocol.packets.KeepAlivePacket;
|
import mc.protocol.packets.PingPacket;
|
||||||
import mc.protocol.packets.client.HandshakePacket;
|
import mc.protocol.packets.client.HandshakePacket;
|
||||||
import mc.protocol.packets.client.LoginStartPacket;
|
import mc.protocol.packets.client.LoginStartPacket;
|
||||||
import mc.protocol.packets.client.StatusServerRequestPacket;
|
import mc.protocol.packets.client.StatusServerRequestPacket;
|
||||||
@@ -20,7 +20,6 @@ import mc.server.config.Config;
|
|||||||
import mc.server.di.ConfigModule;
|
import mc.server.di.ConfigModule;
|
||||||
import mc.server.di.DaggerServerComponent;
|
import mc.server.di.DaggerServerComponent;
|
||||||
import mc.server.di.ServerComponent;
|
import mc.server.di.ServerComponent;
|
||||||
import mc.server.service.PlayerManager;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -49,7 +48,6 @@ public class Main {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
Config config = serverComponent.getConfig();
|
Config config = serverComponent.getConfig();
|
||||||
PlayerManager playerManager = serverComponent.getPlayerManager();
|
|
||||||
|
|
||||||
ProtocolComponent protocolComponent = DaggerProtocolComponent.builder()
|
ProtocolComponent protocolComponent = DaggerProtocolComponent.builder()
|
||||||
.protocolModule(new ProtocolModule(true))
|
.protocolModule(new ProtocolModule(true))
|
||||||
@@ -59,16 +57,13 @@ public class Main {
|
|||||||
PacketHandler packetHandler = serverComponent.getPacketHandler();
|
PacketHandler packetHandler = serverComponent.getPacketHandler();
|
||||||
|
|
||||||
server.onNewConnect(connectionContext -> connectionContext.setState(State.HANDSHAKING));
|
server.onNewConnect(connectionContext -> connectionContext.setState(State.HANDSHAKING));
|
||||||
server.onDisonnect(connectionContext -> {
|
server.onDisonnect(connectionContext -> connectionContext.setState(null));
|
||||||
connectionContext.setState(null);
|
|
||||||
connectionContext.getCustomProperty("player", Player.class).ifPresent(playerManager::remove);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listenPacket(State.HANDSHAKING, HandshakePacket.class, packetHandler::onHandshake);
|
server.listenPacket(State.HANDSHAKING, HandshakePacket.class, packetHandler::onHandshake);
|
||||||
server.listenPacket(State.STATUS, KeepAlivePacket.class, packetHandler::onKeepAlive);
|
server.listenPacket(State.STATUS, PingPacket.class, packetHandler::onKeepAlive);
|
||||||
server.listenPacket(State.STATUS, StatusServerRequestPacket.class, packetHandler::onServerStatus);
|
server.listenPacket(State.STATUS, StatusServerRequestPacket.class, packetHandler::onServerStatus);
|
||||||
server.listenPacket(State.LOGIN, LoginStartPacket.class, packetHandler::onLoginStart);
|
server.listenPacket(State.LOGIN, LoginStartPacket.class, packetHandler::onLoginStart);
|
||||||
server.listenPacket(State.PLAY, KeepAlivePacket.class, packetHandler::onKeepAlivePlay);
|
server.listenPacket(State.PLAY, PingPacket.class, packetHandler::onKeepAlivePlay);
|
||||||
|
|
||||||
server.bind(config.server().host(), config.server().port());
|
server.bind(config.server().host(), config.server().port());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import mc.protocol.api.ConnectionContext;
|
|||||||
import mc.protocol.model.Location;
|
import mc.protocol.model.Location;
|
||||||
import mc.protocol.model.Look;
|
import mc.protocol.model.Look;
|
||||||
import mc.protocol.model.ServerInfo;
|
import mc.protocol.model.ServerInfo;
|
||||||
import mc.protocol.packets.KeepAlivePacket;
|
import mc.protocol.packets.PingPacket;
|
||||||
import mc.protocol.packets.client.HandshakePacket;
|
import mc.protocol.packets.client.HandshakePacket;
|
||||||
import mc.protocol.packets.client.LoginStartPacket;
|
import mc.protocol.packets.client.LoginStartPacket;
|
||||||
import mc.protocol.packets.client.StatusServerRequestPacket;
|
import mc.protocol.packets.client.StatusServerRequestPacket;
|
||||||
@@ -15,10 +15,8 @@ import mc.protocol.packets.server.*;
|
|||||||
import mc.protocol.serializer.TextSerializer;
|
import mc.protocol.serializer.TextSerializer;
|
||||||
import mc.protocol.utils.Difficulty;
|
import mc.protocol.utils.Difficulty;
|
||||||
import mc.protocol.utils.GameMode;
|
import mc.protocol.utils.GameMode;
|
||||||
import mc.protocol.world.Chunk;
|
import mc.protocol.utils.LevelType;
|
||||||
import mc.protocol.world.World;
|
|
||||||
import mc.server.config.Config;
|
import mc.server.config.Config;
|
||||||
import mc.server.service.PlayerManager;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -27,7 +25,7 @@ import java.nio.file.Path;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -35,27 +33,18 @@ public class PacketHandler {
|
|||||||
|
|
||||||
private final Random random = new Random(System.currentTimeMillis());
|
private final Random random = new Random(System.currentTimeMillis());
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final World world;
|
|
||||||
private final PlayerManager playerManager;
|
|
||||||
|
|
||||||
public void onHandshake(ConnectionContext context, HandshakePacket packet) {
|
public void onHandshake(ConnectionContext context, HandshakePacket packet) {
|
||||||
context.setState(packet.getNextState());
|
context.setState(packet.getNextState());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onKeepAlive(ConnectionContext context, KeepAlivePacket packet) {
|
public void onKeepAlive(ConnectionContext context, PingPacket packet) {
|
||||||
context.sendNow(packet);
|
context.sendNow(packet);
|
||||||
context.disconnect();
|
context.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onKeepAlivePlay(ConnectionContext context, KeepAlivePacket packet) {
|
public void onKeepAlivePlay(ConnectionContext context, PingPacket packet) {
|
||||||
try {
|
context.sendNow(packet);
|
||||||
TimeUnit.MILLISECONDS.sleep(50);
|
|
||||||
context.sendNow(packet);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (log.isTraceEnabled()) {
|
|
||||||
log.trace("{}", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@@ -64,11 +53,7 @@ public class PacketHandler {
|
|||||||
serverInfo.version().name(ProtocolConstant.PROTOCOL_NAME);
|
serverInfo.version().name(ProtocolConstant.PROTOCOL_NAME);
|
||||||
serverInfo.version().protocol(ProtocolConstant.PROTOCOL_NUMBER);
|
serverInfo.version().protocol(ProtocolConstant.PROTOCOL_NUMBER);
|
||||||
serverInfo.players().max(config.players().maxOnlile());
|
serverInfo.players().max(config.players().maxOnlile());
|
||||||
if (config.players().fakeOnline().enable()) {
|
serverInfo.players().online(config.players().onlile());
|
||||||
serverInfo.players().online(config.players().fakeOnline().value());
|
|
||||||
} else {
|
|
||||||
serverInfo.players().online(playerManager.online());
|
|
||||||
}
|
|
||||||
serverInfo.players().sample(Collections.emptyList());
|
serverInfo.players().sample(Collections.emptyList());
|
||||||
serverInfo.description(TextSerializer.fromPlain(config.motd()));
|
serverInfo.description(TextSerializer.fromPlain(config.motd()));
|
||||||
|
|
||||||
@@ -82,29 +67,27 @@ public class PacketHandler {
|
|||||||
context.sendNow(response);
|
context.sendNow(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("java:S2589")
|
|
||||||
public void onLoginStart(ConnectionContext context, LoginStartPacket loginStartPacket) {
|
public void onLoginStart(ConnectionContext context, LoginStartPacket loginStartPacket) {
|
||||||
Player player = playerManager.addAndCreate(context, loginStartPacket.getName(), GameMode.SURVIVAL, world.getSpawn());
|
|
||||||
context.setCustomProperty("player", player);
|
|
||||||
|
|
||||||
var loginSuccessPacket = new LoginSuccessPacket();
|
var loginSuccessPacket = new LoginSuccessPacket();
|
||||||
loginSuccessPacket.setUuid(player.getUuid());
|
loginSuccessPacket.setUuid(UUID.randomUUID());
|
||||||
loginSuccessPacket.setName(player.getName());
|
loginSuccessPacket.setName(loginStartPacket.getName());
|
||||||
|
|
||||||
context.sendNow(loginSuccessPacket);
|
context.sendNow(loginSuccessPacket);
|
||||||
context.setState(State.PLAY);
|
context.setState(State.PLAY);
|
||||||
|
|
||||||
var joinGamePacket = new JoinGamePacket();
|
var joinGamePacket = new JoinGamePacket();
|
||||||
joinGamePacket.setEntityId(random.nextInt());
|
joinGamePacket.setEntityId(random.nextInt());
|
||||||
joinGamePacket.setGameMode(player.getGameMode());
|
joinGamePacket.setGameMode(GameMode.SURVIVAL);
|
||||||
joinGamePacket.setDimension(0/*Overworld*/);
|
joinGamePacket.setDimension(0/*Overworld*/);
|
||||||
joinGamePacket.setDifficulty(Difficulty.PEACEFUL);
|
joinGamePacket.setDifficulty(Difficulty.PEACEFUL);
|
||||||
joinGamePacket.setLevelType(world.getLevelType());
|
joinGamePacket.setLevelType(LevelType.FLAT);
|
||||||
|
|
||||||
context.send(joinGamePacket);
|
context.send(joinGamePacket);
|
||||||
|
|
||||||
|
Location spawnLocation = new Location(7d, 130d, 7d);
|
||||||
|
|
||||||
var spawnPositionPacket = new SpawnPositionPacket();
|
var spawnPositionPacket = new SpawnPositionPacket();
|
||||||
spawnPositionPacket.setSpawn(player.getLocation());
|
spawnPositionPacket.setSpawn(spawnLocation);
|
||||||
|
|
||||||
context.send(spawnPositionPacket);
|
context.send(spawnPositionPacket);
|
||||||
|
|
||||||
@@ -120,49 +103,32 @@ public class PacketHandler {
|
|||||||
|
|
||||||
context.flushSending();
|
context.flushSending();
|
||||||
|
|
||||||
Location chunkLocation = player.getLocation().toChunkXZ();
|
|
||||||
Chunk chunk = world.getChunk(chunkLocation.getIntX(), chunkLocation.getIntZ());
|
|
||||||
|
|
||||||
var chunkDataPacket = new ChunkDataPacket();
|
var chunkDataPacket = new ChunkDataPacket();
|
||||||
chunkDataPacket.setX(chunk.getX());
|
chunkDataPacket.setX(0);
|
||||||
chunkDataPacket.setZ(chunk.getZ());
|
chunkDataPacket.setZ(0);
|
||||||
|
|
||||||
context.send(chunkDataPacket);
|
context.sendNow(chunkDataPacket);
|
||||||
|
|
||||||
for (int i = 1; i <= config.world().viewDistance(); i++) {
|
|
||||||
int minX = chunkLocation.getIntX() - i;
|
|
||||||
int minZ = chunkLocation.getIntZ() - i;
|
|
||||||
int maxX = chunkLocation.getIntX() + i;
|
|
||||||
int maxZ = chunkLocation.getIntZ() + i;
|
|
||||||
|
|
||||||
for (int z = minZ; z <= maxZ; z++) {
|
|
||||||
for (int x = minX; x <= maxX; x++) {
|
|
||||||
if ((z == minZ || z == maxZ) || (x == minX || x == maxX)) {
|
|
||||||
chunkDataPacket = new ChunkDataPacket();
|
|
||||||
chunkDataPacket.setX(x);
|
|
||||||
chunkDataPacket.setZ(z);
|
|
||||||
|
|
||||||
context.send(chunkDataPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.flushSending();
|
|
||||||
|
|
||||||
var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket();
|
var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket();
|
||||||
playerPositionAndLookPacket.setPosition(player.getLocation());
|
playerPositionAndLookPacket.setPosition(spawnLocation);
|
||||||
playerPositionAndLookPacket.setLook(new Look(0f, 0f));
|
playerPositionAndLookPacket.setLook(new Look(0f, 0f));
|
||||||
playerPositionAndLookPacket.setTeleportId(random.nextInt());
|
playerPositionAndLookPacket.setTeleportId(random.nextInt());
|
||||||
|
|
||||||
context.send(playerPositionAndLookPacket);
|
context.send(playerPositionAndLookPacket);
|
||||||
|
|
||||||
KeepAlivePacket keepAlivePacket = new KeepAlivePacket();
|
PingPacket pingPacket = new PingPacket();
|
||||||
keepAlivePacket.setPayload(System.currentTimeMillis());
|
pingPacket.setPayload(System.currentTimeMillis());
|
||||||
|
|
||||||
context.send(keepAlivePacket);
|
context.send(pingPacket);
|
||||||
|
|
||||||
context.flushSending();
|
context.flushSending();
|
||||||
|
|
||||||
|
// -- Эксперименты -- //
|
||||||
|
|
||||||
|
var openSignEditorPacket = new OpenSignEditorPacket();
|
||||||
|
openSignEditorPacket.setLocation(spawnLocation);
|
||||||
|
|
||||||
|
context.sendNow(openSignEditorPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String faviconToBase64(Path iconPath) {
|
private static String faviconToBase64(Path iconPath) {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package mc.server;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import mc.protocol.api.ConnectionContext;
|
|
||||||
import mc.protocol.model.Location;
|
|
||||||
import mc.protocol.utils.GameMode;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class Player {
|
|
||||||
|
|
||||||
private final ConnectionContext connectionContext;
|
|
||||||
private final UUID uuid;
|
|
||||||
private final String name;
|
|
||||||
private final GameMode gameMode;
|
|
||||||
private final Location location;
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,6 @@ public class Config {
|
|||||||
|
|
||||||
private final Server server = new Server();
|
private final Server server = new Server();
|
||||||
private final Players players = new Players();
|
private final Players players = new Players();
|
||||||
private final World world = new World();
|
|
||||||
|
|
||||||
private String motd;
|
private String motd;
|
||||||
private String disconnectReason;
|
private String disconnectReason;
|
||||||
@@ -33,23 +32,7 @@ public class Config {
|
|||||||
@Setter
|
@Setter
|
||||||
@ToString
|
@ToString
|
||||||
public static class Players {
|
public static class Players {
|
||||||
private final FakeOnline fakeOnline = new FakeOnline();
|
|
||||||
|
|
||||||
private int maxOnlile;
|
private int maxOnlile;
|
||||||
}
|
private int onlile;
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public static class FakeOnline {
|
|
||||||
private boolean enable;
|
|
||||||
private int value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public static class World {
|
|
||||||
private int viewDistance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,15 +27,10 @@ public class ConfigModule {
|
|||||||
|
|
||||||
config.server().host(fromYamlPath("server/host", map, "127.0.0.1"));
|
config.server().host(fromYamlPath("server/host", map, "127.0.0.1"));
|
||||||
config.server().port(fromYamlPath("server/port", map, 25565));
|
config.server().port(fromYamlPath("server/port", map, 25565));
|
||||||
|
|
||||||
config.motd(fromYamlPath("motd", map, ""));
|
config.motd(fromYamlPath("motd", map, ""));
|
||||||
config.disconnectReason(fromYamlPath("disconnect-reason", map, ""));
|
config.disconnectReason(fromYamlPath("disconnect-reason", map, ""));
|
||||||
|
|
||||||
config.players().maxOnlile(fromYamlPath("players/max-online", map, 0));
|
config.players().maxOnlile(fromYamlPath("players/max-online", map, 0));
|
||||||
config.players().fakeOnline().enable(fromYamlPath("players/fake-online/enable", map, false));
|
config.players().onlile(fromYamlPath("players/online", map, 0));
|
||||||
config.players().fakeOnline().value(fromYamlPath("players/fake-online/value", map, 0));
|
|
||||||
|
|
||||||
config.world().viewDistance(fromYamlPath("world/view-distance", map, 0));
|
|
||||||
|
|
||||||
if (Boolean.TRUE.equals(fromYamlPath("icon/enable", map, false))) {
|
if (Boolean.TRUE.equals(fromYamlPath("icon/enable", map, false))) {
|
||||||
config.iconPath(Paths.get(fromYamlPath("icon/path", map, "favicon.png")));
|
config.iconPath(Paths.get(fromYamlPath("icon/path", map, "favicon.png")));
|
||||||
|
|||||||
@@ -2,16 +2,14 @@ package mc.server.di;
|
|||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import mc.protocol.world.World;
|
|
||||||
import mc.server.PacketHandler;
|
import mc.server.PacketHandler;
|
||||||
import mc.server.config.Config;
|
import mc.server.config.Config;
|
||||||
import mc.server.service.PlayerManager;
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
public class PacketHandlerModule {
|
public class PacketHandlerModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
public PacketHandler providePacketHandler(Config config, World world, PlayerManager playerManager) {
|
public PacketHandler providePacketHandler(Config config) {
|
||||||
return new PacketHandler(config, world, playerManager);
|
return new PacketHandler(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
package mc.server.di;
|
|
||||||
|
|
||||||
import dagger.Module;
|
|
||||||
import dagger.Provides;
|
|
||||||
import mc.protocol.di.ServerScope;
|
|
||||||
import mc.server.service.PlayerManager;
|
|
||||||
|
|
||||||
@Module
|
|
||||||
public class PlayersModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@ServerScope
|
|
||||||
PlayerManager providePlayerManager() {
|
|
||||||
return new PlayerManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,14 @@
|
|||||||
package mc.server.di;
|
package mc.server.di;
|
||||||
|
|
||||||
import dagger.Component;
|
import dagger.Component;
|
||||||
import mc.protocol.di.ServerScope;
|
|
||||||
import mc.server.PacketHandler;
|
import mc.server.PacketHandler;
|
||||||
import mc.server.config.Config;
|
import mc.server.config.Config;
|
||||||
import mc.server.service.PlayerManager;
|
|
||||||
|
|
||||||
@Component(modules = {
|
@Component(modules = {
|
||||||
ConfigModule.class, PacketHandlerModule.class, WorldModule.class, PlayersModule.class
|
ConfigModule.class, PacketHandlerModule.class
|
||||||
})
|
})
|
||||||
@ServerScope
|
|
||||||
public interface ServerComponent {
|
public interface ServerComponent {
|
||||||
|
|
||||||
Config getConfig();
|
Config getConfig();
|
||||||
PacketHandler getPacketHandler();
|
PacketHandler getPacketHandler();
|
||||||
PlayerManager getPlayerManager();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package mc.server.di;
|
|
||||||
|
|
||||||
import dagger.Module;
|
|
||||||
import dagger.Provides;
|
|
||||||
import mc.protocol.di.ServerScope;
|
|
||||||
import mc.protocol.world.World;
|
|
||||||
import mc.server.world.VoidWorld;
|
|
||||||
|
|
||||||
@Module
|
|
||||||
public class WorldModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@ServerScope
|
|
||||||
public World provideWorld() {
|
|
||||||
return new VoidWorld();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package mc.server.service;
|
|
||||||
|
|
||||||
import mc.protocol.api.ConnectionContext;
|
|
||||||
import mc.protocol.model.Location;
|
|
||||||
import mc.protocol.utils.GameMode;
|
|
||||||
import mc.server.Player;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class PlayerManager {
|
|
||||||
|
|
||||||
private final LinkedList<Player> players = new LinkedList<>();
|
|
||||||
|
|
||||||
public Player addAndCreate(ConnectionContext context, String name, GameMode gameMode, Location location) {
|
|
||||||
context.setUsedContext(true);
|
|
||||||
Player player = new Player(context, UUID.randomUUID(), name, gameMode, location);
|
|
||||||
players.add(player);
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(Player player) {
|
|
||||||
players.remove(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int online() {
|
|
||||||
return players.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package mc.server.world;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import mc.protocol.world.Chunk;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class VoidChunk implements Chunk {
|
|
||||||
|
|
||||||
private final int x;
|
|
||||||
private final int z;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package mc.server.world;
|
|
||||||
|
|
||||||
import mc.protocol.model.Location;
|
|
||||||
import mc.protocol.utils.LevelType;
|
|
||||||
import mc.protocol.world.Chunk;
|
|
||||||
import mc.protocol.world.World;
|
|
||||||
|
|
||||||
public class VoidWorld implements World {
|
|
||||||
|
|
||||||
private static final Location spawn = new Location(7d, 130d, 7d);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LevelType getLevelType() {
|
|
||||||
return LevelType.FLAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location getSpawn() {
|
|
||||||
return VoidWorld.spawn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Chunk getChunk(int x, int z) {
|
|
||||||
return new VoidChunk(x, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,14 +10,9 @@ disconnect-reason: '&4Server is not available.'
|
|||||||
|
|
||||||
players:
|
players:
|
||||||
max-online: 0
|
max-online: 0
|
||||||
fake-online:
|
online: 0
|
||||||
enable: false
|
|
||||||
value: 0
|
|
||||||
|
|
||||||
# Размер значка: 64x64 px
|
# Размер значка: 64x64 px
|
||||||
icon:
|
icon:
|
||||||
enable: false
|
enable: false
|
||||||
path: favicon.png
|
path: favicon.png
|
||||||
|
|
||||||
world:
|
|
||||||
view-distance: 1
|
|
||||||
Reference in New Issue
Block a user