Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Project Horizon - Fullstack JVM Habbo Emulation

Newbie Spellweaver
Joined
Dec 20, 2010
Messages
14
Reaction score
6
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:
  • 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:
Junior Spellweaver
Joined
Jan 28, 2013
Messages
157
Reaction score
104
Sulake uses Spring for their server as well, so this should be interesting. Good luck with your project! I'm here if you need any assistance, I'm not the best with Java but I know my packets.
 
Experienced Elementalist
Joined
Jul 5, 2006
Messages
262
Reaction score
193
Interesting use of Spring Boot. That's more suited for web applications than "game servers".
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,688
Looks alright I guess, there really isn't much done for me to fully conceptualise how this project will go but I'm happily awaiting for future updates. Thanks for crediting me. :love:
 
Joined
Jun 23, 2010
Messages
2,318
Reaction score
2,195
Interesting use of Spring Boot. That's more suited for web applications than "game servers".

Technically not. Spring originates as an alternative from the strange butt enterprise apis Java has. Those apis require fair bit of boilerplate code to get it working. Spring wanted developers to focus on the application itself. Yes spring is used it a lot of web applications. But it is surely suited for other types of applications too.

I'm curious to see how this development goes. OP what version are you aiming at?
 
Experienced Elementalist
Joined
Jul 5, 2006
Messages
262
Reaction score
193
Technically not. Spring originates as an alternative from the strange butt enterprise apis Java has. Those apis require fair bit of boilerplate code to get it working. Spring wanted developers to focus on the application itself. Yes spring is used it a lot of web applications. But it is surely suited for other types of applications too.

I'm curious to see how this development goes. OP what version are you aiming at?

I specifically mention Spring Boot not Spring. Spring Boot uses Tomcat by default, a web application server. Using other parts of the Spring framework however like the DI sure, but it isn't fast.
 
Joined
Jun 23, 2010
Messages
2,318
Reaction score
2,195
Spring Boot allows you to add starters, which basicly means each starter you add can auto configure itself. The Spring Boot starter for Web (spring-boot-starter-web) uses Tomcat by default.
 
Back
Top