Archived
0

refactoring

This commit is contained in:
2021-06-17 15:06:10 +03:00
parent e7b5120661
commit e7f7b9654e
38 changed files with 252 additions and 961 deletions

View File

@@ -44,7 +44,7 @@ public class NettyServer {
socketChannel.pipeline()
.addLast("packet_splitter", new ProtocolSplitter())
.addLast("logger", new LoggingHandler(LogLevel.DEBUG))
.addLast("packet_decoder", new ProtocolDecoder())
.addLast("packet_decoder", new ProtocolDecoder(false))
.addLast("packet_encoder", new ProtocolEncoder())
.addLast("packet_handler", new ProtocolInboundHandler(protocolHandlersBus));
}

View File

@@ -0,0 +1,20 @@
package mc.server;
import io.netty.channel.ChannelHandlerContext;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import mc.protocol.model.Location;
import mc.protocol.utils.GameMode;
import java.util.UUID;
@RequiredArgsConstructor
@Getter
public class Player {
private final ChannelHandlerContext ctx;
private final UUID uuid;
private final String name;
private final GameMode gameMode;
private final Location location;
}

View File

@@ -0,0 +1,27 @@
package mc.server;
import io.netty.channel.ChannelHandlerContext;
import mc.protocol.model.Location;
import mc.protocol.utils.GameMode;
import java.util.LinkedList;
import java.util.UUID;
public class PlayerManager {
private final LinkedList<Player> players = new LinkedList<>();
public Player create(ChannelHandlerContext ctx, String name, GameMode gameMode, Location location) {
Player player = new Player(ctx, 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

@@ -0,0 +1,10 @@
package mc.server;
import io.netty.util.AttributeKey;
import lombok.experimental.UtilityClass;
@UtilityClass
public class ServetAttributes {
public static final AttributeKey<Player> PLAYER = AttributeKey.newInstance("PLAYER");
}

View File

@@ -0,0 +1,17 @@
package mc.server.di;
import dagger.Module;
import dagger.Provides;
import mc.server.PlayerManager;
import javax.inject.Singleton;
@Module
public class PlayerManagerModule {
@Provides
@Singleton
PlayerManager providePlayerManager() {
return new PlayerManager();
}
}

View File

@@ -5,11 +5,12 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoSet;
import lombok.RequiredArgsConstructor;
import mc.server.processor.PacketProcessor;
import mc.server.processor.ProcessorHandshake;
import mc.server.processor.ProcessorStatus;
import mc.protocol.world.World;
import mc.server.PlayerManager;
import mc.server.processor.*;
import javax.inject.Singleton;
import java.util.Random;
@Module
@RequiredArgsConstructor
@@ -30,4 +31,18 @@ public class ProcessorModule {
PacketProcessor provideProcessorStatus() {
return new ProcessorStatus(config);
}
@Provides
@IntoSet
@Singleton
PacketProcessor provideProcessorLogin(PlayerManager playerManager, World world) {
return new ProcessorLogin(playerManager, new Random(System.currentTimeMillis()), config, world);
}
@Provides
@IntoSet
@Singleton
PacketProcessor provideProcessorPlay() {
return new ProcessorPlay();
}
}

View File

@@ -8,7 +8,10 @@ import mc.server.processor.PacketProcessor;
import javax.inject.Singleton;
import java.util.Set;
@Component(modules = {ServerModule.class, ProcessorModule.class})
@Component(modules = {
ServerModule.class, ProcessorModule.class, PlayerManagerModule.class,
WorldModule.class
})
@Singleton
public interface ServerComponent {

View File

@@ -0,0 +1,18 @@
package mc.server.di;
import dagger.Module;
import dagger.Provides;
import mc.protocol.world.World;
import mc.server.world.VoidWorld;
import javax.inject.Singleton;
@Module
public class WorldModule {
@Provides
@Singleton
World provideWorld() {
return new VoidWorld();
}
}

View File

@@ -0,0 +1,142 @@
package mc.server.processor;
import com.typesafe.config.Config;
import io.netty.channel.ChannelHandlerContext;
import lombok.RequiredArgsConstructor;
import mc.protocol.ProtocolAttributes;
import mc.protocol.State;
import mc.protocol.handler.ProtocolHandlersBus;
import mc.protocol.model.Location;
import mc.protocol.model.Look;
import mc.protocol.packets.KeepAlivePacket;
import mc.protocol.packets.login.client.LoginStartPacket;
import mc.protocol.packets.login.server.LoginSuccessPacket;
import mc.protocol.packets.play.server.*;
import mc.protocol.utils.Difficulty;
import mc.protocol.utils.GameMode;
import mc.protocol.world.Chunk;
import mc.protocol.world.World;
import mc.server.Player;
import mc.server.PlayerManager;
import mc.server.ServetAttributes;
import mc.server.util.LocationUtils;
import java.util.Random;
@RequiredArgsConstructor
public class ProcessorLogin implements PacketProcessor {
private final PlayerManager playerManager;
private final Random random;
private final Config config;
private final World world;
@Override
public void setup(ProtocolHandlersBus protocolHandlersBus) {
protocolHandlersBus.addHandler(State.LOGIN, LoginStartPacket.class, this::login);
}
private void login(ChannelHandlerContext ctx, LoginStartPacket packet) {
Player player = playerManager.create(ctx, packet.getName(), GameMode.SURVIVAL, world.getSpawn());
ctx.channel().attr(ServetAttributes.PLAYER).set(player);
sendLoginSuccess(player);
sendJoinGame(player);
sendSpawnPosition(player);
sendPlayerAbilities(player);
ctx.flush();
sendWorldData(player);
sendPlayerPositionAndLook(player);
sendKeepAlive(player);
ctx.flush();
}
private void sendLoginSuccess(Player player) {
var loginSuccessPacket = new LoginSuccessPacket();
loginSuccessPacket.setUuid(player.getUuid());
loginSuccessPacket.setName(player.getName());
player.getCtx().writeAndFlush(loginSuccessPacket);
player.getCtx().channel().attr(ProtocolAttributes.STATE).set(State.PLAY);
}
private void sendJoinGame(Player player) {
var joinGamePacket = new JoinGamePacket();
joinGamePacket.setEntityId(random.nextInt());
joinGamePacket.setGameMode(player.getGameMode());
joinGamePacket.setDimension(0/*Overworld*/);
joinGamePacket.setDifficulty(Difficulty.PEACEFUL);
joinGamePacket.setLevelType(world.getLevelType());
player.getCtx().write(joinGamePacket);
}
private void sendSpawnPosition(Player player) {
var spawnPositionPacket = new SpawnPositionPacket();
spawnPositionPacket.setSpawn(player.getLocation());
player.getCtx().write(spawnPositionPacket);
}
private void sendPlayerAbilities(Player player) {
var playerAbilitiesPacket = new PlayerAbilitiesPacket();
playerAbilitiesPacket.setCatFly(true);
playerAbilitiesPacket.setFlying(true);
playerAbilitiesPacket.setCreativeMode(false);
playerAbilitiesPacket.setInvulnerable(true);
playerAbilitiesPacket.setFieldOfView(0.0f);
playerAbilitiesPacket.setFlyingSpeed(0.05f);
player.getCtx().write(playerAbilitiesPacket);
}
@SuppressWarnings("java:S2589")
private void sendWorldData(Player player) {
Location chunkLocation = LocationUtils.toChunkXZ(player.getLocation());
Chunk chunk = world.getChunk((int) chunkLocation.getX(), (int) chunkLocation.getZ());
var chunkDataPacket = new ChunkDataPacket();
chunkDataPacket.setX(chunk.getX());
chunkDataPacket.setZ(chunk.getZ());
player.getCtx().write(chunkDataPacket);
for (int i = 1; i <= config.getInt("world.view-distance"); i++) {
int minX = (int) chunkLocation.getX() - i;
int minZ = (int) chunkLocation.getZ() - i;
int maxX = (int) chunkLocation.getX() + i;
int maxZ = (int) chunkLocation.getZ() + 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);
player.getCtx().write(chunkDataPacket);
}
}
}
}
player.getCtx().flush();
}
private void sendPlayerPositionAndLook(Player player) {
var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket();
playerPositionAndLookPacket.setPosition(player.getLocation());
playerPositionAndLookPacket.setLook(new Look().set(0f, 0f));
playerPositionAndLookPacket.setTeleportId(random.nextInt());
player.getCtx().write(playerPositionAndLookPacket);
}
private void sendKeepAlive(Player player) {
var keepAlivePacket = new KeepAlivePacket();
keepAlivePacket.setPayload(System.currentTimeMillis());
player.getCtx().write(keepAlivePacket);
}
}

