Archived
0

PlayerManager

This commit is contained in:
2021-05-09 20:07:08 +03:00
parent c4767bd240
commit b049352fe3
13 changed files with 167 additions and 13 deletions

View File

@@ -2,12 +2,16 @@ 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 {
@@ -15,6 +19,14 @@ 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();
@@ -25,6 +37,27 @@ 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);

View File

@@ -3,8 +3,16 @@ 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");
} }

View File

@@ -28,7 +28,9 @@ 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);
poolNettyConnectionContext.returnObject(context); if (!context.isUsedContext()) {
poolNettyConnectionContext.returnObject(context);
}
poolPackets.returnObject(packet); poolPackets.returnObject(packet);
} }

View File

@@ -3,11 +3,37 @@ 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();

View File

@@ -17,6 +17,7 @@ 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;
@@ -36,6 +37,8 @@ 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);
@@ -48,6 +51,9 @@ 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);
} }

View File

@@ -20,6 +20,7 @@ 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;
@@ -48,6 +49,7 @@ 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))
@@ -57,7 +59,10 @@ 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 -> connectionContext.setState(null)); server.onDisonnect(connectionContext -> {
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, KeepAlivePacket.class, packetHandler::onKeepAlive);

View File

@@ -18,6 +18,7 @@ import mc.protocol.utils.GameMode;
import mc.protocol.world.Chunk; import mc.protocol.world.Chunk;
import mc.protocol.world.World; 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;
@@ -26,7 +27,6 @@ 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.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@@ -36,6 +36,7 @@ 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 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());
@@ -65,6 +66,8 @@ public class PacketHandler {
serverInfo.players().max(config.players().maxOnlile()); serverInfo.players().max(config.players().maxOnlile());
if (config.players().fakeOnline().enable()) { if (config.players().fakeOnline().enable()) {
serverInfo.players().online(config.players().fakeOnline().value()); 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()));
@@ -81,16 +84,19 @@ public class PacketHandler {
@SuppressWarnings("java:S2589") @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(UUID.randomUUID()); loginSuccessPacket.setUuid(player.getUuid());
loginSuccessPacket.setName(loginStartPacket.getName()); loginSuccessPacket.setName(player.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(GameMode.SURVIVAL); joinGamePacket.setGameMode(player.getGameMode());
joinGamePacket.setDimension(0/*Overworld*/); joinGamePacket.setDimension(0/*Overworld*/);
joinGamePacket.setDifficulty(Difficulty.PEACEFUL); joinGamePacket.setDifficulty(Difficulty.PEACEFUL);
joinGamePacket.setLevelType(world.getLevelType()); joinGamePacket.setLevelType(world.getLevelType());
@@ -98,7 +104,7 @@ public class PacketHandler {
context.send(joinGamePacket); context.send(joinGamePacket);
var spawnPositionPacket = new SpawnPositionPacket(); var spawnPositionPacket = new SpawnPositionPacket();
spawnPositionPacket.setSpawn(world.getSpawn()); spawnPositionPacket.setSpawn(player.getLocation());
context.send(spawnPositionPacket); context.send(spawnPositionPacket);
@@ -114,7 +120,7 @@ public class PacketHandler {
context.flushSending(); context.flushSending();
Location chunkLocation = world.getSpawn().toChunkXZ(); Location chunkLocation = player.getLocation().toChunkXZ();
Chunk chunk = world.getChunk(chunkLocation.getIntX(), chunkLocation.getIntZ()); Chunk chunk = world.getChunk(chunkLocation.getIntX(), chunkLocation.getIntZ());
var chunkDataPacket = new ChunkDataPacket(); var chunkDataPacket = new ChunkDataPacket();
@@ -145,7 +151,7 @@ public class PacketHandler {
context.flushSending(); context.flushSending();
var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket(); var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket();
playerPositionAndLookPacket.setPosition(world.getSpawn()); playerPositionAndLookPacket.setPosition(player.getLocation());
playerPositionAndLookPacket.setLook(new Look(0f, 0f)); playerPositionAndLookPacket.setLook(new Look(0f, 0f));
playerPositionAndLookPacket.setTeleportId(random.nextInt()); playerPositionAndLookPacket.setTeleportId(random.nextInt());

View File

@@ -0,0 +1,20 @@
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;
}

View File

@@ -5,12 +5,13 @@ import dagger.Provides;
import mc.protocol.world.World; 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) { public PacketHandler providePacketHandler(Config config, World world, PlayerManager playerManager) {
return new PacketHandler(config, world); return new PacketHandler(config, world, playerManager);
} }
} }

View File

@@ -0,0 +1,16 @@
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();
}
}

View File

@@ -4,13 +4,15 @@ import dagger.Component;
import mc.protocol.di.ServerScope; 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 ConfigModule.class, PacketHandlerModule.class, WorldModule.class, PlayersModule.class
}) })
@ServerScope @ServerScope
public interface ServerComponent { public interface ServerComponent {
Config getConfig(); Config getConfig();
PacketHandler getPacketHandler(); PacketHandler getPacketHandler();
PlayerManager getPlayerManager();
} }

View File

@@ -0,0 +1,29 @@
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();
}
}

View File

@@ -11,7 +11,7 @@ disconnect-reason: '&4Server is not available.'
players: players:
max-online: 0 max-online: 0
fake-online: fake-online:
enable: true enable: false
value: 0 value: 0
# Размер значка: 64x64 px # Размер значка: 64x64 px