Haxe externs for server?

@endel Basically yes, my goal is react-native multiplayer app. I currently use haxe as main language and with approach I described above I will be able to have both client and server sources kept in single place so that they can share common logic without any hassle.

colyseus-hx does not fit me because of issues in haxe-ws, specifically it does not support nodejs sockets and compiles js.html socket instead which makes it useless in my case. So as a workaround I use colyseus.js, it's just easier and ensures I always have latest client.

Thanks for pointing me that definitions, I will experiment with d.ts -> hx conversion a bit more and will post my results here.

Status update: I converted ts definitions to haxe (had to include ws definitions as well heheh, but perhaps I can get rid of them later). Simple things are already up and running: register lobby and match handlers on server, message listeners and other basic things. This gives me a positive feeling that more complex things like states will go smooth as well. If you curious about current status please check my repo.

Next step would be converting colyseus-example into haxe to demonstrate that extern lib is actually working. After that I'm going to remove the clutter and contribute in amounts that are required for my specific project, but if anyone would like to join I will be happy to accept the pr.

Just another status update: I got states working with haxe externs! Synthax is very similar to what it should be in TS, check this out:

class MyState extends Schema implements ISchema {
  @:type(NUMBER)
  public var myFloat:Float;

  @:type(STRING)
  public var myString:String;

  public function new() {
    myFloat = 88.99;
    myString = 'hello all!';
  }
} 

note that type parameters are defined in enum, and class should implement ISchema in order to macro autobuild magic to happen; default values can be set in constructor.

Now that I moved to ES6 it allowed some nice simplifications to happen here and there. I will continue to work on this library, but it feels like it has enough features covered already.

Next step would be to port examples. Then I will stick to my pet project as this lib already has all that I possibly might need :P

that's pretty cool @serjek! great job!

Hey, it will be final status update as I feel I'm done with the lib and examples. To cut it short:

  • state sync, including mapping states into MapSchema
  • examples pulled to colyseus-hxjs-examples (I didn't add Auth one because I'm too lazy, but for a developer it should be obvious how to handle this case based on other examples)
  • lib repo renamed to colyseus-hxjs, and cleaned up so there is only lib source remain. I'm not going to publish this as haxelib, as developers are encouraged to use lix instead.
  • there are still things to improve like get rid of Dynamic and untyped script injection where possible.

@endel if you feel this extern lib can be a nice contribution to colyseus, I would transfer them to colyseus group provided you will do the review and leave comments or tickets about what to improve.

This looks cool. I will definitely try this when I'm refactoring again!
I'm a bit confused by the yarn stuff but I guess I need to read up on those.

@mdotedot yarn is to get original colyseus lib, because externs are basically just a middleman who is translating calls from haxe app to original js code underneath.

Unfortunately I didn't get it to work. I'm very new to all this yarn/lix/npm stuff so it could be some stupid mistake.

This is what I did:

Installing HaXe using the github install script from jgranick

/usr/lib/haxe/lib
4.0.0-preview.4+1e3e5e0
  • haxe server.hxml
  • cd bin/server
  • npm i yarn -g
  • yarn
  • node index.js

The index.js contains the register_handler

