{$ifdef FPC} OpenSSLSockets, {$endif}
Castle Game Engine does not have (right now) dedicated high-level components for multi-player games. We provide:
Building blocks, like using URLs for all resource access and asynchronous HTTP requests using TCastleDownload
.
And we provide integrations (with examples) with many 3rd-party networking libraries.
The engine provides a cross-platform component TCastleDownload
to asynchronously download any URL and to perform HTTP(S) web requests. In effect, this can be used to communicate with any backend (written using Pascal or not) that uses HTTP(S) protocol.
Features of TCastleDownload
:
Supports various HTTP(S) methods (GET, POST, PUT…).
Handles HTTP(S) redirects automatically.
Allows to send custom HTTP headers.
Gets MIME type from server automatically.
Exposes HTTP response headers and code.
It is really cross-platform and cross-compiler, covering all platforms supported by Castle Game Engine. E.g. it uses FpHttpClient with FPC on most desktops, uses special Android service on Android, on Delphi uses Indy or TNetHTTPClient
(depending on what works better on given platform).
Supports encrypted HTTPS out-of-the-box as much as possible, since HTTPS is standard nowadays. To this end, we adjust some Indy and FpHttpClient to make HTTPS just work.
FPC applications only have to use OpenSSLSockets
unit, e.g. add
{$ifdef FPC} OpenSSLSockets, {$endif}
to the uses clause of one of your units (like GameInitialize
).
Examples:
examples/network/remote_logging/ (sends asynchronous HTTP POST message),
examples/network/put_data/ (send HTTP PUT),
castle-openai: Talking with OpenAI assistant (essentially your own, customized ChatGPT) (sends a series of HTTP POST and GET messages to talk with OpenAI server).
The examples/network/tcp_connection directory in CGE sources demonstrates how to create and use a classic client/server solution, where multiple clients talk to a server over a TCP/IP connection.
It’s a good cross-platform solution when:
The client/server architecture fits your design. That is: one player "hosts" a game, and everyone can reach the host over IP (which typically means that either 1. the host IP, and the relevant port, are accessible publicly on the Internet, 2. or that everyone is within the same local network).
You want reliability (not maximum speed), since it uses TCP connection in a standard fashion.
CastleClientServer
and Indy use standard TCP connection in a standard way, which is good for simplicity and interoperability. E.g. you could develop a server in Java or C++ if needed, to communicate with Pascal clients.
This approach uses the CastleClientServer
unit, which uses Indy (with threads) on most platforms, except on Android where we utilize dedicated asynchronous Android API for this.
To compile it with FPC/Lazarus, be sure to install Indy using one of the options below, and then also compile in Lazarus package castle_indy
. To install Indy:
You can install Indy through the Online Package Manager. The OPM is a great way to install Lazarus packages in general, go ahead and try it :)
You can install "indy" module using fpcupdeluxe. You can install your own FPC and Lazarus using fpcupdeluxe, and add an "indy" module to it.
Alternatively, you can download Indy from packages.lazarus-ide.org (same packages that OPM uses) . Search for "indy" there, download and unpack the zip, open the package indylaz.lpk
inside Lazarus and compile it. Here’s a command-line version:
wget http://packages.lazarus-ide.org/Indy10.zip
unzip Indy10.zip
lazbuild Indy10/indylaz.lpk
In all cases, you should get an additional package indylaz
known by Lazarus. Remember to also install packages/castle_indy.lpk
package, and use it in your projects.
Delphi users don’t need to do anything in this regard, as Indy is already included in Delphi.
All applications using Indy (whether with Castle Game Engine or not) have memory leaks, by default. This is a design choice of Indy — letting the memory leak was better than crashing in some edge-cases at unit finalization.
If you are sure that all the Indy threads are given sufficient time to terminate gracefully before the application exits, you can define the symbol FREE_ON_FINAL
in Indy sources. Search for define FREE_ON_FINAL
inside Indy sources, as of now it means you will find 5 include files doing this:
{.$DEFINE FREE_ON_FINAL}
{$UNDEF FREE_ON_FINAL}
You need to change these lines to
{$DEFINE FREE_ON_FINAL}
{.$UNDEF FREE_ON_FINAL}
Please note that it isn’t always easy to guarantee that "threads are given sufficient time to terminate gracefully before the application exits". It means that disconnecting (by clients) and stopping (by server) cannot be done right when the application exits (or you have to wait for it to finish, potentially hanging your application on exit). Basically, Indy developers had a good reason to not enable this by default.
For similar reason, the internal thread inside CastleClientServer
actually may leak memory in case it didn’t have time to terminate gracefully before the application exits. (But in our case, by default, it will not leak if exits cleanly, i.e. you disconnect client before application exit. It only leaks if the application exits too quickly, disconnecting the client.)
Note: There’s a code in Indy to "register known leak" with some memory managers, but it is not active by default for FPC.
You can test for memory leaks following our instructions about memory leaks. We use FPC HeapTrc to detect memory leaks, and you can just set <compiler_options detect_memory_leaks="true">
in CastleEngineManifest.xml to enable it.
When you edit a project that uses CastleClientServer
with VS Code (or other editor using our LSP) you may see errors like: "unit not found: IdGlobal".
To solve this, you need to tell our LSP where are your Indy units. To do this, create a file:
On Unix: $HOME/.config/pasls/castle-pasls.ini
On Windows: C:/Users/<YOUR-USERNAME>/AppData/Local/pasls/castle-pasls.ini
and inside put these lines:
[extra_options]
;; Specify as many extra FPC options as you want.
;; Each extra option must have a consecutive number, start from 1.
option_1=-Fu/home/myusername/src/Indy10/Core/
option_2=-Fu/home/myusername/src/Indy10/System/
Adjust the above paths (/home/myusername/src/Indy10
) to your system to point to the directory where you have Indy sources.
For more information, see README about Extra configuration in castle-engine/pascal-language-server.
mORMot2 is a feature-rich Object Pascal framework for developing network applications. It can support traditional client-server communication (exchanging messages), ORM (where you pass around objects that can be easily synchronized over the network and can be saved/loaded from the database), and more. It has a number of high-level (like ORM) and low-level (like database access) utilities to make programming of client-server (and other!) applications easier.
See our example integration of Castle Game Engine with mORMot2 in collaborative editing of 3D world using Castle Game Engine and mORMot2.
RNL (Realtime Network Library) is an open-source, reliable UDP network library, for FPC and Delphi, cross-platform, developed by Benjamin Rosseaux . If you want to make real-time communication over a network (e.g. an FPS game like Quake) this is a good start.
In fact, we have already made it :) Not Quake is an example of online first-person shooter, developed using Castle Game Engine and RNL. You can
We plan integration with Nakama in the future. It’s a great open-source solution that provides out-of-the-box common multi-player features and can be customized to each particular project.
There are various other networking solutions for Pascal — and you can use any of them together with Castle Game Engine. Links:
Aforementioned Indy is a big library providing a lot of networking options. You can use it directly in many ways. See the online documentation.
Synapse is a cross-platform networking library. See also FPC wiki about Synapse.
lNet is a cross-platform lightweight networking library for FPC. It’s much smaller (in terms of API and implementation) than Synapse and Indy, which may be an advantage, depending on what you need. See lNet FAQ and FPC wiki about lNET.
FPC includes various networking units in the standard installation already. They work at various levels. In particular if you just want HTTP (REST) networking, FPC has fcl-web which allows to create HTTP(S) servers and clients.
The future may bring to Castle Game Engine more networking options (at a higher-level, to replicate some game state across multiple clients).
Note
|
that you can also make hot seat and split screen games, in which case multiple people just play on the same computer. We fully support multiple joysticks connected to a single desktop application, and connecting / disconnecting them at runtime, which allows to handle input from multiple people in one game. |
To improve this documentation just edit this page and create a pull request to cge-www repository.