diff --git a/pom.xml b/pom.xml index 9e9bea97006..b7532d2ad66 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,12 @@ + + com.nukkitx.network + raknet + 1.6.15 + compile + com.nukkitx fastutil-lite @@ -90,19 +96,6 @@ - - io.netty - netty-handler - 4.1.6.Final - compile - - - io.netty - netty-transport-native-epoll - 4.1.6.Final - compile - linux-x86_64 - org.junit.jupiter junit-jupiter-api @@ -191,6 +184,20 @@ + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + true + lib/ + cn.nukkit.Nukkit + + + + maven-compiler-plugin 3.1 @@ -257,14 +264,10 @@ - - cn.nukkit.Nukkit - - ${project.build.directory}/dependency-reduced-pom.xml diff --git a/src/main/java/cn/nukkit/Nukkit.java b/src/main/java/cn/nukkit/Nukkit.java index ce0fea09dd0..89b2f6344b5 100644 --- a/src/main/java/cn/nukkit/Nukkit.java +++ b/src/main/java/cn/nukkit/Nukkit.java @@ -3,6 +3,9 @@ import cn.nukkit.network.protocol.ProtocolInfo; import cn.nukkit.utils.ServerKiller; import com.google.common.base.Preconditions; +import io.netty.util.ResourceLeakDetector; +import io.netty.util.internal.logging.InternalLoggerFactory; +import io.netty.util.internal.logging.Log4J2LoggerFactory; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; @@ -63,6 +66,10 @@ public static void main(String[] args) { // Force Mapped ByteBuffers for LevelDB till fixed. System.setProperty("leveldb.mmap", "true"); + // Netty logger for debug info + InternalLoggerFactory.setDefaultFactory(Log4J2LoggerFactory.INSTANCE); + ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.PARANOID); + // Define args OptionParser parser = new OptionParser(); parser.allowsUnrecognizedOptions(); diff --git a/src/main/java/cn/nukkit/Player.java b/src/main/java/cn/nukkit/Player.java index eb9c7666813..5d2bc81bd84 100644 --- a/src/main/java/cn/nukkit/Player.java +++ b/src/main/java/cn/nukkit/Player.java @@ -62,7 +62,6 @@ import cn.nukkit.potion.Effect; import cn.nukkit.resourcepacks.ResourcePack; import cn.nukkit.scheduler.AsyncTask; -import cn.nukkit.scheduler.Task; import cn.nukkit.utils.*; import co.aikar.timings.Timing; import co.aikar.timings.Timings; @@ -161,10 +160,9 @@ public class Player extends EntityHuman implements CommandSender, InventoryHolde protected Vector3 teleportPosition = null; protected boolean connected = true; - protected final String ip; + protected final InetSocketAddress socketAddress; protected boolean removeFormat = true; - protected final int port; protected String username; protected String iusername; protected String displayName; @@ -202,8 +200,6 @@ public class Player extends EntityHuman implements CommandSender, InventoryHolde protected boolean checkMovement = true; - private final Int2ObjectOpenHashMap needACK = new Int2ObjectOpenHashMap<>(); - private final Map> batchedPackets = new TreeMap<>(); private PermissibleBase perm = null; @@ -591,16 +587,7 @@ public void sendCommandData() { if (count > 0) { //TODO: structure checking pk.commands = data; - int identifier = this.dataPacket(pk, true); // We *need* ACK so we can be sure that the client received the packet or not - Server.getInstance().getScheduler().scheduleDelayedTask(new Task() { - @Override - public void onRun(int currentTick) { - Boolean status = needACK.get(identifier); - if ((status == null || !status) && isOnline()) { - sendCommandData(); - } - } - }, 60, true); + this.dataPacket(pk); } } @@ -609,14 +596,13 @@ public Map getEffectivePermissions() { return this.perm.getEffectivePermissions(); } - public Player(SourceInterface interfaz, Long clientID, String ip, int port) { + public Player(SourceInterface interfaz, Long clientID, InetSocketAddress socketAddress) { super(null, new CompoundTag()); this.interfaz = interfaz; this.perm = new PermissibleBase(this); this.server = Server.getInstance(); this.lastBreak = -1; - this.ip = ip; - this.port = port; + this.socketAddress = socketAddress; this.clientID = clientID; this.loaderId = Level.generateChunkLoaderId(this); this.chunksPerTick = this.server.getConfig("chunk-sending.per-tick", 4); @@ -679,11 +665,15 @@ public void setSkin(Skin skin) { } public String getAddress() { - return this.ip; + return this.socketAddress.getAddress().getHostAddress(); } public int getPort() { - return port; + return this.socketAddress.getPort(); + } + + public InetSocketAddress getSocketAddress() { + return this.socketAddress; } public Position getNextPosition() { @@ -1060,33 +1050,24 @@ public boolean batchDataPacket(DataPacket packet) { * @return packet successfully sent */ public boolean dataPacket(DataPacket packet) { - return this.dataPacket(packet, false) != -1; - } - - public int dataPacket(DataPacket packet, boolean needACK) { if (!this.connected) { - return -1; + return false; } - try (Timing timing = Timings.getSendDataPacketTiming(packet)) { DataPacketSendEvent ev = new DataPacketSendEvent(this, packet); this.server.getPluginManager().callEvent(ev); if (ev.isCancelled()) { - return -1; - } - - if (log.isTraceEnabled() && !(packet instanceof BatchPacket)) { - log.trace("Outbound {}: {}", this.getName(), packet); + return false; } - Integer identifier = this.interfaz.putPacket(this, packet, needACK, false); - - if (needACK && identifier != null) { - this.needACK.put(identifier, Boolean.FALSE); - return identifier; - } + this.interfaz.putPacket(this, packet, false, false); } - return 0; + return true; + } + + @Deprecated + public int dataPacket(DataPacket packet, boolean needACK) { + return this.dataPacket(packet) ? 0 : -1; } /** @@ -1097,29 +1078,25 @@ public int dataPacket(DataPacket packet, boolean needACK) { * @return packet successfully sent */ public boolean directDataPacket(DataPacket packet) { - return this.directDataPacket(packet, false) != -1; - } - - public int directDataPacket(DataPacket packet, boolean needACK) { if (!this.connected) { - return -1; + return false; } try (Timing timing = Timings.getSendDataPacketTiming(packet)) { DataPacketSendEvent ev = new DataPacketSendEvent(this, packet); this.server.getPluginManager().callEvent(ev); if (ev.isCancelled()) { - return -1; + return false; } - Integer identifier = this.interfaz.putPacket(this, packet, needACK, true); - - if (needACK && identifier != null) { - this.needACK.put(identifier, Boolean.FALSE); - return identifier; - } + this.interfaz.putPacket(this, packet, false, true); } - return 0; + return true; + } + + @Deprecated + public int directDataPacket(DataPacket packet, boolean needACK) { + return this.directDataPacket(packet) ? 0 : -1; } public int getPing() { @@ -2060,8 +2037,8 @@ protected void completeLoginSequence() { this.server.getLogger().info(this.getServer().getLanguage().translateString("nukkit.player.logIn", TextFormat.AQUA + this.username + TextFormat.WHITE, - this.ip, - String.valueOf(this.port), + this.getAddress(), + String.valueOf(this.getPort()), String.valueOf(this.id), this.level.getName(), String.valueOf(NukkitMath.round(this.x, 4)), @@ -2199,7 +2176,7 @@ public void handleDataPacket(DataPacket packet) { @Override public void onRun() { - e = new PlayerAsyncPreLoginEvent(username, uuid, ip, port); + e = new PlayerAsyncPreLoginEvent(username, uuid, Player.this.getAddress(), Player.this.getPort()); server.getPluginManager().callEvent(e); } @@ -3025,7 +3002,7 @@ public void onCompletion(Server server) { if (spamBug) { return; } - + this.setDataFlag(DATA_FLAGS, DATA_FLAG_ACTION, false); if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7)) { @@ -3630,8 +3607,8 @@ public void close(TextContainer message, String reason, boolean notify) { this.spawned = false; this.server.getLogger().info(this.getServer().getLanguage().translateString("nukkit.player.logOut", TextFormat.AQUA + (this.getName() == null ? "" : this.getName()) + TextFormat.WHITE, - this.ip, - String.valueOf(this.port), + this.getAddress(), + String.valueOf(this.getPort()), this.getServer().getLanguage().translateString(reason))); this.windows.clear(); this.usedChunks.clear(); @@ -4875,15 +4852,6 @@ public boolean equals(Object obj) { return Objects.equals(this.getUniqueId(), other.getUniqueId()) && this.getId() == other.getId(); } - /** - * Notifies an ACK response from the client - * - * @param identification packet identity - */ - public void notifyACK(int identification) { - needACK.put(identification, Boolean.TRUE); - } - public boolean isBreakingBlock() { return this.breakingBlock != null; } diff --git a/src/main/java/cn/nukkit/Server.java b/src/main/java/cn/nukkit/Server.java index 570f3c68488..ab6c5054540 100644 --- a/src/main/java/cn/nukkit/Server.java +++ b/src/main/java/cn/nukkit/Server.java @@ -80,6 +80,7 @@ import co.aikar.timings.Timings; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; +import io.netty.buffer.ByteBuf; import lombok.extern.log4j.Log4j2; import org.iq80.leveldb.CompressionType; import org.iq80.leveldb.DB; @@ -90,6 +91,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; @@ -204,12 +208,10 @@ public class Server { private Config properties; private Config config; - private final Map players = new HashMap<>(); + private final Map players = new HashMap<>(); private final Map playerList = new HashMap<>(); - private final Map identifier = new HashMap<>(); - private final Map levels = new HashMap() { public Level put(Integer key, Level value) { Level result = super.put(key, value); @@ -654,10 +656,6 @@ public static void broadcastPacket(Player[] players, DataPacket packet) { } else { getInstance().batchPackets(players, new DataPacket[]{packet}, true); } - - if (packet.encapsulatedPacket != null) { - packet.encapsulatedPacket = null; - } } public void batchPackets(Player[] players, DataPacket[] packets) { @@ -691,10 +689,10 @@ public void batchPackets(Player[] players, DataPacket[] packets, boolean forceSy size += payload[i * 2 + 1].length; } - List targets = new ArrayList<>(); + List targets = new ArrayList<>(); for (Player p : players) { if (p.isConnected()) { - targets.add(this.identifier.get(p.rawHashCode())); + targets.add(p.getSocketAddress()); } } @@ -711,11 +709,11 @@ public void batchPackets(Player[] players, DataPacket[] packets, boolean forceSy Timings.playerNetworkSendTimer.stopTiming(); } - public void broadcastPacketsCallback(byte[] data, List identifiers) { + public void broadcastPacketsCallback(byte[] data, List targets) { BatchPacket pk = new BatchPacket(); pk.payload = data; - for (String i : identifiers) { + for (InetSocketAddress i : targets) { if (this.players.containsKey(i)) { this.players.get(i).dataPacket(pk); } @@ -798,7 +796,11 @@ public void reload() { this.operators.reload(); for (BanEntry entry : this.getIPBans().getEntires().values()) { - this.getNetwork().blockAddress(entry.getName(), -1); + try { + this.getNetwork().blockAddress(InetAddress.getByName(entry.getName()), -1); + } catch (UnknownHostException e) { + // ignore + } } this.pluginManager.registerInterface(JavaPluginLoader.class); @@ -876,7 +878,11 @@ public void start() { } for (BanEntry entry : this.getIPBans().getEntires().values()) { - this.network.blockAddress(entry.getName(), -1); + try { + this.network.blockAddress(InetAddress.getByName(entry.getName()), -1); + } catch (UnknownHostException e) { + // ignore + } } //todo send usage setting @@ -890,15 +896,24 @@ public void start() { this.forceShutdown(); } - public void handlePacket(String address, int port, byte[] payload) { + public void handlePacket(InetSocketAddress address, ByteBuf payload) { try { - if (payload.length > 2 && Arrays.equals(Binary.subBytes(payload, 0, 2), new byte[]{(byte) 0xfe, (byte) 0xfd}) && this.queryHandler != null) { - this.queryHandler.handle(address, port, payload); + if (!payload.isReadable(3)) { + return; + } + byte[] prefix = new byte[2]; + payload.readBytes(prefix); + + if (!Arrays.equals(prefix, new byte[]{(byte) 0xfe, (byte) 0xfd})) { + return; + } + if (this.queryHandler != null) { + this.queryHandler.handle(address, payload); } } catch (Exception e) { log.error("Error whilst handling packet", e); - this.getNetwork().blockAddress(address, 600); + this.network.blockAddress(address.getAddress(), -1); } } @@ -955,9 +970,8 @@ public void onPlayerLogin(Player player) { } } - public void addPlayer(String identifier, Player player) { - this.players.put(identifier, player); - this.identifier.put(player.rawHashCode(), identifier); + public void addPlayer(InetSocketAddress socketAddress, Player player) { + this.players.put(socketAddress, player); } public void addOnlinePlayer(Player player) { @@ -1807,18 +1821,15 @@ public Player[] matchPlayer(String partialName) { } public void removePlayer(Player player) { - if (this.identifier.containsKey(player.rawHashCode())) { - String identifier = this.identifier.get(player.rawHashCode()); - this.players.remove(identifier); - this.identifier.remove(player.rawHashCode()); + Player toRemove = this.players.remove(player.getSocketAddress()); + if (toRemove != null) { return; } - for (String identifier : new ArrayList<>(this.players.keySet())) { - Player p = this.players.get(identifier); + for (InetSocketAddress socketAddress : new ArrayList<>(this.players.keySet())) { + Player p = this.players.get(socketAddress); if (player == p) { - this.players.remove(identifier); - this.identifier.remove(player.rawHashCode()); + this.players.remove(socketAddress); break; } } diff --git a/src/main/java/cn/nukkit/command/defaults/BanIpCommand.java b/src/main/java/cn/nukkit/command/defaults/BanIpCommand.java index 44a6c65d9f7..3a6f9f404fc 100644 --- a/src/main/java/cn/nukkit/command/defaults/BanIpCommand.java +++ b/src/main/java/cn/nukkit/command/defaults/BanIpCommand.java @@ -13,6 +13,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.regex.Pattern; @@ -101,6 +103,10 @@ private void processIPBan(String ip, CommandSender sender, String reason) { } } - sender.getServer().getNetwork().blockAddress(ip, -1); + try { + sender.getServer().getNetwork().blockAddress(InetAddress.getByName(ip), -1); + } catch (UnknownHostException e) { + // ignore + } } } diff --git a/src/main/java/cn/nukkit/command/defaults/PardonIpCommand.java b/src/main/java/cn/nukkit/command/defaults/PardonIpCommand.java index 0fea580f328..bc61968664f 100644 --- a/src/main/java/cn/nukkit/command/defaults/PardonIpCommand.java +++ b/src/main/java/cn/nukkit/command/defaults/PardonIpCommand.java @@ -5,6 +5,8 @@ import cn.nukkit.command.data.CommandParameter; import cn.nukkit.lang.TranslationContainer; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.regex.Pattern; /** @@ -39,7 +41,13 @@ public boolean execute(CommandSender sender, String commandLabel, String[] args) if (Pattern.matches("^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$", value)) { sender.getServer().getIPBans().remove(value); - sender.getServer().getNetwork().unblockAddress(value); + + try { + sender.getServer().getNetwork().unblockAddress(InetAddress.getByName(value)); + } catch (UnknownHostException e) { + sender.sendMessage(new TranslationContainer("commands.unbanip.invalid")); + return true; + } Command.broadcastCommandMessage(sender, new TranslationContainer("commands.unbanip.success", value)); } else { diff --git a/src/main/java/cn/nukkit/event/player/PlayerCreationEvent.java b/src/main/java/cn/nukkit/event/player/PlayerCreationEvent.java index dd408ec13b5..be48b28a203 100644 --- a/src/main/java/cn/nukkit/event/player/PlayerCreationEvent.java +++ b/src/main/java/cn/nukkit/event/player/PlayerCreationEvent.java @@ -5,6 +5,8 @@ import cn.nukkit.event.HandlerList; import cn.nukkit.network.SourceInterface; +import java.net.InetSocketAddress; + /** * author: MagicDroidX * Nukkit Project @@ -21,19 +23,16 @@ public static HandlerList getHandlers() { private final Long clientId; - private final String address; - - private final int port; + private final InetSocketAddress socketAddress; private Class baseClass; private Class playerClass; - public PlayerCreationEvent(SourceInterface interfaz, Class baseClass, Class playerClass, Long clientId, String address, int port) { + public PlayerCreationEvent(SourceInterface interfaz, Class baseClass, Class playerClass, Long clientId, InetSocketAddress socketAddress) { this.interfaz = interfaz; this.clientId = clientId; - this.address = address; - this.port = port; + this.socketAddress = socketAddress; this.baseClass = baseClass; this.playerClass = playerClass; @@ -44,11 +43,15 @@ public SourceInterface getInterface() { } public String getAddress() { - return address; + return this.socketAddress.getAddress().toString(); } public int getPort() { - return port; + return this.socketAddress.getPort(); + } + + public InetSocketAddress getSocketAddress() { + return socketAddress; } public Long getClientId() { diff --git a/src/main/java/cn/nukkit/level/biome/impl/beach/ColdBeachBiome.java b/src/main/java/cn/nukkit/level/biome/impl/beach/ColdBeachBiome.java index 8ec3e1c8c55..98c85216fda 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/beach/ColdBeachBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/beach/ColdBeachBiome.java @@ -13,8 +13,8 @@ public ColdBeachBiome() { } @Override - public int getCoverBlock() { - return SNOW_LAYER; + public int getCoverId(int x, int z) { + return SNOW_LAYER << 4; } @Override diff --git a/src/main/java/cn/nukkit/level/biome/impl/extremehills/ExtremeHillsMBiome.java b/src/main/java/cn/nukkit/level/biome/impl/extremehills/ExtremeHillsMBiome.java index c14909d49a5..df49bc00fc1 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/extremehills/ExtremeHillsMBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/extremehills/ExtremeHillsMBiome.java @@ -32,24 +32,18 @@ public String getName() { } @Override - public int getSurfaceBlock(int y) { - return isGravel ? GRAVEL : super.getSurfaceBlock(y); + public int getSurfaceId(int x, int y, int z) { + return gravelNoise.noise2D(x, z, true) < -0.75f ? GRAVEL << 4 : super.getSurfaceId(x, y, z); } @Override - public int getSurfaceDepth(int y) { - return isGravel ? 4 : super.getSurfaceDepth(y); + public int getSurfaceDepth(int x, int y, int z) { + return gravelNoise.noise2D(x, z, true) < -0.75f ? 4 : super.getSurfaceDepth(x, y, z); } @Override - public int getGroundDepth(int y) { - return isGravel ? 0 : super.getGroundDepth(y); - } - - @Override - public void preCover(int x, int z) { - //-0.75 is farily rare, so there'll be much more gravel than grass - isGravel = gravelNoise.noise2D(x, z, true) < -0.75f; + public int getGroundDepth(int x, int y, int z) { + return gravelNoise.noise2D(x, z, true) < -0.75f ? 0 : super.getGroundDepth(x, y, z); } @Override diff --git a/src/main/java/cn/nukkit/level/biome/impl/extremehills/StoneBeachBiome.java b/src/main/java/cn/nukkit/level/biome/impl/extremehills/StoneBeachBiome.java index 26830acaef5..f5b192bf217 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/extremehills/StoneBeachBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/extremehills/StoneBeachBiome.java @@ -16,22 +16,22 @@ public StoneBeachBiome() { } @Override - public int getSurfaceDepth(int y) { + public int getSurfaceDepth(int x, int y, int z) { return 0; } @Override - public int getSurfaceBlock(int y) { + public int getSurfaceId(int x, int y, int z) { return 0; } @Override - public int getGroundDepth(int y) { + public int getGroundDepth(int x, int y, int z) { return 0; } @Override - public int getGroundBlock(int y) { + public int getGroundId(int x, int y, int z) { return 0; } diff --git a/src/main/java/cn/nukkit/level/biome/impl/iceplains/IcePlainsSpikesBiome.java b/src/main/java/cn/nukkit/level/biome/impl/iceplains/IcePlainsSpikesBiome.java index 7e9aeea8ff5..9675180e674 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/iceplains/IcePlainsSpikesBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/iceplains/IcePlainsSpikesBiome.java @@ -19,8 +19,8 @@ public IcePlainsSpikesBiome() { } @Override - public int getSurfaceBlock(int y) { - return SNOW_BLOCK; + public int getSurfaceId(int x, int y, int z) { + return SNOW_BLOCK << 4; } public String getName() { diff --git a/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaBiome.java b/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaBiome.java index 3bf8fbd84e4..67a3867a159 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaBiome.java @@ -16,11 +16,9 @@ * Handles the placement of stained clay for all mesa variants */ public class MesaBiome extends CoveredBiome { - static final int[] colorLayer = new int[64]; + static final int[] colorLayer = new int[64]; static final SimplexF redSandNoise = new SimplexF(new NukkitRandom(937478913), 2f, 1 / 4f, 1 / 4f); - static final SimplexF colorNoise = new SimplexF(new NukkitRandom(193759875), 2f, 1 / 4f, 1 / 32f); - private SimplexF moundNoise = new SimplexF(new NukkitRandom(347228794), 2f, 1 / 4f, getMoundFrequency()); - protected int moundHeight; + static final SimplexF colorNoise = new SimplexF(new NukkitRandom(193759875), 2f, 1 / 4f, 1 / 32f); static { Random random = new Random(29864); @@ -32,7 +30,7 @@ public class MesaBiome extends CoveredBiome { setRandomLayerColor(random, 10, 14); // red for (int i = 0, j = 0; i < random.nextInt(3) + 3; i++) { j += random.nextInt(6) + 4; - if (j >= colorLayer.length -3) { + if (j >= colorLayer.length - 3) { break; } if (random.nextInt(2) == 0 || j < colorLayer.length - 1 && random.nextInt(2) == 0) { @@ -54,12 +52,8 @@ private static void setRandomLayerColor(Random random, int sliceCount, int color } } - int randY = 0; - int redSandThreshold = 0; - boolean isRedSand = false; - //cache this too so we can access it in getSurfaceBlock and getSurfaceMeta without needing to calculate it twice - int currMeta = 0; - int startY = 0; + private SimplexF moundNoise = new SimplexF(new NukkitRandom(347228794), 2f, 1 / 4f, getMoundFrequency()); + protected int moundHeight; public MesaBiome() { PopulatorCactus cactus = new PopulatorCactus(); @@ -75,45 +69,33 @@ public MesaBiome() { this.setMoundHeight(17); } - public void setMoundHeight(int height) { + public void setMoundHeight(int height) { this.moundHeight = height; } @Override - public int getSurfaceDepth(int y) { - isRedSand = y < redSandThreshold; - startY = y; - //if true, we'll be generating red sand - return isRedSand ? 3 : y - 66; - } - - @Override - public int getSurfaceBlock(int y) { - if (isRedSand) { - return SAND; - } else { - currMeta = colorLayer[(y + randY) & 0x3F]; - return currMeta == -1 ? TERRACOTTA : STAINED_TERRACOTTA; - } + public int getSurfaceDepth(int x, int y, int z) { + return y < (71 + Math.round((redSandNoise.noise2D(x, z, true) + 1) * 1.5f)) ? 3 : y - 66; } @Override - public int getSurfaceMeta(int y) { - if (isRedSand) { - return BlockSand.RED; + public int getSurfaceId(int x, int y, int z) { + if (y < (71 + Math.round((redSandNoise.noise2D(x, z, true) + 1) * 1.5f))) { + return (SAND << 4) | BlockSand.RED; } else { - return Math.max(0, currMeta); + int meta = colorLayer[(y + Math.round((colorNoise.noise2D(x, z, true) + 1) * 1.5f)) & 0x3F]; + return (meta == -1 ? TERRACOTTA << 4 : STAINED_TERRACOTTA << 4) | Math.max(0, meta); } } @Override - public int getGroundDepth(int y) { - return isRedSand ? 2 : 0; + public int getGroundDepth(int x, int y, int z) { + return y < (71 + Math.round((redSandNoise.noise2D(x, z, true) + 1) * 1.5f)) ? 2 : 0; } @Override - public int getGroundBlock(int y) { - return RED_SANDSTONE; + public int getGroundId(int x, int y, int z) { + return RED_SANDSTONE << 4; } @Override @@ -121,14 +103,7 @@ public String getName() { return "Mesa"; } - @Override - public void preCover(int x, int z) { - //random noise from 0-3 - randY = Math.round((colorNoise.noise2D(x, z, true) + 1) * 1.5f); - redSandThreshold = 71 + Math.round((redSandNoise.noise2D(x, z, true) + 1) * 1.5f); - } - - protected float getMoundFrequency() { + protected float getMoundFrequency() { return 1 / 128f; } @@ -139,7 +114,7 @@ public int getHeightOffset(int x, int z) { return (n > a && n < a + 0.2f) ? (int) ((n - a) * 5f * moundHeight) : n < a + 0.1f ? 0 : moundHeight; } - protected float minHill() { + protected float minHill() { return -0.1f; } } diff --git a/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaPlateauFBiome.java b/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaPlateauFBiome.java index a6cb36cf931..3a5433c70af 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaPlateauFBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/mesa/MesaPlateauFBiome.java @@ -17,8 +17,8 @@ public MesaPlateauFBiome() { } @Override - public int getCoverBlock() { - return GRASS; + public int getCoverId(int x, int z) { + return GRASS << 4; } @Override diff --git a/src/main/java/cn/nukkit/level/biome/impl/mushroom/MushroomIslandBiome.java b/src/main/java/cn/nukkit/level/biome/impl/mushroom/MushroomIslandBiome.java index 06b30f9e588..b9e3706034b 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/mushroom/MushroomIslandBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/mushroom/MushroomIslandBiome.java @@ -20,7 +20,7 @@ public String getName() { } @Override - public int getSurfaceBlock(int y) { - return Block.MYCELIUM; + public int getSurfaceId(int x, int y, int z) { + return MYCELIUM << 4; } } diff --git a/src/main/java/cn/nukkit/level/biome/impl/ocean/OceanBiome.java b/src/main/java/cn/nukkit/level/biome/impl/ocean/OceanBiome.java index 786e163e2dc..cda7e9df1ea 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/ocean/OceanBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/ocean/OceanBiome.java @@ -18,8 +18,7 @@ public String getName() { return "Ocean"; } - @Override - public int getGroundBlock(int y) { - return GRAVEL; + public int getGroundId(int y) { + return GRAVEL << 4; } } diff --git a/src/main/java/cn/nukkit/level/biome/impl/taiga/ColdTaigaBiome.java b/src/main/java/cn/nukkit/level/biome/impl/taiga/ColdTaigaBiome.java index 9b8450cc2a6..54332c48d17 100644 --- a/src/main/java/cn/nukkit/level/biome/impl/taiga/ColdTaigaBiome.java +++ b/src/main/java/cn/nukkit/level/biome/impl/taiga/ColdTaigaBiome.java @@ -23,8 +23,8 @@ public String getName() { } @Override - public int getCoverBlock() { - return SNOW_LAYER; + public int getCoverId(int x, int z) { + return SNOW_LAYER << 4; } @Override diff --git a/src/main/java/cn/nukkit/level/biome/type/CoveredBiome.java b/src/main/java/cn/nukkit/level/biome/type/CoveredBiome.java index 9a5ad67cd92..b934cd3b1d1 100644 --- a/src/main/java/cn/nukkit/level/biome/type/CoveredBiome.java +++ b/src/main/java/cn/nukkit/level/biome/type/CoveredBiome.java @@ -1,6 +1,8 @@ package cn.nukkit.level.biome.type; import cn.nukkit.level.biome.Biome; +import cn.nukkit.level.format.FullChunk; +import cn.nukkit.level.generator.Normal; /** * author: DaPorkchop_ @@ -10,97 +12,63 @@ *

*/ public abstract class CoveredBiome extends Biome { - public final Object synchronizeCover = new Object(); - - /** - * A single block placed on top of the surface blocks - * - * @return cover block - */ - public int getCoverBlock() { - return AIR; + public int getCoverId(int x, int z) { + return AIR << 4; } - /** - * The amount of times the surface block should be used - *

- * If < 0 bad things will happen! - *

- * - * @param y y - * @return surface depth - */ - public int getSurfaceDepth(int y) { + public int getSurfaceDepth(int x, int y, int z) { return 1; } - /** - * Between cover and ground - * - * @param y y - * @return surface block - */ - public abstract int getSurfaceBlock(int y); - - /** - * The metadata of the surface block - * - * @param y y - * @return surface meta - */ - public int getSurfaceMeta(int y) { - return 0; - } + public abstract int getSurfaceId(int x, int y, int z); - /** - * The amount of times the ground block should be used - *

- * If < 0 bad things will happen! - * - * @param y y - * @return ground depth - */ - public int getGroundDepth(int y) { + public int getGroundDepth(int x, int y, int z) { return 4; } - /** - * Between surface and stone - * - * @param y y - * @return ground block - */ - public abstract int getGroundBlock(int y); + public abstract int getGroundId(int x, int y, int z); - /** - * The metadata of the ground block - * - * @param y y - * @return ground meta - */ - public int getGroundMeta(int y) { - return 0; - } - - /** - * The block used as stone/below all other surface blocks - * - * @return stone block - */ - public int getStoneBlock() { - return STONE; - } + public void doCover(int x, int z, FullChunk chunk) { + final int fullX = (chunk.getX() << 4) | x; + final int fullZ = (chunk.getZ() << 4) | z; - /** - * Called before a new block column is covered. Biomes can update any relevant variables here before covering. - *

- * Biome covering is synchronized on the biome, so thread safety isn't an issue. - *

- * - * @param x x - * @param z z - */ - public void preCover(int x, int z) { + final int coverBlock = this.getCoverId(fullX, fullZ); + boolean hasCovered = false; + int realY; + //start one below build limit in case of cover blocks + for (int y = 254; y > 32; y--) { + if (chunk.getFullBlock(x, y, z) == STONE << 4) { + COVER: + if (!hasCovered) { + if (y >= Normal.seaHeight) { + chunk.setFullBlockId(x, y + 1, z, coverBlock); + int surfaceDepth = this.getSurfaceDepth(fullX, y, fullZ); + for (int i = 0; i < surfaceDepth; i++) { + realY = y - i; + if (chunk.getFullBlock(x, realY, z) == STONE << 4) { + chunk.setFullBlockId(x, realY, z, this.getSurfaceId(fullX, realY, fullZ)); + } else break COVER; + } + y -= surfaceDepth; + } + int groundDepth = this.getGroundDepth(fullX, y, fullZ); + for (int i = 0; i < groundDepth; i++) { + realY = y - i; + if (chunk.getFullBlock(x, realY, z) == STONE << 4) { + chunk.setFullBlockId(x, realY, z, this.getGroundId(fullX, realY, fullZ)); + } else break COVER; + } + //don't take all of groundDepth away because we do y-- in the loop + y -= groundDepth - 1; + } + hasCovered = true; + } else { + if (hasCovered) { + //reset it if this isn't a valid stone block (allows us to place ground cover on top and below overhangs) + hasCovered = false; + } + } + } } } diff --git a/src/main/java/cn/nukkit/level/biome/type/GrassyBiome.java b/src/main/java/cn/nukkit/level/biome/type/GrassyBiome.java index 3d7afbd9369..91048cab4b7 100644 --- a/src/main/java/cn/nukkit/level/biome/type/GrassyBiome.java +++ b/src/main/java/cn/nukkit/level/biome/type/GrassyBiome.java @@ -20,12 +20,12 @@ public GrassyBiome() { } @Override - public int getSurfaceBlock(int y) { - return GRASS; + public int getSurfaceId(int x, int y, int z) { + return GRASS << 4; } @Override - public int getGroundBlock(int y) { - return DIRT; + public int getGroundId(int x, int y, int z) { + return DIRT << 4; } } diff --git a/src/main/java/cn/nukkit/level/biome/type/SandyBiome.java b/src/main/java/cn/nukkit/level/biome/type/SandyBiome.java index f094309143c..e7b854e0ae8 100644 --- a/src/main/java/cn/nukkit/level/biome/type/SandyBiome.java +++ b/src/main/java/cn/nukkit/level/biome/type/SandyBiome.java @@ -7,24 +7,23 @@ * Nukkit Project */ public abstract class SandyBiome extends CoveredBiome { - @Override - public int getSurfaceDepth(int y) { + public int getSurfaceDepth(int x, int y, int z) { return 3; } @Override - public int getSurfaceBlock(int y) { - return Block.SAND; + public int getSurfaceId(int x, int y, int z) { + return SAND << 4; } @Override - public int getGroundDepth(int y) { + public int getGroundDepth(int x, int y, int z) { return 2; } @Override - public int getGroundBlock(int y) { - return Block.SANDSTONE; + public int getGroundId(int x, int y, int z) { + return SANDSTONE << 4; } } diff --git a/src/main/java/cn/nukkit/level/biome/type/SnowyBiome.java b/src/main/java/cn/nukkit/level/biome/type/SnowyBiome.java index 81445bbf943..686d941e415 100644 --- a/src/main/java/cn/nukkit/level/biome/type/SnowyBiome.java +++ b/src/main/java/cn/nukkit/level/biome/type/SnowyBiome.java @@ -15,7 +15,7 @@ public SnowyBiome() { } @Override - public int getCoverBlock() { - return SNOW_LAYER; + public int getCoverId(int x, int z) { + return SNOW_LAYER << 4; } } diff --git a/src/main/java/cn/nukkit/level/biome/type/WateryBiome.java b/src/main/java/cn/nukkit/level/biome/type/WateryBiome.java index 2caa9e8c834..17ba88e2aa4 100644 --- a/src/main/java/cn/nukkit/level/biome/type/WateryBiome.java +++ b/src/main/java/cn/nukkit/level/biome/type/WateryBiome.java @@ -6,23 +6,23 @@ */ public abstract class WateryBiome extends CoveredBiome { @Override - public int getSurfaceDepth(int y) { + public int getSurfaceDepth(int x, int y, int z) { return 0; } @Override - public int getSurfaceBlock(int y) { + public int getSurfaceId(int x, int y, int z) { //doesn't matter, surface depth is 0 return 0; } @Override - public int getGroundDepth(int y) { + public int getGroundDepth(int x, int y, int z) { return 5; } @Override - public int getGroundBlock(int y) { - return DIRT; + public int getGroundId(int x, int y, int z) { + return DIRT << 4; } } diff --git a/src/main/java/cn/nukkit/level/generator/Flat.java b/src/main/java/cn/nukkit/level/generator/Flat.java index 005b1129513..2739c083a9b 100644 --- a/src/main/java/cn/nukkit/level/generator/Flat.java +++ b/src/main/java/cn/nukkit/level/generator/Flat.java @@ -6,8 +6,8 @@ import cn.nukkit.level.format.FullChunk; import cn.nukkit.level.format.generic.BaseFullChunk; import cn.nukkit.level.generator.object.ore.OreType; -import cn.nukkit.level.generator.populator.type.Populator; import cn.nukkit.level.generator.populator.impl.PopulatorOre; +import cn.nukkit.level.generator.populator.type.Populator; import cn.nukkit.math.NukkitRandom; import cn.nukkit.math.Vector3; @@ -70,8 +70,7 @@ public Flat(Map options) { this.options = options; if (this.options.containsKey("decoration")) { - PopulatorOre ores = new PopulatorOre(); - ores.setOreTypes(new OreType[]{ + PopulatorOre ores = new PopulatorOre(BlockID.STONE, new OreType[]{ new OreType(new BlockOreCoal(), 20, 16, 0, 128), new OreType(new BlockOreIron(), 20, 8, 0, 64), new OreType(new BlockOreRedstone(), 8, 7, 0, 16), diff --git a/src/main/java/cn/nukkit/level/generator/Nether.java b/src/main/java/cn/nukkit/level/generator/Nether.java index 205af838f65..ad1a801def4 100644 --- a/src/main/java/cn/nukkit/level/generator/Nether.java +++ b/src/main/java/cn/nukkit/level/generator/Nether.java @@ -15,6 +15,7 @@ import cn.nukkit.level.generator.populator.type.Populator; import cn.nukkit.math.NukkitRandom; import cn.nukkit.math.Vector3; + import java.util.*; public class Nether extends Generator { @@ -81,8 +82,7 @@ public void init(ChunkManager level, NukkitRandom random) { this.localSeed1 = this.random.nextLong(); this.localSeed2 = this.random.nextLong(); - PopulatorOre ores = new PopulatorOre(Block.NETHERRACK); - ores.setOreTypes(new OreType[]{ + PopulatorOre ores = new PopulatorOre(Block.NETHERRACK, new OreType[]{ new OreType(new BlockOreQuartz(), 20, 16, 0, 128), new OreType(new BlockSoulSand(), 5, 64, 0, 128), new OreType(new BlockGravel(), 5, 64, 0, 128), @@ -100,8 +100,7 @@ public void init(ChunkManager level, NukkitRandom random) { lava.setRandomAmount(2); this.populators.add(lava); this.populators.add(new PopulatorGlowStone()); - PopulatorOre ore = new PopulatorOre(Block.NETHERRACK); - ore.setOreTypes(new OreType[]{ + PopulatorOre ore = new PopulatorOre(Block.NETHERRACK, new OreType[]{ new OreType(new BlockOreQuartz(), 40, 16, 0, 128, NETHERRACK), new OreType(new BlockSoulSand(), 1, 64, 30, 35, NETHERRACK), new OreType(new BlockLava(), 32, 1, 0, 32, NETHERRACK), diff --git a/src/main/java/cn/nukkit/level/generator/Normal.java b/src/main/java/cn/nukkit/level/generator/Normal.java index f509e8c8155..defa3f0dbfa 100644 --- a/src/main/java/cn/nukkit/level/generator/Normal.java +++ b/src/main/java/cn/nukkit/level/generator/Normal.java @@ -9,14 +9,12 @@ import cn.nukkit.level.generator.noise.vanilla.f.NoiseGeneratorOctavesF; import cn.nukkit.level.generator.noise.vanilla.f.NoiseGeneratorPerlinF; import cn.nukkit.level.generator.object.ore.OreType; -import cn.nukkit.level.generator.populator.impl.PopulatorBedrock; -import cn.nukkit.level.generator.populator.impl.PopulatorCaves; -import cn.nukkit.level.generator.populator.impl.PopulatorGroundCover; -import cn.nukkit.level.generator.populator.impl.PopulatorOre; +import cn.nukkit.level.generator.populator.impl.*; import cn.nukkit.level.generator.populator.type.Populator; import cn.nukkit.math.MathHelper; import cn.nukkit.math.NukkitRandom; import cn.nukkit.math.Vector3; +import com.google.common.collect.ImmutableList; import java.util.*; @@ -113,8 +111,8 @@ public class Normal extends Generator { } } - private final List populators = new ArrayList<>(); - private final List generationPopulators = new ArrayList<>(); + private List populators = Collections.emptyList(); + private List generationPopulators = Collections.emptyList(); public static final int seaHeight = 64; public NoiseGeneratorOctavesF scaleNoise; public NoiseGeneratorOctavesF depthNoise; @@ -136,7 +134,7 @@ public class Normal extends Generator { private NoiseGeneratorPerlinF surfaceNoise; public Normal() { - this(new HashMap<>()); + this(Collections.emptyMap()); } public Normal(Map options) { @@ -150,7 +148,7 @@ public int getId() { @Override public ChunkManager getChunkManager() { - return level; + return this.level; } @Override @@ -160,7 +158,7 @@ public String getName() { @Override public Map getSettings() { - return new HashMap<>(); + return Collections.emptyMap(); } public Biome pickBiome(int x, int z) { @@ -186,43 +184,37 @@ public void init(ChunkManager level, NukkitRandom random) { this.depthNoise = new NoiseGeneratorOctavesF(random, 16); //this should run before all other populators so that we don't do things like generate ground cover on bedrock or something - PopulatorGroundCover cover = new PopulatorGroundCover(); - this.generationPopulators.add(cover); - - PopulatorBedrock bedrock = new PopulatorBedrock(); - this.generationPopulators.add(bedrock); - - PopulatorOre ores = new PopulatorOre(); - ores.setOreTypes(new OreType[]{ - new OreType(new BlockOreCoal(), 20, 17, 0, 128), - new OreType(new BlockOreIron(), 20, 9, 0, 64), - new OreType(new BlockOreRedstone(), 8, 8, 0, 16), - new OreType(new BlockOreLapis(), 1, 7, 0, 16), - new OreType(new BlockOreGold(), 2, 9, 0, 32), - new OreType(new BlockOreDiamond(), 1, 8, 0, 16), - new OreType(new BlockDirt(), 10, 33, 0, 128), - new OreType(new BlockGravel(), 8, 33, 0, 128), - new OreType(new BlockStone(BlockStone.GRANITE), 10, 33, 0, 80), - new OreType(new BlockStone(BlockStone.DIORITE), 10, 33, 0, 80), - new OreType(new BlockStone(BlockStone.ANDESITE), 10, 33, 0, 80) - }); - this.populators.add(ores); - - PopulatorCaves caves = new PopulatorCaves(); - this.populators.add(caves); - - //TODO: fix ravines - //PopulatorRavines ravines = new PopulatorRavines(); - //this.populators.add(ravines); + this.generationPopulators = ImmutableList.of( + new PopulatorBedrock(), + new PopulatorGroundCover() + ); + + this.populators = ImmutableList.of( + new PopulatorOre(STONE, new OreType[]{ + new OreType(new BlockOreCoal(), 20, 17, 0, 128), + new OreType(new BlockOreIron(), 20, 9, 0, 64), + new OreType(new BlockOreRedstone(), 8, 8, 0, 16), + new OreType(new BlockOreLapis(), 1, 7, 0, 16), + new OreType(new BlockOreGold(), 2, 9, 0, 32), + new OreType(new BlockOreDiamond(), 1, 8, 0, 16), + new OreType(new BlockDirt(), 10, 33, 0, 128), + new OreType(new BlockGravel(), 8, 33, 0, 128), + new OreType(new BlockStone(BlockStone.GRANITE), 10, 33, 0, 80), + new OreType(new BlockStone(BlockStone.DIORITE), 10, 33, 0, 80), + new OreType(new BlockStone(BlockStone.ANDESITE), 10, 33, 0, 80) + }), + new PopulatorCaves()//, + //new PopulatorRavines() + ); } @Override public void generateChunk(final int chunkX, final int chunkZ) { int baseX = chunkX << 4; int baseZ = chunkZ << 4; - this.nukkitRandom.setSeed(chunkX * localSeed1 ^ chunkZ * localSeed2 ^ this.level.getSeed()); + this.nukkitRandom.setSeed(chunkX * this.localSeed1 ^ chunkZ * this.localSeed2 ^ this.level.getSeed()); - BaseFullChunk chunk = level.getChunk(chunkX, chunkZ); + BaseFullChunk chunk = this.level.getChunk(chunkX, chunkZ); //generate base noise values float[] depthRegion = this.depthNoise.generateNoiseOctaves(this.depthRegion.get(), chunkX * 4, chunkZ * 4, 5, 5, 200f, 200f, 0.5f); @@ -243,11 +235,11 @@ public void generateChunk(final int chunkX, final int chunkZ) { float heightVariationSum = 0.0F; float baseHeightSum = 0.0F; float biomeWeightSum = 0.0F; - Biome biome = pickBiome(baseX + (xSeg * 4), baseZ + (zSeg * 4)); + Biome biome = this.pickBiome(baseX + (xSeg * 4), baseZ + (zSeg * 4)); for (int xSmooth = -2; xSmooth <= 2; ++xSmooth) { for (int zSmooth = -2; zSmooth <= 2; ++zSmooth) { - Biome biome1 = pickBiome(baseX + (xSeg * 4) + xSmooth, baseZ + (zSeg * 4) + zSmooth); + Biome biome1 = this.pickBiome(baseX + (xSeg * 4) + xSmooth, baseZ + (zSeg * 4) + zSmooth); float baseHeight = biome1.getBaseHeight(); float heightVariation = biome1.getHeightVariation(); @@ -376,7 +368,7 @@ public void generateChunk(final int chunkX, final int chunkZ) { for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - Biome biome = selector.pickBiome(baseX | x, baseZ | z); + Biome biome = this.selector.pickBiome(baseX | x, baseZ | z); chunk.setBiome(x, z, biome); } @@ -390,12 +382,13 @@ public void generateChunk(final int chunkX, final int chunkZ) { @Override public void populateChunk(int chunkX, int chunkZ) { - BaseFullChunk chunk = level.getChunk(chunkX, chunkZ); + BaseFullChunk chunk = this.level.getChunk(chunkX, chunkZ); this.nukkitRandom.setSeed(0xdeadbeef ^ (chunkX << 8) ^ chunkZ ^ this.level.getSeed()); for (Populator populator : this.populators) { populator.populate(this.level, chunkX, chunkZ, this.nukkitRandom, chunk); } + @SuppressWarnings("deprecation") Biome biome = EnumBiome.getBiome(chunk.getBiomeId(7, 7)); biome.populateChunk(this.level, chunkX, chunkZ, this.nukkitRandom); } @@ -404,4 +397,4 @@ public void populateChunk(int chunkX, int chunkZ) { public Vector3 getSpawn() { return new Vector3(0.5, 256, 0.5); } -} +} \ No newline at end of file diff --git a/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorCaves.java b/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorCaves.java index bfadd32b2a8..59eaed143aa 100644 --- a/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorCaves.java +++ b/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorCaves.java @@ -206,7 +206,7 @@ protected void generateCaveNode(long seed, FullChunk chunk, double x, double y, // If grass was just deleted, try to // move it down if (grassFound && (chunk.getBlockId(xx, yy - 1, zz) == Block.DIRT)) { - chunk.setBlock(xx, yy - 1, zz, ((CoveredBiome) biome).getSurfaceBlock(yy - 1)); + chunk.setFullBlockId(xx, yy - 1, zz, ((CoveredBiome) biome).getSurfaceId(xx, yy - 1, zz)); } } } diff --git a/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorGroundCover.java b/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorGroundCover.java index 09806df1066..b34290591ca 100644 --- a/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorGroundCover.java +++ b/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorGroundCover.java @@ -11,63 +11,17 @@ import cn.nukkit.math.NukkitRandom; /** - * author: DaPorkchop_ - * Nukkit Project + * @author DaPorkchop_ */ public class PopulatorGroundCover extends Populator { - public static final int STONE = BlockID.STONE << 4; - @Override public void populate(ChunkManager level, int chunkX, int chunkZ, NukkitRandom random, FullChunk chunk) { - int realX = chunkX << 4; - int realZ = chunkZ << 4; - for (int x = 0; x < 16; ++x) { - for (int z = 0; z < 16; ++z) { + //reverse iteration to 0 is faster + for (int x = 15; x >= 0; x--) { + for (int z = 15; z >= 0; z--) { Biome realBiome = EnumBiome.getBiome(chunk.getBiomeId(x, z)); if (realBiome instanceof CoveredBiome) { - final CoveredBiome biome = (CoveredBiome) realBiome; - //just in case! - synchronized (biome.synchronizeCover) { - biome.preCover(realX | x, realZ | z); - int coverBlock = biome.getCoverBlock() << 4; - - boolean hasCovered = false; - int realY; - //start one below build limit in case of cover blocks - for (int y = 254; y > 32; y--) { - if (chunk.getFullBlock(x, y, z) == STONE) { - COVER: - if (!hasCovered) { - if (y >= Normal.seaHeight) { - chunk.setFullBlockId(x, y + 1, z, coverBlock); - int surfaceDepth = biome.getSurfaceDepth(y); - for (int i = 0; i < surfaceDepth; i++) { - realY = y - i; - if (chunk.getFullBlock(x, realY, z) == STONE) { - chunk.setFullBlockId(x, realY, z, (biome.getSurfaceBlock(realY) << 4) | biome.getSurfaceMeta(realY)); - } else break COVER; - } - y -= surfaceDepth; - } - int groundDepth = biome.getGroundDepth(y); - for (int i = 0; i < groundDepth; i++) { - realY = y - i; - if (chunk.getFullBlock(x, realY, z) == STONE) { - chunk.setFullBlockId(x, realY, z, (biome.getGroundBlock(realY) << 4) | biome.getGroundMeta(realY)); - } else break COVER; - } - //don't take all of groundDepth away because we do y-- in the loop - y -= groundDepth - 1; - } - hasCovered = true; - } else { - if (hasCovered) { - //reset it if this isn't a valid stone block (allows us to place ground cover on top and below overhangs) - hasCovered = false; - } - } - } - } + ((CoveredBiome) realBiome).doCover(x, z, chunk); } } } diff --git a/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorOre.java b/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorOre.java index ee762f6def8..472d587354e 100644 --- a/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorOre.java +++ b/src/main/java/cn/nukkit/level/generator/populator/impl/PopulatorOre.java @@ -9,19 +9,15 @@ import cn.nukkit.math.NukkitRandom; /** - * author: MagicDroidX - * Nukkit Project + * @author DaPorkchop_ */ public class PopulatorOre extends Populator { private final int replaceId; - private OreType[] oreTypes = new OreType[0]; + private final OreType[] oreTypes; - public PopulatorOre() { - this(Block.STONE); - } - - public PopulatorOre(int id) { - this.replaceId = id; + public PopulatorOre(int replaceId, OreType[] oreTypes) { + this.replaceId = replaceId; + this.oreTypes = oreTypes; } @Override @@ -42,8 +38,4 @@ public void populate(ChunkManager level, int chunkX, int chunkZ, NukkitRandom ra } } } - - public void setOreTypes(OreType[] oreTypes) { - this.oreTypes = oreTypes; - } } diff --git a/src/main/java/cn/nukkit/network/AdvancedSourceInterface.java b/src/main/java/cn/nukkit/network/AdvancedSourceInterface.java index 6902856b74c..6a982696c63 100644 --- a/src/main/java/cn/nukkit/network/AdvancedSourceInterface.java +++ b/src/main/java/cn/nukkit/network/AdvancedSourceInterface.java @@ -1,18 +1,23 @@ package cn.nukkit.network; +import io.netty.buffer.ByteBuf; + +import java.net.InetAddress; +import java.net.InetSocketAddress; + /** * author: MagicDroidX * Nukkit Project */ public interface AdvancedSourceInterface extends SourceInterface { - void blockAddress(String address); + void blockAddress(InetAddress address); - void blockAddress(String address, int timeout); + void blockAddress(InetAddress address, int timeout); - void unblockAddress(String address); + void unblockAddress(InetAddress address); void setNetwork(Network network); - void sendRawPacket(String address, int port, byte[] payload); + void sendRawPacket(InetSocketAddress socketAddress, ByteBuf payload); } diff --git a/src/main/java/cn/nukkit/network/CacheEncapsulatedPacket.java b/src/main/java/cn/nukkit/network/CacheEncapsulatedPacket.java deleted file mode 100644 index 4272d0d41e8..00000000000 --- a/src/main/java/cn/nukkit/network/CacheEncapsulatedPacket.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.nukkit.network; - -import cn.nukkit.raknet.protocol.EncapsulatedPacket; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class CacheEncapsulatedPacket extends EncapsulatedPacket { - - public byte[] internalData = null; - - @Override - public byte[] toBinary() { - return this.toBinary(false); - } - - @Override - public byte[] toBinary(boolean internal) { - if (this.internalData == null) { - this.internalData = super.toBinary(internal); - } - return this.internalData; - } -} \ No newline at end of file diff --git a/src/main/java/cn/nukkit/network/CompressBatchedPacket.java b/src/main/java/cn/nukkit/network/CompressBatchedPacket.java index 6cc6ab3f738..b45811951e2 100644 --- a/src/main/java/cn/nukkit/network/CompressBatchedPacket.java +++ b/src/main/java/cn/nukkit/network/CompressBatchedPacket.java @@ -4,7 +4,7 @@ import cn.nukkit.scheduler.AsyncTask; import cn.nukkit.utils.Zlib; -import java.util.ArrayList; +import java.net.InetSocketAddress; import java.util.List; /** @@ -17,17 +17,17 @@ public class CompressBatchedPacket extends AsyncTask { public byte[] data; public byte[] finalData; public int channel = 0; - public List targets = new ArrayList<>(); + public List targets; - public CompressBatchedPacket(byte[] data, List targets) { + public CompressBatchedPacket(byte[] data, List targets) { this(data, targets, 7); } - public CompressBatchedPacket(byte[] data, List targets, int level) { + public CompressBatchedPacket(byte[] data, List targets, int level) { this(data, targets, level, 0); } - public CompressBatchedPacket(byte[] data, List targets, int level, int channel) { + public CompressBatchedPacket(byte[] data, List targets, int level, int channel) { this.data = data; this.targets = targets; this.level = level; diff --git a/src/main/java/cn/nukkit/network/CompressBatchedTask.java b/src/main/java/cn/nukkit/network/CompressBatchedTask.java index bafffba677d..5f0880f4248 100644 --- a/src/main/java/cn/nukkit/network/CompressBatchedTask.java +++ b/src/main/java/cn/nukkit/network/CompressBatchedTask.java @@ -4,7 +4,7 @@ import cn.nukkit.scheduler.AsyncTask; import cn.nukkit.utils.Zlib; -import java.util.ArrayList; +import java.net.InetSocketAddress; import java.util.List; /** @@ -17,17 +17,17 @@ public class CompressBatchedTask extends AsyncTask { public byte[][] data; public byte[] finalData; public int channel = 0; - public List targets = new ArrayList<>(); + public List targets; - public CompressBatchedTask(byte[][] data, List targets) { + public CompressBatchedTask(byte[][] data, List targets) { this(data, targets, 7); } - public CompressBatchedTask(byte[][] data, List targets, int level) { + public CompressBatchedTask(byte[][] data, List targets, int level) { this(data, targets, level, 0); } - public CompressBatchedTask(byte[][] data, List targets, int level, int channel) { + public CompressBatchedTask(byte[][] data, List targets, int level, int channel) { this.data = data; this.targets = targets; this.level = level; diff --git a/src/main/java/cn/nukkit/network/Network.java b/src/main/java/cn/nukkit/network/Network.java index d939f284f2f..7386c0d9681 100644 --- a/src/main/java/cn/nukkit/network/Network.java +++ b/src/main/java/cn/nukkit/network/Network.java @@ -4,15 +4,19 @@ import cn.nukkit.Player; import cn.nukkit.Server; import cn.nukkit.network.protocol.*; +import cn.nukkit.utils.Binary; import cn.nukkit.utils.BinaryStream; import cn.nukkit.utils.MainLogger; import cn.nukkit.utils.Utils; import cn.nukkit.utils.VarInt; import cn.nukkit.utils.Zlib; +import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import lombok.extern.log4j.Log4j2; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; @@ -103,9 +107,11 @@ public void registerInterface(SourceInterface interfaz) { interfaz.setName(this.name + "!@#" + this.subName); } - public void unregisterInterface(SourceInterface interfaz) { - this.interfaces.remove(interfaz); - this.advancedInterfaces.remove(interfaz); + public void unregisterInterface(SourceInterface sourceInterface) { + this.interfaces.remove(sourceInterface); + if (sourceInterface instanceof AdvancedSourceInterface) { + this.advancedInterfaces.remove(sourceInterface); + } } public void setName(String name) { @@ -217,25 +223,27 @@ public DataPacket getPacket(byte id) { return null; } - public void sendPacket(String address, int port, byte[] payload) { - for (AdvancedSourceInterface interfaz : this.advancedInterfaces) { - interfaz.sendRawPacket(address, port, payload); + public void sendPacket(InetSocketAddress socketAddress, ByteBuf payload) { + for (AdvancedSourceInterface sourceInterface : this.advancedInterfaces) { + sourceInterface.sendRawPacket(socketAddress, payload); } } - public void blockAddress(String address) { - this.blockAddress(address, 300); + public void blockAddress(InetAddress address) { + for (AdvancedSourceInterface sourceInterface : this.advancedInterfaces) { + sourceInterface.blockAddress(address); + } } - public void blockAddress(String address, int timeout) { - for (AdvancedSourceInterface interfaz : this.advancedInterfaces) { - interfaz.blockAddress(address, timeout); + public void blockAddress(InetAddress address, int timeout) { + for (AdvancedSourceInterface sourceInterface : this.advancedInterfaces) { + sourceInterface.blockAddress(address, timeout); } } - public void unblockAddress(String address) { - for (AdvancedSourceInterface interfaz : this.advancedInterfaces) { - interfaz.unblockAddress(address); + public void unblockAddress(InetAddress address) { + for (AdvancedSourceInterface sourceInterface : this.advancedInterfaces) { + sourceInterface.unblockAddress(address); } } diff --git a/src/main/java/cn/nukkit/network/RakNetInterface.java b/src/main/java/cn/nukkit/network/RakNetInterface.java index 1f0ebbe1b5a..1bda4d466f8 100644 --- a/src/main/java/cn/nukkit/network/RakNetInterface.java +++ b/src/main/java/cn/nukkit/network/RakNetInterface.java @@ -1,6 +1,5 @@ package cn.nukkit.network; -import cn.nukkit.Nukkit; import cn.nukkit.Player; import cn.nukkit.Server; import cn.nukkit.event.player.PlayerCreationEvent; @@ -8,27 +7,33 @@ import cn.nukkit.network.protocol.BatchPacket; import cn.nukkit.network.protocol.DataPacket; import cn.nukkit.network.protocol.ProtocolInfo; -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.EncapsulatedPacket; -import cn.nukkit.raknet.protocol.packet.PING_DataPacket; -import cn.nukkit.raknet.server.RakNetServer; -import cn.nukkit.raknet.server.ServerHandler; -import cn.nukkit.raknet.server.ServerInstance; -import cn.nukkit.utils.Binary; -import cn.nukkit.utils.MainLogger; import cn.nukkit.utils.Utils; -import cn.nukkit.utils.Zlib; +import com.google.common.base.Strings; +import com.nukkitx.network.raknet.*; +import com.nukkitx.network.util.DisconnectReason; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.DatagramPacket; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.Map; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeUnit; /** * author: MagicDroidX * Nukkit Project */ -public class RakNetInterface implements ServerInstance, AdvancedSourceInterface { +@Log4j2 +public class RakNetInterface implements RakNetServerListener, AdvancedSourceInterface { private final Server server; @@ -36,23 +41,18 @@ public class RakNetInterface implements ServerInstance, AdvancedSourceInterface private final RakNetServer raknet; - private final Map players = new ConcurrentHashMap<>(); + private Set sessionListeners = Collections.newSetFromMap(new ConcurrentHashMap<>()); - private final Map networkLatency = new ConcurrentHashMap<>(); - - private final Map identifiers = new ConcurrentHashMap<>(); - - private final Map identifiersACK = new ConcurrentHashMap<>(); - - private final ServerHandler handler; - - private int[] channelCounts = new int[256]; + private byte[] advertisement; public RakNetInterface(Server server) { this.server = server; - this.raknet = new RakNetServer(this.server.getLogger(), this.server.getPort(), this.server.getIp().equals("") ? "0.0.0.0" : this.server.getIp()); - this.handler = new ServerHandler(this.raknet, this); + InetSocketAddress bindAddress = new InetSocketAddress(Strings.isNullOrEmpty(this.server.getIp()) ? "0.0.0.0" : this.server.getIp(), this.server.getPort()); + + this.raknet = new RakNetServer(bindAddress, Runtime.getRuntime().availableProcessors()); + this.raknet.bind().join(); + this.raknet.setListener(this); } @Override @@ -62,32 +62,27 @@ public void setNetwork(Network network) { @Override public boolean process() { - boolean work = false; - if (this.handler.handlePacket()) { - work = true; - while (this.handler.handlePacket()) { - + Iterator iterator = this.sessionListeners.iterator(); + while (iterator.hasNext()) { + NukkitSessionListener listener = iterator.next(); + Player player = listener.player; + if (listener.disconnectReason != null) { + player.close(player.getLeaveMessage(), listener.disconnectReason, false); + iterator.remove(); + continue; + } + DataPacket packet; + while ((packet = listener.packets.poll()) != null) { + listener.player.handleDataPacket(packet); } } - - return work; - } - - @Override - public void closeSession(String identifier, String reason) { - if (this.players.containsKey(identifier)) { - Player player = this.players.get(identifier); - this.identifiers.remove(player.rawHashCode()); - this.players.remove(identifier); - this.networkLatency.remove(identifier); - this.identifiersACK.remove(identifier); - player.close(player.getLeaveMessage(), reason); - } + return true; } @Override public int getNetworkLatency(Player player) { - return this.networkLatency.get(this.identifiers.get(player.rawHashCode())); + RakNetServerSession session = this.raknet.getSession(player.getSocketAddress()); + return session == null ? -1 : (int) session.getPing(); } @Override @@ -97,235 +92,177 @@ public void close(Player player) { @Override public void close(Player player, String reason) { - if (this.identifiers.containsKey(player.rawHashCode())) { - String id = this.identifiers.get(player.rawHashCode()); - this.players.remove(id); - this.networkLatency.remove(id); - this.identifiersACK.remove(id); - this.closeSession(id, reason); - this.identifiers.remove(player.rawHashCode()); + RakNetServerSession session = this.raknet.getSession(player.getSocketAddress()); + if (session != null) { + session.close(); } } @Override public void shutdown() { - this.handler.shutdown(); + this.raknet.close(); } @Override public void emergencyShutdown() { - this.handler.emergencyShutdown(); + this.raknet.close(); } @Override - public void openSession(String identifier, String address, int port, long clientID) { - PlayerCreationEvent ev = new PlayerCreationEvent(this, Player.class, Player.class, null, address, port); - this.server.getPluginManager().callEvent(ev); - Class clazz = ev.getPlayerClass(); - - try { - Constructor constructor = clazz.getConstructor(SourceInterface.class, Long.class, String.class, int.class); - Player player = (Player) constructor.newInstance(this, ev.getClientId(), ev.getAddress(), ev.getPort()); - this.players.put(identifier, player); - this.networkLatency.put(identifier, 0); - this.identifiersACK.put(identifier, 0); - this.identifiers.put(player.rawHashCode(), identifier); - this.server.addPlayer(identifier, player); - } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { - Server.getInstance().getLogger().logException(e); - } + public void blockAddress(InetAddress address) { + this.raknet.block(address); } @Override - public void handleEncapsulated(String identifier, EncapsulatedPacket packet, int flags) { - if (this.players.containsKey(identifier)) { - DataPacket pk = null; - try { - if (packet.buffer.length > 0) { - if (packet.buffer[0] == PING_DataPacket.ID) { - PING_DataPacket pingPacket = new PING_DataPacket(); - pingPacket.buffer = packet.buffer; - pingPacket.decode(); - - this.networkLatency.put(identifier, (int) pingPacket.pingID); - return; - } - - pk = this.getPacket(packet.buffer); - if (pk != null) { - pk.decode(); - this.players.get(identifier).handleDataPacket(pk); - } - } - } catch (Exception e) { - this.server.getLogger().logException(e); - if (Nukkit.DEBUG > 1 && pk != null) { - MainLogger logger = this.server.getLogger(); -// if (logger != null) { - logger.debug("Packet " + pk.getClass().getName() + " 0x" + Binary.bytesToHexString(packet.buffer)); - //logger.logException(e); -// } - } - - if (this.players.containsKey(identifier)) { - this.handler.blockAddress(this.players.get(identifier).getAddress(), 5); - } - } - } + public void blockAddress(InetAddress address, int timeout) { + this.raknet.block(address, timeout, TimeUnit.SECONDS); } @Override - public void blockAddress(String address) { - this.blockAddress(address, 300); + public void unblockAddress(InetAddress address) { + this.raknet.unblock(address); } @Override - public void blockAddress(String address, int timeout) { - this.handler.blockAddress(address, timeout); + public void sendRawPacket(InetSocketAddress socketAddress, ByteBuf payload) { + this.raknet.send(socketAddress, payload); } @Override - public void unblockAddress(String address) { - this.handler.unblockAddress(address); + public void setName(String name) { + QueryRegenerateEvent info = this.server.getQueryInformation(); + String[] names = name.split("!@#"); //Split double names within the program + String motd = Utils.rtrim(names[0].replace(";", "\\;"), '\\'); + String subMotd = names.length > 1 ? Utils.rtrim(names[1].replace(";", "\\;"), '\\') : ""; + StringJoiner joiner = new StringJoiner(";") + .add("MCPE") + .add(motd) + .add(Integer.toString(ProtocolInfo.CURRENT_PROTOCOL)) + .add(ProtocolInfo.MINECRAFT_VERSION_NETWORK) + .add(Integer.toString(info.getPlayerCount())) + .add(Integer.toString(info.getMaxPlayerCount())) + .add(Long.toString(this.raknet.getGuid())) + .add(subMotd) + .add(Server.getGamemodeString(this.server.getDefaultGamemode(), true)) + .add("1"); + + this.advertisement = joiner.toString().getBytes(StandardCharsets.UTF_8); } @Override - public void handleRaw(String address, int port, byte[] payload) { - this.server.handlePacket(address, port, payload); + public Integer putPacket(Player player, DataPacket packet) { + return this.putPacket(player, packet, false); } @Override - public void sendRawPacket(String address, int port, byte[] payload) { - this.handler.sendRaw(address, port, payload); + public Integer putPacket(Player player, DataPacket packet, boolean needACK) { + return this.putPacket(player, packet, needACK, false); } @Override - public void notifyACK(String identifier, int identifierACK) { - // TODO: Better ACK notification implementation! - for (Player p : server.getOnlinePlayers().values()) { - p.notifyACK(identifierACK); + public Integer putPacket(Player player, DataPacket packet, boolean needACK, boolean immediate) { + RakNetServerSession session = this.raknet.getSession(player.getSocketAddress()); + if (session == null) { + return null; } - } - @Override - public void setName(String name) { - QueryRegenerateEvent info = this.server.getQueryInformation(); - String[] names = name.split("!@#"); //Split double names within the program - this.handler.sendOption("name", - "MCPE;" + Utils.rtrim(names[0].replace(";", "\\;"), '\\') + ";" + - ProtocolInfo.CURRENT_PROTOCOL + ";" + - ProtocolInfo.MINECRAFT_VERSION_NETWORK + ";" + - info.getPlayerCount() + ";" + - info.getMaxPlayerCount() + ";" + - this.server.getServerUniqueId().toString() + ";" + - (names.length > 1 ? Utils.rtrim(names[1].replace(";", "\\;"), '\\') : "") + ";" + - Server.getGamemodeString(this.server.getDefaultGamemode(), true) + ";"); - } + byte[] buffer; + if (packet.pid() == ProtocolInfo.BATCH_PACKET) { + buffer = ((BatchPacket) packet).payload; + if (buffer == null) { + return null; + } + } else { + this.server.batchPackets(new Player[]{player}, new DataPacket[]{packet}, true); + return null; + } + + ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer(1 + buffer.length); + byteBuf.writeByte(0xfe); + byteBuf.writeBytes(buffer); + byteBuf.readerIndex(0); + + session.send(byteBuf, immediate ? RakNetPriority.IMMEDIATE : RakNetPriority.MEDIUM, packet.reliability, + packet.getChannel()); - public void setPortCheck(boolean value) { - this.handler.sendOption("portChecking", String.valueOf(value)); + return null; } @Override - public void handleOption(String name, String value) { - if ("bandwidth".equals(name)) { - String[] v = value.split(";"); - this.network.addStatistics(Double.valueOf(v[0]), Double.valueOf(v[1])); - } + public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) { + return true; } @Override - public Integer putPacket(Player player, DataPacket packet) { - return this.putPacket(player, packet, false); + public byte[] onQuery(InetSocketAddress inetSocketAddress) { + return this.advertisement; } @Override - public Integer putPacket(Player player, DataPacket packet, boolean needACK) { - return this.putPacket(player, packet, needACK, false); + public void onSessionCreation(RakNetServerSession session) { + PlayerCreationEvent ev = new PlayerCreationEvent(this, Player.class, Player.class, null, session.getAddress()); + this.server.getPluginManager().callEvent(ev); + Class clazz = ev.getPlayerClass(); + + try { + Constructor constructor = clazz.getConstructor(SourceInterface.class, Long.class, InetSocketAddress.class); + Player player = (Player) constructor.newInstance(this, ev.getClientId(), ev.getSocketAddress()); + this.server.addPlayer(session.getAddress(), player); + NukkitSessionListener listener = new NukkitSessionListener(player); + this.sessionListeners.add(listener); + session.setListener(listener); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { + Server.getInstance().getLogger().logException(e); + } } @Override - public Integer putPacket(Player player, DataPacket packet, boolean needACK, boolean immediate) { - if (this.identifiers.containsKey(player.rawHashCode())) { - byte[] buffer; - if (packet.pid() == ProtocolInfo.BATCH_PACKET) { - buffer = ((BatchPacket) packet).payload; - } else if (!needACK) { - this.server.batchPackets(new Player[]{player}, new DataPacket[]{packet}, true); - return null; - } else { - if (!packet.isEncoded) { - packet.encode(); - packet.isEncoded = true; - } - buffer = packet.getBuffer(); - try { - buffer = Zlib.deflate( - Binary.appendBytes(Binary.writeUnsignedVarInt(buffer.length), buffer), - Server.getInstance().networkCompressionLevel); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - String identifier = this.identifiers.get(player.rawHashCode()); - EncapsulatedPacket pk = null; - if (!needACK) { - if (packet.encapsulatedPacket == null) { - packet.encapsulatedPacket = new CacheEncapsulatedPacket(); - packet.encapsulatedPacket.identifierACK = null; - packet.encapsulatedPacket.buffer = Binary.appendBytes((byte) 0xfe, buffer); - if (packet.getChannel() != 0) { - packet.encapsulatedPacket.reliability = 3; - packet.encapsulatedPacket.orderChannel = packet.getChannel(); - packet.encapsulatedPacket.orderIndex = 0; - } else { - packet.encapsulatedPacket.reliability = 2; - } - } - pk = packet.encapsulatedPacket; - } + public void onUnhandledDatagram(ChannelHandlerContext ctx, DatagramPacket datagramPacket) { + this.server.handlePacket(datagramPacket.sender(), datagramPacket.content()); + } - if (pk == null) { - pk = new EncapsulatedPacket(); - pk.buffer = Binary.appendBytes((byte) 0xfe, buffer); - if (packet.getChannel() != 0) { - packet.reliability = 3; - packet.orderChannel = packet.getChannel(); - packet.orderIndex = 0; - } else { - packet.reliability = 2; - } + @RequiredArgsConstructor + private class NukkitSessionListener implements RakNetSessionListener { + private final Player player; + private final Queue packets = new ConcurrentLinkedQueue<>(); + private String disconnectReason = null; - if (needACK) { - int iACK = this.identifiersACK.get(identifier); - iACK++; - pk.identifierACK = iACK; - this.identifiersACK.put(identifier, iACK); - } - } + @Override + public void onSessionChangeState(RakNetState rakNetState) { - this.handler.sendEncapsulated(identifier, pk, (needACK ? RakNet.FLAG_NEED_ACK : 0) | (immediate ? RakNet.PRIORITY_IMMEDIATE : RakNet.PRIORITY_NORMAL)); + } - return pk.identifierACK; + @Override + public void onDisconnect(DisconnectReason disconnectReason) { + if (disconnectReason == DisconnectReason.TIMED_OUT) { + this.disconnectReason = "Timed out"; + } else { + this.disconnectReason = "Disconnected from Server"; + } } - return null; - } + @Override + public void onEncapsulated(EncapsulatedPacket packet) { + ByteBuf buffer = packet.getBuffer(); + short packetId = buffer.readUnsignedByte(); + if (packetId == 0xfe) { + DataPacket batchPacket = RakNetInterface.this.network.getPacket(ProtocolInfo.BATCH_PACKET); + if (batchPacket == null) { + return; + } - private DataPacket getPacket(byte[] buffer) { - int start = 0; + byte[] packetBuffer = new byte[buffer.readableBytes()]; + buffer.readBytes(packetBuffer); + batchPacket.setBuffer(packetBuffer); + batchPacket.decode(); - if (buffer[0] == (byte) 0xfe) { - start++; + packets.offer(batchPacket); + } } - DataPacket data = this.network.getPacket(ProtocolInfo.BATCH_PACKET); - if (data == null) { - return null; + @Override + public void onDirect(ByteBuf byteBuf) { + // We don't allow any direct packets so ignore. } - - data.setBuffer(buffer, start); - - return data; } } diff --git a/src/main/java/cn/nukkit/network/protocol/BatchPacket.java b/src/main/java/cn/nukkit/network/protocol/BatchPacket.java index c6ba45f9c2d..5e67c79ef79 100644 --- a/src/main/java/cn/nukkit/network/protocol/BatchPacket.java +++ b/src/main/java/cn/nukkit/network/protocol/BatchPacket.java @@ -1,7 +1,5 @@ package cn.nukkit.network.protocol; -import cn.nukkit.network.CacheEncapsulatedPacket; - /** * author: MagicDroidX * Nukkit Project @@ -28,12 +26,5 @@ public void encode() { public void trim() { setBuffer(null); - if (encapsulatedPacket != null) { - payload = null; - if (encapsulatedPacket instanceof CacheEncapsulatedPacket && !encapsulatedPacket.hasSplit) { - CacheEncapsulatedPacket cached = (CacheEncapsulatedPacket) encapsulatedPacket; - if (cached.internalData != null) cached.buffer = null; - } - } } } diff --git a/src/main/java/cn/nukkit/network/protocol/DataPacket.java b/src/main/java/cn/nukkit/network/protocol/DataPacket.java index 601add933c7..f3b82956922 100644 --- a/src/main/java/cn/nukkit/network/protocol/DataPacket.java +++ b/src/main/java/cn/nukkit/network/protocol/DataPacket.java @@ -1,10 +1,10 @@ package cn.nukkit.network.protocol; import cn.nukkit.Server; -import cn.nukkit.raknet.protocol.EncapsulatedPacket; import cn.nukkit.utils.Binary; import cn.nukkit.utils.BinaryStream; import cn.nukkit.utils.Zlib; +import com.nukkitx.network.raknet.RakNetReliability; /** * author: MagicDroidX @@ -15,10 +15,7 @@ public abstract class DataPacket extends BinaryStream implements Cloneable { public boolean isEncoded = false; private int channel = 0; - public EncapsulatedPacket encapsulatedPacket; - public byte reliability; - public Integer orderIndex = null; - public Integer orderChannel = null; + public RakNetReliability reliability = RakNetReliability.RELIABLE_ORDERED; public abstract byte pid(); diff --git a/src/main/java/cn/nukkit/network/protocol/ResourcePacksInfoPacket.java b/src/main/java/cn/nukkit/network/protocol/ResourcePacksInfoPacket.java index 9a01f9e2f14..9bce9daee48 100644 --- a/src/main/java/cn/nukkit/network/protocol/ResourcePacksInfoPacket.java +++ b/src/main/java/cn/nukkit/network/protocol/ResourcePacksInfoPacket.java @@ -9,7 +9,7 @@ public class ResourcePacksInfoPacket extends DataPacket { public static final byte NETWORK_ID = ProtocolInfo.RESOURCE_PACKS_INFO_PACKET; public boolean mustAccept; - public boolean unknownBool; + public boolean scripting; public ResourcePack[] behaviourPackEntries = new ResourcePack[0]; public ResourcePack[] resourcePackEntries = new ResourcePack[0]; @@ -22,7 +22,7 @@ public void decode() { public void encode() { this.reset(); this.putBoolean(this.mustAccept); - this.putBoolean(this.unknownBool); + this.putBoolean(this.scripting); encodePacks(this.resourcePackEntries); encodePacks(this.behaviourPackEntries); @@ -37,7 +37,7 @@ private void encodePacks(ResourcePack[] packs) { this.putString(""); // encryption key this.putString(""); // sub-pack name this.putString(""); // content identity - this.putBoolean(false); // ??? + this.putBoolean(false); // scripting } } diff --git a/src/main/java/cn/nukkit/network/query/QueryHandler.java b/src/main/java/cn/nukkit/network/query/QueryHandler.java index c0e886e7a03..d9b45fb9c06 100644 --- a/src/main/java/cn/nukkit/network/query/QueryHandler.java +++ b/src/main/java/cn/nukkit/network/query/QueryHandler.java @@ -2,11 +2,18 @@ import cn.nukkit.Server; import cn.nukkit.event.server.QueryRegenerateEvent; -import cn.nukkit.utils.Binary; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; /** * author: MagicDroidX @@ -54,53 +61,57 @@ public void regenerateToken() { this.token = token; } - public static String getTokenString(byte[] token, String salt) { - return getTokenString(new String(token), salt); + public static byte[] getTokenString(String token, InetAddress address) { + return getTokenString(token.getBytes(StandardCharsets.UTF_8), address); } - - public static String getTokenString(String token, String salt) { + public static byte[] getTokenString(byte[] token, InetAddress address) { try { - return String.valueOf(Binary.readInt(Binary.subBytes(MessageDigest.getInstance("SHA-512").digest((salt + ":" + token).getBytes()), 7, 4))); + MessageDigest digest = MessageDigest.getInstance("MD5"); + digest.update(address.toString().getBytes(StandardCharsets.UTF_8)); + digest.update(token); + return Arrays.copyOf(digest.digest(), 4); } catch (NoSuchAlgorithmException e) { - return String.valueOf(new Random().nextInt()); + return ByteBuffer.allocate(4).putInt(ThreadLocalRandom.current().nextInt()).array(); } } - public void handle(String address, int port, byte[] packet) { - int offset = 2; //skip MAGIC - byte packetType = packet[offset++]; - int sessionID = Binary.readInt(Binary.subBytes(packet, offset, 4)); - offset += 4; - byte[] payload = Binary.subBytes(packet, offset); + public void handle(InetSocketAddress address, ByteBuf packet) { + short packetId = packet.readUnsignedByte(); + int sessionId = packet.readInt(); - switch (packetType) { + switch (packetId) { case HANDSHAKE: - byte[] reply = Binary.appendBytes( - HANDSHAKE, - Binary.writeInt(sessionID), - getTokenString(this.token, address).getBytes(), - new byte[]{0x00} - ); - - this.server.getNetwork().sendPacket(address, port, reply); + ByteBuf reply = ByteBufAllocator.DEFAULT.ioBuffer(10); // 1 + 4 + 4 + 1 + reply.writeByte(HANDSHAKE); + reply.writeInt(sessionId); + reply.writeBytes(getTokenString(this.token, address.getAddress())); + reply.writeByte(0); + + this.server.getNetwork().sendPacket(address, reply); break; case STATISTICS: - String token = String.valueOf(Binary.readInt(Binary.subBytes(payload, 0, 4))); - if (!token.equals(getTokenString(this.token, address)) && !token.equals(getTokenString(this.lastToken, address))) { + byte[] token = new byte[4]; + packet.readBytes(token); + + if (!Arrays.equals(token, getTokenString(this.token, address.getAddress())) && + !Arrays.equals(token, getTokenString(this.lastToken, address.getAddress()))) { break; } if (this.timeout < System.currentTimeMillis()) { this.regenerateInfo(); } - reply = Binary.appendBytes( - STATISTICS, - Binary.writeInt(sessionID), - payload.length == 8 ? this.longData : this.shortData - ); + reply = ByteBufAllocator.DEFAULT.ioBuffer(64); + reply.writeByte(STATISTICS); + reply.writeInt(sessionId); + if (packet.readableBytes() == 8) { + reply.writeBytes(this.longData); + } else { + reply.writeBytes(this.shortData); + } - this.server.getNetwork().sendPacket(address, port, reply); + this.server.getNetwork().sendPacket(address, reply); break; } } diff --git a/src/main/java/cn/nukkit/raknet/RakNet.java b/src/main/java/cn/nukkit/raknet/RakNet.java deleted file mode 100644 index 29d52788602..00000000000 --- a/src/main/java/cn/nukkit/raknet/RakNet.java +++ /dev/null @@ -1,120 +0,0 @@ -package cn.nukkit.raknet; - -/** - * author: MagicDroidX - * Nukkit Project - * UDP network library that follows the RakNet protocol for Nukkit Project - * This is not affiliated with Jenkins Software LLC nor RakNet. - */ -public abstract class RakNet { - - public static final String VERSION = "1.1.0"; - public static final byte PROTOCOL = 9; - public static final byte[] MAGIC = new byte[]{ - (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0x00, - (byte) 0xfe, (byte) 0xfe, (byte) 0xfe, (byte) 0xfe, - (byte) 0xfd, (byte) 0xfd, (byte) 0xfd, (byte) 0xfd, - (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78 - }; - - public static final byte PRIORITY_NORMAL = 0; - public static final byte PRIORITY_IMMEDIATE = 1; - - public static final byte FLAG_NEED_ACK = 0b00001000; - - /* - * ENCAPSULATED payload: - * byte (identifier length) - * byte[] (identifier) - * byte (flags, last 3 bits, priority) - * payload (binary internal EncapsulatedPacket) - */ - public static final byte PACKET_ENCAPSULATED = 0x01; - - /* - * OPEN_SESSION payload: - * byte (identifier length) - * byte[] (identifier) - * byte (address length) - * byte[] (address) - * short (port) - * long (clientID) - */ - public static final byte PACKET_OPEN_SESSION = 0x02; - - /* - * CLOSE_SESSION payload: - * byte (identifier length) - * byte[] (identifier) - * string (reason) - */ - public static final byte PACKET_CLOSE_SESSION = 0x03; - - /* - * INVALID_SESSION payload: - * byte (identifier length) - * byte[] (identifier) - */ - public static final byte PACKET_INVALID_SESSION = 0x04; - - /* SEND_QUEUE payload: - * byte (identifier length) - * byte[] (identifier) - */ - public static final byte PACKET_SEND_QUEUE = 0x05; - - /* - * ACK_NOTIFICATION payload: - * byte (identifier length) - * byte[] (identifier) - * int (identifierACK) - */ - public static final byte PACKET_ACK_NOTIFICATION = 0x06; - - /* - * SET_OPTION payload: - * byte (option name length) - * byte[] (option name) - * byte[] (option value) - */ - public static final byte PACKET_SET_OPTION = 0x07; - - /* - * RAW payload: - * byte (address length) - * byte[] (address from/to) - * short (port) - * byte[] (payload) - */ - public static final byte PACKET_RAW = 0x08; - - /* - * BLOCK_ADDRESS payload: - * byte (address length) - * byte[] (address) - * int (timeout) - */ - public static final byte PACKET_BLOCK_ADDRESS = 0x09; - - /* - * UNBLOCK_ADDRESS payload: - * byte (adress length) - * byte[] (address) - */ - public static final byte PACKET_UNBLOCK_ADDRESS = 0x10; - - /* - * No payload - * - * Sends the disconnect message, removes sessions correctly, closes sockets. - */ - public static final byte PACKET_SHUTDOWN = 0x7e; - - /* - * No payload - * - * Leaves everything as-is and halts, other Threads can be in a post-crash condition. - */ - public static final byte PACKET_EMERGENCY_SHUTDOWN = 0x7f; - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/AcknowledgePacket.java b/src/main/java/cn/nukkit/raknet/protocol/AcknowledgePacket.java deleted file mode 100644 index c61ba24fbf5..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/AcknowledgePacket.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.nukkit.raknet.protocol; - -import cn.nukkit.utils.Binary; -import cn.nukkit.utils.BinaryStream; - -import java.util.TreeMap; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public abstract class AcknowledgePacket extends Packet { - - public TreeMap packets; - - @Override - public void encode() { - super.encode(); - int count = this.packets.size(); - int[] packets = new int[count]; - - int index = 0; - for (int i : this.packets.values()) { - packets[index++] = i; - } - short records = 0; - BinaryStream payload = new BinaryStream(); - - if (count > 0) { - int pointer = 1; - int start = packets[0]; - int last = packets[0]; - - while (pointer < count) { - int current = packets[pointer++]; - int diff = current - last; - if (diff == 1) { - last = current; - } else if (diff > 1) { - - if (start == last) { - payload.putByte((byte) 0x01); - payload.put(Binary.writeLTriad(start)); - start = last = current; - } else { - payload.putByte((byte) 0x00); - payload.put(Binary.writeLTriad(start)); - payload.put(Binary.writeLTriad(last)); - start = last = current; - } - ++records; - } - } - - if (start == last) { - payload.putByte((byte) 0x01); - payload.put(Binary.writeLTriad(start)); - } else { - payload.putByte((byte) 0x00); - payload.put(Binary.writeLTriad(start)); - payload.put(Binary.writeLTriad(last)); - } - ++records; - } - - this.putShort(records); - this.buffer = Binary.appendBytes( - this.buffer, - payload.getBuffer() - ); - } - - @Override - public void decode() { - super.decode(); - short count = this.getSignedShort(); - this.packets = new TreeMap<>(); - int cnt = 0; - for (int i = 0; i < count && !this.feof() && cnt < 4096; ++i) { - if (this.getByte() == 0) { - int start = this.getLTriad(); - int end = this.getLTriad(); - if ((end - start) > 512) { - end = start + 512; - } - for (int c = start; c <= end; ++c) { - packets.put(cnt++, c); - } - } else { - this.packets.put(cnt++, this.getLTriad()); - } - } - } - - @Override - public Packet clean() { - this.packets = new TreeMap<>(); - return super.clean(); - } - - @Override - public AcknowledgePacket clone() throws CloneNotSupportedException { - AcknowledgePacket packet = (AcknowledgePacket) super.clone(); - packet.packets = new TreeMap<>(this.packets); - return packet; - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/DataPacket.java deleted file mode 100644 index 5ab3dfda0d8..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/DataPacket.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.nukkit.raknet.protocol; - -import cn.nukkit.utils.Binary; - -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public abstract class DataPacket extends Packet { - - public ConcurrentLinkedQueue packets = new ConcurrentLinkedQueue<>(); - - public Integer seqNumber; - - @Override - public void encode() { - super.encode(); - this.putLTriad(this.seqNumber); - for (Object packet : this.packets) { - this.put(packet instanceof EncapsulatedPacket ? ((EncapsulatedPacket) packet).toBinary() : (byte[]) packet); - } - } - - public int length() { - int length = 4; - for (Object packet : this.packets) { - length += packet instanceof EncapsulatedPacket ? ((EncapsulatedPacket) packet).getTotalLength() : ((byte[]) packet).length; - } - - return length; - } - - @Override - public void decode() { - super.decode(); - this.seqNumber = this.getLTriad(); - - while (!this.feof()) { - byte[] data = Binary.subBytes(this.buffer, this.offset); - EncapsulatedPacket packet = EncapsulatedPacket.fromBinary(data, false); - this.offset += packet.getOffset(); - if (packet.buffer.length == 0) { - break; - } - this.packets.add(packet); - } - } - - @Override - public Packet clean() { - this.packets = new ConcurrentLinkedQueue<>(); - this.seqNumber = null; - return super.clean(); - } - - @Override - public DataPacket clone() throws CloneNotSupportedException { - DataPacket packet = (DataPacket) super.clone(); - packet.packets = new ConcurrentLinkedQueue<>(this.packets); - return packet; - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/EncapsulatedPacket.java b/src/main/java/cn/nukkit/raknet/protocol/EncapsulatedPacket.java deleted file mode 100644 index a836dfb3919..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/EncapsulatedPacket.java +++ /dev/null @@ -1,138 +0,0 @@ -package cn.nukkit.raknet.protocol; - -import cn.nukkit.utils.Binary; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class EncapsulatedPacket implements Cloneable { - - public int reliability; - public boolean hasSplit = false; - public int length = 0; - public Integer messageIndex = null; - public Integer orderIndex = null; - public Integer orderChannel = null; - public Integer splitCount = null; - public Integer splitID = null; - public Integer splitIndex = null; - public byte[] buffer; - public boolean needACK = false; - public Integer identifierACK = null; - - private int offset; - - public int getOffset() { - return offset; - } - - public static EncapsulatedPacket fromBinary(byte[] binary) { - return fromBinary(binary, false); - } - - public static EncapsulatedPacket fromBinary(byte[] binary, boolean internal) { - EncapsulatedPacket packet = new EncapsulatedPacket(); - - int flags = binary[0] & 0xff; - - packet.reliability = ((flags & 0b11100000) >> 5); - packet.hasSplit = (flags & 0b00010000) > 0; - int length, offset; - if (internal) { - length = Binary.readInt(Binary.subBytes(binary, 1, 4)); - packet.identifierACK = Binary.readInt(Binary.subBytes(binary, 5, 4)); - offset = 9; - } else { - length = (int) Math.ceil(((double) Binary.readShort(Binary.subBytes(binary, 1, 2)) / 8)); - offset = 3; - packet.identifierACK = null; - } - - if (packet.reliability > 0) { - if (packet.reliability >= 2 && packet.reliability != 5) { - packet.messageIndex = Binary.readLTriad(Binary.subBytes(binary, offset, 3)); - offset += 3; - } - - if (packet.reliability <= 4 && packet.reliability != 2) { - packet.orderIndex = Binary.readLTriad(Binary.subBytes(binary, offset, 3)); - offset += 3; - packet.orderChannel = binary[offset++] & 0xff; - } - } - - if (packet.hasSplit) { - packet.splitCount = Binary.readInt(Binary.subBytes(binary, offset, 4)); - offset += 4; - packet.splitID = Binary.readShort(Binary.subBytes(binary, offset, 2)); - offset += 2; - packet.splitIndex = Binary.readInt(Binary.subBytes(binary, offset, 4)); - offset += 4; - } - - packet.buffer = Binary.subBytes(binary, offset, length); - offset += length; - packet.offset = offset; - - return packet; - } - - public int getTotalLength() { - return 3 + this.buffer.length + (this.messageIndex != null ? 3 : 0) + (this.orderIndex != null ? 4 : 0) + (this.hasSplit ? 10 : 0); - } - - public byte[] toBinary() { - return toBinary(false); - } - - public byte[] toBinary(boolean internal) { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - stream.write((reliability << 5) | (hasSplit ? 0b00010000 : 0)); - if (internal) { - stream.write(Binary.writeInt(buffer.length)); - stream.write(Binary.writeInt(identifierACK == null ? 0 : identifierACK)); - } else { - stream.write(Binary.writeShort(buffer.length << 3)); - } - - if (reliability > 0) { - if (reliability >= 2 && reliability != 5) { - stream.write(Binary.writeLTriad(messageIndex == null ? 0 : messageIndex)); - } - if (reliability <= 4 && reliability != 2) { - stream.write(Binary.writeLTriad(orderIndex)); - stream.write((byte) (orderChannel & 0xff)); - } - } - - if (hasSplit) { - stream.write(Binary.writeInt(splitCount)); - stream.write(Binary.writeShort(splitID)); - stream.write(Binary.writeInt(splitIndex)); - } - - stream.write(buffer); - } catch (IOException e) { - throw new RuntimeException(e); - } - - return stream.toByteArray(); - } - - @Override - public String toString() { - return Binary.bytesToHexString(this.toBinary()); - } - - @Override - public EncapsulatedPacket clone() throws CloneNotSupportedException { - EncapsulatedPacket packet = (EncapsulatedPacket) super.clone(); - packet.buffer = this.buffer.clone(); - return packet; - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/Packet.java b/src/main/java/cn/nukkit/raknet/protocol/Packet.java deleted file mode 100644 index 0020998d433..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/Packet.java +++ /dev/null @@ -1,186 +0,0 @@ -package cn.nukkit.raknet.protocol; - -import cn.nukkit.utils.Binary; - -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public abstract class Packet implements Cloneable { - - protected int offset = 0; - public byte[] buffer; - public Long sendTime; - - public abstract byte getID(); - - protected byte[] get(int len) { - if (len < 0) { - this.offset = this.buffer.length - 1; - return new byte[0]; - } - - byte[] buffer = new byte[len]; - for (int i = 0; i < len; i++) { - buffer[i] = this.buffer[this.offset++]; - } - return buffer; - } - - protected byte[] getAll() { - return this.get(); - } - - protected byte[] get() { - try { - return Arrays.copyOfRange(this.buffer, this.offset, this.buffer.length - 1); - } catch (Exception e) { - return new byte[0]; - } - } - - protected long getLong() { - return Binary.readLong(this.get(8)); - } - - protected int getInt() { - return Binary.readInt(this.get(4)); - } - - protected short getSignedShort() { - return (short) this.getShort(); - } - - protected int getShort() { - return Binary.readShort(this.get(2)); - } - - protected int getTriad() { - return Binary.readTriad(this.get(3)); - } - - protected int getLTriad() { - return Binary.readLTriad(this.get(3)); - } - - protected byte getByte() { - return this.buffer[this.offset++]; - } - - protected String getString() { - return new String(this.get(this.getSignedShort()), StandardCharsets.UTF_8); - } - - protected InetSocketAddress getAddress() { - byte version = this.getByte(); - if (version == 4) { - String addr = ((~this.getByte()) & 0xff) + "." + ((~this.getByte()) & 0xff) + "." + ((~this.getByte()) & 0xff) + "." + ((~this.getByte()) & 0xff); - int port = this.getShort(); - return new InetSocketAddress(addr, port); - } else { - //todo IPV6 SUPPORT - return null; - } - } - - protected boolean feof() { - return !(this.offset >= 0 && this.offset + 1 <= this.buffer.length); - } - - protected void put(byte[] b) { - this.buffer = Binary.appendBytes(this.buffer, b); - } - - protected void putLong(long v) { - this.put(Binary.writeLong(v)); - } - - protected void putInt(int v) { - this.put(Binary.writeInt(v)); - } - - protected void putShort(int v) { - this.put(Binary.writeShort(v)); - } - - protected void putSignedShort(short v) { - this.put(Binary.writeShort(v & 0xffff)); - } - - protected void putTriad(int v) { - this.put(Binary.writeTriad(v)); - } - - protected void putLTriad(int v) { - this.put(Binary.writeLTriad(v)); - } - - protected void putByte(byte b) { - byte[] newBytes = new byte[this.buffer.length + 1]; - System.arraycopy(this.buffer, 0, newBytes, 0, this.buffer.length); - newBytes[this.buffer.length] = b; - this.buffer = newBytes; - } - - protected void putString(String str) { - byte[] b = str.getBytes(StandardCharsets.UTF_8); - this.putShort(b.length); - this.put(b); - } - - protected void putAddress(String addr, int port) { - this.putAddress(addr, port, (byte) 4); - } - - protected void putAddress(String addr, int port, byte version) { - this.putByte(version); - if (version == 4) { - for (String b : addr.split("\\.")) { - this.putByte((byte) ((~Integer.valueOf(b)) & 0xff)); - } - this.putShort(port); - } else { - //todo ipv6 - } - } - - protected void putAddress(InetSocketAddress address) { - this.putAddress(address.getHostString(), address.getPort()); - } - - public void encode() { - this.buffer = new byte[]{getID()}; - } - - public void decode() { - this.offset = 1; - } - - public Packet clean() { - this.buffer = null; - this.offset = 0; - this.sendTime = null; - return this; - } - - @Override - public Packet clone() throws CloneNotSupportedException { - Packet packet = (Packet) super.clone(); - packet.buffer = this.buffer.clone(); - return packet; - } - - /** - * A factory to create new packet instances - */ - public interface PacketFactory { - /** - * Creates the packet - */ - Packet create(); - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/ACK.java b/src/main/java/cn/nukkit/raknet/protocol/packet/ACK.java deleted file mode 100644 index 1c8fa169d86..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/ACK.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.AcknowledgePacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class ACK extends AcknowledgePacket { - - public static final byte ID = (byte) 0xc0; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new ACK(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/ADVERTISE_SYSTEM.java b/src/main/java/cn/nukkit/raknet/protocol/packet/ADVERTISE_SYSTEM.java deleted file mode 100644 index 2f7a50fbb37..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/ADVERTISE_SYSTEM.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class ADVERTISE_SYSTEM extends UNCONNECTED_PONG { - public static final byte ID = (byte) 0x1d; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new ADVERTISE_SYSTEM(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_CONNECT_DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_CONNECT_DataPacket.java deleted file mode 100644 index dbe5b01f452..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_CONNECT_DataPacket.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class CLIENT_CONNECT_DataPacket extends Packet { - public static final byte ID = (byte) 0x09; - - @Override - public byte getID() { - return ID; - } - - public long clientID; - public long sendPing; - public boolean useSecurity = false; - - @Override - public void encode() { - super.encode(); - this.putLong(this.clientID); - this.putLong(this.sendPing); - this.putByte((byte) (this.useSecurity ? 1 : 0)); - } - - @Override - public void decode() { - super.decode(); - this.clientID = this.getLong(); - this.sendPing = this.getLong(); - this.useSecurity = this.getByte() > 0; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new CLIENT_CONNECT_DataPacket(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_DISCONNECT_DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_DISCONNECT_DataPacket.java deleted file mode 100644 index b3f12ff3c99..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_DISCONNECT_DataPacket.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class CLIENT_DISCONNECT_DataPacket extends Packet { - public static final byte ID = (byte) 0x15; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new CLIENT_DISCONNECT_DataPacket(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_HANDSHAKE_DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_HANDSHAKE_DataPacket.java deleted file mode 100644 index 92f065bbe16..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/CLIENT_HANDSHAKE_DataPacket.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -import java.net.InetSocketAddress; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class CLIENT_HANDSHAKE_DataPacket extends Packet { - public static final byte ID = (byte) 0x13; - - @Override - public byte getID() { - return ID; - } - - public String address; - public int port; - public final InetSocketAddress[] systemAddresses = new InetSocketAddress[10]; - - public long sendPing; - public long sendPong; - - @Override - public void encode() { - } - - @Override - public void decode() { - super.decode(); - InetSocketAddress addr = this.getAddress(); - this.address = addr.getHostString(); - this.port = addr.getPort(); - - for (int i = 0; i < 10; i++) { - this.systemAddresses[i] = this.getAddress(); - } - - this.sendPing = this.getLong(); - this.sendPong = this.getLong(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new CLIENT_HANDSHAKE_DataPacket(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_0.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_0.java deleted file mode 100644 index 5ed30433399..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_0.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_0 extends DataPacket { - public static final byte ID = (byte) 0x80; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_0(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_1.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_1.java deleted file mode 100644 index 746cd36f8b4..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_1.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_1 extends DataPacket { - public static final byte ID = (byte) 0x81; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_1(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_2.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_2.java deleted file mode 100644 index 784324e42bf..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_2.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_2 extends DataPacket { - public static final byte ID = (byte) 0x82; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_2(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_3.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_3.java deleted file mode 100644 index 947e3f6683d..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_3.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_3 extends DataPacket { - public static final byte ID = (byte) 0x83; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_3(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_4.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_4.java deleted file mode 100644 index 5e982e97e9c..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_4.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_4 extends DataPacket { - public static final byte ID = (byte) 0x84; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_4(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_5.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_5.java deleted file mode 100644 index 8c4eb4d7fc5..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_5.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_5 extends DataPacket { - public static final byte ID = (byte) 0x85; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_5(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_6.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_6.java deleted file mode 100644 index 80264017e47..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_6.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_6 extends DataPacket { - public static final byte ID = (byte) 0x86; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_6(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_7.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_7.java deleted file mode 100644 index e91b81d3fdb..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_7.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_7 extends DataPacket { - public static final byte ID = (byte) 0x87; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_7(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_8.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_8.java deleted file mode 100644 index 1e751215eba..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_8.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_8 extends DataPacket { - public static final byte ID = (byte) 0x88; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_8(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_9.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_9.java deleted file mode 100644 index ea64ae49ea4..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_9.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_9 extends DataPacket { - public static final byte ID = (byte) 0x89; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_9(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_A.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_A.java deleted file mode 100644 index 0505dbc8e61..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_A.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_A extends DataPacket { - public static final byte ID = (byte) 0x8a; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_A(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_B.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_B.java deleted file mode 100644 index d2ee52794c5..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_B.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_B extends DataPacket { - public static final byte ID = (byte) 0x8b; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_B(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_C.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_C.java deleted file mode 100644 index 704e6a7c519..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_C.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_C extends DataPacket { - public static final byte ID = (byte) 0x8c; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_C(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_D.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_D.java deleted file mode 100644 index cb30600a6d2..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_D.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_D extends DataPacket { - public static final byte ID = (byte) 0x8d; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_D(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_E.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_E.java deleted file mode 100644 index e6f7930f066..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_E.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_E extends DataPacket { - public static final byte ID = (byte) 0x8e; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_E(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_F.java b/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_F.java deleted file mode 100644 index 17d2b5467fc..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/DATA_PACKET_F.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class DATA_PACKET_F extends DataPacket { - public static final byte ID = (byte) 0x8f; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new DATA_PACKET_F(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/NACK.java b/src/main/java/cn/nukkit/raknet/protocol/packet/NACK.java deleted file mode 100644 index 2ff9403000c..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/NACK.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.AcknowledgePacket; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class NACK extends AcknowledgePacket { - - public static final byte ID = (byte) 0xa0; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new NACK(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REPLY_1.java b/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REPLY_1.java deleted file mode 100644 index feaba3fdc2e..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REPLY_1.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class OPEN_CONNECTION_REPLY_1 extends Packet { - public static final byte ID = (byte) 0x06; - - @Override - public byte getID() { - return ID; - } - - public long serverID; - public short mtuSize; - - @Override - public void encode() { - super.encode(); - this.put(RakNet.MAGIC); - this.putLong(this.serverID); - this.putByte((byte) 0); //server security - this.putShort(this.mtuSize); - } - - @Override - public void decode() { - super.decode(); - this.offset += 16; //skip magic bytes - this.serverID = this.getLong(); - this.getByte(); //skip security - this.mtuSize = this.getSignedShort(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new OPEN_CONNECTION_REPLY_1(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REPLY_2.java b/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REPLY_2.java deleted file mode 100644 index b9290c4ed29..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REPLY_2.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.Packet; - -import java.net.InetSocketAddress; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class OPEN_CONNECTION_REPLY_2 extends Packet { - public static final byte ID = (byte) 0x08; - - @Override - public byte getID() { - return ID; - } - - public long serverID; - public String clientAddress; - public int clientPort; - public short mtuSize; - - @Override - public void encode() { - super.encode(); - this.put(RakNet.MAGIC); - this.putLong(this.serverID); - this.putAddress(this.clientAddress, this.clientPort); - this.putShort(this.mtuSize); - this.putByte((byte) 0); //server security - } - - @Override - public void decode() { - super.decode(); - this.offset += 16; //skip magic bytes - this.serverID = this.getLong(); - InetSocketAddress address = this.getAddress(); - this.clientAddress = address.getHostString(); - this.clientPort = address.getPort(); - this.mtuSize = this.getSignedShort(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new OPEN_CONNECTION_REPLY_2(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REQUEST_1.java b/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REQUEST_1.java deleted file mode 100644 index 3379830b448..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REQUEST_1.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class OPEN_CONNECTION_REQUEST_1 extends Packet { - public static final byte ID = (byte) 0x05; - - @Override - public byte getID() { - return ID; - } - - public byte protocol = RakNet.PROTOCOL; - public short mtuSize; - - @Override - public void encode() { - super.encode(); - this.put(RakNet.MAGIC); - this.putByte(this.protocol); - this.put(new byte[this.mtuSize - 18]); - } - - @Override - public void decode() { - super.decode(); - this.offset += 16; //skip magic bytes - this.protocol = this.getByte(); - this.mtuSize = (short) this.buffer.length; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new OPEN_CONNECTION_REQUEST_1(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REQUEST_2.java b/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REQUEST_2.java deleted file mode 100644 index 845d55e017a..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/OPEN_CONNECTION_REQUEST_2.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.Packet; - -import java.net.InetSocketAddress; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class OPEN_CONNECTION_REQUEST_2 extends Packet { - public static final byte ID = (byte) 0x07; - - @Override - public byte getID() { - return ID; - } - - public long clientID; - public String serverAddress; - public int serverPort; - public short mtuSize; - - @Override - public void encode() { - super.encode(); - this.put(RakNet.MAGIC); - this.putAddress(this.serverAddress, this.serverPort); - this.putShort(this.mtuSize); - this.putLong(this.clientID); - } - - @Override - public void decode() { - super.decode(); - this.offset += 16; //skip magic bytes - InetSocketAddress address = this.getAddress(); - this.serverAddress = address.getHostString(); - this.serverPort = address.getPort(); - this.mtuSize = this.getSignedShort(); - this.clientID = this.getLong(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new OPEN_CONNECTION_REQUEST_2(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/PING_DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/packet/PING_DataPacket.java deleted file mode 100644 index 626426be310..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/PING_DataPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class PING_DataPacket extends Packet { - public static final byte ID = (byte) 0x00; - - @Override - public byte getID() { - return ID; - } - - public long pingID; - - @Override - public void encode() { - super.encode(); - this.putLong(this.pingID); - } - - @Override - public void decode() { - super.decode(); - this.pingID = this.getLong(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new PING_DataPacket(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/PONG_DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/packet/PONG_DataPacket.java deleted file mode 100644 index 643e9c79c8b..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/PONG_DataPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class PONG_DataPacket extends Packet { - public static final byte ID = (byte) 0x03; - - @Override - public byte getID() { - return ID; - } - - public long pingID; - - @Override - public void encode() { - super.encode(); - this.putLong(this.pingID); - } - - @Override - public void decode() { - super.decode(); - this.pingID = this.getLong(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new PONG_DataPacket(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/SERVER_HANDSHAKE_DataPacket.java b/src/main/java/cn/nukkit/raknet/protocol/packet/SERVER_HANDSHAKE_DataPacket.java deleted file mode 100644 index 85a9f22d120..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/SERVER_HANDSHAKE_DataPacket.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -import java.net.InetSocketAddress; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class SERVER_HANDSHAKE_DataPacket extends Packet { - public static final byte ID = (byte) 0x10; - - @Override - public byte getID() { - return ID; - } - - public String address; - public int port; - public final InetSocketAddress[] systemAddresses = new InetSocketAddress[]{ - new InetSocketAddress("127.0.0.1", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0), - new InetSocketAddress("0.0.0.0", 0) - }; - - public long sendPing; - public long sendPong; - - @Override - public void encode() { - super.encode(); - this.putAddress(new InetSocketAddress(this.address, this.port)); - this.putShort(0); - for (int i = 0; i < 10; ++i) { - this.putAddress(this.systemAddresses[i]); - } - - this.putLong(this.sendPing); - this.putLong(this.sendPong); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new SERVER_HANDSHAKE_DataPacket(); - } - - } - -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PING.java b/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PING.java deleted file mode 100644 index 00f6b15e553..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PING.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class UNCONNECTED_PING extends Packet { - public static final byte ID = (byte) 0x01; - - @Override - public byte getID() { - return ID; - } - - public long pingID; - - @Override - public void encode() { - super.encode(); - this.putLong(this.pingID); - this.put(RakNet.MAGIC); - } - - @Override - public void decode() { - super.decode(); - this.pingID = this.getLong(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new UNCONNECTED_PING(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PING_OPEN_CONNECTIONS.java b/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PING_OPEN_CONNECTIONS.java deleted file mode 100644 index 9e7be154a78..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PING_OPEN_CONNECTIONS.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class UNCONNECTED_PING_OPEN_CONNECTIONS extends UNCONNECTED_PING { - public static final byte ID = (byte) 0x02; - - @Override - public byte getID() { - return ID; - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new UNCONNECTED_PING_OPEN_CONNECTIONS(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PONG.java b/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PONG.java deleted file mode 100644 index 16d210b7875..00000000000 --- a/src/main/java/cn/nukkit/raknet/protocol/packet/UNCONNECTED_PONG.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.nukkit.raknet.protocol.packet; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.Packet; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class UNCONNECTED_PONG extends Packet { - public static final byte ID = (byte) 0x1c; - - @Override - public byte getID() { - return ID; - } - - public long pingID; - public long serverID; - public String serverName; - - @Override - public void encode() { - super.encode(); - this.putLong(this.pingID); - this.putLong(this.serverID); - this.put(RakNet.MAGIC); - this.putString(this.serverName); - } - - @Override - public void decode() { - super.decode(); - this.pingID = this.getLong(); - this.serverID = this.getLong(); - this.offset += 16; //skip magic bytes todo:check magic? - this.serverName = this.getString(); - } - - public static final class Factory implements Packet.PacketFactory { - - @Override - public Packet create() { - return new UNCONNECTED_PONG(); - } - - } -} diff --git a/src/main/java/cn/nukkit/raknet/server/RakNetServer.java b/src/main/java/cn/nukkit/raknet/server/RakNetServer.java deleted file mode 100644 index 0858334de04..00000000000 --- a/src/main/java/cn/nukkit/raknet/server/RakNetServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package cn.nukkit.raknet.server; - -import cn.nukkit.Server; -import cn.nukkit.utils.ThreadedLogger; - -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class RakNetServer extends Thread { - protected final int port; - protected String interfaz; - - protected ThreadedLogger logger; - - protected ConcurrentLinkedQueue externalQueue; - protected ConcurrentLinkedQueue internalQueue; - - protected boolean shutdown; - - - public RakNetServer(ThreadedLogger logger, int port) { - this(logger, port, "0.0.0.0"); - } - - public RakNetServer(ThreadedLogger logger, int port, String interfaz) { - this.port = port; - if (port < 1 || port > 65536) { - throw new IllegalArgumentException("Invalid port range"); - } - - this.interfaz = interfaz; - this.logger = logger; - - this.externalQueue = new ConcurrentLinkedQueue<>(); - this.internalQueue = new ConcurrentLinkedQueue<>(); - - this.start(); - } - - public boolean isShutdown() { - return shutdown; - } - - public void shutdown() { - this.shutdown = true; - } - - public int getPort() { - return port; - } - - public String getInterface() { - return interfaz; - } - - public ThreadedLogger getLogger() { - return logger; - } - - public ConcurrentLinkedQueue getExternalQueue() { - return externalQueue; - } - - public ConcurrentLinkedQueue getInternalQueue() { - return internalQueue; - } - - public void pushMainToThreadPacket(byte[] data) { - this.internalQueue.add(data); - } - - public byte[] readMainToThreadPacket() { - return this.internalQueue.poll(); - } - - public void pushThreadToMainPacket(byte[] data) { - this.externalQueue.add(data); - } - - public byte[] readThreadToMainPacket() { - return this.externalQueue.poll(); - } - - private class ShutdownHandler extends Thread { - public void run() { - if (!shutdown) { - logger.emergency("RakNet crashed!"); - } - } - } - - @Override - public void run() { - this.setName("RakNet Thread #" + Thread.currentThread().getId()); - Runtime.getRuntime().addShutdownHook(new ShutdownHandler()); - UDPServerSocket socket = new UDPServerSocket(this.getLogger(), port, this.interfaz); - try { - new SessionManager(this, socket); - } catch (Exception e) { - Server.getInstance().getLogger().logException(e); - } - } -} diff --git a/src/main/java/cn/nukkit/raknet/server/ServerHandler.java b/src/main/java/cn/nukkit/raknet/server/ServerHandler.java deleted file mode 100644 index c75e462d8c9..00000000000 --- a/src/main/java/cn/nukkit/raknet/server/ServerHandler.java +++ /dev/null @@ -1,182 +0,0 @@ -package cn.nukkit.raknet.server; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.EncapsulatedPacket; -import cn.nukkit.utils.Binary; - -import java.nio.charset.StandardCharsets; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class ServerHandler { - - protected final RakNetServer server; - - protected final ServerInstance instance; - - public ServerHandler(RakNetServer server, ServerInstance instance) { - this.server = server; - this.instance = instance; - } - - public void sendEncapsulated(String identifier, EncapsulatedPacket packet) { - this.sendEncapsulated(identifier, packet, RakNet.PRIORITY_NORMAL); - } - - public void sendEncapsulated(String identifier, EncapsulatedPacket packet, int flags) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_ENCAPSULATED, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8), - new byte[]{(byte) (flags & 0xff)}, - packet.toBinary(true) - ); - this.server.pushMainToThreadPacket(buffer); - } - - public void sendRaw(String address, int port, byte[] payload) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_RAW, - new byte[]{(byte) (address.length() & 0xff)}, - address.getBytes(StandardCharsets.UTF_8), - Binary.writeShort(port), - payload - ); - this.server.pushMainToThreadPacket(buffer); - } - - public void closeSession(String identifier, String reason) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_CLOSE_SESSION, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8), - new byte[]{(byte) (reason.length() & 0xff)}, - reason.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushMainToThreadPacket(buffer); - } - - public void sendOption(String name, String value) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_SET_OPTION, - new byte[]{(byte) (name.length() & 0xff)}, - name.getBytes(StandardCharsets.UTF_8), - value.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushMainToThreadPacket(buffer); - } - - public void blockAddress(String address, int timeout) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_BLOCK_ADDRESS, - new byte[]{(byte) (address.length() & 0xff)}, - address.getBytes(StandardCharsets.UTF_8), - Binary.writeInt(timeout) - ); - this.server.pushMainToThreadPacket(buffer); - } - - public void unblockAddress(String address) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_UNBLOCK_ADDRESS, - new byte[]{(byte) (address.length() & 0xff)}, - address.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushMainToThreadPacket(buffer); - } - - public void shutdown() { - this.server.pushMainToThreadPacket(new byte[]{RakNet.PACKET_SHUTDOWN}); - this.server.shutdown(); - synchronized (this) { - try { - this.wait(20); - } catch (InterruptedException e) { - //ignore - } - } - try { - this.server.join(); - } catch (InterruptedException e) { - //ignore - } - } - - public void emergencyShutdown() { - this.server.shutdown(); - this.server.pushMainToThreadPacket(new byte[]{RakNet.PACKET_EMERGENCY_SHUTDOWN}); - } - - protected void invalidSession(String identifier) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_INVALID_SESSION, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushMainToThreadPacket(buffer); - } - - public boolean handlePacket() { - byte[] packet = this.server.readThreadToMainPacket(); - if (packet != null && packet.length > 0) { - byte id = packet[0]; - int offset = 1; - if (id == RakNet.PACKET_ENCAPSULATED) { - int len = packet[offset++]; - String identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - int flags = packet[offset++]; - byte[] buffer = Binary.subBytes(packet, offset); - this.instance.handleEncapsulated(identifier, EncapsulatedPacket.fromBinary(buffer, true), flags); - } else if (id == RakNet.PACKET_RAW) { - int len = packet[offset++]; - String address = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - int port = Binary.readShort(Binary.subBytes(packet, offset, 2)) & 0xffff; - offset += 2; - byte[] payload = Binary.subBytes(packet, offset); - this.instance.handleRaw(address, port, payload); - } else if (id == RakNet.PACKET_SET_OPTION) { - int len = packet[offset++]; - String name = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - String value = new String(Binary.subBytes(packet, offset), StandardCharsets.UTF_8); - this.instance.handleOption(name, value); - } else if (id == RakNet.PACKET_OPEN_SESSION) { - int len = packet[offset++]; - String identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - len = packet[offset++]; - String address = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - int port = Binary.readShort(Binary.subBytes(packet, offset, 2)) & 0xffff; - offset += 2; - long clientID = Binary.readLong(Binary.subBytes(packet, offset, 8)); - this.instance.openSession(identifier, address, port, clientID); - } else if (id == RakNet.PACKET_CLOSE_SESSION) { - int len = packet[offset++]; - String identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - len = packet[offset++]; - String reason = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - this.instance.closeSession(identifier, reason); - } else if (id == RakNet.PACKET_INVALID_SESSION) { - int len = packet[offset++]; - String identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - this.instance.closeSession(identifier, "Invalid session"); - } else if (id == RakNet.PACKET_ACK_NOTIFICATION) { - int len = packet[offset++]; - String identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - int identifierACK = Binary.readInt(Binary.subBytes(packet, offset, 4)); - this.instance.notifyACK(identifier, identifierACK); - } - return true; - } - - return false; - } - -} diff --git a/src/main/java/cn/nukkit/raknet/server/ServerInstance.java b/src/main/java/cn/nukkit/raknet/server/ServerInstance.java deleted file mode 100644 index 8b55c696e2b..00000000000 --- a/src/main/java/cn/nukkit/raknet/server/ServerInstance.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.nukkit.raknet.server; - -import cn.nukkit.raknet.protocol.EncapsulatedPacket; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public interface ServerInstance { - - void openSession(String identifier, String address, int port, long clientID); - - void closeSession(String identifier, String reason); - - void handleEncapsulated(String identifier, EncapsulatedPacket packet, int flags); - - void handleRaw(String address, int port, byte[] payload); - - void notifyACK(String identifier, int identifierACK); - - void handleOption(String option, String value); -} diff --git a/src/main/java/cn/nukkit/raknet/server/Session.java b/src/main/java/cn/nukkit/raknet/server/Session.java deleted file mode 100644 index 867afc249ac..00000000000 --- a/src/main/java/cn/nukkit/raknet/server/Session.java +++ /dev/null @@ -1,555 +0,0 @@ -package cn.nukkit.raknet.server; - -import cn.nukkit.math.NukkitMath; -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.DataPacket; -import cn.nukkit.raknet.protocol.EncapsulatedPacket; -import cn.nukkit.raknet.protocol.Packet; -import cn.nukkit.raknet.protocol.packet.*; -import cn.nukkit.utils.Binary; -import cn.nukkit.utils.BinaryStream; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class Session { - public final static int STATE_UNCONNECTED = 0; - public final static int STATE_CONNECTING_1 = 1; - public final static int STATE_CONNECTING_2 = 2; - public final static int STATE_CONNECTED = 3; - - public final static int MAX_SPLIT_SIZE = 128; - public final static int MAX_SPLIT_COUNT = 4; - - public static final int WINDOW_SIZE = 2048; - - private static final int MAX_MTU_SIZE = 1492; - private static final int MIN_MTU_SIZE = 400; - - private int messageIndex = 0; - private final Map channelIndex = new ConcurrentHashMap<>(); - - private SessionManager sessionManager; - private final String address; - private final int port; - private int state = STATE_UNCONNECTED; - //private List preJoinQueue = new ArrayList<>(); - private int mtuSize = MIN_MTU_SIZE; - private long id = 0; - private int splitID = 0; - - private int sendSeqNumber = 0; - private int lastSeqNumber = -1; - - private long lastUpdate; - private final long startTime; - - private boolean isTemporal = true; - - private final List packetToSend = new ArrayList<>(); - - private boolean isActive; - - private Map ACKQueue = new HashMap<>(); - private Map NACKQueue = new HashMap<>(); - - private final Map recoveryQueue = new TreeMap<>(); - - private final Map> splitPackets = new HashMap<>(); - - private final Map> needACK = new TreeMap<>(); - - private DataPacket sendQueue; - - private int windowStart; - private final Map receivedWindow = new TreeMap<>(); - private int windowEnd; - - private int reliableWindowStart; - private int reliableWindowEnd; - private final Map reliableWindow = new TreeMap<>(); - private int lastReliableIndex = -1; - - public Session(SessionManager sessionManager, String address, int port) { - this.sessionManager = sessionManager; - this.address = address; - this.port = port; - this.sendQueue = new DATA_PACKET_4(); - this.lastUpdate = System.currentTimeMillis(); - this.startTime = System.currentTimeMillis(); - this.isActive = false; - this.windowStart = -1; - this.windowEnd = WINDOW_SIZE; - - this.reliableWindowStart = 0; - this.reliableWindowEnd = WINDOW_SIZE; - - for (int i = 0; i < 32; i++) { - this.channelIndex.put(i, 0); - } - } - - public String getAddress() { - return this.address; - } - - public int getPort() { - return this.port; - } - - public long getID() { - return this.id; - } - - public void update(long time) throws Exception { - if (!this.isActive && (this.lastUpdate + 10000) < time) { //10 second timeout - this.disconnect("timeout"); - - return; - } - this.isActive = false; - - if (!this.ACKQueue.isEmpty()) { - ACK pk = new ACK(); - pk.packets = new TreeMap<>(this.ACKQueue); - this.sendPacket(pk); - this.ACKQueue = new HashMap<>(); - } - - if (!this.NACKQueue.isEmpty()) { - NACK pk = new NACK(); - pk.packets = new TreeMap<>(this.NACKQueue); - this.sendPacket(pk); - this.NACKQueue = new HashMap<>(); - } - - if (!this.packetToSend.isEmpty()) { - int limit = 16; - for (int i = 0; i < this.packetToSend.size(); i++) { - DataPacket pk = this.packetToSend.get(i); - pk.sendTime = time; - pk.encode(); - this.recoveryQueue.put(pk.seqNumber, pk); - this.packetToSend.remove(pk); - this.sendPacket(pk); - - if (limit-- <= 0) { - break; - } - } - } - - if (this.packetToSend.size() > WINDOW_SIZE) { - this.packetToSend.clear(); - } - - if (!this.needACK.isEmpty()) { - for (int identifierACK : new ArrayList<>(this.needACK.keySet())) { - Map indexes = this.needACK.get(identifierACK); - if (indexes.isEmpty()) { - this.needACK.remove(identifierACK); - this.sessionManager.notifyACK(this, identifierACK); - } - } - } - - for (int seq : new ArrayList<>(this.recoveryQueue.keySet())) { - DataPacket pk = this.recoveryQueue.get(seq); - if (pk.sendTime < System.currentTimeMillis() - 8000) { - this.packetToSend.add(pk); - this.recoveryQueue.remove(seq); - } else { - break; - } - } - - for (int seq : new ArrayList<>(this.receivedWindow.keySet())) { - if (seq < this.windowStart) { - this.receivedWindow.remove(seq); - } else { - break; - } - } - - this.sendQueue(); - } - - public void disconnect() throws Exception { - this.disconnect("unknown"); - } - - public void disconnect(String reason) throws Exception { - this.sessionManager.removeSession(this, reason); - } - - private void sendPacket(Packet packet) throws IOException { - this.sessionManager.sendPacket(packet, this.address, this.port); - } - - public void sendQueue() throws IOException { - if (!this.sendQueue.packets.isEmpty()) { - this.sendQueue.seqNumber = sendSeqNumber++; - this.sendPacket(sendQueue); - this.sendQueue.sendTime = System.currentTimeMillis(); - this.recoveryQueue.put(this.sendQueue.seqNumber, this.sendQueue); - this.sendQueue = new DATA_PACKET_4(); - } - } - - private void addToQueue(EncapsulatedPacket pk) throws Exception { - addToQueue(pk, RakNet.PRIORITY_NORMAL); - } - - private void addToQueue(EncapsulatedPacket pk, int flags) throws Exception { - int priority = flags & 0b0000111; - if (pk.needACK && pk.messageIndex != null) { - if (!this.needACK.containsKey(pk.identifierACK)) { - this.needACK.put(pk.identifierACK, new HashMap<>()); - } - this.needACK.get(pk.identifierACK).put(pk.messageIndex, pk.messageIndex); - } - - if (priority == RakNet.PRIORITY_IMMEDIATE) { //Skip queues - DataPacket packet = new DATA_PACKET_0(); - packet.seqNumber = this.sendSeqNumber++; - if (pk.needACK) { - packet.packets.add(pk.clone()); - pk.needACK = false; - } else { - packet.packets.add(pk.toBinary()); - } - - this.sendPacket(packet); - packet.sendTime = System.currentTimeMillis(); - this.recoveryQueue.put(packet.seqNumber, packet); - - return; - } - int length = this.sendQueue.length(); - if (length + pk.getTotalLength() > this.mtuSize) { - this.sendQueue(); - } - - if (pk.needACK) { - this.sendQueue.packets.add(pk.clone()); - pk.needACK = false; - } else { - this.sendQueue.packets.add(pk.toBinary()); - } - } - - public void addEncapsulatedToQueue(EncapsulatedPacket packet) throws Exception { - addEncapsulatedToQueue(packet, RakNet.PRIORITY_NORMAL); - } - - public void addEncapsulatedToQueue(EncapsulatedPacket packet, int flags) throws Exception { - if ((packet.needACK = (flags & RakNet.FLAG_NEED_ACK) > 0)) { - this.needACK.put(packet.identifierACK, new HashMap<>()); - } - - if (packet.reliability == 2 || - packet.reliability == 3 || - packet.reliability == 4 || - packet.reliability == 6 || - packet.reliability == 7) { - packet.messageIndex = this.messageIndex++; - - if (packet.reliability == 3) { - int index = this.channelIndex.get(packet.orderChannel) + 1; - packet.orderIndex = index; - channelIndex.put(packet.orderChannel, index); - } - } - - if (packet.getTotalLength() + 4 > this.mtuSize) { - byte[][] buffers = Binary.splitBytes(packet.buffer, this.mtuSize - 34); - int splitID = ++this.splitID % 65536; - for (int count = 0; count < buffers.length; count++) { - byte[] buffer = buffers[count]; - EncapsulatedPacket pk = new EncapsulatedPacket(); - pk.splitID = splitID; - pk.hasSplit = true; - pk.splitCount = buffers.length; - pk.reliability = packet.reliability; - pk.splitIndex = count; - pk.buffer = buffer; - if (count > 0) { - pk.messageIndex = this.messageIndex++; - } else { - pk.messageIndex = packet.messageIndex; - } - if (pk.reliability == 3) { - pk.orderChannel = packet.orderChannel; - pk.orderIndex = packet.orderIndex; - } - this.addToQueue(pk, flags | RakNet.PRIORITY_IMMEDIATE); - } - } else { - this.addToQueue(packet, flags); - } - } - - private void handleSplit(EncapsulatedPacket packet) throws Exception { - if (packet.splitCount >= MAX_SPLIT_SIZE || packet.splitIndex >= MAX_SPLIT_SIZE || packet.splitIndex < 0) { - return; - } - - if (!this.splitPackets.containsKey(packet.splitID)) { - if (this.splitPackets.size() >= MAX_SPLIT_COUNT) { - return; - } - this.splitPackets.put(packet.splitID, new HashMap() {{ - put(packet.splitIndex, packet); - }}); - } else { - this.splitPackets.get(packet.splitID).put(packet.splitIndex, packet); - } - - if (this.splitPackets.get(packet.splitID).size() == packet.splitCount) { - EncapsulatedPacket pk = new EncapsulatedPacket(); - BinaryStream stream = new BinaryStream(); - for (int i = 0; i < packet.splitCount; i++) { - stream.put(this.splitPackets.get(packet.splitID).get(i).buffer); - } - pk.buffer = stream.getBuffer(); - pk.length = pk.buffer.length; - this.splitPackets.remove(packet.splitID); - - this.handleEncapsulatedPacketRoute(pk); - } - } - - private void handleEncapsulatedPacket(EncapsulatedPacket packet) throws Exception { - if (packet.messageIndex == null) { - this.handleEncapsulatedPacketRoute(packet); - } else { - if (packet.messageIndex < this.reliableWindowStart || packet.messageIndex > this.reliableWindowEnd) { - return; - } - - if ((packet.messageIndex - this.lastReliableIndex) == 1) { - this.lastReliableIndex++; - this.reliableWindowStart++; - this.reliableWindowEnd++; - this.handleEncapsulatedPacketRoute(packet); - - if (!this.reliableWindow.isEmpty()) { - TreeMap sortedMap = new TreeMap<>(this.reliableWindow); - - for (int index : sortedMap.keySet()) { - EncapsulatedPacket pk = this.reliableWindow.get(index); - - if ((index - this.lastReliableIndex) != 1) { - break; - } - - this.lastReliableIndex++; - this.reliableWindowStart++; - this.reliableWindowEnd++; - this.handleEncapsulatedPacketRoute(pk); - this.reliableWindow.remove(index); - } - } - } else { - this.reliableWindow.put(packet.messageIndex, packet); - } - } - - } - - public int getState() { - return state; - } - - public boolean isTemporal() { - return isTemporal; - } - - private void handleEncapsulatedPacketRoute(EncapsulatedPacket packet) throws Exception { - if (this.sessionManager == null) { - return; - } - - if (packet.hasSplit) { - if (this.state == STATE_CONNECTED) { - this.handleSplit(packet); - } - return; - } - - byte id = packet.buffer[0]; - if ((id & 0xff) < 0x80) { //internal data packet - if (state == STATE_CONNECTING_2) { - if (id == CLIENT_CONNECT_DataPacket.ID) { - CLIENT_CONNECT_DataPacket dataPacket = new CLIENT_CONNECT_DataPacket(); - dataPacket.buffer = packet.buffer; - dataPacket.decode(); - SERVER_HANDSHAKE_DataPacket pk = new SERVER_HANDSHAKE_DataPacket(); - pk.address = this.address; - pk.port = this.port; - pk.sendPing = dataPacket.sendPing; - pk.sendPong = dataPacket.sendPing + 1000L; - pk.encode(); - - EncapsulatedPacket sendPacket = new EncapsulatedPacket(); - sendPacket.reliability = 0; - sendPacket.buffer = pk.buffer; - this.addToQueue(sendPacket, RakNet.PRIORITY_IMMEDIATE); - } else if (id == CLIENT_HANDSHAKE_DataPacket.ID) { - CLIENT_HANDSHAKE_DataPacket dataPacket = new CLIENT_HANDSHAKE_DataPacket(); - dataPacket.buffer = packet.buffer; - dataPacket.decode(); - - if (dataPacket.port == this.sessionManager.getPort() || !this.sessionManager.portChecking) { - this.state = STATE_CONNECTED; //FINALLY! - this.isTemporal = false; - this.sessionManager.openSession(this); - } - } - } else if (id == CLIENT_DISCONNECT_DataPacket.ID) { - disconnect("client disconnect"); - } else if (id == PING_DataPacket.ID) { - PING_DataPacket dataPacket = new PING_DataPacket(); - dataPacket.buffer = packet.buffer; - dataPacket.decode(); - - PONG_DataPacket pk = new PONG_DataPacket(); - pk.pingID = dataPacket.pingID; - pk.encode(); - - EncapsulatedPacket sendPacket = new EncapsulatedPacket(); - sendPacket.reliability = 0; - sendPacket.buffer = pk.buffer; - this.addToQueue(sendPacket); - - //Latency measurement - PING_DataPacket pingPacket = new PING_DataPacket(); - pingPacket.pingID = System.currentTimeMillis(); - pingPacket.encode(); - - sendPacket = new EncapsulatedPacket(); - sendPacket.reliability = 0; - sendPacket.buffer = pingPacket.buffer; - this.addToQueue(sendPacket); - } else if (id == PONG_DataPacket.ID) { - if (state == STATE_CONNECTED) { - PONG_DataPacket dataPacket = new PONG_DataPacket(); - dataPacket.buffer = packet.buffer; - dataPacket.decode(); - - if (state == STATE_CONNECTED) { - PING_DataPacket pingPacket = new PING_DataPacket(); - pingPacket.pingID = (System.currentTimeMillis() - dataPacket.pingID) / 10; - pingPacket.encode(); - packet.buffer = pingPacket.buffer; - this.sessionManager.streamEncapsulated(this, packet); - } - } - } - } else if (state == STATE_CONNECTED) { - this.sessionManager.streamEncapsulated(this, packet); - } else { - //this.sessionManager.getLogger().notice("Received packet before connection: "+Binary.bytesToHexString(packet.buffer)); - } - } - - public void handlePacket(Packet packet) throws Exception { - this.isActive = true; - this.lastUpdate = System.currentTimeMillis(); - if (this.state == STATE_CONNECTED || this.state == STATE_CONNECTING_2) { - if (((packet.buffer[0] & 0xff) >= 0x80 || (packet.buffer[0] & 0xff) <= 0x8f) && packet instanceof DataPacket) { - DataPacket dp = (DataPacket) packet; - dp.decode(); - - if (dp.seqNumber < this.windowStart || dp.seqNumber > this.windowEnd || this.receivedWindow.containsKey(dp.seqNumber)) { - return; - } - - int diff = dp.seqNumber - this.lastSeqNumber; - - this.NACKQueue.remove(dp.seqNumber); - this.ACKQueue.put(dp.seqNumber, dp.seqNumber); - this.receivedWindow.put(dp.seqNumber, dp.seqNumber); - - if (diff != 1) { - for (int i = this.lastSeqNumber + 1; i < dp.seqNumber; i++) { - if (!this.receivedWindow.containsKey(i)) { - this.NACKQueue.put(i, i); - } - } - } - - if (diff >= 1) { - this.lastSeqNumber = dp.seqNumber; - this.windowStart += diff; - this.windowEnd += diff; - } - - for (Object pk : dp.packets) { - if (pk instanceof EncapsulatedPacket) { - this.handleEncapsulatedPacket((EncapsulatedPacket) pk); - } - } - } else { - if (packet instanceof ACK) { - packet.decode(); - for (int seq : new ArrayList<>(((ACK) packet).packets.values())) { - if (this.recoveryQueue.containsKey(seq)) { - for (Object pk : this.recoveryQueue.get(seq).packets) { - if (pk instanceof EncapsulatedPacket && ((EncapsulatedPacket) pk).needACK && ((EncapsulatedPacket) pk).messageIndex != null) { - if (this.needACK.containsKey(((EncapsulatedPacket) pk).identifierACK)) { - this.needACK.get(((EncapsulatedPacket) pk).identifierACK).remove(((EncapsulatedPacket) pk).messageIndex); - } - } - } - this.recoveryQueue.remove(seq); - } - } - } else if (packet instanceof NACK) { - packet.decode(); - for (int seq : new ArrayList<>(((NACK) packet).packets.values())) { - if (this.recoveryQueue.containsKey(seq)) { - DataPacket pk = this.recoveryQueue.get(seq); - pk.seqNumber = this.sendSeqNumber++; - this.packetToSend.add(pk); - this.recoveryQueue.remove(seq); - } - } - } - } - } else if ((packet.buffer[0] & 0xff) > 0x00 || (packet.buffer[0] & 0xff) < 0x80) { //Not Data packet :) - packet.decode(); - if (packet instanceof OPEN_CONNECTION_REQUEST_1) { - //TODO: check protocol number and refuse connections - OPEN_CONNECTION_REPLY_1 pk = new OPEN_CONNECTION_REPLY_1(); - pk.mtuSize = ((OPEN_CONNECTION_REQUEST_1) packet).mtuSize; - pk.serverID = sessionManager.getID(); - this.sendPacket(pk); - this.state = STATE_CONNECTING_1; - } else if (this.state == STATE_CONNECTING_1 && packet instanceof OPEN_CONNECTION_REQUEST_2) { - this.id = ((OPEN_CONNECTION_REQUEST_2) packet).clientID; - if (((OPEN_CONNECTION_REQUEST_2) packet).serverPort == this.sessionManager.getPort() || !this.sessionManager.portChecking) { - this.mtuSize = NukkitMath.clamp(Math.abs(((OPEN_CONNECTION_REQUEST_2) packet).mtuSize), MIN_MTU_SIZE, MAX_MTU_SIZE); - OPEN_CONNECTION_REPLY_2 pk = new OPEN_CONNECTION_REPLY_2(); - pk.mtuSize = (short) this.mtuSize; - pk.serverID = this.sessionManager.getID(); - pk.clientAddress = this.address; - pk.clientPort = this.port; - this.sendPacket(pk); - this.state = STATE_CONNECTING_2; - } - } - } - } - - public void close() throws Exception { - byte[] data = new byte[]{0x60, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15}; //CLIENT_DISCONNECT packet 0x15 - this.addEncapsulatedToQueue(EncapsulatedPacket.fromBinary(data)); - this.sessionManager = null; - } -} diff --git a/src/main/java/cn/nukkit/raknet/server/SessionManager.java b/src/main/java/cn/nukkit/raknet/server/SessionManager.java deleted file mode 100644 index df6053554e8..00000000000 --- a/src/main/java/cn/nukkit/raknet/server/SessionManager.java +++ /dev/null @@ -1,513 +0,0 @@ -package cn.nukkit.raknet.server; - -import cn.nukkit.raknet.RakNet; -import cn.nukkit.raknet.protocol.EncapsulatedPacket; -import cn.nukkit.raknet.protocol.Packet; -import cn.nukkit.raknet.protocol.packet.*; -import cn.nukkit.utils.Binary; -import cn.nukkit.utils.ThreadedLogger; -import io.netty.buffer.ByteBuf; -import io.netty.channel.socket.DatagramPacket; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.*; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class SessionManager { - protected final Packet.PacketFactory[] packetPool = new Packet.PacketFactory[256]; - - protected final RakNetServer server; - - protected final UDPServerSocket socket; - - protected int receiveBytes = 0; - protected int sendBytes = 0; - - protected final Map sessions = new HashMap<>(); - - protected String name = ""; - - protected int packetLimit = 1000; - - protected boolean shutdown = false; - - protected long ticks = 0; - protected long lastMeasure; - - protected final Map block = new HashMap<>(); - protected final Map ipSec = new HashMap<>(); - - public boolean portChecking = true; - - public final long serverId; - - protected String currentSource = ""; - - public SessionManager(RakNetServer server, UDPServerSocket socket) throws Exception { - this.server = server; - this.socket = socket; - this.registerPackets(); - - this.serverId = new Random().nextLong(); - - this.run(); - } - - public int getPort() { - return this.server.port; - } - - public ThreadedLogger getLogger() { - return this.server.getLogger(); - } - - public void run() throws Exception { - this.tickProcessor(); - } - - private void tickProcessor() throws Exception { - this.lastMeasure = System.currentTimeMillis(); - while (!this.shutdown) { - long start = System.currentTimeMillis(); - int max = 5000; - while (max > 0) { - try { - if (!this.receivePacket()) { - break; - } - --max; - } catch (Exception e) { - if (!currentSource.isEmpty()) { - this.blockAddress(currentSource); - } - // else ignore - } - } - while (this.receiveStream()) ; - - long time = System.currentTimeMillis() - start; - if (time < 50) { - try { - Thread.sleep(50 - time); - } catch (InterruptedException e) { - //ignore - } - } - this.tick(); - } - } - - private void tick() throws Exception { - long time = System.currentTimeMillis(); - for (Session session : new ArrayList<>(this.sessions.values())) { - session.update(time); - } - - for (String address : this.ipSec.keySet()) { - int count = this.ipSec.get(address); - if (count >= this.packetLimit) { - this.blockAddress(address); - } - } - this.ipSec.clear(); - - if ((this.ticks & 0b1111) == 0) { - double diff = Math.max(5d, (double) time - this.lastMeasure); - this.streamOption("bandwidth", this.sendBytes / diff + ";" + this.receiveBytes / diff); - this.lastMeasure = time; - this.sendBytes = 0; - this.receiveBytes = 0; - - if (!this.block.isEmpty()) { - long now = System.currentTimeMillis(); - for (String address : new ArrayList<>(this.block.keySet())) { - long timeout = this.block.get(address); - if (timeout <= now) { - this.block.remove(address); - this.getLogger().notice("Unblocked " + address); - } else { - break; - } - } - } - } - - ++this.ticks; - } - - private boolean receivePacket() throws Exception { - DatagramPacket datagramPacket = this.socket.readPacket(); - if (datagramPacket != null) { - // Check this early - try { - String source = datagramPacket.sender().getHostString(); - currentSource = source; //in order to block address - if (this.block.containsKey(source)) { - return true; - } - - if (this.ipSec.containsKey(source)) { - this.ipSec.put(source, this.ipSec.get(source) + 1); - } else { - this.ipSec.put(source, 1); - } - - ByteBuf byteBuf = datagramPacket.content(); - if (byteBuf.readableBytes() == 0) { - // Exit early to process another packet - return true; - } - byte[] buffer = new byte[byteBuf.readableBytes()]; - byteBuf.readBytes(buffer); - int len = buffer.length; - int port = datagramPacket.sender().getPort(); - - this.receiveBytes += len; - - byte pid = buffer[0]; - - if (pid == UNCONNECTED_PONG.ID) { - return false; - } - - Packet packet = this.getPacketFromPool(pid); - if (packet != null) { - packet.buffer = buffer; - this.getSession(source, port).handlePacket(packet); - return true; - } else if (pid == UNCONNECTED_PING.ID) { - packet = new UNCONNECTED_PING(); - packet.buffer = buffer; - packet.decode(); - - UNCONNECTED_PONG pk = new UNCONNECTED_PONG(); - pk.serverID = this.getID(); - pk.pingID = ((UNCONNECTED_PING) packet).pingID; - pk.serverName = this.getName(); - this.sendPacket(pk, source, port); - } else if (buffer.length != 0) { - this.streamRAW(source, port, buffer); - return true; - } else { - return false; - } - } finally { - datagramPacket.release(); - } - } - - return false; - } - - public void sendPacket(Packet packet, String dest, int port) throws IOException { - packet.encode(); - this.sendBytes += this.socket.writePacket(packet.buffer, dest, port); - } - - public void sendPacket(Packet packet, InetSocketAddress dest) throws IOException { - packet.encode(); - this.sendBytes += this.socket.writePacket(packet.buffer, dest); - } - - public void streamEncapsulated(Session session, EncapsulatedPacket packet) { - this.streamEncapsulated(session, packet, RakNet.PRIORITY_NORMAL); - } - - public void streamEncapsulated(Session session, EncapsulatedPacket packet, int flags) { - String id = session.getAddress() + ":" + session.getPort(); - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_ENCAPSULATED, - new byte[]{(byte) (id.length() & 0xff)}, - id.getBytes(StandardCharsets.UTF_8), - new byte[]{(byte) (flags & 0xff)}, - packet.toBinary(true) - ); - this.server.pushThreadToMainPacket(buffer); - } - - public void streamRAW(String address, int port, byte[] payload) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_RAW, - new byte[]{(byte) (address.length() & 0xff)}, - address.getBytes(StandardCharsets.UTF_8), - Binary.writeShort(port), - payload - ); - this.server.pushThreadToMainPacket(buffer); - } - - protected void streamClose(String identifier, String reason) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_CLOSE_SESSION, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8), - new byte[]{(byte) (reason.length() & 0xff)}, - reason.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushThreadToMainPacket(buffer); - } - - protected void streamInvalid(String identifier) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_INVALID_SESSION, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushThreadToMainPacket(buffer); - } - - protected void streamOpen(Session session) { - String identifier = session.getAddress() + ":" + session.getPort(); - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_OPEN_SESSION, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8), - new byte[]{(byte) (session.getAddress().length() & 0xff)}, - session.getAddress().getBytes(StandardCharsets.UTF_8), - Binary.writeShort(session.getPort()), - Binary.writeLong(session.getID()) - ); - this.server.pushThreadToMainPacket(buffer); - } - - protected void streamACK(String identifier, int identifierACK) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_ACK_NOTIFICATION, - new byte[]{(byte) (identifier.length() & 0xff)}, - identifier.getBytes(StandardCharsets.UTF_8), - Binary.writeInt(identifierACK) - ); - this.server.pushThreadToMainPacket(buffer); - } - - protected void streamOption(String name, String value) { - byte[] buffer = Binary.appendBytes( - RakNet.PACKET_SET_OPTION, - new byte[]{(byte) (name.length() & 0xff)}, - name.getBytes(StandardCharsets.UTF_8), - value.getBytes(StandardCharsets.UTF_8) - ); - this.server.pushThreadToMainPacket(buffer); - } - - private void checkSessions() { - int size = this.sessions.size(); - if (size > 4096) { - List keyToRemove = new ArrayList<>(); - for (String i : this.sessions.keySet()) { - Session s = this.sessions.get(i); - if (s.isTemporal()) { - keyToRemove.add(i); - size--; - if (size <= 4096) { - break; - } - } - } - - for (String i : keyToRemove) { - this.sessions.remove(i); - } - } - } - - public boolean receiveStream() throws Exception { - byte[] packet = this.server.readMainToThreadPacket(); - if (packet != null && packet.length > 0) { - byte id = packet[0]; - int offset = 1; - switch (id) { - case RakNet.PACKET_ENCAPSULATED: - int len = packet[offset++]; - String identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - if (this.sessions.containsKey(identifier)) { - byte flags = packet[offset++]; - byte[] buffer = Binary.subBytes(packet, offset); - this.sessions.get(identifier).addEncapsulatedToQueue(EncapsulatedPacket.fromBinary(buffer, true), flags); - } else { - this.streamInvalid(identifier); - } - break; - case RakNet.PACKET_RAW: - len = packet[offset++]; - String address = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - int port = Binary.readShort(Binary.subBytes(packet, offset, 2)); - offset += 2; - byte[] payload = Binary.subBytes(packet, offset); - this.socket.writePacket(payload, address, port); - break; - case RakNet.PACKET_CLOSE_SESSION: - len = packet[offset++]; - identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - if (this.sessions.containsKey(identifier)) { - this.removeSession(this.sessions.get(identifier)); - } else { - this.streamInvalid(identifier); - } - break; - case RakNet.PACKET_INVALID_SESSION: - len = packet[offset++]; - identifier = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - if (this.sessions.containsKey(identifier)) { - this.removeSession(this.sessions.get(identifier)); - } - break; - case RakNet.PACKET_SET_OPTION: - len = packet[offset++]; - String name = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - String value = new String(Binary.subBytes(packet, offset), StandardCharsets.UTF_8); - switch (name) { - case "name": - this.name = value; - break; - case "portChecking": - this.portChecking = Boolean.valueOf(value); - break; - case "packetLimit": - this.packetLimit = Integer.valueOf(value); - break; - } - break; - case RakNet.PACKET_BLOCK_ADDRESS: - len = packet[offset++]; - address = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - offset += len; - int timeout = Binary.readInt(Binary.subBytes(packet, offset, 4)); - this.blockAddress(address, timeout); - break; - case RakNet.PACKET_UNBLOCK_ADDRESS: - len = packet[offset++]; - address = new String(Binary.subBytes(packet, offset, len), StandardCharsets.UTF_8); - this.unblockAddress(address); - break; - case RakNet.PACKET_SHUTDOWN: - for (Session session : new ArrayList<>(this.sessions.values())) { - this.removeSession(session); - } - - this.socket.close(); - this.shutdown = true; - break; - case RakNet.PACKET_EMERGENCY_SHUTDOWN: - this.shutdown = true; - default: - return false; - } - return true; - } - - return false; - } - - public void blockAddress(String address) { - this.blockAddress(address, 300); - } - - public void blockAddress(String address, int timeout) { - long finalTime = System.currentTimeMillis() + timeout * 1000; - if (!this.block.containsKey(address) || timeout == -1) { - if (timeout == -1) { - finalTime = Long.MAX_VALUE; - } else { - this.getLogger().notice("Blocked " + address + " for " + timeout + " seconds"); - } - this.block.put(address, finalTime); - } else if (this.block.get(address) < finalTime) { - this.block.put(address, finalTime); - } - } - - public void unblockAddress(String address) { - this.block.remove(address); - } - - public Session getSession(String ip, int port) { - String id = ip + ":" + port; - if (!this.sessions.containsKey(id)) { - this.checkSessions(); - Session session = new Session(this, ip, port); - this.sessions.put(id, session); - - return session; - } - - return this.sessions.get(id); - } - - public void removeSession(Session session) throws Exception { - this.removeSession(session, "unknown"); - } - - public void removeSession(Session session, String reason) throws Exception { - String id = session.getAddress() + ":" + session.getPort(); - if (this.sessions.containsKey(id)) { - this.sessions.get(id).close(); - this.sessions.remove(id); - this.streamClose(id, reason); - } - } - - public void openSession(Session session) { - this.streamOpen(session); - } - - public void notifyACK(Session session, int identifierACK) { - this.streamACK(session.getAddress() + ":" + session.getPort(), identifierACK); - } - - public String getName() { - return name; - } - - public long getID() { - return this.serverId; - } - - private void registerPacket(byte id, Packet.PacketFactory factory) { - this.packetPool[id & 0xFF] = factory; - } - - public Packet getPacketFromPool(byte id) { - return this.packetPool[id & 0xFF].create(); - } - - private void registerPackets() { - // fill with dummy returning null - Arrays.fill(this.packetPool, (Packet.PacketFactory) () -> null); - - //this.registerPacket(UNCONNECTED_PING.ID, UNCONNECTED_PING.class); - this.registerPacket(UNCONNECTED_PING_OPEN_CONNECTIONS.ID, new UNCONNECTED_PING_OPEN_CONNECTIONS.Factory()); - this.registerPacket(OPEN_CONNECTION_REQUEST_1.ID, new OPEN_CONNECTION_REQUEST_1.Factory()); - this.registerPacket(OPEN_CONNECTION_REPLY_1.ID, new OPEN_CONNECTION_REPLY_1.Factory()); - this.registerPacket(OPEN_CONNECTION_REQUEST_2.ID, new OPEN_CONNECTION_REQUEST_2.Factory()); - this.registerPacket(OPEN_CONNECTION_REPLY_2.ID, new OPEN_CONNECTION_REPLY_2.Factory()); - this.registerPacket(UNCONNECTED_PONG.ID, new UNCONNECTED_PONG.Factory()); - this.registerPacket(ADVERTISE_SYSTEM.ID, new ADVERTISE_SYSTEM.Factory()); - this.registerPacket(DATA_PACKET_0.ID, new DATA_PACKET_0.Factory()); - this.registerPacket(DATA_PACKET_1.ID, new DATA_PACKET_1.Factory()); - this.registerPacket(DATA_PACKET_2.ID, new DATA_PACKET_2.Factory()); - this.registerPacket(DATA_PACKET_3.ID, new DATA_PACKET_3.Factory()); - this.registerPacket(DATA_PACKET_4.ID, new DATA_PACKET_4.Factory()); - this.registerPacket(DATA_PACKET_5.ID, new DATA_PACKET_5.Factory()); - this.registerPacket(DATA_PACKET_6.ID, new DATA_PACKET_6.Factory()); - this.registerPacket(DATA_PACKET_7.ID, new DATA_PACKET_7.Factory()); - this.registerPacket(DATA_PACKET_8.ID, new DATA_PACKET_8.Factory()); - this.registerPacket(DATA_PACKET_9.ID, new DATA_PACKET_9.Factory()); - this.registerPacket(DATA_PACKET_A.ID, new DATA_PACKET_A.Factory()); - this.registerPacket(DATA_PACKET_B.ID, new DATA_PACKET_B.Factory()); - this.registerPacket(DATA_PACKET_C.ID, new DATA_PACKET_C.Factory()); - this.registerPacket(DATA_PACKET_D.ID, new DATA_PACKET_D.Factory()); - this.registerPacket(DATA_PACKET_E.ID, new DATA_PACKET_E.Factory()); - this.registerPacket(DATA_PACKET_F.ID, new DATA_PACKET_F.Factory()); - this.registerPacket(NACK.ID, new NACK.Factory()); - this.registerPacket(ACK.ID, new ACK.Factory()); - } -} diff --git a/src/main/java/cn/nukkit/raknet/server/UDPServerSocket.java b/src/main/java/cn/nukkit/raknet/server/UDPServerSocket.java index 11aec058495..e69de29bb2d 100644 --- a/src/main/java/cn/nukkit/raknet/server/UDPServerSocket.java +++ b/src/main/java/cn/nukkit/raknet/server/UDPServerSocket.java @@ -1,93 +0,0 @@ -package cn.nukkit.raknet.server; - -import cn.nukkit.utils.ThreadedLogger; -import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.PooledByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelOption; -import io.netty.channel.epoll.Epoll; -import io.netty.channel.epoll.EpollDatagramChannel; -import io.netty.channel.epoll.EpollEventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.DatagramPacket; -import io.netty.channel.socket.nio.NioDatagramChannel; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * author: MagicDroidX - * Nukkit Project - */ -public class UDPServerSocket extends ChannelInboundHandlerAdapter { - - protected final ThreadedLogger logger; - protected Bootstrap bootstrap; - protected Channel channel; - public static final boolean EPOLL = Epoll.isAvailable(); - - protected ConcurrentLinkedQueue packets = new ConcurrentLinkedQueue<>(); - - public UDPServerSocket(ThreadedLogger logger) { - this(logger, 19132, "0.0.0.0"); - } - - public UDPServerSocket(ThreadedLogger logger, int port) { - this(logger, port, "0.0.0.0"); - } - - public UDPServerSocket(ThreadedLogger logger, int port, String interfaz) { - this.logger = logger; - try { - bootstrap = new Bootstrap() - .channel(EPOLL ? EpollDatagramChannel.class : NioDatagramChannel.class) - .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) - .handler(this) - .group(EPOLL ? new EpollEventLoopGroup() : new NioEventLoopGroup()); - this.logger.info("Epoll Status is " + EPOLL); - channel = bootstrap.bind(interfaz, port).sync().channel(); - } catch (Exception e) { - this.logger.critical("**** FAILED TO BIND TO " + interfaz + ":" + port + "!"); - this.logger.critical("Perhaps a server is already running on that port?"); - System.exit(1); - } - } - - public void close() { - bootstrap.config().group().shutdownGracefully(); - if (channel != null) { - channel.close().syncUninterruptibly(); - } - } - - public void clearPacketQueue() { - this.packets.clear(); - } - - public DatagramPacket readPacket() throws IOException { - return this.packets.poll(); - } - - public int writePacket(byte[] data, String dest, int port) throws IOException { - return this.writePacket(data, new InetSocketAddress(dest, port)); - } - - public int writePacket(byte[] data, InetSocketAddress dest) throws IOException { - channel.writeAndFlush(new DatagramPacket(Unpooled.wrappedBuffer(data), dest)); - return data.length; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - this.packets.add((DatagramPacket) msg); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - this.logger.warning(cause.getMessage(), cause); - } -} diff --git a/src/main/resources/lang b/src/main/resources/lang index 49caa033925..e39cdad344e 160000 --- a/src/main/resources/lang +++ b/src/main/resources/lang @@ -1 +1 @@ -Subproject commit 49caa033925b316d6a5738c6cb221253c4f70dc9 +Subproject commit e39cdad344ee2919e619ef352236489f32fb3cde