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!

[C#] Project H(S)R - 'Full' R38 Server

Status
Not open for further replies.
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
[C#] [DotNetty] [Fluent NHibernate] [R38] [v9] Project Tornaado

Before flaming and disallowing this thread, first read the following text. (Spoiler because too much text otherwise...)

This project is originally made a WHILE (!) back. I wanted to create a fully oldskool project written from scratch including most of the features available. Alas, I got busy with school and internship, and I had some stress, so features were never made after a certain point. Also, I lost my interest for Habbo, mostly due to the lack of time & the stress. The thread got closed and I didn't really care much, until I started doing some Habbo stuff again. I did 2 releases, one of the being v36 dcrs with more catalogue icons and a v36 server with furnidata matching the database. These 2 things were the start of one project, originally called HSR (Habbo Shockwave Revival), as a way to create the best shockwave stuff.

Of course, the more I used Holo, the more I realised it is pretty crap (No hate Nillus, vista4life, and idkWHOELSEWORKEDONIT), so yeah, I decided to start from scratch. My intention was to use my old source but it was messed up and lost the database so I started over.

I have a bit more time now and no stress so that's why I decided to try this out..

Enough about this, this is the thread of my big project, a full R38 server working for both shockwave as flash, written from scratch in C# (since C# is my best language, I have no intention to learn C/C++/Swift for it and I dislike Java, oh yeah Moogly I KNOW THERE'S ALSO PYTHON!!!), and a full v9 server in Java (because of problems I had with MUS in v9, so camera would be a bit harder). Some tech poop:

- Written from scratch
- C#
- R38 both shockwave and flash
- Using Fluent NHibernate (you can use any DBMS in the future: SQL Server, MySQL, PostgreSQL, ...)
- Using DotNetty
- Configuration in .xml except of .ini
- WeakCache (Thanks Cecer1)
- Intention to complete most of it.


Oh yeah, I've changed; any people who have CONSTRUCTIVE criticism, feel free to let me know (this means: "You shouldn't be doing X because Y" and not "OMFG U USE X SO BAD")

Oh yeah, fun fact: the database will contain relations (unlike most databases out there) as it's much cleaner and if you do it correctly it's much better than getting multiple errors because somebody uses item definition id 1002 when he meant 1001 and 1002 doesn't exist.

More information about te rewrite is on http://forum.ragezone.com/f331/project-r38-server-1118079/index8.html.

Some snippets:

PHP:
public static void BuildSessionFactory()
        {
            var configuration = Fluently.Configure()
                .Database(MySQLConfiguration.Standard.ConnectionString((sb) =>
                {
                    sb.Server("127.0.0.1").Username("root").Password("").Database("tornaado_db");
                }).Raw("hbm2ddl.keywords", "none"))
                .Mappings(m => m.FluentMappings.Add<MemberMap>());
            _sessionFactory = configuration.BuildSessionFactory();

            // following code is used to create all tables for example using the classmaps
            var exporter = new SchemaExport(configuration.BuildConfiguration());
            exporter.Execute(true, true, false);
        }

PHP:
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using System;

namespace Tornaado.Core
{
    public class Configuration
    {
        private XmlDocument _document;
        private Dictionary<string, Dictionary<string, string>> _values;

        public Configuration(string file)
        {
            if (File.Exists(file))
            {
                _document = new XmlDocument();
                _document.Load(file);
                _values = new Dictionary<string, Dictionary<string, string>>();

                CacheValues();
            }
        }

        public void CacheValues()
        {
            foreach (XmlNode categoryNode in _document.GetElementsByTagName("configuration")[0].ChildNodes)
            {
                _values.Add(categoryNode.Name, new Dictionary<string, string>());

                foreach (XmlNode itemNode in categoryNode.ChildNodes)
                {
                    _values[categoryNode.Name].Add(itemNode.Name, itemNode.InnerText);
                }
            }
        }

        public string GetString(string category, string key)
        {
            string value = "";

            return (from kvp
                   in _values
                          where kvp.Key == category && kvp.Value.TryGetValue(key, out value)
                          select value).FirstOrDefault();
        }

        public int GetInt(string category, string key)
        {
            int value = 0;

            return (from kvp
                   in _values
                    where kvp.Key == category && kvp.Value.TryGetValue(key, out string rawval)
                    && int.TryParse(rawval, out value)
                    select value).FirstOrDefault();
        }

        public uint GetUInt(string category, string key)
        {
            uint value = 0;

            return (from kvp
                   in _values
                    where kvp.Key == category && kvp.Value.TryGetValue(key, out string rawval)
                    && uint.TryParse(rawval, out value)
                    select value).FirstOrDefault();
        }

        public static implicit operator bool(Configuration configuration)
        {
            return configuration != null && configuration._document != null && configuration._values != null;
        }
    }
}

PHP:
using DotNetty.Transport.Channels;
using Tornaado.Core;
using System.Text;
using DotNetty.Buffers;
using Tornaado.Utilities.Encoding;
using Tornaado.Game.Clients;
using Tornaado.Communication;

namespace Tornaado.Network.Game
{
    internal class GameNetworkHandler : ChannelHandlerAdapter
    {
        public GameNetworkHandler()
        {
        }

        public override void ChannelActive(IChannelHandlerContext ctx)
        {
            base.ChannelActive(ctx);

            Engine.Game.GameClients.AddNewClient(ctx);

            Log.Debug($"Client connected to client: {ctx.Channel.RemoteAddress.ToString()}");
        }

        public override void ChannelInactive(IChannelHandlerContext ctx)
        {
            base.ChannelInactive(ctx);

            Engine.Game.GameClients.RemoveClient(ctx.Channel.Id);

            Log.Debug($"Client disconnected from client: {ctx.Channel.RemoteAddress.ToString()}");
        }

        public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

        public override void ChannelRead(IChannelHandlerContext ctx, object msg)
        {
            GameClient client = Engine.Game.GameClients.GetClient(ctx);
            var message = msg as IByteBuffer;

            if (message.ReadByte() == 60)
            {
                string policy = "<?xml version=\"1.0\"?>\r\n<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\r\n<cross-domain-policy>\r\n   <allow-access-from domain=\"*\" to-ports=\"1-65535\" />\r\n</cross-domain-policy>\0";
                ctx.Channel.WriteAndFlushAsync(Unpooled.CopiedBuffer(Encoding.Default.GetBytes(policy))).Wait();
            }
            else
            {
                int length = Base64Encoding.Decode(message.ReadBytes(2).ToArray());
                IByteBuffer packet = message.ReadBytes(length);

                Engine.CommunicationHandler.Handle(client, new ClientMessage(packet));
            }

            base.ChannelRead(ctx, msg);
        }
    }
}

PHP:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Tornaado.Core;
using Tornaado.Game.Clients;

namespace Tornaado.Communication
{
    public class CommunicationHandler
    {
        private IDictionary<int, IMessageEvent> message_events;

        public CommunicationHandler()
        {
            message_events = new Dictionary<int, IMessageEvent>();

            // Code to automatically load 
            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                if (type.Namespace.StartsWith("Tornaado.Communication.Incoming") && type.IsDefined(typeof(HabboPacketHeaderAttribute)) && type.GetInterfaces().Contains(typeof(IMessageEvent)))
                {
                    HabboPacketHeaderAttribute attr = type.GetCustomAttribute(typeof(HabboPacketHeaderAttribute)) as HabboPacketHeaderAttribute;
                    IMessageEvent message_event = type.GetConstructor(Type.EmptyTypes).Invoke(new object[] { }) as IMessageEvent;
                    message_events.Add(attr.Header, message_event);
                }
            }

            Log.Info($"Loaded {message_events.Count} message events.");
        }

        public void Handle(GameClient client, ClientMessage request)
        {
            if (message_events.TryGetValue(request.Header, out IMessageEvent message_event))
                message_event.InvokeHandler(client, request);
            else
                Log.Debug($"[{request.Header}] Unregistered handler -> {request.ToString()}.");
        }
    }
}

PHP:
using System;
using Tornaado.Game.Clients;

namespace Tornaado.Communication.Incoming.Handshake
{
    [HabboPacketHeader(206)]
    class InitCryptoMessageEvent : IMessageEvent
    {
        public void InvokeHandler(GameClient client, ClientMessage request)
        {

        }
    }
}

PHP:
using NHibernate;
using NHibernate.Criterion;
using Tornaado.Core;
using Tornaado.Models;
using Tornaado.Utilities.Bluedot;

namespace Tornaado.Game
{
    public class GameMembers
    {
        public WeakCache<int, Member> MembersById { get; }
        public WeakCache<string, Member> MembersByName { get; }

        public GameMembers()
        {
            MembersById = new WeakCache<int, Member>((id) => GetMemberById(id));
            MembersByName = new WeakCache<string, Member>((name) => GetMemberByName(name));
        }

        private Member GetMemberById(int id)
        {
            Member member;

            using (ISession session = Engine.SessionFactory.OpenSession())
            {
                member = session.Get<Member>(id);
            }

            return member;
        }

        private Member GetMemberByName(string name)
        {
            Member member;

            using (ISession session = Engine.SessionFactory.GetCurrentSession())
            {
                member = session.CreateCriteria<Member>().Add(Restrictions.Eq("name", name)).UniqueResult<Member>();
            }

            return member;
        }
    }
}

Another note: I won't put this project on Github/Gitlab/any git platform. The only reason is me being lazy to update the git project etc. This project will be put onto a git platform when the first release is out (NOT the ALPHA/BETA). This way, anybody who wants can fork the project and work on it, or even use the project and make it work for example on the latest release. I'll put snippets here though. If you want to see how I've done something, you can
ask me and I can make a snippet out of it, no problem.

PLEASE NOTE: I won't be using any queries, don't come here with anything about queries: everything is done with the mapping. Thanks.

Also, screenies will be added again soon as this is a rewrite I don't have the functionality anymore I used to have.
 
Last edited:
git bisect -m
Loyal Member
Joined
Sep 2, 2011
Messages
2,171
Reaction score
916
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

OH MY HEARTH. Are you kidding me Glaceon?
OMG that's just amazing.
I feel the nostalgia coming. I FEEL THE NOSTALGIA.

---
Good work Glaceon, with your development skills i think this will be a success.
I wish the best for this development. And please keep it alive!
Finally something useful. And it's Habbo Beta. That mean.. FLASH wigga.
That's the nearest thing with Oldschool and compatible with newest navigators.

---
If i can be useful for something, tell me.
And i'm dreaming with the community project, oh gosh.
Maybe we do a HTML client for this.
Habbo Beta had a very clean design/client.

Best wishes,
Claudio



Technical stuff:
1. Why not ORM?
2. Why not NHibernate (first question)
3. Caching system? SuperSocket? Socket in C++? DotNetty?
4. Log4Net?
5. REST?
6. Security? How?
7. Prepared Statements? Transactions?
 
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

Technical stuff:
1. Why not ORM?
2. Why not NHibernate (first question)
3. Caching system? SuperSocket? Socket in C++? DotNetty?
4. Log4Net?
5. REST?
6. Security? How?
7. Prepared Statements? Transactions?

1/2. I wasn't originally going to use it, but I might consider switching to Fluent NHibernate
3. What do you mean exactly? Caching system? And I tried SuperSocket once but I didn't understand much of it. I have no intention of learning any more C++ at this moment, and I don't know much about DotNetty. How good is it compared to SAEA?
4. I could implement this, but at the other side, there won't be much logs at the final release so I don't see a big need for it.
5. Haven't thought about that, you mean for CMS-Server connections?
6. What are you trying to ask?
7. No transactions, but if I switch to Fluent NHibernate no need for it anymore.

And no help is needed, UNLESS you can do one of these things:

- Help me crack the encryption
- Reverse engineer the DCR/CCT files

Cheers.
 
Joined
Aug 10, 2011
Messages
7,399
Reaction score
3,307
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

Wait you are going to waste time on relations for a database that doesnt even have the Check constraint implemented?

Also statistically speaking this emulator doesnt get past room loading but I got my hopes up xD

Not sure what the Java part is. Could have read past it. Its 3:34AM. Think we should just sleep Glaceon lol

Edit: Does V39 have snowstorm?
 
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

The General true, didn't think of that first. The Java part is for the older versions (v13, v26, v1, ...) and I like to keep the same thread title format. No, v39 doesn't have snowstorm (flash doesn't, shockwave does if I remember correctly.

-- EDIT:

No, I don't get the Java part either, guess I made the topic thread before deciding which project I was going to focus on.
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,688
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

Yes, we need a beta server, I've not seen many of these :):

Please keep us up to date I really like the early swf revisions.
 
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

Proof shockwave works (almost) as good:

lqymXZG - [C#] Project H(S)R - 'Full' R38 Server - RaGEZONE Forums

Furniture don't load because the sprite index hasn't been sent yet (as this isn't needed in Flash and I was focusing on Flash). Besides that, no need to edit furnidata because it's generated automatically (maybe will do that too with the productdata):

PHP:
<?php

// Creates items array
$items = array();

// Open MySQLi connection
$mysqli = mysqli_connect('localhost', 'root', '123', 'hr_v38');

// Get items results and their dynamic_items row
$getItems = mysqli_query($mysqli, 'SELECT * FROM `furniture_templates`');
					   
// Loop over all items
while ($item = mysqli_fetch_assoc($getItems))
{	
	$item = array($item['sprite_type'], $item['id'], $item['sprite'], 1337, '0', $item['length'], $item['width'], $item['color'], '', '', '');
	
	// Push the item in the items array
	array_push($items, $item);
}

// Encode the items array to json
echo json_encode($items);

?>

Now I only have to make a script so I can generate furniture templates for every item available so I don't have to add all entries in MySQL myself.

Oh yeah, a Flash screenie I forgot (badges):

zDvpMwD - [C#] Project H(S)R - 'Full' R38 Server - RaGEZONE Forums

All left to do is change the state of badges (wear/unwear) and then it's done for that part. Everything is loaded from the database and a big thanks to Nillus for the structure of navigator categories in shockwave.

Also, if anybody has time I'd appreciate it if somebody can help me with encryption. v31?/v34-v39 shockwave didn't really have forced encryption but the loading bar didn't load 100% until the encryption was done correctly. Also, using encryption is neater, though I have no experience with encryption in Habbo.

-- UPDATE
vista4life you know how I am with encryption:sleep:

-- UPDATE 2
Also, if anybody has some experience with reverse engineering the client files I'd appreciate it if I can get some help. If you don't wanna share your method or anything, helping with BB and SS packets is enough.

-- UPDATE 3
And this is how the catalogue looks in shockwave when 2 packets are sent with just one int 0...
1Wdd7U - [C#] Project H(S)R - 'Full' R38 Server - RaGEZONE Forums
 

Attachments

You must be registered for see attachments list
Last edited:
git bisect -m
Loyal Member
Joined
Sep 2, 2011
Messages
2,171
Reaction score
916
Re: [C#/Java] Project H(S)R - 'Full' R38 Server

1/2. I wasn't originally going to use it, but I might consider switching to Fluent NHibernate
3. What do you mean exactly? Caching system? And I tried SuperSocket once but I didn't understand much of it. I have no intention of learning any more C++ at this moment, and I don't know much about DotNetty. How good is it compared to SAEA?
4. I could implement this, but at the other side, there won't be much logs at the final release so I don't see a big need for it.
5. Haven't thought about that, you mean for CMS-Server connections?
6. What are you trying to ask?
7. No transactions, but if I switch to Fluent NHibernate no need for it anymore.

And no help is needed, UNLESS you can do one of these things:

- Help me crack the encryption
- Reverse engineer the DCR/CCT files

Cheers.

1. Yes Fluent NHibernate it's a good choice.
3. Caching System for Models. NHibernate does the basics about this. Need something more powerful.
4. SuperSocket its hard... DotNetty it's a C# port of Java Netty, it's a reactive library. It's so much powerful and good. Easy to use. I implemented it on Yupi. Already in the OLD version of Yupi.. ( )
5. Yeah, for initial scenario, i was thinking about SSO being from REST between server and client
6. About Encryption. Would you implement Habbo Encryption? Why not just use Joopie's Habbo Encryption. You will be all set.. Oh no forget, Habbo Beta encryption it's to much different. Use Nillus ION/Deltar. It's the encryption of that time.
Link.: http://forum.ragezone.com/f353/ion-deltar-ion16-habbo-hotel-746450/
I can try help with security/encryption and decompiling swf/cracking it/searching packets. But i can't do it now, i'm using OS X.. Need setup a Virtual Machine with Windows..
7. Okay, no Transactions. But Fluent NHibernate will do everything.
4 (again). Log4net will be useful. If i remember the full debug logs of NHibernate are just massive. You can't understand what is happening. It's to much messages.

Also will you use reverse database engineering provided by Hibernate?



Ups. I provided wrong ION/Deltar version. I can't find the right. Maybe lost in the internet.
 
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
@saamus ION/Deltar had no encryption, the 'encryption' implemented wasn't finished and incorrect. Also, I have no clue how much different the shockwave encryption is from the flash encryption. I don't get your point of the SSO with rest, please explain better. You don't need a Windows VM to do some research, I can give you the scripts (not atm since I don't have my virtual machine on I develop on since I can only use my work/school laptop as my other one is broken as duck) later.
 
git bisect -m
Loyal Member
Joined
Sep 2, 2011
Messages
2,171
Reaction score
916
@saamus ION/Deltar had no encryption, the 'encryption' implemented wasn't finished and incorrect. Also, I have no clue how much different the shockwave encryption is from the flash encryption. I don't get your point of the SSO with rest, please explain better. You don't need a Windows VM to do some research, I can give you the scripts (not atm since I don't have my virtual machine on I develop on since I can only use my work/school laptop as my other one is broken as duck) later.

I will love scripts that are Linux compatible. I don't know if exists a RABDASM Linux compatible. Give me the scripts and the Habbo.swf and i do my research about the encryption inside Habbo.swf

But what exactly you need. Did you already cracked the SWF or not? If not, i need also research how the crack works in Habbo Beta revision. It's a lot of research.

I will be glad helping you.
I paused Yupi for a little, since the other debs are so much busy.
I can help a little you, but i need make clear that i don't have so much time.

Good luck.
 
Last edited by a moderator:
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,688
Don't waste your time with encryption early on in development, this is something that you can leave until later as it's not like it requires an entire rewrite of the server :p:
 
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
@Quackster true, although I can't figure it out (since I don't understand anything of it) so if I can get somebody to figure it out for me I can work in the meantime on the emulator. If I have to figure out it on my own, I'll most likely do this at a later stage, yes.

saamus you need to edit something in the SWF or just view the SWF? But as far as I remember RABCDASM is written in D which is multiplatform. As for cracking, I don't know if you need to crack anything that has to do with the encryption but besides that you don't need to crack anything as it doesn't have like IP/images protection. I will give you the scripts later as now I'm too busy on my XBOX One :p
 
git bisect -m
Loyal Member
Joined
Sep 2, 2011
Messages
2,171
Reaction score
916
Okay Glaceon, waiting for your scripts.
I want to view first at all the ActionScript files. and if necessary edit something.
Idk if the Habbo Beta already uses RSA encryption.
Need to check exactly how it's coded.
I ever don't know if need to do RC4 patch.
 
Custom Title Activated
Loyal Member
Joined
Oct 26, 2012
Messages
2,357
Reaction score
1,086
The General you got a point there. I won't be 100% focusing on it myself though. The encryption isn't necessary in order to enter rooms and buy items etc. The main game is though. First comes the basic functionality, then extras such as achievement, games and encryption.
 
Status
Not open for further replies.
Back
Top