Archived
0

Bridge: универсальный подход

(cherry picked from commit b921a3611e)
This commit is contained in:
2017-05-17 13:09:51 +03:00
parent 6526553d2c
commit 606ed43bde
12 changed files with 272 additions and 123 deletions

View File

@@ -1,5 +1,5 @@
group = 'asys' group = 'asys'
version = '0.6-SNAPSHOT' version = '0.7-SNAPSHOT'
repositories { repositories {
maven { url 'https://hub.spigotmc.org/nexus/content/groups/public/' } maven { url 'https://hub.spigotmc.org/nexus/content/groups/public/' }

View File

@@ -0,0 +1,49 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.bukkit;
import asys.bridge.client.AbstractBridge;
import asys.bridge.client.IBridge;
import asys.bridge.client.IConfig;
import asys.bridge.client.ILogger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;
public class BridgeBukkitImpl extends AbstractBridge implements IBridge {
private BridgePlugin plugin;
private LoggerBukkitImpl logger;
private ConfigBukkitImpl configBukkit;
public BridgeBukkitImpl(BridgePlugin plugin) {
this.plugin = plugin;
this.logger = new LoggerBukkitImpl(plugin.getLogger());
this.configBukkit = new ConfigBukkitImpl(plugin.getConfig());
((Logger) LogManager.getRootLogger()).addAppender(new BridgeLoggerAppender());
}
@Override
public ILogger getLogger() {
return logger;
}
@Override
public IConfig getConfig() {
return configBukkit;
}
@Override
public int getCountOnlinePlayers() {
return plugin.getServer().getOnlinePlayers().size();
}
@Override
public void dispatchCommand(String command) {
plugin.getServer().dispatchCommand(
plugin.getServer().getConsoleSender(),
command
);
}
}

View File

@@ -4,51 +4,26 @@
*/ */
package asys.bridge.bukkit; package asys.bridge.bukkit;
import asys.bridge.client.Client;
import asys.mcsmanager.packets.CS_Ping;
import io.netty.channel.Channel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
public class BridgePlugin extends JavaPlugin { public class BridgePlugin extends JavaPlugin {
public static BridgePlugin INSTANCE; private BridgeBukkitImpl bridgeBukkit;
private Client client;
private TaskTicker connectTicker, pingTicker;
private int tryConnect = 0;
private BridgeLoggerAppender loggerAppender;
private boolean needReconnect = true;
@Override @Override
public void onLoad() { public void onLoad() {
((Logger)LogManager.getRootLogger()).addAppender(loggerAppender = new BridgeLoggerAppender()); saveDefaultConfig();
onEnable(); this.bridgeBukkit = new BridgeBukkitImpl(this);
} this.bridgeBukkit.startReconnect();
@Override
public void onEnable() {
if (INSTANCE == null) {
INSTANCE = this;
saveDefaultConfig();
startReconnect();
}
} }
@Override @Override
public void onDisable() { public void onDisable() {
setNeedReconnect(false); this.bridgeBukkit.setNeedReconnect(false);
stopReconnect(); this.bridgeBukkit.stopPing();
stopPing(); this.bridgeBukkit.stopReconnect();
this.bridgeBukkit.disconnect();
if (client.isConnected()) {
getLogger().info("Disconnect...");
client.disconnect();
}
INSTANCE = null;
} }
@Override @Override
@@ -56,67 +31,4 @@ public class BridgePlugin extends JavaPlugin {
sender.sendMessage("ASys Bridge by DmitriyMX"); sender.sendMessage("ASys Bridge by DmitriyMX");
return true; return true;
} }
public void startReconnect() {
client = new Client();
connectTicker = new TaskTicker().setStepTimeMs(5000L);
connectTicker.setTask(() -> {
getLogger().info(String.format("Connect(%d) to ASys...", ++tryConnect));
client.connect(getConfig().getString("host"), getConfig().getInt("port"));
if (client.isConnected()) {
stopReconnect();
} else {
getLogger().warning(
String.format("Connection(%d) fail. Try reconnect...", tryConnect));
}
}).start();
}
public void stopReconnect() {
if (connectTicker != null) {
connectTicker.stop();
tryConnect = 0;
}
}
public void startPing(Channel channel) {
getLoggerAppender().setChannel(channel);
pingTicker = new TaskTicker().setStepTimeMs(5000L);
pingTicker.setTask(() -> {
channel.write(new CS_Ping(
System.currentTimeMillis(),
20.0D, //FIXME
getServer().getOnlinePlayers().size()
));
if (channel.isWritable()) {
channel.flush();
} else {
getLogger().warning("Lost connection!");
channel.close();
stopPing();
getLogger().warning("Try reconnect...");
startReconnect();
}
}).start();
}
public void stopPing() {
getLoggerAppender().setChannel(null);
if (pingTicker != null) {
pingTicker.stop();
}
}
public BridgeLoggerAppender getLoggerAppender() {
return loggerAppender;
}
public boolean isNeedReconnect() {
return needReconnect;
}
public void setNeedReconnect(boolean needReconnect) {
this.needReconnect = needReconnect;
}
} }

View File

@@ -0,0 +1,26 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.bukkit;
import asys.bridge.client.IConfig;
import org.bukkit.configuration.file.FileConfiguration;
public class ConfigBukkitImpl implements IConfig {
private FileConfiguration fileConfiguration;
public ConfigBukkitImpl(FileConfiguration fileConfiguration) {
this.fileConfiguration = fileConfiguration;
}
@Override
public String getString(String path) {
return fileConfiguration.getString(path);
}
@Override
public int getInt(String path) {
return fileConfiguration.getInt(path);
}
}

View File

@@ -0,0 +1,32 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.bukkit;
import asys.bridge.client.ILogger;
import java.util.logging.Logger;
public class LoggerBukkitImpl implements ILogger {
private Logger logger;
LoggerBukkitImpl(Logger logger) {
this.logger = logger;
}
@Override
public void info(String string) {
logger.info(string);
}
@Override
public void warn(String string) {
logger.warning(string);
}
@Override
public void error(String string) {
logger.severe(string);
}
}

View File

@@ -10,23 +10,23 @@ public class TaskTicker implements Runnable {
private Thread thread; private Thread thread;
private boolean loop = false; private boolean loop = false;
TaskTicker setTask(Runnable task) { public TaskTicker setTask(Runnable task) {
this.task = task; this.task = task;
return this; return this;
} }
TaskTicker setStepTimeMs(long stepTimeMs) { public TaskTicker setStepTimeMs(long stepTimeMs) {
this.stepTimeMs = stepTimeMs; this.stepTimeMs = stepTimeMs;
return this; return this;
} }
void start() { public void start() {
thread = new Thread(this, "TaskTicker"); thread = new Thread(this, "TaskTicker");
loop = true; loop = true;
thread.start(); thread.start();
} }
void stop() { public void stop() {
loop = false; loop = false;
if (thread != null) { if (thread != null) {
thread.interrupt(); thread.interrupt();

View File

@@ -0,0 +1,86 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.client;
import asys.bridge.bukkit.TaskTicker;
import asys.mcsmanager.packets.CS_Ping;
import io.netty.channel.Channel;
public abstract class AbstractBridge implements IBridge {
private Client client;
private TaskTicker connectTicker, pingTicker;
private int tryConnect = 0;
private boolean needReconnect = true;
@Override
public void startReconnect() {
client = new Client(this);
connectTicker = new TaskTicker().setStepTimeMs(5000L);
connectTicker.setTask(() -> {
getLogger().info(String.format("Connect(%d) to ASys...", ++tryConnect));
client.connect(getConfig().getString("host"), getConfig().getInt("port"));
if (client.isConnected()) {
stopReconnect();
} else {
getLogger().warn(String.format("Connection(%d) fail. Try reconnect...", tryConnect));
}
}).start();
}
@Override
public boolean isNeedReconnect() {
return needReconnect;
}
@Override
public void setNeedReconnect(boolean value) {
this.needReconnect = value;
}
@Override
public void stopReconnect() {
if (connectTicker != null) {
connectTicker.stop();
tryConnect = 0;
}
}
@Override
public void startPing(Channel channel) {
pingTicker = new TaskTicker().setStepTimeMs(5000L);
pingTicker.setTask(() -> {
channel.write(new CS_Ping(
System.currentTimeMillis(),
20.0D, //FIXME fake tps
getCountOnlinePlayers()
));
if (channel.isWritable()) {
channel.flush();
} else {
getLogger().warn("Lost connection!");
channel.close();
stopPing();
getLogger().warn("Try reconnect...");
startReconnect();
}
}).start();
}
@Override
public void stopPing() {
if (pingTicker != null) {
pingTicker.stop();
}
}
@Override
public void disconnect() {
if (client.isConnected()) {
getLogger().info("Disconnect...");
client.disconnect();
}
}
}

View File

@@ -19,6 +19,11 @@ public class Client {
private EventLoopGroup group; private EventLoopGroup group;
private Bootstrap bootstrap; private Bootstrap bootstrap;
private ChannelFuture channelFuture; private ChannelFuture channelFuture;
private IBridge bridge;
public Client(IBridge bridge) {
this.bridge = bridge;
}
public void connect(String host, int port) { public void connect(String host, int port) {
if (group == null || bootstrap == null) { if (group == null || bootstrap == null) {
@@ -55,7 +60,7 @@ public class Client {
new PacketEncoder(), new PacketEncoder(),
new PacketDecoder(), new PacketDecoder(),
new PacketHandler(), new PacketHandler(),
new ClientPacketHandler() new ClientPacketHandler(bridge)
); );
} }
}; };

View File

@@ -29,8 +29,10 @@ public class ClientPacketHandler extends ChannelInboundHandlerAdapter implements
4, CS_ConsoleMessage.class, 4, CS_ConsoleMessage.class,
5, SC_Command.class 5, SC_Command.class
); );
private IBridge bridge;
ClientPacketHandler() { ClientPacketHandler(IBridge bridge) {
this.bridge = bridge;
if (handshakeHandlers == null) { if (handshakeHandlers == null) {
handshakeHandlers = ImmutableMap.of( handshakeHandlers = ImmutableMap.of(
SC_HandshakeResult.class, this, SC_HandshakeResult.class, this,
@@ -41,26 +43,24 @@ public class ClientPacketHandler extends ChannelInboundHandlerAdapter implements
@Override @Override
public void channelActive(ChannelHandlerContext context) throws Exception { public void channelActive(ChannelHandlerContext context) throws Exception {
BridgePlugin.INSTANCE.getLogger().info("channelActive"); bridge.getLogger().info("channelActive");
context.channel().attr(KNOWN_PACKETS).set(handshakePackets); context.channel().attr(KNOWN_PACKETS).set(handshakePackets);
context.channel().attr(KNOWN_HANDLERS).set(handshakeHandlers); context.channel().attr(KNOWN_HANDLERS).set(handshakeHandlers);
CS_Handshake packet = new CS_Handshake( CS_Handshake packet = new CS_Handshake(
BridgePlugin.INSTANCE.getConfig().getString("clientId"), bridge.getConfig().getString("clientId"),
BridgePlugin.INSTANCE.getConfig().getString("passcode")); bridge.getConfig().getString("passcode"));
BridgePlugin.INSTANCE.getLogger().info("send Handshake packet..."); bridge.getLogger().info("send Handshake packet...");
context.channel().writeAndFlush(packet); context.channel().writeAndFlush(packet);
super.channelActive(context); super.channelActive(context);
} }
@Override @Override
public void channelInactive(ChannelHandlerContext context) throws Exception { public void channelInactive(ChannelHandlerContext context) throws Exception {
if (BridgePlugin.INSTANCE != null) { bridge.stopPing();
BridgePlugin.INSTANCE.stopPing(); if (bridge.isNeedReconnect()) {
if (BridgePlugin.INSTANCE.isNeedReconnect()) { bridge.getLogger().warn("Lost connection! Try reconnect...");
BridgePlugin.INSTANCE.getLogger().warning("Lost connection! Try reconnect..."); bridge.startReconnect();
BridgePlugin.INSTANCE.startReconnect();
}
} }
context.channel().attr(KNOWN_PACKETS).remove(); context.channel().attr(KNOWN_PACKETS).remove();
context.channel().attr(KNOWN_HANDLERS).remove(); context.channel().attr(KNOWN_HANDLERS).remove();
@@ -69,7 +69,7 @@ public class ClientPacketHandler extends ChannelInboundHandlerAdapter implements
@Override @Override
public void handle(Packet packet, ChannelHandlerContext context) { public void handle(Packet packet, ChannelHandlerContext context) {
BridgePlugin.INSTANCE.getLogger().info("handle : " + packet.getClass().getSimpleName()); bridge.getLogger().info("handle : " + packet.getClass().getSimpleName());
if (packet instanceof SC_HandshakeResult) { if (packet instanceof SC_HandshakeResult) {
handleHandshakeResult((SC_HandshakeResult) packet, context); handleHandshakeResult((SC_HandshakeResult) packet, context);
} else if (packet instanceof SC_Command) { } else if (packet instanceof SC_Command) {
@@ -79,21 +79,18 @@ public class ClientPacketHandler extends ChannelInboundHandlerAdapter implements
private void handleHandshakeResult(SC_HandshakeResult packet, ChannelHandlerContext context) { private void handleHandshakeResult(SC_HandshakeResult packet, ChannelHandlerContext context) {
if (packet.getErrorCode() != 0) { if (packet.getErrorCode() != 0) {
BridgePlugin.INSTANCE.getLogger().severe( bridge.getLogger().error(
String.format("Handshake: #%d %s", packet.getErrorCode(), packet.getMessage())); String.format("Handshake: #%d %s", packet.getErrorCode(), packet.getMessage()));
BridgePlugin.INSTANCE.setNeedReconnect(false); bridge.setNeedReconnect(false);
} else { } else {
context.channel().attr(KNOWN_PACKETS).set(pingPackets); context.channel().attr(KNOWN_PACKETS).set(pingPackets);
BridgePlugin.INSTANCE.getLogger().info("Handshake: OK"); bridge.getLogger().info("Handshake: OK");
BridgePlugin.INSTANCE.startPing(context.channel()); bridge.startPing(context.channel());
} }
} }
private void handleCommand(SC_Command packet) { private void handleCommand(SC_Command packet) {
BridgePlugin.INSTANCE.getLogger().info("Command: " + packet.getCommand()); bridge.getLogger().info("Command: " + packet.getCommand());
BridgePlugin.INSTANCE.getServer().dispatchCommand( bridge.dispatchCommand(packet.getCommand());
BridgePlugin.INSTANCE.getServer().getConsoleSender(),
packet.getCommand()
);
} }
} }

View File

@@ -0,0 +1,21 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.client;
import io.netty.channel.Channel;
public interface IBridge {
ILogger getLogger();
IConfig getConfig();
int getCountOnlinePlayers();
void dispatchCommand(String command);
void startReconnect();
boolean isNeedReconnect();
void setNeedReconnect(boolean value);
void stopReconnect();
void startPing(Channel channel);
void stopPing();
void disconnect();
}

View File

@@ -0,0 +1,10 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.client;
public interface IConfig {
String getString(String path);
int getInt(String path);
}

View File

@@ -0,0 +1,11 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-05-17
*/
package asys.bridge.client;
public interface ILogger {
void info(String string);
void warn(String string);
void error(String string);
}