Archived
0

Первые намётки событийной модели

This commit is contained in:
2018-05-02 15:27:39 +03:00
parent 6295c63443
commit 31f3d21997
15 changed files with 309 additions and 96 deletions

View File

@@ -0,0 +1,42 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-05-02
*/
package mc.core.network.proto_125.netty;
import com.google.common.eventbus.Subscribe;
import lombok.RequiredArgsConstructor;
import mc.core.Config;
import mc.core.Player;
import mc.core.PlayerManager;
import mc.core.events.LoginEvent;
import mc.core.events.ServerPingEvent;
import java.util.Optional;
@RequiredArgsConstructor
public class EventListener {
private final Config config;
private final PlayerManager playerManager;
@Subscribe
public void onServerPingEvent(ServerPingEvent event) {
if (event.isLastProcess() || event.isCanceled()) return;
event.setDescription(config.getDescriptionServer());
event.setOnline(playerManager.getCountOnlinePlayers());
event.setMaxOnline(config.getMaxPlayers());
}
@Subscribe
public void onLoginEvent(LoginEvent event) {
if (event.isLastProcess()) return;
Optional<Player> optPlayer = playerManager.getPlayer(event.getPlayerName());
if (optPlayer.isPresent() && optPlayer.get().isOnline()) {
event.setDeny(true);
event.setDenyReason("Player is exists in server");
}
}
}

View File

