Skip to content

Commit

Permalink
initial writeup of new bungee handler
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Jun 17, 2019
1 parent f3b084f commit c05d277
Show file tree
Hide file tree
Showing 9 changed files with 361 additions and 3 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ Depenizen
- **Support Discord**: https://discord.gg/Q6pZGSR
- **Builds (Download)**: https://ci.citizensnpcs.co/job/Depenizen/
- **Supported Plugin List**: [Docs/BukkitPlugins.md](Docs/BukkitPlugins.md)
- **DepenizenBungee**: https://github.com/DenizenScript/DepenizenBungee

### Version 2.x notice:

Depenizen version 2.x is a rewrite of many of the core functions of Depenizen.

If you need the 1.x (legacy) version, you can find the last official build of that here: https://ci.citizensnpcs.co/job/Depenizen/476/

**Status:** Depenizen 2.x rewrite has rewritten all the basic core functionality, but the Bungee bridge rebuild is pending.
The plan for this bungee bridge is to be significantly different from a usage perspective, so you **will** have to change configuration details when this is available.
**Status:** Depenizen 2.x rewrite has rewritten all the basic core functionality, but the Bungee bridge rebuild is incomplete.
The new bungee bridge is significantly different from a usage perspective, so you **will** have to change configuration details when this is available.

### Licensing pre-note:

Expand Down
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@
<type>jar</type>
<scope>provided</scope>
</dependency>
<!-- Special Support Targets -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.34.Final</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<!-- Support Targets (Optional) -->
<dependency>
<groupId>com.github.TheComputerGeek2</groupId>
Expand Down
22 changes: 21 additions & 1 deletion src/main/java/com/denizenscript/depenizen/bukkit/Depenizen.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.denizenscript.depenizen.bukkit;

import com.denizenscript.depenizen.bukkit.bridges.*;
import com.denizenscript.depenizen.bukkit.bungee.BungeeBridge;
import com.denizenscript.depenizen.bukkit.utilities.BridgeLoadException;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.utilities.CoreUtilities;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
Expand All @@ -22,12 +24,30 @@ public class Depenizen extends JavaPlugin {
@Override
public void onEnable() {
dB.log("Depenizen loading...");
saveDefaultConfig();
instance = this;
registerCoreBridges();
for (Map.Entry<String, Supplier<Bridge>> bridge : allBridges.entrySet()) {
loadBridge(bridge.getKey(), bridge.getValue());
}
dB.log("Depenizen loaded! " + loadedBridges.size() + " bridges loaded (of " + allBridges.size() + " available)");
try {
checkLoadBungeeBridge();
}
catch (Throwable ex) {
dB.echoError("Cannot load Depenizen-Bungee bridge: Internal exception was thrown!");
dB.echoError(ex);
}
dB.log("Depenizen loaded! " + loadedBridges.size() + " plugin bridge(s) loaded (of " + allBridges.size() + " available)");
}

public void checkLoadBungeeBridge() {
String bungeeServer = getConfig().getString("Bungee server address", "none");
if (CoreUtilities.toLowerCase(bungeeServer).equals("none")) {
dB.log("<G>Depenizen will not load bungee bridge.");
return;
}
new BungeeBridge().init(bungeeServer, getConfig().getInt("Bungee server port", 25565));
dB.log("Depenizen loaded bungee bridge!");
}

public void loadBridge(String name, Supplier<Bridge> bridgeSupplier) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package com.denizenscript.depenizen.bukkit.bungee;

import com.denizenscript.depenizen.bukkit.properties.bungee.BungeePlayerProperties;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.objects.properties.PropertyParser;

import java.net.SocketAddress;

public class BungeeBridge {

public static BungeeBridge instance;

public static class NettyExceptionHandler extends ChannelDuplexHandler {

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
dB.echoError(cause);
}

@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
ctx.connect(remoteAddress, localAddress, promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
dB.echoError(future.cause());
}
}
}));
}

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
ctx.write(msg, promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
dB.echoError(future.cause());
}
}
}));
}
}

