Navigation

  • Recent
  • Tags
  • Users
  • Search
  • Login
Colyseus
  • Login
  • Search
  • Recent
  • Tags
  • Users

Documentation GitHub

We're migrating to GitHub Discussions. This forum does not accept new registrations since April 6, 2023.
  1. Home
  2. TeeTeeHaa
TeeTeeHaa

TeeTeeHaa

@TeeTeeHaa

Chat Follow Unfollow
3
Reputation
14
Posts
1.9k
Profile views
0
Followers
0
Following
Joined 5 Dec 2020, 21:12 Last Online 23 Jan 2022, 13:42

  • Profile
  • More
    • Continue chat with TeeTeeHaa
    • Flag Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups
TeeTeeHaa Follow

Posts made by TeeTeeHaa

C# equivalent of Schema library?

I currently use Colyseus for a TypeScript/browser project and really like it. I especially like its Schema library, because after getting the basic things running (server, client, rooms, state) it is sooooo easy to add (and change and remove) variables which are automatically synchronized from the server to the client.

Can anybody recommend a pure C# library which provides exactly that feature (making adding and changing synchronized variables as easy as possible)?

On its GitHub page Schema lists some libraries under "inspiration" (protocol buffers, flatbuffers, schemapack, avro) but those don't seem to completely provide what I am looking for (only serialization, not the whole incremental delta synchronization).

I am aware that Colyseus has a C#/Unity client but in a project with a C#/Unity client I would prefer a C# server because having the same programming language everywhere makes things easier in my opinion.

posted in General Discussion • 2 Jan 2022, 14:54
preventing client from creating rooms on the server

If your server is fully responsible for the creation and deletion of rooms and the matchmaking of players into them and...
if your server will give the client a room reservation in some way and...
if your client will only connect to the server with a room reservation using client.consumeSeatReservation and...
if you want to prevent any client from ever creating a room on the server and...
if you do not mind to use a dirty workaround...

