Haxe externs for server?

One of biggest advantages of haxe language is that developer can compile server and client using same source. And since there is a client for haxe I would like to ask: did someone create haxe externs for server already?

I'm looking to add some pvp into my single player turn based game that is written on haxe, and colyseus seem to be the right thing. It would be really nice to reuse haxe code for server part.

Hi @serjek, that's really interesting, I didn't know that was possible. I'm totally interested in supporting this. If you have an initial implementation I can help you out. Cheers!

@serjek does Haxe have stable support for Node.js externs and some popular HTTP libraries, like express?

@endel hey! sure haxe has node extern library - https://github.com/HaxeFoundation/hxnodejs
also there is lib with externs for express - https://github.com/abedev/hxexpress (a bit outdated though) but it's not a big deal to create/update existing externs with things that one may immediately require in own project. This is how haxe react and haxe react native appeared and supported for example ( https://github.com/haxe-react )

There is still a lot to do in regard of externs for popular libs, but once you start haxefying things you just keep going.

@endel since there no such thing as colyseus externs for server yet, I will start the project here then https://github.com/serjek/colyseus-server-hx

Regarding http, haxe has libraries that are actively developed this very moment but already are production grade, perhaps you will be interested checking them out:

https://haxetink.github.io/tink_http/ (abstract layer)
https://haxetink.github.io/tink_web/ (web router built on tink_http)

@serjek awesome, let me know when you got something working, wanna jump on this as well! :)

about tink_http, I think that's not really useful because Colyseus has been tested only along with Node.js' http module and the express framework.

Hey @endel it seem like colyseus-hx client can not target nodejs/react due to limitations of haxe-ws lib, so I created new client haxe lib that is based on colyseus.js; it's limited to js/nodejs target. It's basically just made of externs that I convert from d.ts.

Also if you have d.ts for colyseus server it would be real quick to create haxe externs out of them as well.

Final goal of my effort is to give me and other haxe developers possibility to always use latest colyseus client and server (and easy to manage if there are api changes) within haxe environment so we could create client-server js/nodejs/react/react-native apps from single source with shared business logic. Perhaps I should keep client and server in single repo that I would call like colyseus-haxe-js-kit, or something. WDYT?

@serjek nice, when you install both colyseus and colyseus.js through npm install, you'll find all .d.ts files inside the node_modules/colyseus/lib and node_modules/colyseus.js/lib directories.

Not sure if I understand why not to use the colyseus-hx project for the client-side. I think there's no need to make externs for the JavaScript client here. If server (Node.js) and client (React.js) are two different applications, the server doesn't need to have the client module as a dependency (colyseus-hx). The client-side would, though, and it's compatible with the browser. The problem would be react-native indeed.

Are you currently wanting to make a react-native app with Colyseus + Haxe?

@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!