-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e26e33b
Showing
15 changed files
with
487 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ | ||
/.swiftpm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"object": { | ||
"pins": [ | ||
{ | ||
"package": "Rainbow", | ||
"repositoryURL": "https://github.com/onevcat/Rainbow", | ||
"state": { | ||
"branch": null, | ||
"revision": "626c3d4b6b55354b4af3aa309f998fae9b31a3d9", | ||
"version": "3.2.0" | ||
} | ||
}, | ||
{ | ||
"package": "swift-log", | ||
"repositoryURL": "https://github.com/apple/swift-log.git", | ||
"state": { | ||
"branch": null, | ||
"revision": "173f567a2dfec11d74588eea82cecea555bdc0bc", | ||
"version": "1.4.0" | ||
} | ||
}, | ||
{ | ||
"package": "swift-nio", | ||
"repositoryURL": "https://github.com/apple/swift-nio.git", | ||
"state": { | ||
"branch": null, | ||
"revision": "c3e2359c55cd8b47207ab7363b77c9c398a95294", | ||
"version": "2.23.0" | ||
} | ||
} | ||
] | ||
}, | ||
"version": 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// swift-tools-version:5.3 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "Swiftcraft", | ||
platforms: [ | ||
.macOS(.v10_10), | ||
], | ||
products: [ | ||
.executable(name: "Swiftcraft", targets: ["Swiftcraft"]), | ||
.library(name: "SwiftcraftLibrary", targets: ["SwiftcraftLibrary"]), | ||
], | ||
dependencies: [ | ||
// Dependencies declare other packages that this package depends on. | ||
// .package(url: /* package url */, from: "1.0.0"), | ||
|
||
.package(url: "https://github.com/onevcat/Rainbow", from: "3.0.0"), | ||
.package(url: "https://github.com/apple/swift-nio.git", from: "2.23.0"), | ||
.package(url: "https://github.com/apple/swift-log.git", from: "1.4.0"), | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package. A target can define a module or a test suite. | ||
// Targets can depend on other targets in this package, and on products in packages this package depends on. | ||
.target( | ||
name: "Swiftcraft", | ||
dependencies: [ | ||
.product(name: "Logging", package: "swift-log"), | ||
.product(name: "NIO", package: "swift-nio"), | ||
"Rainbow", | ||
"SwiftcraftLibrary", | ||
] | ||
), | ||
.target( | ||
name: "SwiftcraftLibrary", | ||
dependencies: [ | ||
.product(name: "Logging", package: "swift-log"), | ||
.product(name: "NIO", package: "swift-nio"), | ||
"Rainbow", | ||
] | ||
), | ||
.testTarget( | ||
name: "SwiftcraftLibraryTests", | ||
dependencies: [ | ||
"SwiftcraftLibrary", | ||
.product(name: "NIO", package: "swift-nio"), | ||
] | ||
), | ||
.testTarget( | ||
name: "SwiftcraftTests", | ||
dependencies: [ | ||
"Swiftcraft", | ||
.product(name: "NIO", package: "swift-nio"), | ||
] | ||
), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Swiftcraft | ||
|
||
Swiftcraft is a swift implementation of the Minecraft Server. The goal of this project is to provide a fast resource efficient Minecraft server. | ||
**This is an active WIP.** Currently in the first steps of implementing the Minecraft Protocol. | ||
You should expect massive amounts of refactoring. | ||
|
||
## Protocol | ||
|
||
This server is built from the ground up implementing [Minecraft's Protocol.](https://wiki.vg/Protocol) | ||
|
||
## Credits | ||
|
||
I would like to give a huge shoutout to #mcdevs for their working in maintaining [Wiki.vg](wiki.vg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import Foundation | ||
import NIO | ||
import SwiftcraftLibrary | ||
import Rainbow | ||
|
||
// seed linux random number | ||
#if os(Linux) | ||
srand(UInt(time(nil))) | ||
#endif | ||
|
||
signal(SIGINT) {_ in | ||
if (server.isRunning == true) { | ||
server.shutdown() | ||
} | ||
exit(0) | ||
} | ||
|
||
print("Welcome to Swiftcraft!".green) | ||
|
||
let host = "127.0.0.1" | ||
let port = 25564 | ||
|
||
var server = Server(host: host, port: port) | ||
|
||
defer { | ||
server.shutdown() | ||
} | ||
|
||
do { | ||
try server.run() | ||
} catch let error { | ||
print(error) | ||
print("Shutting down server due to fatal error") | ||
server.shutdown() | ||
} | ||
|
||
print("Server closed") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// | ||
// DataTypes.swift | ||
// Swiftcraft | ||
// | ||
// Created by Marz Rover on 11/21/20. | ||
// | ||
|
||
import Foundation | ||
import NIO | ||
|
||
typealias Byte = UInt8 | ||
typealias ByteArray = [Byte] | ||
|
||
enum VarIntError: Error { | ||
case varIntIsTooBig | ||
} | ||
|
||
enum VarLongError: Error { | ||
case varLongIsTooBig | ||
} | ||
|
||
extension Int32 { | ||
init(buffer byteBuffer: inout ByteBuffer) throws { | ||
self.init() | ||
var result: Self = 0 | ||
var shift = 0 | ||
var input: Byte | ||
repeat { | ||
input = Byte(byteBuffer.readBytes(length: 1)![0]) | ||
result |= Self((input & Byte(0x7F)) << (shift * 7)) | ||
shift += 1 | ||
if (shift > 5) { | ||
throw VarIntError.varIntIsTooBig | ||
} | ||
} while ((input & 0x80) != 0x80) | ||
self = result | ||
} | ||
|
||
var varInt: ByteArray { | ||
var out: ByteArray = [] | ||
var part: Byte | ||
var value = self | ||
repeat { | ||
part = Byte(value & 0x7F) | ||
value >>= 7 | ||
if (value != 0) { | ||
part |= 0x80 | ||
} | ||
out.append(part) | ||
} while (value == 0) | ||
return out | ||
} | ||
} | ||
|
||
extension Int64 { | ||
init(buffer byteBuffer: inout ByteBuffer) throws { | ||
self.init() | ||
var result: Self = 0 | ||
var shift = 0 | ||
var input: Byte | ||
repeat { | ||
input = Byte(byteBuffer.readBytes(length: 1)![0]) | ||
result |= Self((input & Byte(0x7F)) << (shift * 7)) | ||
shift += 1 | ||
if (shift > 10) { | ||
throw VarLongError.varLongIsTooBig | ||
} | ||
} while ((input & 0x80) != 0x80) | ||
self = result | ||
} | ||
|
||
var varLong: ByteArray { | ||
var out: ByteArray = [] | ||
var part: Byte | ||
var value = self | ||
repeat { | ||
part = Byte(value & 0x7F) | ||
value >>= 7 | ||
if (value != 0) { | ||
part |= 0x80 | ||
} | ||
out.append(part) | ||
} while (value == 0) | ||
return out | ||
} | ||
} | ||
|
||
extension String { | ||
init(buffer: inout ByteBuffer) throws { | ||
self.init() | ||
let length = Int(try! Int32(buffer: &buffer)) | ||
self = buffer.readString(length: length)! | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
Sources/SwiftcraftLibrary/Networking/Handlers/HandshakeHandler.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import NIO | ||
|
||
public final class HandshakeHandler: ChannelInboundHandler { | ||
public typealias InboundIn = ByteBuffer | ||
public typealias OutboundOut = ByteBuffer | ||
|
||
public func channelActive(context: ChannelHandlerContext) { | ||
debug("Active connection at \(context.remoteAddress!)") | ||
} | ||
|
||
public func channelInactive(context: ChannelHandlerContext) { | ||
debug("Inactive connection at \(context.remoteAddress!)") | ||
} | ||
|
||
public func channelRegistered(context: ChannelHandlerContext) { | ||
debug("Registered connection at \(context.remoteAddress!)") | ||
} | ||
|
||
public func channelUnregistered(context: ChannelHandlerContext) { | ||
debug("Unregistered connection at \(context.remoteAddress!)") | ||
} | ||
|
||
public func channelRead(context: ChannelHandlerContext, data: NIOAny) { | ||
// As we are not really interested getting notified on success or failure we just pass nil as promise to | ||
// reduce allocations. | ||
// context.write(data, promise: nil) | ||
/// The last three bytes of the handshake buffer are used for an Unsigned Short and a VarInt [source](https://wiki.vg/Protocol#Handshake) | ||
/// Up to 1023 bytes before the last three are used for String (255) preceded with a VarInt of how many bytes | ||
/// The first set of bytes is a VarInt | ||
var byteBuffer = self.unwrapInboundIn(data) | ||
try! print(Int32(buffer: &byteBuffer)) | ||
try! print(String(buffer: &byteBuffer)) | ||
|
||
} | ||
|
||
// Flush it out. This can make use of gathering writes if multiple buffers are pending | ||
public func channelReadComplete(context: ChannelHandlerContext) { | ||
context.flush() | ||
} | ||
|
||
public func channelWritabilityChanged(context: ChannelHandlerContext) { | ||
debug("Writability changed at \(context.remoteAddress!)") | ||
} | ||
|
||
public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) { | ||
debug("User \(context.remoteAddress!)") | ||
debug("Event \(event)") | ||
} | ||
|
||
public func errorCaught(context: ChannelHandlerContext, error: Error) { | ||
print("error: ", error) | ||
|
||
// As we are not really interested getting notified on success or failure we just pass nil as promise to | ||
// reduce allocations. | ||
context.close(promise: nil) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// | ||
// Server.swift | ||
// Swiftcraft | ||
// | ||
// Created by Marz Rover on 11/17/20. | ||
// | ||
|
||
import Foundation | ||
import NIO | ||
|
||
open class Server { | ||
public var isRunning: Bool | ||
public var host: String | ||
public var port: Int | ||
public var channel: Channel? | ||
|
||
public let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) | ||
|
||
public var bootstrap: ServerBootstrap { | ||
ServerBootstrap(group: group) | ||
// Specify backlog and enable SO_REUSEADDR for the server itself | ||
.serverChannelOption(ChannelOptions.backlog, value: 256) | ||
.serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) | ||
|
||
// Set the handlers that are appled to the accepted Channels | ||
.childChannelInitializer { channel in | ||
// Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline. | ||
channel.pipeline.addHandler(BackPressureHandler()).flatMap { v in | ||
channel.pipeline.addHandler(HandshakeHandler()) | ||
} | ||
} | ||
|
||
// Enable SO_REUSEADDR for the accepted Channels | ||
.childChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) | ||
.childChannelOption(ChannelOptions.maxMessagesPerRead, value: 16) | ||
.childChannelOption(ChannelOptions.recvAllocator, value: AdaptiveRecvByteBufferAllocator()) | ||
} | ||
|
||
public init(host: String, port: Int) { | ||
self.isRunning = true | ||
self.host = host | ||
self.port = port | ||
} | ||
|
||
public func run() throws { | ||
self.channel = try { () -> Channel in | ||
return try self.bootstrap.bind(host: self.host, port: self.port).wait() | ||
}() | ||
|
||
print("Server started and listening on \(channel!.localAddress!)") | ||
|
||
// This will never unblock as we don't close the ServerChannel | ||
try channel!.closeFuture.wait() | ||
} | ||
|
||
public func shutdown() { | ||
do { | ||
try self.group.syncShutdownGracefully() | ||
} catch let error { | ||
print(error) | ||
print("Forcing exit") | ||
exit(1) | ||
} | ||
print("Server Shutdown") | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
Sources/SwiftcraftLibrary/SwiftcraftLibrary-Bridging-Header.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// | ||
// Use this file to import your target's public headers that you would like to expose to Swift. | ||
// | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// | ||
// SwiftcraftLibrary.swift | ||
// Swiftcraft | ||
// | ||
// Created by Marz Rover on 12/2/20. | ||
// | ||
|
||
import Foundation | ||
|
||
public func debug(_ object: Any) { | ||
#if DEBUG | ||
Swift.print(object) | ||
#endif | ||
} |
Oops, something went wrong.