Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProtocolLib & Fully implement network-part #116

Draft
wants to merge 54 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
a8f8877
build.gradle.kts: registered bedrock-protocol library
alvin0319 Aug 30, 2021
48d3c2d
Fix build failure
alvin0319 Aug 31, 2021
9b7fa8f
WIP
alvin0319 Aug 31, 2021
1517b6e
Revert "WIP"
alvin0319 Aug 31, 2021
e3d9f87
Merge branch 'main' into refactor/protocollib
alvin0319 Sep 1, 2021
3229bd9
Basic implementation of Login handler
alvin0319 Sep 1, 2021
ab2048b
WIP 2
alvin0319 Sep 3, 2021
e400bed
Remove InvalidPacketException
alvin0319 Sep 3, 2021
c610e12
Delete NetworkPacketListener.kt
alvin0319 Sep 3, 2021
8cd2a51
again
alvin0319 Sep 25, 2021
881faa2
Merge branch 'main' into refactor/protocollib
alvin0319 Oct 23, 2021
c6ce544
Merge branch 'main' into refactor/protocollib
alvin0319 Jan 28, 2022
1043f09
Bump protocol version
alvin0319 Jan 28, 2022
18e3f50
Bump protocol library version
alvin0319 Jan 28, 2022
f1bdcfc
Fixed ktlint
alvin0319 Jan 28, 2022
d743993
Server: bump protocol version
alvin0319 Jan 28, 2022
db77ea9
WIP LoginPacketHandler
alvin0319 Jan 28, 2022
577cac9
InventoryManager: Implemented various methods
alvin0319 Jan 28, 2022
bda0fb0
InventoryManager: Implemented all methods
alvin0319 Jan 28, 2022
c8adb00
WIP NetworkSession
alvin0319 Jan 28, 2022
c014a82
NetworkSession: Implemented un-implemented methods
alvin0319 Jan 29, 2022
63c10c6
Form: added handleResponse method
alvin0319 Jan 29, 2022
72c764a
Merge branch 'main' into refactor/protocollib
alvin0319 Jan 29, 2022
8dc1d09
Prepare to ditch built-in protocol packets
alvin0319 Jan 29, 2022
54397dc
Removed all built-in protocol packets
alvin0319 Jan 29, 2022
ec91402
Implemented Batch handler
alvin0319 Jan 29, 2022
f95eb0e
NetworkSession: Implementd (Off)Hand item change
alvin0319 Jan 29, 2022
de01992
KookieToNukkitProtocolConverter: Added missing @JvmStatic annotaion
alvin0319 Jan 29, 2022
2603610
Timings: Added all timings
alvin0319 Jan 29, 2022
b6bde7b
Server: enable timings on ticking
alvin0319 Jan 29, 2022
73d3e1d
Fully implemented NetworkSession
alvin0319 Jan 29, 2022
da71eb6
NetworkSession: uncomment some implemented methods
alvin0319 Jan 29, 2022
8b146c8
WIP Player
alvin0319 Jan 29, 2022
918633f
PerissibleBase: uncomment Timings
alvin0319 Jan 30, 2022
1f5a857
Player: implement PermissibleDelegate
alvin0319 Jan 30, 2022
795974f
Player: uncomment implemented method
alvin0319 Jan 30, 2022
c22fcc8
chore: Added missing license headers
alvin0319 Jan 31, 2022
c2a7631
script: Added copyright script
alvin0319 Jan 31, 2022
76319d0
Updated submodule
alvin0319 Feb 1, 2022
2d785b9
kookie.yml: removed unused settings
alvin0319 Feb 1, 2022
6a3ba4c
Player: Implemented isValidUserName
alvin0319 Feb 1, 2022
ad90dc9
Player: Implemented few methods
alvin0319 Feb 1, 2022
984f4a6
Player: Implemented few methods
alvin0319 Feb 1, 2022
0ce68f5
auto-generated license header
alvin0319 Feb 1, 2022
b5ebbce
Player: fixed Map type
alvin0319 Feb 2, 2022
1c5d59f
Player: Implemented few methods
alvin0319 Feb 3, 2022
f247e6b
Player: inline return statement
alvin0319 Feb 3, 2022
ef8257a
Fixed build failure
alvin0319 Feb 3, 2022
c69c02c
Updated copyright year
alvin0319 Feb 3, 2022
0ab8b36
Implement extra entities (#64)
alvin0319 Feb 5, 2022
5360767
Player: implemented Movement handle process
alvin0319 Feb 5, 2022
fcea092
Merge branch 'refactor/protocollib' of https://github.com/organizatio…
alvin0319 Feb 5, 2022
42df1ec
more stuffs
alvin0319 Feb 5, 2022
48301c7
Implemented IPlayer and OfflinePlayer
alvin0319 Feb 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 14 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* A server software for Minecraft: Bedrock Edition
*
* Copyright (C) 2021 organization Team
* Copyright (C) 2021 - 2022 organization Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -35,6 +35,8 @@ plugins {

val tag = System.getenv("VERSION_TAG") ?: "SNAPSHOT"

val protocolVer = 475 // 1.18

group = "be.zvz"
version = "0.0.1-$tag"
java.sourceCompatibility = JavaVersion.VERSION_1_8
Expand All @@ -50,6 +52,14 @@ repositories {
name = "powernukkit-snapshots"
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
maven {
name = "nukkitx-repo-release"
url = uri("https://repo.nukkitx.com/maven-releases/")
}
maven {
name = "nukkitx-repo-snapshots"
url = uri("https://repo.nukkitx.com/maven-snapshots/")
}
maven {
name = "jitpack"
url = uri("https://jitpack.io")
Expand Down Expand Up @@ -114,6 +124,9 @@ dependencies {
runtimeOnly(group = "io.jsonwebtoken", name = "jjwt-jackson", version = "0.11.2")
implementation(group = "org.whispersystems", name = "curve25519-java", version = "0.5.0")

// Bedrock Protocol
implementation(group = "org.powernukkit.bedrock.protocol", name = "bedrock-v$protocolVer", version = "2.9.4-PN-SNAPSHOT")

// Use the Kotlin test library.
testImplementation(group = "org.jetbrains.kotlin", name = "kotlin-test")

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/be/zvz/kookie/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* A server software for Minecraft: Bedrock Edition
*
* Copyright (C) 2021 organization Team
* Copyright (C) 2021 - 2022 organization Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/be/zvz/kookie/MemoryManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* A server software for Minecraft: Bedrock Edition
*
* Copyright (C) 2021 organization Team
* Copyright (C) 2021 - 2022 organization Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down
165 changes: 104 additions & 61 deletions app/src/main/kotlin/be/zvz/kookie/Server.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* A server software for Minecraft: Bedrock Edition
*
* Copyright (C) 2021 organization Team
* Copyright (C) 2021 - 2022 organization Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -25,6 +25,7 @@ import be.zvz.kookie.console.brightCyan
import be.zvz.kookie.constant.CorePaths
import be.zvz.kookie.constant.FilePermission
import be.zvz.kookie.crafting.CraftingManager
import be.zvz.kookie.event.player.PlayerLoginEvent
import be.zvz.kookie.event.server.CommandEvent
import be.zvz.kookie.event.server.DataPacketSendEvent
import be.zvz.kookie.event.server.QueryRegenerateEvent
Expand All @@ -34,13 +35,9 @@ import be.zvz.kookie.lang.TranslationContainer
import be.zvz.kookie.nbt.tag.CompoundTag
import be.zvz.kookie.network.Network
import be.zvz.kookie.network.mcpe.NetworkSession
import be.zvz.kookie.network.mcpe.NetworkSessionManager
import be.zvz.kookie.network.mcpe.PacketBroadcaster
import be.zvz.kookie.network.mcpe.compression.CompressBatchPromise
import be.zvz.kookie.network.mcpe.compression.Compressor
import be.zvz.kookie.network.mcpe.protocol.ClientboundPacket
import be.zvz.kookie.network.mcpe.protocol.ProtocolInfo
import be.zvz.kookie.network.mcpe.protocol.serializer.PacketBatch
import be.zvz.kookie.network.mcpe.raklib.RakLibInterface
import be.zvz.kookie.network.mcpe.convert.TypeConverter
import be.zvz.kookie.network.query.QueryInfo
import be.zvz.kookie.permission.BanList
import be.zvz.kookie.permission.DefaultPermissions
Expand All @@ -51,7 +48,6 @@ import be.zvz.kookie.plugin.PluginEnableOrder
import be.zvz.kookie.plugin.PluginManager
import be.zvz.kookie.plugin.PluginOwned
import be.zvz.kookie.scheduler.AsyncPool
import be.zvz.kookie.scheduler.AsyncTask
import be.zvz.kookie.timings.Timings
import be.zvz.kookie.timings.TimingsHandler
import be.zvz.kookie.utils.Config
Expand All @@ -65,6 +61,12 @@ import be.zvz.kookie.world.WorldManager
import ch.qos.logback.classic.Logger
import com.koloboke.collect.map.hash.HashObjObjMaps
import com.koloboke.collect.set.hash.HashObjSets
import com.nukkitx.protocol.bedrock.BedrockPacket
import com.nukkitx.protocol.bedrock.BedrockPong
import com.nukkitx.protocol.bedrock.BedrockServer
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler
import com.nukkitx.protocol.bedrock.BedrockServerSession
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475
import org.apache.commons.io.IOUtils
import org.slf4j.LoggerFactory
import java.io.BufferedOutputStream
Expand All @@ -84,7 +86,7 @@ class Server(dataPath: Path, pluginPath: Path) {
val name: String get() = VersionInfo.NAME
val kookieVersion: String = TODO()
val apiVersion: String get() = VersionInfo.BASE_VERSION
val version: String get() = ProtocolInfo.MINECRAFT_VERSION_NETWORK
val version: String get() = currentVersion.minecraftVersion

val ip: String get() = configGroup.getConfigString("server-ip", "0.0.0.0").takeIf { it.isNotBlank() } ?: "0.0.0.0"
val port: Int get() = configGroup.getConfigLong("server-port", 19132).toInt()
Expand Down Expand Up @@ -198,6 +200,10 @@ class Server(dataPath: Path, pluginPath: Path) {

private val broadcastSubscribers: MutableMap<String, MutableSet<CommandSender>> = HashObjObjMaps.newMutableMap()

private val bedrockServer: BedrockServer

val sessionManager: NetworkSessionManager = NetworkSessionManager()

init {
instance = this

Expand Down Expand Up @@ -317,17 +323,55 @@ class Server(dataPath: Path, pluginPath: Path) {
}
}

network.addInterface(
RakLibInterface(
this,
network.getSessionManager(),
InetSocketAddress("0.0.0.0", configGroup.getConfigLong("server-port").toInt())
)
)
bedrockServer = BedrockServer(InetSocketAddress("0.0.0.0", port))
bedrockServer.bind().whenComplete { _, throwable ->
if (throwable != null) {
logger.error("Failed to start server")
throwable.printStackTrace()
return@whenComplete
}
}

bedrockServer.handler = object : BedrockServerEventHandler {

override fun onConnectionRequest(address: InetSocketAddress): Boolean {
return true // TODO: check IP bans
}

override fun onQuery(address: InetSocketAddress): BedrockPong {
val pong = BedrockPong()
pong.edition = "MCPE"
pong.motd = motd
pong.protocolVersion = currentVersion.protocolVersion
pong.version = currentVersion.minecraftVersion
pong.gameType = TypeConverter.protocolGameModeName(GameMode.SURVIVAL) // TODO
pong.playerCount = playerList.size
pong.maximumPlayerCount = maxPlayers
/*
val plugins: MutableList<String> = mutableListOf()
val extraData: MutableMap<String, String> = mutableMapOf()
extraData.put("spliitnum", 0x128.toChar().toString())
extraData.put("hostname", motd) // TODO: Server Name
extraData.put("gametype", TypeConverter.protocolGameModeName(GameMode.SURVIVAL)) // TODO
extraData.put("game_id", "MINECRAFTPE")
extraData.put("version", currentVersion.minecraftVersion)
extraData.put("server_engine", )
extraData.put("plugins", )
*/
// TODO
return pong
}

override fun onSessionCreation(serverSession: BedrockServerSession) {
sessionManager.add(
NetworkSession(this@Server, sessionManager, serverSession)
)
}
}

language.translateString(
KnownTranslationKeys.POCKETMINE_SERVER_START,
listOf(ProtocolInfo.MINECRAFT_VERSION_NETWORK.brightCyan())
listOf(currentVersion.minecraftVersion.brightCyan())
)

thread(isDaemon = true, name = "${VersionInfo.NAME}-console") {
Expand All @@ -337,7 +381,7 @@ class Server(dataPath: Path, pluginPath: Path) {
asyncPool = AsyncPool(
configGroup.getProperty("settings.async-workers").text().run {
var poolSize = 2
if (this ?: "auto" == "auto") {
if ((this ?: "auto") == "auto") {
val processors = Runtime.getRuntime().availableProcessors() - 2

if (processors > 0) {
Expand Down Expand Up @@ -450,7 +494,8 @@ class Server(dataPath: Path, pluginPath: Path) {
}
}

fun isWhitelisted(username: String): Boolean = !hasWhiteList || isOp(username) || whitelist.exists(username.lowercase())
fun isWhitelisted(username: String): Boolean =
!hasWhiteList || isOp(username) || whitelist.exists(username.lowercase())

/**
* Subscribes to a particular message broadcast channel.
Expand Down Expand Up @@ -531,7 +576,7 @@ class Server(dataPath: Path, pluginPath: Path) {
return recipients.size
}

fun broadcastPackets(players: List<Player>, packets: List<ClientboundPacket>): Boolean {
fun broadcastPackets(players: List<Player>, packets: List<BedrockPacket>): Boolean {
if (players.isEmpty() || packets.isEmpty()) return true

Timings.broadcastPackets.time {
Expand All @@ -541,7 +586,8 @@ class Server(dataPath: Path, pluginPath: Path) {
return false
}

val broadcasterTargets: MutableMap<PacketBroadcaster, MutableList<NetworkSession>> = HashObjObjMaps.newMutableMap()
val broadcasterTargets: MutableMap<PacketBroadcaster, MutableList<NetworkSession>> =
HashObjObjMaps.newMutableMap()
ev.targets.forEach { recipient ->
/** TODO: Implements after implementing NetworkSession::getBroadcaster()
* val broadcaster = recipient.getBroadcaster()
Expand All @@ -556,32 +602,6 @@ class Server(dataPath: Path, pluginPath: Path) {
}
}

/** Broadcasts a list of packets in a batch to a list of players */
fun prepareBatch(stream: PacketBatch, compressor: Compressor, sync: Boolean? = null): CompressBatchPromise {
try {
Timings.playerNetworkSendCompress.startTiming()

val buffer = stream.getBuffer()
val promise = CompressBatchPromise()
if (!(sync ?: !(networkCompressionAsync && compressor.willCompress(buffer)))) {
asyncPool.submit(
AsyncTask(
{
promise.resolve(compressor.compress(buffer))
},
Unit
)
)
} else {
promise.resolve(compressor.compress(buffer))
}

return promise
} finally {
Timings.playerNetworkSendCompress.stopTiming()
}
}

fun enablePlugins(type: PluginEnableOrder) {
/** TODO: Implements after implementing PluginManager::getPlugins()
* pluginManager.getPlugins().forEach { plugin ->
Expand Down Expand Up @@ -632,7 +652,31 @@ class Server(dataPath: Path, pluginPath: Path) {
}
}

fun addOnlinePlayer(player: Player) {
fun addOnlinePlayer(player: Player): Boolean {
val ev = PlayerLoginEvent(player, "Plugin reason")
ev.call()
if (ev.isCancelled /* TODO: || !player.isConnected() */) {
// TODO: player.disconnect(ev.kickMessage)
return false
}

val session = player.networkSession
val position = player.getPosition()
logger.info(
language.translateString(
KnownTranslationKeys.POCKETMINE_PLAYER_LOGIN,
listOf(
TextFormat.AQUA + player.name + TextFormat.WHITE,
session.ip,
session.port.toString(),
player.getId().toString(),
position.world!!.displayName,
position.floorX.toString(),
position.floorY.toString(),
position.floorZ.toString()
)
)
)
playerList.values.forEach {
/** TODO: Implements after implementing NetworkSession::onPlayerAdded()
* it.networkSession.onPlayerAdded(player)
Expand All @@ -642,6 +686,7 @@ class Server(dataPath: Path, pluginPath: Path) {
if (sendUsageTicker > 0) {
uniquePlayers.add(player.uuid)
}
return true
}

fun removeOnlinePlayer(player: Player) {
Expand All @@ -668,23 +713,23 @@ class Server(dataPath: Path, pluginPath: Path) {
return
}

// TODO: Timings.serverTick.startTiming()
Timings.serverTick.startTiming()

++tickCounter

Timings.schedulerSync.startTiming()
// TODO: pluginManager.tickSchedulers()
Timings.schedulerSync.startTiming()

// TODO: Timings.schedulerAsync.startTiming()
Timings.schedulerAsync.startTiming()
// TODO: asyncPool.collectTasks()
// TODO: Timings.schedulerAsync.stopTiming()
Timings.schedulerAsync.stopTiming()

// TODO: worldManager.tick(tickCounter)
worldManager.tick(tickCounter)

// TODO: Timings.connection.startTiming()
Timings.connection.startTiming()
// TODO: network.tick()
// TODO: Timings.connection.stopTiming()
Timings.connection.stopTiming()
if ((tickCounter % 20) == 0L) {
if (doTitleTick) {
titleTick()
Expand All @@ -706,22 +751,18 @@ class Server(dataPath: Path, pluginPath: Path) {
}

if ((tickCounter % 100) == 0L) {
/*
TODO:
worldManager.worlds.forEach {
it.clearCache()
worldManager.worlds.forEach { (_, world) ->
world.clearCache()
}

*/

if (ticksPerSecondAverage < 12) {
logger.warn(language.translateString("pocketmine.server.tickOverload"))
}
}

memoryManager.check()

// TODO: Timings.serverTick.stopTiming()
Timings.serverTick.stopTiming()

val now = System.currentTimeMillis()

Expand All @@ -748,5 +789,7 @@ class Server(dataPath: Path, pluginPath: Path) {

@JvmStatic
lateinit var instance: Server

val currentVersion = Bedrock_v475.V475_CODEC
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/be/zvz/kookie/ServerConfigGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* A server software for Minecraft: Bedrock Edition
*
* Copyright (C) 2021 organization Team
* Copyright (C) 2021 - 2022 organization Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/be/zvz/kookie/VersionInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* A server software for Minecraft: Bedrock Edition
*
* Copyright (C) 2021 organization Team
* Copyright (C) 2021 - 2022 organization Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down
Loading