Hey there, I just started with a new project, called Horizon.
My goal is to write a fullstack Habbo Emulation (including Gameserver and Webserver / CMS) based on the Java Virtual Machine.
I just started with the Gameserver, which is in really early developement stage.
About the Gameserver:
It's a kind of experiment, to use the Spring Framework for an application like this.
* = I'm really new into TCP/IP communication, wherefore I mostly copied network architecture from other emulators (for yet, I will definitely refactor it to the component based approach).
Some code snippets:
HorizonGameserverApplication.kt (Main):
TcpServer.kt
ClientVariablesEvent.kt
IncomingHandshakePacketHeaderConfig.kt
application.yml (Config) (Packet header will be outsourced, to external "incoming-packets.yml")
I will upload the source code, once I'm satisfied with the base architecture from the emulator.
I will start to work on a CMS, once I got a stable Gameserver.
Many thanks go out to:
- The General for Arcturus, from which I looked up some Netty- and Message related stuff
- Quackster for Kepler, from which I looked up some Netty architecture related stuff
- billsonnn for Nitro, from which I looked up some ClientMessage related stuff and his pre-hosted SWF's which I'm currently using
My goal is to write a fullstack Habbo Emulation (including Gameserver and Webserver / CMS) based on the Java Virtual Machine.
I just started with the Gameserver, which is in really early developement stage.
About the Gameserver:
- Written in Kotlin
- Using Spring Boot (Command Line Runner) as "Lifecycle"
- Using Spring Boot Data JPA as ORM
- Using Netty for Network Communication*
- Component based architechture (made possible by the awesome Spring Dependency Injection Framework)
- Targeting PRODUCTION-201611291003-338511768
It's a kind of experiment, to use the Spring Framework for an application like this.
* = I'm really new into TCP/IP communication, wherefore I mostly copied network architecture from other emulators (for yet, I will definitely refactor it to the component based approach).
Some code snippets:
HorizonGameserverApplication.kt (Main):
Code:
package com.habbo.horizon.gameserver
import com.habbo.horizon.gameserver.console.ConsoleHandler
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.boot.runApplication
[USER=1333374184]sprin[/USER]gBootApplication
[USER=2000035658]Configura[/USER]tionPropertiesScan("com.habbo.horizon.gameserver")
class HorizonGameserverApplication(val consoleHandler: ConsoleHandler) : CommandLineRunner {
override fun run(vararg args: String?) {
this.consoleHandler.start()
}
}
fun main(args: Array<String>) {
runApplication<HorizonGameserverApplication>(*args)
}
TcpServer.kt
Code:
package com.habbo.horizon.gameserver.network
import com.habbo.horizon.gameserver.network.config.NetworkConfig
import com.habbo.horizon.gameserver.network.handler.TcpServerInitializer
import io.netty.bootstrap.ServerBootstrap
import io.netty.buffer.UnpooledByteBufAllocator
import io.netty.channel.ChannelOption
import io.netty.channel.FixedRecvByteBufAllocator
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.logging.LogLevel
import io.netty.handler.logging.LoggingHandler
import org.springframework.stereotype.Component
[USER=744669]CoM[/USER]ponent
class TcpServer(
private val networkConfig: NetworkConfig,
private val tcpServerInitializer: TcpServerInitializer
) {
private val bossGroup = NioEventLoopGroup()
private val workerGroup = NioEventLoopGroup()
init {
this.start()
}
fun start() {
val server = ServerBootstrap()
val tcpServerStatus = server
.group(this.bossGroup, this.workerGroup)
.channel(NioServerSocketChannel::class.java)
.childOption(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.SO_REUSEADDR, true)
.childOption(ChannelOption.SO_RCVBUF, 5120)
.childOption(ChannelOption.RCVBUF_ALLOCATOR, FixedRecvByteBufAllocator(5120))
.childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator(false))
.handler(LoggingHandler(LogLevel.INFO))
.childHandler(this.tcpServerInitializer)
.bind(this.networkConfig.gamePort)
.sync()
if (!tcpServerStatus.isSuccess) {
// TODO: Handle TCPServer Startup Failure
}
}
fun shutdown() {
this.bossGroup.shutdownGracefully()
this.workerGroup.shutdownGracefully()
}
}
ClientVariablesEvent.kt
Code:
package com.habbo.horizon.gameserver.network.messages.incoming.handshake
import com.habbo.horizon.gameserver.network.config.IncomingHandshakePacketHeaderConfig
import com.habbo.horizon.gameserver.network.messages.ClientMessageEvent
import com.habbo.horizon.gameserver.network.messages.NettyRequest
import org.springframework.stereotype.Component
[USER=744669]CoM[/USER]ponent
class ClientVariablesEvent(
private val incomingHandshakePacketHeaderConfig: IncomingHandshakePacketHeaderConfig
) : ClientMessageEvent {
override val headerID: Short
get() = this.incomingHandshakePacketHeaderConfig.clientVariables
override fun read(message: NettyRequest) {
val unknownInt = message.readInt()
val swfsUrl = message.readString()
val gamedataVariablesUrl = message.readString()
// TODO("Check correct swfs & gamedata variables URL")
}
}
IncomingHandshakePacketHeaderConfig.kt
Code:
package com.habbo.horizon.gameserver.network.config
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConstructorBinding
[USER=797832]constructor[/USER]Binding
[USER=2000035658]Configura[/USER]tionProperties(prefix = "horizon.network.incoming-packets.handshake")
data class IncomingHandshakePacketHeaderConfig(
val clientVariables: Short,
val machineID: Short,
val releaseVersion: Short,
val secureLogin: Short
)
application.yml (Config) (Packet header will be outsourced, to external "incoming-packets.yml")
Code:
horizon:
network:
game-port: 30000
incoming-packets:
handshake:
clientVariables: 1053
machineId: 2490
releaseVersion: 4000
secureLogin: 2419
outgoing-packets:
handshake:
machineId: 1488
secureLogin: 2491
I will upload the source code, once I'm satisfied with the base architecture from the emulator.
I will start to work on a CMS, once I got a stable Gameserver.
Many thanks go out to:
- The General for Arcturus, from which I looked up some Netty- and Message related stuff
- Quackster for Kepler, from which I looked up some Netty architecture related stuff
- billsonnn for Nitro, from which I looked up some ClientMessage related stuff and his pre-hosted SWF's which I'm currently using
Last edited: