Git Product home page Git Product logo

thnk's Introduction

๐Ÿค” THNK

The THNK Framework Banner

An authoritative multiplayer games framework for the FLOSS engine GDevelop.

Links

Contributors

Thanks to all the contributors to THNK! Here is the full list of all contributors of all kinds to the project:

All Contributors

Ko-fi contributors
Ko-fi contributors

๐Ÿ’ต
Arthur Pacaud
Arthur Pacaud

๐Ÿšง ๐Ÿ’ป ๐Ÿ“– ๐Ÿ“
Rinax
Rinax

๐Ÿ›
Leo_Red
Leo_Red

๐ŸŽจ
Tim
Tim

๐Ÿ“–
triloute
triloute

๐Ÿ“–
Emily Lemonly
Emily Lemonly

๐Ÿ“–
dartpk
dartpk

๐Ÿ› ๐Ÿ’ป

Contributing

Installing

To install all dependencies, run yarn. You may use npm, but note that only a yarn lockfile will be provided and accepted in PRs. If you have disabled postinstall scripts, run yarn generate-protocol to run the code generator on the flatbuffer files.

Building

Run yarn build to execute the full build pipeline. You can also build individual parts with the other build scripts in package.json:

Building THNK with yarn build:thnk and the adapters with yarn build:adapters outputs a bundle to the dist folder. yarn build:extensions automatically inserts those into the THNK extensions in extensions.

To test your changes, import the extension with your changes into GDevelop. If you make changes to the extension itself, don't forget to export it back to the extensions folder.

Submitting changes

Before submitting a PR, make sure that your code builds & fully functions within the extension, and that it passes both typescript & jest tests. Run yarn ts && yarn test to run both checks. Make sure the extensions in extensions are properly generated with the latest version of your code. In case of doubts, run yarn build again before committing.

Understanding the file structure

There are a few main folders that you need to keep in mind while contributing:

  • extensions - Contains the GDevelop extensions files. While most of the important code is in code, the extensions themselves need to be modified to add actions, conditions, etc. You also need them to actually use the built THNK code.
  • protocol - Contains FlatBuffers protocol definitions. Anything that transits between the server and client must be defined through a FlatBuffer ServerMessage or ClientMessage, depending on which side will be sending that message.
    • After changing a file there, you need to run yarn generate-protocol to run codegen for the FlatBuffers files before using the modified interfaces in code
  • types - GDJS type definitions. They were generated automatically with TSC.
  • docs - The docusaurus website and documentation.
  • scripts - A few scripts used for building.
  • code - Contains all the THNK extension's typescript code. All imports are relative to this directory: import "server"; would import code/server.
    • server - All the server-relevant code.
    • client - All the client-relevant code.
    • adapters - Contains the different adapters' implementations.
    • types - Useful type definitions: global.d.ts defines the THNK global namespace and thnk.d.ts overrides GDevelop type definitions with the additional properties THNK adds.
    • utils - Misc. Code that is relevant for both server and client.

thnk's People

Contributors

allcontributors[bot] avatar arthuro555 avatar dartpk avatar emilylemonly avatar entr0py404 avatar triloute avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

thnk's Issues

Internal unreliability compensation

Packets on the network get dropped. That is problematic if a packet containing a an update to a state that is not updated often is lost, as that makes this state remain in an outdated invalid state for long. THNK must include a mechanism to ACK received updates, and resend updates there were not ACK-ed alongside the next updates.

Server replicas system

Servers may always go down. That is a risk, and can cause a lot of issues: Clients suddenly left hanging, data lost, etc.
THNK could replicate not only client-only state, but also between servers: that way, if a server disconnects, the replica can take over: the replica would always get state updates alongside the clients, with potentially extra data that is private to the server, and the clients would be given by the server the details to connect to the replica. When and if the main server goes down, clients will automatically connect to the replica, which will start running the main server loop in the stead of the server.

This should be an opt-in behavior: Replicas don't make sense in some games and multiplayer types. For example, in a P2P among us clone, a replica would be another client, which could use a cheat client to read the private server state and know the imposters.
Replicas may also not work if some private server state that is crucial is not marked as such and therefore not synchronized.

