refactoring
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
20
server-new/src/main/java/mc/server/Player.java
Normal file
20
server-new/src/main/java/mc/server/Player.java
Normal 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;
|
||||
}
|
||||
27
server-new/src/main/java/mc/server/PlayerManager.java
Normal file
27
server-new/src/main/java/mc/server/PlayerManager.java
Normal 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();
|
||||
}
|
||||
}
|
||||
10
server-new/src/main/java/mc/server/ServetAttributes.java
Normal file
10
server-new/src/main/java/mc/server/ServetAttributes.java
Normal 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");
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
18
server-new/src/main/java/mc/server/di/WorldModule.java
Normal file
18
server-new/src/main/java/mc/server/di/WorldModule.java
Normal 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();
|
||||
}
|
||||
}
|
||||
142
server-new/src/main/java/mc/server/processor/ProcessorLogin.java
Normal file
142
server-new/src/main/java/mc/server/processor/ProcessorLogin.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
server-new/src/main/java/mc/server/util/LocationUtils.java
Normal file
12
server-new/src/main/java/mc/server/util/LocationUtils.java
Normal 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);
|
||||
}
|
||||
}
|
||||
11
server-new/src/main/java/mc/server/world/VoidChunk.java
Normal file
11
server-new/src/main/java/mc/server/world/VoidChunk.java
Normal 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;
|
||||
}
|
||||
26
server-new/src/main/java/mc/server/world/VoidWorld.java
Normal file
26
server-new/src/main/java/mc/server/world/VoidWorld.java
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user