@@ -13,11 +13,16 @@ import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import mc.core.Config;
import mc.core.PlayerManager;
import mc.core.events.EventBusGetter;
import mc.core.network.Server;
import mc.core.network.StartServerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Map;
@Slf4j
@@ -31,6 +36,20 @@ public class NettyServer implements Server {
@Setter
private int workerGroupCount = 0;
private EventLoopGroup bossGroup, workerGroup;
private EventListener eventListener;
@PostConstruct
public void init() {
eventListener = new EventListener(
applicationContext.getBean(Config.class),
applicationContext.getBean(PlayerManager.class));
EventBusGetter.INSTANCE.register(eventListener);
}
@PreDestroy
public void destruct() {
EventBusGetter.INSTANCE.unregister(eventListener);
}
private ChannelInitializer buildChannelInitializer() {
return new ChannelInitializer<SocketChannel>() {

View File

@@ -12,6 +12,7 @@ import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import mc.core.*;
import mc.core.events.*;
import mc.core.network.CSPacket;
import mc.core.network.proto_125.netty.wrappers.WrapperNetChannel;
import mc.core.network.proto_125.packets.*;
@@ -61,121 +62,145 @@ public class PacketHandler extends SimpleChannelInboundHandler<CSPacket> {
}
}
public void onPingPacket(Channel channel, PingPacket packet) {
KickPacket pkt = new KickPacket();
pkt.setPongMessage(config.getDescriptionServer(), 0, config.getMaxPlayers());
channel.writeAndFlush(pkt);
private void onPingPacket(Channel channel, PingPacket packet) {
ServerPingEvent event = new ServerPingEvent(channel.remoteAddress());
EventBusGetter.INSTANCE.post(event);
if (event.isCanceled()) {
channel.disconnect();
} else {
String response = String.format("%s%s%d%s%d",
event.getDescription(), ChatStyle.SPECIAL_CHAR,
event.getOnline(), ChatStyle.SPECIAL_CHAR,
event.getMaxOnline()
);
KickPacket pkt = new KickPacket();
pkt.setReason(response);
channel.writeAndFlush(pkt);
}
}
public void onHandshakePacket(Channel channel, HandshakePacket packet) {
private void onHandshakePacket(Channel channel, HandshakePacket packet) {
channel.writeAndFlush(packet);
}
public void onLoginPacket(Channel channel, LoginPacket packet) {
Player player;
private void onLoginPacket(Channel channel, LoginPacket packet) {
LoginEvent event = new LoginEvent(channel.remoteAddress());
event.setPlayerName(packet.getPlayerName());
EventBusGetter.INSTANCE.post(event);
Optional<Player> optPlayer = playerManager.getPlayer(packet.getPlayerName());
if (optPlayer.isPresent()) {
player = optPlayer.get();
if (player.isOnline()) {
channel.writeAndFlush(new KickPacket("Player is exists in server"))
.addListener(ChannelFutureListener.CLOSE);
return;
}
if (event.isDeny()) {
channel.writeAndFlush(new KickPacket(event.getDenyReason()))
.addListener(ChannelFutureListener.CLOSE);
} else {
player = playerManager.createPlayer(packet.getPlayerName());
Player player = playerManager.createPlayer(packet.getPlayerName());
player.setLocation(world.getSpawn());
player.setLook(new Look(0f, 0f));
// Response login
packet.setPlayerId(player.getId());
packet.setLevelType("flat");
packet.setServerMode(1/*creative*/);
packet.setDimension(0/*Overworld*/);
packet.setDifficulty(0/*Peaceful*/);
packet.setMaxPlayers(config.getMaxPlayers());
channel.write(packet);
// send Spawn position
SpawnPositionPacket spawnPkt = new SpawnPositionPacket();
spawnPkt.setLocation(world.getSpawn());
channel.write(spawnPkt);
// send Player abilities
PlayerAbilitiesPacket abilitiesPkt = new PlayerAbilitiesPacket();
abilitiesPkt.setCanFly(true);
abilitiesPkt.setFlying(true);
abilitiesPkt.setGodMode(true);
abilitiesPkt.setInstantDestroyBlocks(true);
channel.write(abilitiesPkt);
// send Chunk allocation
ChunkAllocationPacket chInitPkt = new ChunkAllocationPacket();
chInitPkt.setX(0);
chInitPkt.setZ(0);
chInitPkt.setInitChunk(true);
channel.write(chInitPkt);
// send Chunk data
ChunkDataPacket chDataPkt = new ChunkDataPacket();
chDataPkt.setX(0);
chDataPkt.setZ(0);
chDataPkt.setChunk(world.getChunk(0, 0));
chDataPkt.setNeedInitChunk(true);
chDataPkt.setYMin(1);
chDataPkt.setYMax(0);
channel.write(chDataPkt);
// send Position and look
PositionAndLookPacket posLookPkt = new PositionAndLookPacket();
posLookPkt.setLocation(player.getLocation());
posLookPkt.setStance(player.getLocation().getY() + 1.64d);
posLookPkt.setLook(player.getLook());
posLookPkt.setOnGround(false);
channel.write(posLookPkt);
channel.flush();
// send Spawn named entity
SpawnNamedEntityPacket spawnPlayer = new SpawnNamedEntityPacket();
spawnPlayer.setId(player.getId());
spawnPlayer.setEntityName(player.getName());
spawnPlayer.setPosition(player.getLocation());
spawnPlayer.setLook(player.getLook());
playerManager.getBroadcastChannel().writeAndFlush(spawnPlayer);
channel.attr(ATTR_PLAYER).set(player);
player.setChannel(new WrapperNetChannel(channel));
playerManager.joinServer(player);
}
// Response login
packet.setPlayerId(player.getId());
packet.setLevelType("flat");
packet.setServerMode(1/*creative*/);
packet.setDimension(0/*Overworld*/);
packet.setDifficulty(0/*Peaceful*/);
packet.setMaxPlayers(config.getMaxPlayers());
channel.write(packet);
// send Spawn position
SpawnPositionPacket spawnPkt = new SpawnPositionPacket();
spawnPkt.setLocation(world.getSpawn());
channel.write(spawnPkt);
// send Player abilities
PlayerAbilitiesPacket abilitiesPkt = new PlayerAbilitiesPacket();
abilitiesPkt.setCanFly(true);
abilitiesPkt.setFlying(true);
abilitiesPkt.setGodMode(true);
abilitiesPkt.setInstantDestroyBlocks(true);
channel.write(abilitiesPkt);
// send Chunk allocation
ChunkAllocationPacket chInitPkt = new ChunkAllocationPacket();
chInitPkt.setX(0);
chInitPkt.setZ(0);
chInitPkt.setInitChunk(true);
channel.write(chInitPkt);
// send Chunk data
ChunkDataPacket chDataPkt = new ChunkDataPacket();
chDataPkt.setX(0);
chDataPkt.setZ(0);
chDataPkt.setChunk(world.getChunk(0, 0));
chDataPkt.setNeedInitChunk(true);
chDataPkt.setYMin(1);
chDataPkt.setYMax(0);
channel.write(chDataPkt);
// send Position and look
PositionAndLookPacket posLookPkt = new PositionAndLookPacket();
posLookPkt.setLocation(player.getLocation());
posLookPkt.setStance(player.getLocation().getY() + 1.64d);
posLookPkt.setLook(player.getLook());
posLookPkt.setOnGround(false);
channel.write(posLookPkt);
channel.flush();
// send Spawn named entity
SpawnNamedEntityPacket spawnPlayer = new SpawnNamedEntityPacket();
spawnPlayer.setId(player.getId());
spawnPlayer.setEntityName(player.getName());
spawnPlayer.setPosition(player.getLocation());
spawnPlayer.setLook(player.getLook());
playerManager.getBroadcastChannel().writeAndFlush(spawnPlayer);
channel.attr(ATTR_PLAYER).set(player);
player.setChannel(new WrapperNetChannel(channel));
playerManager.joinServer(player);
}
public void onKickPacket(Channel channel, KickPacket packet) {
private void onKickPacket(Channel channel, KickPacket packet) {
if (packet.getReason().equals("Quitting")) {
channel.disconnect();
}
}
public void onPlayerPositionPacket(Channel channel, PlayerPositionPacket packet) {
private void onPlayerPositionPacket(Channel channel, PlayerPositionPacket packet) {
Player player = channel.attr(ATTR_PLAYER).get();
player.getLocation().setX(packet.getX());
player.getLocation().setY(packet.getY());
player.getLocation().setZ(packet.getZ());
PlayerPositionEvent event = new PlayerPositionEvent(player);
event.setNewPosition(new Location(packet.getX(), packet.getY(), packet.getZ()));
EventBusGetter.INSTANCE.post(event);
if (!event.isCanceled()) {
player.getLocation().setX(event.getNewPosition().getX());
player.getLocation().setY(event.getNewPosition().getY());
player.getLocation().setZ(event.getNewPosition().getZ());
//TODO если позиция была изменена, нужно оповестить клиент
}
}
public void onPlayerLookPacket(Channel channel, PlayerLookPacket packet) {
private void onPlayerLookPacket(Channel channel, PlayerLookPacket packet) {
Player player = channel.attr(ATTR_PLAYER).get();
player.getLook().setYaw(packet.getYaw());
player.getLook().setPitch(packet.getPitch());
PlayerLookEvent event = new PlayerLookEvent(player);
event.setNewLook(new Look(packet.getYaw(), packet.getPitch()));
EventBusGetter.INSTANCE.post(event);
if (!event.isCanceled()) {
player.getLook().setYaw(event.getNewLook().getYaw());
player.getLook().setPitch(event.getNewLook().getPitch());
//TODO если обзор был изменен, нужно оповестить клиент
}
}
public void onPlayerAbilitiesPacket(Channel channel, PlayerAbilitiesPacket packet) {
log.debug("Player new sets: {}", packet.toString());
private void onPlayerAbilitiesPacket(Channel channel, PlayerAbilitiesPacket packet) {
Player player = channel.attr(ATTR_PLAYER).get();
player.setFlying(packet.isFlying());
}
public void onChatMessagePacket(Channel channel, ChatMessagePacket packet) {
private void onChatMessagePacket(Channel channel, ChatMessagePacket packet) {
log.info(CHAT_MARKER, "<{}>: {}", channel.attr(ATTR_PLAYER).get().getName(), ChatStyle.escapeStyle(packet.getMessage()));
playerManager.getBroadcastChannel().writeAndFlush(packet);
}