MainServer.main = function() {
...
        gameServer.register("state_handler",server_rooms_StateHandlerRoom);
...

When I make a change in the src/MainServer.hx file the index.js relfects that change after running haxe server.hxml.

Then I modified the javascript 02-state-handler.html static example to point to new environment:

 var client = new Colyseus.Client('ws://SERVER_THAT_HAS_HAXE_EXTERNS:2567');
 var room = client.join("state_handler");

This is the output on Server-Side console:

node index.js
src/MainServer.hx:40: -- listening on 0.0.0.0:2567... --
MatchMaking couldn't process message: 10,state_handler,[object Object]

What am I missing?!

Looks like the client-side is still on version 0.9, and the server is 0.10. I haven't tried this Haxe setup yet though!

Really nice work @serjek! if you're interested in supporting it, would be nice to move it to the organization, then I give you rights to it :)

When using the 0.10 client it complaints about :

   var room = client.join("state_handler");

Not using new operator.

The same client runs with the npm started 0.10 server just fine.

When I don't start the haxe-extern-server and fire up the client it tells that it can't connect.

So apparently in both 0.9 and 0.10 the client connect works, but the room fails.

Hello guys! first, @mdotedot thanks for trying it out! Let me help you a bit.
First of all, let's say we can simplify the whole setup by doing following steps (assuming we use clean machine with only node and npm installed - you can do this kind of experiment with docker container).

First, we install lix globally. lix is a dependency package manager for haxe and it also allows you to use/download/switch multiple versions of haxe at a time.

npm install lix -g

Then clone the git repo to wherever your projects reside. It's better than downloading zip because it's just faster.

cd ~/Documents/Projects
git clone https://github.com/serjek/colyseus-hxjs-examples.git
cd colyseus-hxjs-examples

Next, note that we need haxe 4.0.0-rc.2 for this because ES6 support came only at rc2 that is newer than preview4. And ES6 support allows haxe compiling js classes instead of functions, that is crucial for state handling in colyseus.

lix use haxe 4.0.0-rc.2

Tell lix to download and use all required haxe libraries, including new colyseus-hxjs.

lix download

After that you are good to compile proper example server, as you have all the stuff you need for haxe side.

haxe server.hxml

Running server is another thing though. For this you will need node (obviously), yarn as it's package manager and original colyseus server library. Npm will certainly do as well, yarn is just my personal preference. For reference: npm and yarn use package.json file to determine dependencies and install them automatically into node_modules folder. node knows about this and references modules to node_modules automatically. You should never commit node_modules and you can always remove and recreate it in case if something isn't right. Now, with yarn you install colyseus to the ./bin/server location:

cd ./bin/server
yarn

After that feel free to run the server that has been compiled into index.js file several steps before:

node index.js

Basically this wraps up the server build and run process. In order to build client from examples (like you don't want to get into original examples but would like to quickly verify it's working) you compile client from project root with

haxe client.hxml

(note that all required haxe libs are already installed)
and then run yarn in ./bin/client. After that you are good to run client(s) with node:

cd ./bin/client
yarn
node index.js

Please let me know if this makes things clearer, I will be happy to help and will update readme accordingly.

@endel I would support those externs of course, should any API change occur, or if you would add new feature, or in case if something left not covered. So yep, if everything is okay for you and you don't see any major flaws then I'm ready for transfer.

Hey Serjek,

Thank you for your detailed steps.
These steps work perfectly together when both client and server are made with haXe.

I'm a bit confused why the externs would not work with, for instance the html demo from colyseus-examples static/02-state-handler.html ...

I need to experiment with pure haXe client to see if that can communicate with the haxe externs.

Thanks for your work. It is appreciated!

@mdotedot oh I understand your concern. I should've added more details on how to run official examples with server build with haxe. So, in order to run those examples you will need to checkout colyseus examples in your projects folder and bundle colyseus client lib:

git clone https://github.com/colyseus/colyseus-examples.git
cd colyseus-examples
npm install
npm run bundle-colyseus-client

Now things are going to be bit complicated since you will need to configure and run your http server to serve client static bundle.

There are multiple options how you can do this, I would recommend nginx server as you can install and run this server as local host, and it's easy to configure as well! Once you start serving those examples you can run the server and verify that clients and server are actually talking. Just make sure that port is the same for client and server and you're good. Let me know if I can help with anything.

Oh and I didn't verify how official haxe client works with latest official server as this is bit out of scope of my current task ;) This is why I created externs for js client as well, because this makes sure that client and server are up to date and compliment each other.

@mdotedot now to think of it. Perhaps static/02-state-handler.html does not work for you because you don't use haxe rc2 to compile server. Thing is that haxe prior to rc2 will still compile the js server code but it will be ES5 javascript. Code generated in this way does not work with states for example; perhaps I need to add some compilation error for this case.

So you need to be sure that js got generated with ES6 features with classes and all that. Check generated index.js - it should contain classes, something like this: class server_rooms_StateHandlerRoom extends colyseus_server_Room