public static class ClientHandler extends ChannelInboundHandlerAdapter {

public static final byte[] FAKE_HANDSHAKE = new byte[] {
5 + 5 + 3, // Packet length prefix
0, // Packet ID 0
20, // "Protocol 20"
1 + 1 + 5, // 1-byte host name, 1 byte null, 5 bytes 'depen'
68, // Host name is the letter 'D'
0, // null byte to sneak in our identifier
(byte)'d', (byte)'e', (byte)'p', (byte)'e', (byte)'n', // Special identifier 'depen'
80, 0, // "We're connecting to port 80"
1 // We request protocol 1: ping status (to avoid uneeded proxy functionality)
};

public ByteBuf tmp;

public void fail(String reason) {
dB.echoError("Depenizen-Bungee connection failed: " + reason);
channel.close();
}

public static enum Stage {
AWAIT_HEADER,
AWAIT_DATA
}

public Channel channel;

public int waitingLength;

public int packetId;

public Stage currentStage = Stage.AWAIT_HEADER;

@Override
public void handlerAdded(ChannelHandlerContext ctx) {
tmp = ctx.alloc().buffer(4);
}

@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
dB.log("Depenizen-Bungee connection ended.");
tmp.release();
tmp = null;
// TODO: trigger reconnect (after a delay)
}

@Override
public void channelActive(ChannelHandlerContext ctx) {
dB.log("Depenizen-Bungee bridge sending handshake...");
// Send a fake minecraft handshake to get us in
ByteBuf handshake = ctx.alloc().buffer(FAKE_HANDSHAKE.length);
handshake.writeBytes(FAKE_HANDSHAKE);
ctx.writeAndFlush(handshake); // Will release handshake
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf m = (ByteBuf) msg;
tmp.writeBytes(m);
m.release();
if (currentStage == Stage.AWAIT_HEADER) {
if (tmp.readableBytes() >= 8) {
waitingLength = tmp.readInt();
packetId = tmp.readInt();
currentStage = Stage.AWAIT_DATA;
/*if (!DepenizenBungee.instance.packets.containsKey(packetId)) {
fail("Invalid packet id: " + packetId);
return;
}*/
}
}
if (currentStage == Stage.AWAIT_DATA) {
if (tmp.readableBytes() >= waitingLength) {
try {
//DepenizenBungee.instance.packets.get(packetId).process(this, tmp);
currentStage = Stage.AWAIT_HEADER;
}
catch (Throwable ex) {
ex.printStackTrace();
fail("Internal exception.");
return;
}
}
}
}
}

public Channel channel;

public NioEventLoopGroup workerGroup;

public String address;

public int port;

public void sendPacket(Packet packet) {
ByteBuf buf = channel.alloc().buffer();
packet.writeTo(buf);
ByteBuf header = channel.alloc().buffer();
header.writeInt(buf.writerIndex());
header.writeInt(packet.getPacketId());
channel.write(header);
channel.writeAndFlush(buf);
}

public void init(String address, int port) {
this.address = address;
this.port = port;
workerGroup = new NioEventLoopGroup();
connect();
successInit();
}

public void connect() {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ClientHandler handler = new ClientHandler();
handler.channel = ch;
ch.pipeline().addLast(handler).addLast(new NettyExceptionHandler());
channel = ch;
}
});
b.connect(address, port);
}

public void successInit() {
instance = this;
PropertyParser.registerProperty(BungeePlayerProperties.class, dPlayer.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.denizenscript.depenizen.bukkit.bungee;

import com.denizenscript.depenizen.bukkit.bungee.packets.out.SendPlayerPacket;

import java.util.UUID;

public class BungeeHelpers {

public static void sendPlayer(UUID id, String server) {
SendPlayerPacket packet = new SendPlayerPacket();
packet.playerToSend = id;
packet.serverTarget = server;
BungeeBridge.instance.sendPacket(packet);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.denizenscript.depenizen.bukkit.bungee;

import io.netty.buffer.ByteBuf;

public abstract class Packet {

public abstract int getPacketId();

public abstract void writeTo(ByteBuf buf);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.denizenscript.depenizen.bukkit.bungee.packets.out;

import com.denizenscript.depenizen.bukkit.bungee.Packet;
import com.google.common.base.Charsets;
import io.netty.buffer.ByteBuf;

import java.util.UUID;

public class SendPlayerPacket extends Packet {

public UUID playerToSend;

public String serverTarget;

@Override
public int getPacketId() {
return 10;
}

@Override
public void writeTo(ByteBuf buf) {
buf.writeLong(playerToSend.getMostSignificantBits());
buf.writeLong(playerToSend.getLeastSignificantBits());
byte[] serverTargetBytes = serverTarget.getBytes(Charsets.UTF_8);
buf.writeInt(serverTargetBytes.length);
buf.writeBytes(serverTargetBytes);
}
}
Loading

0 comments on commit c05d277

Please sign in to comment.