...you can override the private (D'OH) property exposedMethods of the Server class:

const gameServer = new Server();
const tempServer = gameServer as any; // force access to private property by casting to any
tempServer.exposedMethods = []; // override property with empty array to not expose those methods anymore
gameServer.listen(port);

Yes, it is dirty, it might break in the future, it might not work for you, but it works perfectly for me and it made me giggle maniacally.

posted in Questions & Help • 2 Jun 2021, 21:37
RE: Dynamic Rooms (sovled)

From what I know about Colyseus and Mazmorra they seem to be the perfect fit: Each dungeon floor in Mazmorra is exactly one room in Colyseus, created and deleted by demand. But as far as I know players in different dungeon floors / rooms do not see each other and do not interact with each other - except within the chat, which is a totally different system.

But what about cross-room-interaction?

Let's assume I want to make a MMORPG with a (logically) twodimensional, persistent game world and hundreds of players. Players have a "sight range", both for gameplay and technical reasons. Players only see each other and can interact with each other inside that sight range. Based on that sight range players could technically be "clustered" in some way - maybe rooms, maybe not, maybe something else. In case they are clustered in rooms, maybe even according to predefined areas of the game world, in the simplest case in quadratic areas, there needs to be some interaction/connection between the rooms, because the player being near the border of such an area need to see the players on the other side of the border, at least up to their sight range.

Are there any "best practices" regarding such a scenario?

Currently I use one single room (of Colyseus) for the whole game world, created at server start and deleted at server shutdown, and never ever a second room. Regarding the state synchronization (of Colyseus) including all player data like position for example I currently think about using the filter functions (of Colyseus). But so far I really doubt that this is a great idea, mostly for performance reasons and because those functions might not be intended for that.

I'd really appreciate some suggestions and pros and cons for this scenario.

posted in Questions & Help • 2 Jun 2021, 12:24
RE: Async authoritative turn-based multiplayer in scope for Colyseus? (sovled)

I really like Colyseus and use it for my games with synchronous gameplay. For the game you described, with asynchronous gameplay, I personally would not use Colyseus.

Small definition of terms to avoid misunderstandings:
"synchronous gameplay" means players who are online and playing see each other and can interact with each other instantly.
"asynchronous gameplay" means players go online and play independently from each other, comparable with physical board games with a turn order for players.

If I would make a game which has asychronous gameplay and which has a game client (frontend) and game server (backend) being implemented in JavaScript or TypeScript and the game server is running on node.js...

...I would make the game server a simple HTTP server receiving requests over HTTP POST including "stringified" JSON objects and again sending back "stringified" JSON objects as HTTP responses. As hillarious as it might sound I would start with the "hello world" example on the website of node.js (see here) and start building the game server from there (actually I already did exactly that myself). The game client would simply do HTTP POST requests to the server, with all data required for the game, for example authentication or gameplay inputs, in the POST-part of the request, nicely wrapped as JSON object. The game server would process those requests and send the game state back, again as JSON object. Especially at the beginning of a JavaScript/TypeScript project using JSON is great because it is so simple. Later, if the game gets bigger, either because of growing amount of data or growing amount of players, the JSON could be swapped against something else, for example BSON or MsgPack.

In this scenario any "event" is initiated by the game client and the game server only reacts to those. If this scenario must be extended because the game server wants to initiate an event, for example because one player wants to send a chat message to the another player who might currently be registered as "online", the simplest way would be to use long polling. A friend of mine currently makes an asynchronous game just like that and it is working really good, probably because of the simplicity of the used network technology.

Maybe an asynchronous game can even be made with Colyseus, but from what I know about Colyseus it is not a good fit.

posted in Questions & Help • 2 Jun 2021, 12:06
How to reset callbacks for state changes?

Hello everybody. I have two questions about resetting callbacks for state changes for data based on schema:

#1

Set onChange callback for collection of primitive types based on schema:
https://docs.colyseus.io/state/schema/#onchange-instance-key

room.state.players.onChange = (player, key) => {
    console.log(player, "have changes at", key);
};

Question: How to reset that callback? Is the following correct?

room.state.players.onChange = undefined;

#2

Set listen callback on single property based on schema:
https://docs.colyseus.io/state/schema/#listenprop-callback

state.listen("currentTurn", (currentValue, previousValue) => {
    console.log(`currentTurn is now ${currentValue}`);
    console.log(`previous value was: ${previousValue}`);
});

Question: How to reset that callback? The following does not work (at least not in TypeScript)!

state.listen("currentTurn", undefined); // compiler error, at least in TypeScript

P.S.:
Plenty other features of Colyseus work really fine for me. 👍

posted in Questions & Help • 18 Apr 2021, 17:21
RE: Documentation improvement suggestions

Thank you for your fast and positive response, @endel. I suggest the following additional changes to make the documentation fully consistent within in itself:

send(type, message)
I think this should be:
send(identifier, message)

Send message a type of message to the client.
I think this should be:
Send message with identifier and payload message to the client.

The type can be either a string or a number.
I think this should be:
The identifier can be either a string or a number.

// sending message with string type
I think this should be:
// sending message with string identifier
Because it should be consistent with:
// sending message with number identifier

The green "Tip - See how to handle these messages on client-side." was removed. I'm not sure whether this was intentional. I think it should come back.

posted in General Discussion • 16 Feb 2021, 20:13
Documentation improvement suggestions

https://docs.colyseus.io/server/client/#sendtype-message

send(type, message)

I suggest not to call this "type" because "type" has a meaning in JavaScript/TypeScript (pun intended, proving my point). Maybe call it "messageId", similar to "roomId" or "clientId".

//
// sending message with string type
//
client.send("powerup", { type: "ammo" });

//
// sending message with number type
//
client.send(1, { type: "ammo"});

Regarding { type: "ammo" } I suggest not to call this "type" because of the very same reason and because it currently can be mistaked for the "type" mentioned above. Maybe call it "poweruptype" or "category" or any other synonym for "type".

class MyMessage extends Schema {
  @type("string") message: string;
}

const data = new MyMessage();
data.message = "Hello world!";

client.send(data);

Why does client.send have no "type" (in the sense of "messageId") as the first parameter?

https://docs.colyseus.io/client/room/#onmessage
C# example

class PowerUpMessage {
  string type;
}

room.OnMessage<PowerUpMessage>("powerup", (message) => {
  Debug.Log ("message received from server");
  Debug.Log(message);
});

/**
 * Handling schema-encoded messages:
 */
room.OnMessage("powerup", (message) => {
  if (message is MyMessage)
  {
    Debug.Log ("MyMessage type has been received");
    Debug.Log(message);
  }
  else if (message is AnotherMessage) {
    // ...
  }
});

In both room.OnMessage functions there actually is a "type" (in the sense of "messageId") as first parameter.

In general I am missing TypeScript examples in the client documentation. In the server documentation there are plenty of those.

This being said the whole documentation is quite good in my opinion. Nevertheless there are some details which could be clearer, for example those mentioned here.

posted in General Discussion • 13 Feb 2021, 22:44
RE: Can I extend the Client and the Room class?

I want the code of my own classes for rooms look and work similar both on the client and on the server.

In a Colyseus server the function creating rooms, Server.define, takes a custom room class as argument. That custom class has to extend the server's room class, for example export class MyServerRoom extends Room<MyState>, and is instantiated by Server.define on demand.

export class MyServerRoom extends Room<MyState> { /* ... */ }

Server.define("myserverroom", MyServerRoom, options)

In a Colyseus client the functions creating rooms, Client.joinOrCreate or Client.consumeSeatReservation or the others, do not take a custom class as argument. Instead they instantiate and return (a promise to) the client's room class, Room<MyState>. As far as I know one cannot simply cast this to a custom room class which extends the client's room class.

Client.consumeSeatReservation<MyState>(roomReservation, MyState)
.then((room: Room<MyState>) => { /* ... */ }

The code in my first post tries to overload the client's internal method createRoom to instantiate a custom room class (extending the client's room class), which is then cast "down" to the client's room class and which is then cast "back up" to the custom room class after it is returned by Client.joinOrCreate or Client.consumeSeatReservation.

I assume what I want is Client.joinOrCreate or Client.consumeSeatReservation taking a custom room class (extending the client's room class) as argument and returning an instance of that class (instead of the plain client's room class).

Another thing about similarity: The server's room class has its "room lifecycle" methods, for example onCreate or onLeave, which can be overloaded in a custom class. The client's room class does not have those, but instead has member variables which can be set to callback functions, for example onStateChange or onLeave. That simply is not similar in my opinion - but probably it is like that for good reasons - reasons I do not understand yet.

posted in Questions & Help • 11 Jan 2021, 20:53
Can I extend the Client and the Room class?

Is the following (client-side) code possible?

import * as Colyseus from 'colyseus.js'

export class MyOwnClassExtendingColyseusRoom<T> extends Colyseus.Room<T> {
}

class MyOwnClassExtendingColyseusClient extends Colyseus.Client {

  protected createRoom<T> (roomName: string, rootSchema?: Colyseus.SchemaConstructor<T>) {
    return new MyOwnClassExtendingColyseusRoom(roomName, rootSchema) as Colyseus.Room<T>
  }
}

I am using colyseus.js 0.14.1 and the compiler error message is:

Namespace '"c:/mygame/node_modules/colyseus.js/lib/index"' has no exported member 'SchemaConstructor'.

Bonus question: In case it is possible, is there any good reason against extending those classes?

posted in Questions & Help • 10 Jan 2021, 22:00
RE: Can server-side matchmaking be done in the server's verifyClient?

Hello @endel . I will have a look at that example. Your recommendation regarding an HTTP route for authentication and seat reservation sounds like a better idea than the one I explained above. Thank you for your input. 👍

posted in Questions & Help • 8 Dec 2020, 19:55

© 2023 Endel Dreyer