View File

@@ -0,0 +1,30 @@
package mc.server.processor;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import mc.protocol.State;
import mc.protocol.handler.ProtocolHandlersBus;
import mc.protocol.packets.KeepAlivePacket;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ProcessorPlay implements PacketProcessor {
@Override
public void setup(ProtocolHandlersBus protocolHandlersBus) {
protocolHandlersBus
.addHandler(State.PLAY, KeepAlivePacket.class, this::keepAlive);
}
private void keepAlive(ChannelHandlerContext ctx, KeepAlivePacket packet) {
try {
TimeUnit.MILLISECONDS.sleep(50);
ctx.writeAndFlush(packet);
} catch (InterruptedException e) {
if (log.isTraceEnabled()) {
log.trace("{}", e.getMessage(), e);
}
}
}
}

View File

@@ -0,0 +1,12 @@
package mc.server.util;
import lombok.experimental.UtilityClass;
import mc.protocol.model.Location;
@UtilityClass
public class LocationUtils {
public Location toChunkXZ(Location location) {
return new Location().set((int) location.getX() >> 4, 0d, (int) location.getZ() >> 4);
}
}

View File

@@ -0,0 +1,11 @@
package mc.server.world;
import lombok.Data;
import mc.protocol.world.Chunk;
@Data
public class VoidChunk implements Chunk {
private final int x;
private final int z;
}

View File

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