Remove Netty
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import me.unlegitdqrk.fakeminecraftserver.streams.MojewInputStream;
|
||||
import me.unlegitdqrk.fakeminecraftserver.streams.MojewOutputStream;
|
||||
|
||||
|
||||
/**
|
||||
* @author UnlegitDqrk
|
||||
*/
|
||||
|
||||
public class BasePacketHandler extends ChannelInboundHandlerAdapter {
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
MojewInputStream inputStream = new MojewInputStream((ByteBuf) msg);
|
||||
|
||||
// handshake
|
||||
int length = inputStream.readInt();
|
||||
int id = inputStream.readInt();
|
||||
|
||||
if (id == 0) {
|
||||
// status request
|
||||
try {
|
||||
int version = inputStream.readInt();
|
||||
String address = inputStream.readUTF();
|
||||
int port = inputStream.readUnsignedShort();
|
||||
int state = inputStream.readInt();
|
||||
System.out.println("Received request: " + length + ", " + id + ", " + version + ", " + address + ", " + port + ", " + state);
|
||||
} catch (Exception ignored) {
|
||||
// status request packet is sent inconsistently, so we ignore it
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
|
||||
// status response
|
||||
String response = gson.toJson(FakeMinecraftServer.response).replace(ChatConverter.ESCAPE + "", "\\u00A7"); // Mojew's parser needs this escaped (classic)
|
||||
|
||||
if (FakeMinecraftServer.response.favicon == null)
|
||||
System.out.println("Sending response: " + response);
|
||||
else
|
||||
System.out.println("Sent response with image data.");
|
||||
|
||||
MojewOutputStream outputStream = new MojewOutputStream(Unpooled.buffer());
|
||||
MojewOutputStream dataOutputStream = new MojewOutputStream(Unpooled.buffer());
|
||||
|
||||
dataOutputStream.writeInt(0);
|
||||
dataOutputStream.writeUTF(response);
|
||||
dataOutputStream.close();
|
||||
|
||||
outputStream.writeInt(dataOutputStream.writtenBytes());
|
||||
outputStream.write(dataOutputStream.getData());
|
||||
outputStream.close();
|
||||
|
||||
ctx.writeAndFlush(outputStream.buffer());
|
||||
} else if (id == 1) {
|
||||
// ping request
|
||||
long time = inputStream.readLong();
|
||||
System.out.println("Received ping packet: " + length + ", " + id + ", " + time);
|
||||
|
||||
// ping response
|
||||
MojewOutputStream outputStream = new MojewOutputStream(Unpooled.buffer());
|
||||
MojewOutputStream dataOutputStream = new MojewOutputStream(Unpooled.buffer());
|
||||
|
||||
dataOutputStream.writeInt(1);
|
||||
dataOutputStream.writeLong(time);
|
||||
dataOutputStream.close();
|
||||
|
||||
outputStream.writeInt(dataOutputStream.writtenBytes());
|
||||
outputStream.write(dataOutputStream.getData());
|
||||
outputStream.close();
|
||||
|
||||
ctx.writeAndFlush(outputStream.buffer());
|
||||
} else if (id == 2) {
|
||||
// TODO: Fixing kick message
|
||||
|
||||
// login attempt
|
||||
System.out.println("Received login packet: " + length + ", " + id);
|
||||
|
||||
// login response
|
||||
MojewOutputStream outputStream = new MojewOutputStream(Unpooled.buffer());
|
||||
MojewOutputStream dataOutputStream = new MojewOutputStream(Unpooled.buffer());
|
||||
|
||||
dataOutputStream.writeInt(2);
|
||||
dataOutputStream.writeUTF("{text:\""+ ChatConverter.replaceColors(FakeMinecraftServer.KICK_MESSAGE).replace("\\n", "\n") + "\", color: white}");
|
||||
dataOutputStream.close();
|
||||
|
||||
outputStream.writeInt(dataOutputStream.writtenBytes());
|
||||
outputStream.write(dataOutputStream.getData());
|
||||
outputStream.close();
|
||||
|
||||
ctx.writeAndFlush(outputStream.buffer());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@@ -1,41 +0,0 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
|
||||
/**
|
||||
* @author UnlegitDqrk
|
||||
*/
|
||||
|
||||
public class SLPServer {
|
||||
private int port;
|
||||
|
||||
public SLPServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup();
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
|
||||
try {
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap();
|
||||
serverBootstrap.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
public void initChannel(Channel channel) {
|
||||
channel.pipeline().addLast(new BasePacketHandler());
|
||||
}
|
||||
}).option(ChannelOption.SO_BACKLOG, 128)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true);
|
||||
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
|
||||
channelFuture.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Settings {
|
||||
|
||||
public static final int START_PORT = 25565;
|
||||
|
||||
public static final String ENGINE = "classic";
|
||||
public static final int SOCKET_TIMEOUT_IN_SECONDS = 3;
|
||||
|
||||
public static final int MAX_PLAYERS = 100;
|
||||
public static final int ONLINE_PLAYERS = 10;
|
||||
|
||||
public static final int PROTOCOL_VERSION = 47;
|
||||
public static final String PROTOCOL_TEXT = "1.8.8";
|
||||
|
||||
public static final String MOTD_LINE1 = "&4Ein fake Minecraftserver";
|
||||
public static final String MOTD_LINE2 = "&cDeveloped by UnlegitDqrk";
|
||||
|
||||
public static final String KICK_MESSAGE = "&4Just a Fakeserver!\n&aDeveloped by UnlegitDqrk";
|
||||
public static final List<String> SAMPLES = Arrays.asList("&4Fakeserver", "&5by", "&aUnlegitDqrk");
|
||||
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver.data;
|
||||
|
||||
import me.unlegitdqrk.fakeminecraftserver.ChatConverter;
|
||||
import me.unlegitdqrk.fakeminecraftserver.FakeMinecraftServer;
|
||||
import me.unlegitdqrk.fakeminecraftserver.Message;
|
||||
import me.unlegitdqrk.fakeminecraftserver.Settings;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author UnlegitDqrk
|
||||
@@ -44,7 +46,7 @@ public class StatusResponse {
|
||||
this.online = online;
|
||||
this.sample = new ArrayList<>();
|
||||
|
||||
for (String sample : FakeMinecraftServer.SAMPLES) {
|
||||
for (String sample : Settings.SAMPLES) {
|
||||
this.sample.add(new Sample(ChatConverter.replaceColors(sample)));
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,113 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver.network;
|
||||
|
||||
/*
|
||||
* This file is part of Flow Networking, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2013 Spout LLC <http://www.spout.org/>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
/**
|
||||
* A class containing various utility methods that act on byte buffers.
|
||||
*/
|
||||
public class ByteBufUtils {
|
||||
/**
|
||||
* Reads an UTF8 string from a byte buffer.
|
||||
*
|
||||
* @param buf The byte buffer to read from
|
||||
* @return The read string
|
||||
* @throws java.io.IOException If the reading fails
|
||||
*/
|
||||
public static String readUTF8(DataInput buf) throws IOException {
|
||||
// Read the string's length
|
||||
final int len = readVarInt(buf);
|
||||
final byte[] bytes = new byte[len];
|
||||
buf.readFully(bytes);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an UTF8 string to a byte buffer.
|
||||
*
|
||||
* @param buf The byte buffer to write too
|
||||
* @param value The string to write
|
||||
* @throws java.io.IOException If the writing fails
|
||||
*/
|
||||
public static void writeUTF8(DataOutput buf, String value) throws IOException {
|
||||
final byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
|
||||
if (bytes.length >= Short.MAX_VALUE) {
|
||||
throw new IOException("Attempt to write a string with a length greater than Short.MAX_VALUE to ByteBuf!");
|
||||
}
|
||||
// Write the string's length
|
||||
writeVarInt(buf, bytes.length);
|
||||
buf.write(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an integer written into the byte buffer as one of various bit sizes.
|
||||
*
|
||||
* @param buf The byte buffer to read from
|
||||
* @return The read integer
|
||||
* @throws java.io.IOException If the reading fails
|
||||
*/
|
||||
public static int readVarInt(DataInput buf) throws IOException {
|
||||
int out = 0;
|
||||
int bytes = 0;
|
||||
byte in;
|
||||
while (true) {
|
||||
in = buf.readByte();
|
||||
out |= (in & 0x7F) << (bytes * 7);
|
||||
if (bytes > 32) {
|
||||
throw new IOException("Attempt to read int bigger than allowed for a varint!");
|
||||
}
|
||||
if ((in & 0x80) != 0x80) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an integer into the byte buffer using the least possible amount of bits.
|
||||
*
|
||||
* @param buf The byte buffer to write too
|
||||
* @param value The integer value to write
|
||||
*/
|
||||
public static void writeVarInt(DataOutput buf, int value) throws IOException {
|
||||
int part;
|
||||
while (true) {
|
||||
part = value & 0x7F;
|
||||
value >>>= 7;
|
||||
if (value != 0) {
|
||||
part |= 0x80;
|
||||
}
|
||||
buf.writeByte(part);
|
||||
if (value == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver.network;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import me.unlegitdqrk.fakeminecraftserver.ChatConverter;
|
||||
import me.unlegitdqrk.fakeminecraftserver.FakeMinecraftServer;
|
||||
import me.unlegitdqrk.fakeminecraftserver.Settings;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
/**
|
||||
* @author UnlegitDqrk
|
||||
*/
|
||||
|
||||
public class ResponderThread extends Thread {
|
||||
|
||||
private final Socket socket;
|
||||
private final DataInputStream inputStream;
|
||||
private final DataOutputStream outputStream;
|
||||
private final String remoteHost;
|
||||
private int clientProtocolVersion;
|
||||
private Thread thread = null;
|
||||
private boolean enabled = false;
|
||||
|
||||
public ResponderThread(Socket socket) throws IOException {
|
||||
this.socket = socket;
|
||||
|
||||
this.inputStream = new DataInputStream(socket.getInputStream());
|
||||
this.outputStream = new DataOutputStream(socket.getOutputStream());
|
||||
|
||||
this.remoteHost = socket.getRemoteSocketAddress().toString().substring(1);
|
||||
|
||||
socket.setSoTimeout(Settings.SOCKET_TIMEOUT_IN_SECONDS * 1000);
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.thread = Thread.currentThread();
|
||||
boolean showMotd = false;
|
||||
|
||||
try {
|
||||
while (this.socket.isConnected() && this.enabled) {
|
||||
final int length = ByteBufUtils.readVarInt(this.inputStream);
|
||||
final int packetId = ByteBufUtils.readVarInt(this.inputStream);
|
||||
|
||||
System.out.println("length: " + length + " packet id: " + packetId);
|
||||
|
||||
if (length == 0) return;
|
||||
|
||||
// handshake
|
||||
if (packetId == 0) {
|
||||
if (!showMotd) {
|
||||
final int version = ByteBufUtils.readVarInt(this.inputStream);
|
||||
@SuppressWarnings("unused") final String ip = ByteBufUtils.readUTF8(this.inputStream);
|
||||
@SuppressWarnings("unused") final int port = this.inputStream.readUnsignedShort();
|
||||
final int state = ByteBufUtils.readVarInt(this.inputStream);
|
||||
|
||||
System.out.println("(State request) length:" + length + " id:" + packetId + " version:" + version + " state:" + state);
|
||||
clientProtocolVersion = version;
|
||||
|
||||
// state 1=status 2=login
|
||||
if (state == 1) {
|
||||
// ping / status request
|
||||
showMotd = true;
|
||||
System.out.println("ping: " + this.remoteHost);
|
||||
} else if (state == 2) {
|
||||
// login attempt
|
||||
writeData("{text:\"" + ChatConverter.replaceColors(Settings.KICK_MESSAGE) + "\", color: white}");
|
||||
System.out.println("Kick: " + this.remoteHost + " - " + Settings.KICK_MESSAGE);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// info packet
|
||||
System.out.println("(Info request) length:" + length + " id:" + packetId);
|
||||
final String motd = createInfo();
|
||||
|
||||
if (motd == null || motd.isEmpty()) {
|
||||
System.out.println("Info is not initialized!");
|
||||
return;
|
||||
}
|
||||
|
||||
writeData(motd);
|
||||
showMotd = false;
|
||||
}
|
||||
} else if (packetId == 1) {
|
||||
long receivedLong = this.inputStream.readLong();
|
||||
System.out.println("Pong: " + receivedLong);
|
||||
|
||||
ByteBufUtils.writeVarInt(this.outputStream, 9);
|
||||
ByteBufUtils.writeVarInt(this.outputStream, 1);
|
||||
|
||||
this.outputStream.writeLong(receivedLong);
|
||||
this.outputStream.flush();
|
||||
} else {
|
||||
System.out.println("Unknown packet: " + packetId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ignore this unnecessary error
|
||||
catch (EOFException ignored) {
|
||||
System.out.println("(end of socket)");
|
||||
} catch (SocketTimeoutException ignored) {
|
||||
System.out.println("(socket timeout)");
|
||||
} catch (SocketException ignored) {
|
||||
System.out.println("(socket closed)");
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
} finally {
|
||||
closeSocket();
|
||||
this.thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
public final int getClientProtocolVersion() {
|
||||
return clientProtocolVersion;
|
||||
}
|
||||
|
||||
private final void closeSocket() {
|
||||
this.enabled = false;
|
||||
|
||||
FakeMinecraftServer.safeClose(this.inputStream);
|
||||
FakeMinecraftServer.safeClose(this.outputStream);
|
||||
FakeMinecraftServer.safeClose(this.socket);
|
||||
|
||||
if (this.thread != null) this.thread.interrupt();
|
||||
}
|
||||
|
||||
private final void writeData(final String data) throws IOException {
|
||||
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
|
||||
|
||||
ByteBufUtils.writeVarInt(dataOutputStream, 0);
|
||||
ByteBufUtils.writeUTF8(dataOutputStream, data);
|
||||
ByteBufUtils.writeVarInt(this.outputStream, byteArrayOutputStream.size());
|
||||
|
||||
this.outputStream.write(byteArrayOutputStream.toByteArray());
|
||||
this.outputStream.flush();
|
||||
}
|
||||
|
||||
private final String createInfo() {
|
||||
return new Gson().toJson(FakeMinecraftServer.getResponse());
|
||||
}
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver.streams;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author UnlegitDqrk
|
||||
*/
|
||||
|
||||
public class MojewInputStream extends ByteBufInputStream {
|
||||
public MojewInputStream(ByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readUTF() throws IOException {
|
||||
byte[] input = new byte[readInt()];
|
||||
readFully(input);
|
||||
return new String(input, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() throws IOException {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (true) {
|
||||
int k = readByte();
|
||||
i |= (k & 0x7F) << j++ * 7;
|
||||
if (j > 5) throw new RuntimeException("VarInt too big");
|
||||
if ((k & 0x80) != 128) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
package me.unlegitdqrk.fakeminecraftserver.streams;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author UnlegitDqrk
|
||||
*/
|
||||
|
||||
public class MojewOutputStream extends ByteBufOutputStream {
|
||||
public MojewOutputStream(ByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeUTF(String s) throws IOException {
|
||||
byte[] data = s.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(s.length());
|
||||
write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(int paramInt) throws IOException {
|
||||
while (true) {
|
||||
if ((paramInt & 0xFFFFFF80) == 0) {
|
||||
writeByte(paramInt);
|
||||
return;
|
||||
}
|
||||
writeByte(paramInt & 0x7F | 0x80);
|
||||
paramInt >>>= 7;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return Arrays.copyOfRange(buffer().array(), 0, writtenBytes());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user