Add QoS to THNK messages

Some THNK messages might need to be received at all costs, some might be less critical. THNK should provide an option to decide whether or not the message should be sent reliably (e.g. re-send the message as long as it is not ACK by the server + ignore duplicates). Note that THNK will never provide a guarantee of messages being ordered, as that is a terrible idea for realtime gaming.

Disconnection features

Under various circumstances, a player can be lead to be disconnected: whether through a temporary connection failure, a match ending, or the player getting kicked. THNK should support those cases by providing actions to handle those different cases:

  1. Force disconnection - THNK should allow a server to remove a client from the game
  2. Check if disconnected - THNK clients should be able to check whether or not the server is still connected
  3. Disconnection reason - THNK clients should know what kind of disconnect it is dealing with, to react appropriately.

Saving system

THNK knows what data is relevant or not, and serialize the whole relevant data set. While this is good for multiplayer, it can also be applied to another use case: Saving! THNK can make very small saves containing only what is absolutely needed.

THNK local or P2P

The issue is the following: I made a protoype 2D top-down shooter. The issue is the same for local or P2P. One player is a server, the other connects as a client. Players move left and right (airplanes), while the bullets are moving from the bottom of the screen to the top (think of the older game 1942). Movement is working ok as expected. Problem is, when I hold the firing button (in my case "space") bullets spawn normally and move; however, after like five seconds of holding down the firing button, bullets stop spawning at the center of the player object, but instead at the X position of 0. Now I release the firing button, then press again and now they start spawning immediately from X = 0 (instead of the player's X position). On the server it shows normally, bullets are spawning from the position of the player object who is firing the bullets. The issue is on the client's player object (in the client's game window). The bullets begin to spawn normally again if I press shortly the left or the right arrow (move a little bit to the left or right) while firing. However, after standing still and holding firing button for about 5 - 8 seconds, the glitch happens again (bullets begin to spawn at X = 0). What could be the issue? Is the position information being stopped being sent after a while?

EDIT: I am using the behavior "FireBullet", but I have also tried to "fire manually", that is, listening for player input, then spawning manually the bullets and moving them accross the screen. The issue remains the same.

Don't understand how to make work the ยซ Quick start ยป Scene in the THNK example

Hello Arthuro ! Please i'm a newbie and i don't know how to make work the ServerQuickStart and the ClientQuickStart Scenes in your THNK example in GDevelop.

I tried to preview the first before the second, while connected to the internet, but it displayed an error like : A JavaScript error occurred in the main process / Uncaught Exception : Error : EPERM : operation not permitted, open 'C:\Program Files\GDevelop\geckos-server.zip'

I have put an eye in this and i noticed that i don't have the geckos-server.zip file.

What should i do please ?

[Bug] Bitmap text is not Synced

As the title says, Bitmap text is not getting synced with clients.

in the example i provided, i create 2 text objects

  • one of them is normal text object
  • one of them is Bitmap text object
    and i set the events as:
    Host side:
  • Client connected
    • Create normal text object
    • Modify the normal text to "Working"
    • Create Bitmap text object
    • Modify the Bitmap text to "Working"

Both objects have sync behavior.

Result:
on host preview, both text objects are created and both says "Working"
on client preview, the normal text object says "Working" BUT the Bitmap object says "Empty" (which is the default text).

The example:
Test2.zip

Authentication support

Not everyone is supposed to be authorized to access all scenes. Some games can contain confidential information, and should not be synchronized with a client before authorization has been ensured for them. THNK would provide a function to listen for connection request. By default, they are accepted, but they can be marked as delayed or refused. Delaying them can be useful for asynchronous operations, like checking on a database for user permissions. Only once accepted will the user trigger the "Connected" event and be sent a snapshot of the scene.

Game wont start when p2p adapter is used

Attempting to load the game while previewing as an application or locally via network preview causes the loading screen to freeze at the start. I believe the onFirstSceneLoaded of P2P adapter is causing this. I have removed just that and it loads showing the issue is isolated there. I had a look at the debugger and I get the following error
Internal crash: TypeError: Class extends value undefined is not a constructor or null
Attempting a network preview and using developer tools console shows this and a few more errors
image

Example:
Bug.zip

Infinite Windows Opening With Local Server

Attempting to run my project utilizing the new local server adapter causes an infinite amount of game windows to spawn. This occurs with and without the "Trigger Once" condition.

Context isolation

The server and client may run on the same game instance when the server is not running as a dedicated server. This is problematic, as client events can interfere with the game state that is synced with everybody, causing all kinds of issues.

The server should:

  • Run in another context (instance of the scene) than the client, so that anything done on the client does not touch the true server state
  • Not run code for rendering
  • Run the server update loop independently from the client, so that it continues running even if the game window is not visible (an issue rn due to how the GDevelop rendering event loop is made)

To do so, we'll probably want to create a web worker, where we load the game and hot-patch it with the patches from https://github.com/arthuro555/cloud-gdjs as to not use any render code. Communication can be done through normal THNK serialisation over worker message APIs.

Teams system

Often, games will separate players in groups or teams: Red vs Blue vs Yellow vs Purple, Crewmates vs Imposters, 3 vs 3...
Or generally, you may want to have multiple groups of users depicting different access levels: Members, Moderators, Administrators...

In those kinds of cases, it can be useful to give to give players of such a team messages intended only for them. Therefore, THNK could have a Teams system where:

  • A player can be added or removed from a group by the server
  • Both server and client can check if the currently picked player is in a specific team
  • The server can set a State variable shared with the whole team (and not players outside the team)
  • The server has an action to randomly create teams of players

Connection manager

Connections to a server are just started in a promise and at some point resolve, or fail and log something to the console. In the longer term, this is not OK - we cannot try to connect everywhere at once, we need error handling, etc.

Instead, we should have a connection manager for the client:

  • THNK.startClient requests the manager to start the connection. It will be rejected if an attempt at connecting is already in progress (with a log in the console).
  • The connection manager keeps track of the current connection state:
    • idle - Not connected to a server in any capacity
    • connecting - adapter.prepare() is still running
    • authenticating - The adapter connected to the server, and has sent a connection request
    • failed - Connection or authentication have failed
    • reconnecting - Connection to the server has been ungracefully terminated, attempt to reconnect with 10s interval between attempts
    • disconnected - The server has shutdown gracefully, kicked you, or couldn't be reconnected after configured amount of max attempts
  • The manager provides actions and expression to query this state and details (e.g. failure reason, disconnection reason, etc.)

Geckos.io Adapter

An adapter for https://geckos.io networking. It allows to establish a WebRTC DataConnection in a similar way to socket.io/WebSockets.
It is made for realtime, performance and communication across all types of machines, using UDP in the background and automatically encrypting all connections without requiring a certificate, and is therefore very good for all types of game servers.

Snapshot system

Snapshots is a system that keeps the diff data from the last few frames in memory. This allows to resend data that a client missed due to UDP packet loss.

Having a snapshot of the latest frame also allows to serialize the game state differently for each player. FlatBuffers being immutable, we need to keep that data stored for multiple reserialisation with player-spcific data, like the Player state variable.

Necessary for #5 and #20

Add sync support to more properties of objects

We need to ensure that all of the fields one may want to use are available to be synchronized.

Fields

  • Position
  • Width & Height
  • Angle
  • zOrder
  • Layer
  • Scale
  • Visibility
  • Opacity
  • Current animation
  • String of a text/text entry/text input object
  • State variable
  • Flipping
  • Tint
Please comment any other properties you wish to be synchronized

[Bug] Creating object on UI layer

Hello, as the title says, there is a bug in THNK, when you set the events as:

  • on server side
    • Client connected โ†’ Create ObjectA in UI layer.

The results are:

  • When the host player spawn โ†’ ObjectA will spawn on UI layer โœ…
  • When the client player spawn โ†’ ObjectA will spawn on Base Layer โŒ

Here is a very simple project I made that shows the bug:
Test.zip

WebSockets adapter

An adapter to host games over websockets (PC only) or join such a game.
This could be used in pair with cloud-gdjs to make a dedicated server build.

Player state variables

Oftentimes, players need to display some private data, like one's inventory & stats in an MMO or whether or not one is an imposter in Among Us. That kind of data shouldn't be left in the State variable, since only a single player player is supposed to know of it, and the State variable is shared with all clients. A hacker could abuse this to get access to and exploit that kind of confidential data to gain an unfair advantage.

The solution is to make a state variable for all players. It would be a structure mapping the player IDs to a state variable only synchronized with that specific user.

Camera boundary support

Cameras are client side for multiple reasons (they are client specific, they are rendering related, they need to be updated on each frame when interpolating and not on each server tick...), but that leaves room for cheating by seeing things one is not supposed to.
An example would be the game "Among us": If a cheater could see everything everywhere, they could see the imposter make their kill, and that would ruin the game.

The solution to this is adding camera boundaries. This would define a window of objects that the client is able to see, and only those objects would be synced with the client. That way, even if a hacker changes its camera to see everything, the other objects won't even be sent to the client and the hacker won't be able to see anything ๐Ÿ˜Ž

There should be multiple camera boundaries, to allow seeing two places but not what is in between. Taking again "Among Us" as an example, when watching through the cameras, the zone of those cameras should be synchronized & made visible to the player, but without making a giant camera boundary that covers both the field of sight of the player and of each cameras. Instead, each camera should add an additional camera boundary that allows the client to see what's at their position when they are active.

Linking objects to a player

Linking an object to a player is possible by simply setting an object variable to their player ID, but that is pretty inefficient (picking an object by variable is O(n) where n is the amount of objects) and inconvenient (you have to put the same "Variable ID == THNK::CurrentPlayer()" condition all the time ๐Ÿ™„).

Instead, you could link an object to a player, and when the currently picked player is changed, so would the picked objects list to reflect the player's linked objects. Accessing all objects would still be possible via the pick all objects.

Rollback-based networking support for the platformer behavior

The network is slow. Even on the speediest connections, there is a slight delay between a message sent from a client and the moment the server receives it. Especially on lower-grade connections, this delay can completely destroy a user's game experience: if a client sends a jump input a few moments before falling into a pit, if the delay is high enough, the server won't allow the jump to be done because he already fell off, even though it was valid at the time the player pressed the button.

To help with that, THNK would make snapshots of the platformer behavior's state every frame, e.g. The position of the character, and the platform it is standing on (if any), and save them for the last few server ticks. When it is time for the platformer behavior to handle inputs, we'll revert the state of the server to that of the tick at which the player did the input. That way, we can prevent unfair behavior due to latency ๐Ÿ˜Ž

Split-Screen adapter

The Split-Screen adapter would be a fake adapter: It would like as an adapter by controlling the scene, but not do any networking or enable serializing, unlike a real adapter. Instead, it would use the "Render to Sprite" extension to take the connected players, and automatically render each of the connected players into a sprite to create a Split-Screen experience out of a game automatically.

Scene switching support

THNK should not stop working when swithcing scenes, here is how it should behave:

On the client

Full scene switch

Stop the THNK client and start the next scene in normal singleplayer mode

Pausing the scene

Don't disconnect from the server yet, and launch the scene in singleplayer mode. The server will not send any state updates while paused. If resumed, the server will send back a full scene snapshot again. If the scene is topped while paused, the server will finally see the client as disconnected.

Returning to paused scene

Stop the THNK client and go back to to the previous scene in singleplayer mode.

On the server

Full scene switch

Tell all the clients to switch to that scene as well, run the connection event for all connected clients on the new scene, and send a snapshot of the scene after running a first tick to all clients.

Pausing the scene

Tell all the clients to pause the current scene and go to that scene as well, run the connection event for all connected clients on the new scene, and send a snapshot of the scene after running a first tick to all clients.

Returning to paused scene

If the server returns to the scene before it was a server, close the THNK server.
Else, send a message to all players telling them to go back to the previous scene, and send to the players that have joined after the pausing the scene state at the moment of pausing.

Cant leave the server after hosting one

Video.mp4

If you Host a scene (THNK-P2P), and then go back to main menu (disconnect from the server), and then join a server as a client not a host, the game still thinks you are the host.
As you can see in the video, the game still thinks I am the host in the right preview, even though I left and disconnect from that server.

Events:
ss2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.