переведен функционал keep alive на сетевой модуль
This commit is contained in:
@@ -16,9 +16,6 @@ import java.util.Optional;
|
|||||||
|
|
||||||
public class FakePlayerManager implements PlayerManager {
|
public class FakePlayerManager implements PlayerManager {
|
||||||
public static class FakeNetChannet implements NetChannel {
|
public static class FakeNetChannet implements NetChannel {
|
||||||
@Override
|
|
||||||
public void sendKeepAlive() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendTimeUpdate(long time, long age) {
|
public void sendTimeUpdate(long time, long age) {
|
||||||
|
|||||||
@@ -16,11 +16,6 @@ import java.util.stream.Stream;
|
|||||||
public class BroadcastNetChannel implements NetChannel {
|
public class BroadcastNetChannel implements NetChannel {
|
||||||
private final Stream<Player> playerStream;
|
private final Stream<Player> playerStream;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendKeepAlive() {
|
|
||||||
playerStream.forEach(player -> player.getChannel().sendKeepAlive());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendTimeUpdate(final long time, final long age) {
|
public void sendTimeUpdate(final long time, final long age) {
|
||||||
playerStream.forEach(player -> player.getChannel().sendTimeUpdate(time, age));
|
playerStream.forEach(player -> player.getChannel().sendTimeUpdate(time, age));
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import mc.core.text.Text;
|
|||||||
import mc.core.text.Title;
|
import mc.core.text.Title;
|
||||||
|
|
||||||
public interface NetChannel {
|
public interface NetChannel {
|
||||||
void sendKeepAlive();
|
|
||||||
void sendTimeUpdate(long time, long age);
|
void sendTimeUpdate(long time, long age);
|
||||||
default void sendChatMessage(Text text) {
|
default void sendChatMessage(Text text) {
|
||||||
sendChatMessage(text, MessageType.CHAT_MESSAGE);
|
sendChatMessage(text, MessageType.CHAT_MESSAGE);
|
||||||
|
|||||||
@@ -24,22 +24,14 @@ import static org.slf4j.helpers.MessageFormatter.format;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class H2PlayerManager implements PlayerManager, Runnable {
|
public class H2PlayerManager implements PlayerManager {
|
||||||
@Setter
|
@Setter
|
||||||
@Autowired
|
@Autowired
|
||||||
private H2PlayerDAO h2playerDao;
|
private H2PlayerDAO h2playerDao;
|
||||||
private List<H2Player> playerList = Collections.synchronizedList(new ArrayList<>());
|
private List<H2Player> playerList = Collections.synchronizedList(new ArrayList<>());
|
||||||
private final Object lock = new Object();
|
|
||||||
@Setter
|
|
||||||
private int keepAliveInterval = 1;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private World world;
|
private World world;
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
(new Thread(this, "KeepAlive")).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Player createPlayer(String name, EntityLocation location, World world) {
|
public Player createPlayer(String name, EntityLocation location, World world) {
|
||||||
//TODO в дальнейшем следует в этом методе только имплементацию Player
|
//TODO в дальнейшем следует в этом методе только имплементацию Player
|
||||||
@@ -65,11 +57,8 @@ public class H2PlayerManager implements PlayerManager, Runnable {
|
|||||||
public void joinServer(Player player) {
|
public void joinServer(Player player) {
|
||||||
//TODO в дальнейшем следует именно этому методу передать функции инсерта в БД
|
//TODO в дальнейшем следует именно этому методу передать функции инсерта в БД
|
||||||
H2Player h2Player = (H2Player) player;
|
H2Player h2Player = (H2Player) player;
|
||||||
synchronized (lock) {
|
playerList.add(h2Player);
|
||||||
playerList.add(h2Player);
|
h2Player.setOnline(true);
|
||||||
h2Player.setOnline(true);
|
|
||||||
lock.notify();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,13 +68,9 @@ public class H2PlayerManager implements PlayerManager, Runnable {
|
|||||||
h2playerDao.update(h2Player);
|
h2playerDao.update(h2Player);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error(format("Update player '{}'", h2Player.getName()).getMessage(), e);
|
log.error(format("Update player '{}'", h2Player.getName()).getMessage(), e);
|
||||||
synchronized (lock) {
|
playerList.remove(h2Player);
|
||||||
playerList.remove(h2Player);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
h2Player.setId(0);
|
|
||||||
h2Player.setOnline(false);
|
h2Player.setOnline(false);
|
||||||
h2Player.setWorld(null);
|
|
||||||
h2Player.getLoadedChunks().clear();
|
h2Player.getLoadedChunks().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,27 +138,4 @@ public class H2PlayerManager implements PlayerManager, Runnable {
|
|||||||
return h2Player;
|
return h2Player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
|
||||||
while(getCountPlayers() == 0) {
|
|
||||||
synchronized (lock) {
|
|
||||||
try {
|
|
||||||
lock.wait();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getBroadcastChannel().sendKeepAlive();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(keepAliveInterval);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package mc.core.network.proto_1_12_2.netty;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import mc.core.network.proto_1_12_2.packets.KeepAlivePacket;
|
||||||
|
import mc.core.player.PlayerManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class KeepAliveThread extends Thread {
|
||||||
|
private static final Random RAND = new Random();
|
||||||
|
private final Object lock = new Object();
|
||||||
|
@Autowired
|
||||||
|
private PlayerManager playerManager;
|
||||||
|
@Setter
|
||||||
|
private int interval = 10;
|
||||||
|
|
||||||
|
public void notifyLock() {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
while(playerManager.getCountPlayers() == 0) {
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playerManager.getBroadcastChannel().writeAndFlush(new KeepAlivePacket(RAND.nextLong()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(interval);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
/*
|
|
||||||
* DmitriyMX <dimon550@gmail.com>
|
|
||||||
* 2018-06-10
|
|
||||||
*/
|
|
||||||
package mc.core.network.proto_1_12_2.netty;
|
package mc.core.network.proto_1_12_2.netty;
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
@@ -22,16 +19,20 @@ import mc.core.network.proto_1_12_2.packets.StatusResponsePacket;
|
|||||||
import mc.core.player.Player;
|
import mc.core.player.Player;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Component
|
||||||
public class NettyServer implements Server {
|
public class NettyServer implements Server {
|
||||||
public static final AttributeKey<State> ATTR_STATE = AttributeKey.newInstance("ATTR_STATE");
|
public static final AttributeKey<State> ATTR_STATE = AttributeKey.newInstance("ATTR_STATE");
|
||||||
public static final AttributeKey<Player> ATTR_PLAYER = AttributeKey.newInstance("ATTR_PLAYER");
|
public static final AttributeKey<Player> ATTR_PLAYER = AttributeKey.newInstance("ATTR_PLAYER");
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApplicationContext applicationContext;
|
private ApplicationContext context;
|
||||||
|
@Autowired
|
||||||
|
private KeepAliveThread keepAliveThread;
|
||||||
@Setter
|
@Setter
|
||||||
private String host;
|
private String host;
|
||||||
@Setter
|
@Setter
|
||||||
@@ -44,7 +45,7 @@ public class NettyServer implements Server {
|
|||||||
return new ChannelInitializer<SocketChannel>() {
|
return new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(SocketChannel socketChannel) {
|
protected void initChannel(SocketChannel socketChannel) {
|
||||||
Map<String, ChannelHandler> beans = applicationContext.getBeansOfType(ChannelHandler.class);
|
Map<String, ChannelHandler> beans = context.getBeansOfType(ChannelHandler.class);
|
||||||
beans.forEach(socketChannel.pipeline()::addLast);
|
beans.forEach(socketChannel.pipeline()::addLast);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -73,7 +74,9 @@ public class NettyServer implements Server {
|
|||||||
|
|
||||||
log.info("Start server: {}:{}", host, port);
|
log.info("Start server: {}:{}", host, port);
|
||||||
try {
|
try {
|
||||||
serverBootstrap.bind(host, port).sync().channel().closeFuture().sync();
|
ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync();
|
||||||
|
keepAliveThread.start();
|
||||||
|
channelFuture.channel().closeFuture().sync();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new StartServerException(e);
|
throw new StartServerException(e);
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,7 @@ public class NettyServer implements Server {
|
|||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
log.info("Server shutdown");
|
log.info("Server shutdown");
|
||||||
|
keepAliveThread.interrupt();
|
||||||
workerGroup.shutdownGracefully();
|
workerGroup.shutdownGracefully();
|
||||||
bossGroup.shutdownGracefully();
|
bossGroup.shutdownGracefully();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
/*
|
|
||||||
* DmitriyMX <dimon550@gmail.com>
|
|
||||||
* 2018-06-23
|
|
||||||
*/
|
|
||||||
package mc.core.network.proto_1_12_2.netty.handlers;
|
package mc.core.network.proto_1_12_2.netty.handlers;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
@@ -10,6 +6,7 @@ import mc.core.eventbus.events.CS_PlayerMoveEvent;
|
|||||||
import mc.core.eventbus.EventBusGetter;
|
import mc.core.eventbus.EventBusGetter;
|
||||||
import mc.core.network.proto_1_12_2.State;
|
import mc.core.network.proto_1_12_2.State;
|
||||||
import mc.core.network.proto_1_12_2.TeleportManager;
|
import mc.core.network.proto_1_12_2.TeleportManager;
|
||||||
|
import mc.core.network.proto_1_12_2.netty.KeepAliveThread;
|
||||||
import mc.core.network.proto_1_12_2.netty.wrappers.WrapperNetChannel;
|
import mc.core.network.proto_1_12_2.netty.wrappers.WrapperNetChannel;
|
||||||
import mc.core.network.proto_1_12_2.packets.*;
|
import mc.core.network.proto_1_12_2.packets.*;
|
||||||
import mc.core.player.Player;
|
import mc.core.player.Player;
|
||||||
@@ -32,6 +29,8 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PlayerManager playerManager;
|
private PlayerManager playerManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private KeepAliveThread keepAliveThread;
|
||||||
|
@Autowired
|
||||||
private World world;
|
private World world;
|
||||||
|
|
||||||
@Handler
|
@Handler
|
||||||
@@ -131,6 +130,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
|
|||||||
channel.writeAndFlush(pkt5);
|
channel.writeAndFlush(pkt5);
|
||||||
|
|
||||||
playerManager.joinServer(player);
|
playerManager.joinServer(player);
|
||||||
|
keepAliveThread.notifyLock();
|
||||||
|
|
||||||
CS_PlayerMoveEvent event = new CS_PlayerMoveEvent(player, player.getLocation());
|
CS_PlayerMoveEvent event = new CS_PlayerMoveEvent(player, player.getLocation());
|
||||||
event.setNewLocation(player.getLocation());
|
event.setNewLocation(player.getLocation());
|
||||||
|
|||||||
@@ -20,14 +20,8 @@ import java.util.Random;
|
|||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class WrapperNetChannel implements NetChannel {
|
public class WrapperNetChannel implements NetChannel {
|
||||||
private static final Random RAND = new Random();
|
|
||||||
private final Channel channel;
|
private final Channel channel;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendKeepAlive() {
|
|
||||||
writeAndFlush(new KeepAlivePacket(RAND.nextLong()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendTimeUpdate(long time, long age) {
|
public void sendTimeUpdate(long time, long age) {
|
||||||
writeAndFlush(new TimeUpdatePacket(time, age));
|
writeAndFlush(new TimeUpdatePacket(time, age));
|
||||||
|
|||||||
Reference in New Issue
Block a user