Gets SDL3 building again on macOS. The game is able to boot to the main
menu and play with hlsdk-portable and HL assets. Some bugs when changing
video modes.
Doesn't fix the root cause of the problem, which is the mysterious setting of decal->pnext to decal which doesn't happen in GL, but does act as a blockade and a temporary fix
This is an annoying message that's caused by the game code. Decals, without
custom renderer, cannot be rendered on non-brush entities, and everybody knows
that anyway.
Previously, it would always return on the first one that had activity.
In practice, this meant that if IPv4 starts getting slammed, IPv6 reads
wouldn't happen.
* Use offsets into dbspmodel_t struct, get rid of srcmodel global variable.
* Allocate dbspmodel_t when it's required
* Make srclumps const, move Blue-Shift hack into lump loader's flag.
Mod_StudioComputeBounds incorrectly assumed that all models across all body parts were laid out contiguously in memory. This caused out-of-bounds reads or reading garbage data when loading complex models, leading to crashes.
Is this a mistake? This define effectively forces `--enable-ffmpeg-dlopen` at all times ignoring configuration (which in turn makes build to fail with ffmpeg 8.1).
In GoldSrc default branch interpreted as WALKMOVE_NORMAL, and there might be
some mods that expect this.
But Xash never did this, and if Xash-specific games rely on that behavior, we
better know about it.
AMD убрала в новых драйверах поддержку расширения GL_ATI_texture_compression_3dc, из-за чего сломалась загрузка ATI2 текстур. Формат RGTC включен в стандарт OpenGL 3.0, а единственные видеокарты с поддержкой 3DC, но без RGTC - это серия Radeon X1000 (2005г.). Можно было бы только ради Х1000 проверять поддерживаемые расширения и переключаться на 3DC, но без явной необходимости этого делать не хочется.
* readme: update README.md for android build instruction
* Update Android build instructions in README
Corrected instructions for running in Android Studio and added a new section for building on Android.
---------
Co-authored-by: a1batross <a1ba.omarov@gmail.com>
On GPUs where GL_ARB_shading_language_100 isn't available (i.e. all mobile GPUs
I believe) this function would return total amount of texture units available.
But ref_gl only tracks and uses MAX_TEXTURE_UNITS texture units, causing memory
corruption in functions that doesn't check the limit.
vfs.cfg executed before game directory is mounted, this way we can know which
folders must be mounted before engine initialization.
This commit also removes buggy hot reload of the addon folders.
It was reported on Discord with no additional information attached. But I guess
it might be better to prefix our math- and crtlib functions in general.
- Added support for GoldSrc voice mode, including initialization and shutdown functions.
- Implemented data size verification for the GoldSrc voice package.
- Creation and processing of voice packets, CRC verification of data integrity.
- Added a Steam ID field to the client_static_t structure
- Automatic gain control has been introduced for voice samples.
- The voice status structure has been updated.
- Refactored voice data handling for better type consistency and maintainability.
- Fixed ISO C90 compliance issues for better portability.
- Fixed decoder index usage.
Fixes translucent brush model on renderfx2.bsp (https://twhl.info/vault/view/6933)
which so happened to draw after agrunt sprite, that has "lightmap" enabled
It also adds a fix found in JoeQuake (which traces back to FitzQuake, in which
it is attributed to LadyHavoc, Darkplaces author) to exactly calculate whether
the light hits the surface, so we don't wrongly enable lighting on a surface by
an increased radius.
It allows us to not lose engine-side description when client or gameui registers cvar with the same name. In case of
menu it's the only way to get cvar pointer.
That could happen when default game directory depends on base directory that don't have gameinfo.txt.
Because all game directories with liblist.gam automatically have dependency on default game directory, it causes cyclic dependency.
- Looks for game data in SDL pref path (Application Support)
- Sets XASH3D_EXTRAS_PAK1 to SDL base path (Resources dir in App Bundle
- Added option to force search for SDL dylib via pkgconfig on Darwin instead of Framework (option for Mac Source Ports build process)
In future, net_buffer might get moved to libpublic.
Also, get rid of 32-th bit write mask, it's only get used when we're trying to
write zero bits value which is nonsense.
This intentionally will not build without --enable-ffmpeg for now.
We add new functions to the RenderAPI called AVI_Think and AVI_SetParm. Game
developer is supposed to call AVI_Think each frame and set video playback
parameters through AVI_SetParm function.
What's tested:
* Intro cinematics.
* Looping videos.
* Playing back an hour long video.
* API extension (PrimeXT's avi branch at https://github.com/a1batross/PrimeXT).
What's broken:
* There is no way to seek a video file, only rewind to the start.
check_frag(FRAGMENT_DL_ITERATE_PHDR % 'link.h', ' dl_iterate_phdr function in link.h', 'HAVE_DL_ITERATE_PHDR_LINK_H', after_tests=['link.h']),
check_frag(FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', ' dl_iterate_phdr function in sys/link.h', 'HAVE_DL_ITERATE_PHDR_SYS_LINK_H', after_tests=['sys/link.h']),
* This project uses mixed Quake's and HLSDK's C/C++ code style convention.
* In short:
* Use spaces in parenthesis.
* Use spaces in parenthesis, but not when two parentheses are consecutive.
* Only tabs for indentation.
* Any brace must have it's own line.
* Short blocks, if statements and loops on single line are allowed.
* Prefer generic utilities from libpublic over rolling your own.
* Avoid magic numbers.
* While macros are powerful, it's better to avoid overusing them.
* If you unsure, try to mimic code style from anywhere else of engine source code.
@@ -45,3 +46,8 @@
Tags can be any: subsystem, simple feature name or even just a filename, without extension.
Just keep them always same, it helps keep history clean and commit messages short.
## LLM-based tools usage.
While we wouldn't recommend using any LLM-based (also misleadingly called AI) tools, we understand that they are here to stay.
Whether you're reporting bug or contributing the code, you take complete authorship and responsibility over provided content and the same rules will apply to you as for everybody else, so validate the bug report or the patch before sending it.
This documentation is an attempt on explaining inner workings of Valve's Half-Life (R) engine, also known as GoldSource, from programmer's perspective. A deep knowledge of Quake (NQ, QW and Q2) engines is required.
Everything discussed here is it's author assumption based on studying Xash3D source code and reverse engineering Half-Life mods. Xash3D API extensions is out of scope of this document and will be explained separately.
`client.dll` has got multiple ways of initialization during it's life but we will go through the simplest and the most common route here.
Here we expect that reader has knowledge of loading dynamic shared objects on their platform. On Windows it's done through `LoadLibrary`/`GetProcAddress`/`FreeLibrary` functions, on POSIX-complaint systems it's done through `dlopen`/`dlsym`/`dlclose` functions.
## client.dll lifetime
`client.dll` is expected to be loaded during client initialization and unloaded on client shutdown. Essentially, in non-dedicated builds, it always exists during the engine lifetime. Judging by the API, it might look like `client.dll` might be safely unloaded and loaded again, for example for implementing classic `Change Game` functionality from WON versions of Half-Life, but in practice it's nearly impossible to do this clean in standard and portable manner. If you want to implement changing games, consider using `execv`-like functions.
## client.dll exported functions
The first thing you should do, is to acquire pointers to all exported functions, which you can find in the next chapter. Some of them are optional, and might not present in the `client.dll`, and will be labeled as such.
## client.dll initialization process
1. The first function you call is `Initialize` function, which lets `client.dll` to store a copy of an engine API functions.
2. Since SDK 2.0, `client.dll` have player movement code in it, which you must initialize through `HUD_PlayerMoveInit` function. `client.dll` might want to override player hulls, which can be grabbed with `HUD_GetHullBounds` function.
3. HUD functionality must be started up with `HUD_Init` function and can be de-initialized with `HUD_Shutdown` export function.
4. And finally, SDK 2.1 brings studio model renderer, which has separate set of API functions, which must be initialized with `HUD_GetStudioModelInterface` function.
### `int Initialize( cl_enginefuncs_t *enginefuncs, int version )`
> [!IMPORTANT]
> This function is only called once.
Called after loading DLL and exports engine API to the `client.dll`.
*`enginefuncs` must be set to a pointer to a struct filled with engine function pointers, it will be described in next chapters.
*`version` must be always set to `7`. (HLSDK 1.0 uses version `6`, and is binary incompatible with `7`).
Return value: `0` on error, otherwise success.
### `void HUD_PlayerMoveInit( struct playermove_s *ppmove, int server )`
> [!IMPORTANT]
> This function is only called once.
Called on player movement prediction initialization, before HUD. In GoldSrc, engine only runs prediction loop, the players physics are implemented in `client.dll`.
*`ppmove` must be set to a pointer to a client instance of player movement structure, which also exports it's own API and will be discussed in the next chapters.
*`server` must be always set to `0` on client side.
This function is called only once.
### `void HUD_Init( void )`
> [!IMPORTANT]
> This function is only called once.
Called to initialize the HUD. At this moment engine should be ready to register new commands, console variables and user messages. No rendering or loading graphics done at this moment.
This function is called after initializing HUD and exports studio model interface to the `client.dll`.
*`version` must be always set to `1`.
*`ppinterface` will be set by `client.dll` to a pointer to `r_studio_interface_s` structure.
*`pstudio` must be set to a pointer to `engine_studio_api_s` structure. The studio model interface will be discussed in the next chapters.
Return value: `0` on error, otherwise success.
### `void HUD_Shutdown( void )`
> [!IMPORTANT]
> This function is only called once.
Called at client shutdown.
### `int HUD_GetHullBounds( int hull, vec3_t mins, vec3_t maxs )`
> [!IMPORTANT]
> This function is only called once.
Called by the engine after `HUD_PlayerMoveInit` to let `client.dll` override hull bounds used for in player movement prediction.
*`hull` is the hull index (0: player standing, 1: player crouched, 2: point hull, 3: large hull).
*`mins` will contain hull mins.
*`maxs` will contain hull maxs.
Return value: if 0, don't override this hull and stop reading, non-zero means hull is valid _and_ there is more.
> [!NOTE]
> This function is broken in most implementations. It might return non-zero value, but don't write anything to the `mins` and `maxs` vectors, so be prepared to have some default values.
### `int HUD_VidInit( void )`
Called when client receives `svc_serverdata` message. It is called before any parsing of that message is done, thus the state is preserved from the previous connection. It lets `client.dll` to re-initialize graphics, if required. At this point, engine is expected to have video subsystem running, but no rendering is done here.
### `int HUD_Redraw( float flTime, int intermission )`
Called each frame to redraw the HUD. Only 2D is drawn here.
*`flTime` must be set to `cl.time`, i.e. synchronized with server.
*`intermission` must be set to `1` during intermission (set through `svc_intermission` message), otherwise it's set to `0`.
Return value: ignored.
### `void HUD_Reset( void )`
Called on demo recording or playback start and stop.
*`cdata` contains pointer to `client_data_t` structure, populated by engine.
*`flTime` must be set to `cl.time`, i.e. synchronized with server.
Return value: if non-zero, will override engine viewangles and FOV value.
### `void HUD_PlayerMove( struct playermove_s *pmove, int server )`
When prediction is enabled, use this function to run player movement prediction. Note that this correlates to QW/Q2's prediction mechanism. It does not include weapon prediction.
Called by the engine on unknown connectionless packets. Lets `client.dll` and `server.dll` have custom query protocol.
*`from` is set to network address where this packet is coming from.
*`args` raw network buffer, minus the connectionless packet header (0xFFFFFFFF).
*`response_buffer` set by `client.dll` if there is a response.
*`response_buffer_size` is initialized by the engine with buffer maximum size. Set by `client.dll` if there is a response.
Return value: non-zero if handled.
### `void HUD_Frame( double time )`
Called each frame after sending command to the remote server. No rendering is normally done in this function.
*`time` is the local delta time between previous and this frame (i.e. `host.frametime`)
### `void HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, usercmd_t *cmd, int runfuncs, double time, unsigned int random_seed )`
Always called after `HUD_PlayerMove`, even if movement prediction is disabled. Used for weapon prediction stuff.
*`from` is a pointer to `local_state_s` object of the previous predicted frame
*`to` is a pointer to `local_state_s` object of this current frame
*`cmd` is current user command
*`runfuncs` is set to `1` if this frame was never predicted before, and to `0` if it is being predicted again
*`random_seed` is set to `incoming_acknowledged` plus number of predicted frames starting with `1`. This way it's synchronized between client and server.
### `int HUD_Key_Event( int down, int key, const char *current_binding )`
Called on keyboard event.
*`down` is set to `1` if key is being pressed or set to `0` on being released.
*`key` is set to the key number. The key IDs are predefined.
*`current_binding` is set to a null-terminated string with commands bound to this key
Return value: `0` if `client.dll` wants engine to ignore that key.
When client processes entity updates, for local client it might be truncated, don't have enough precision, miss some critical info, so engine calls this function as `client.dll` might choose to use client data came from `svc_clientdata` message. Note that it is called on raw, non-interpolated networked entity state.
*`state` is a pointer to the local client entity state coming from the network
*`client` is a pointer to local client data object
When client processes entity updates, it calls this function for player entities as `client.dll` might want to override some data or fill the missing parts, but usually it just copies from `src` to `dst`.
*`src` is a target pointer to the player entity data (stored in frames, for example)
*`dst` is a source pointer to the player entity data coming from network
When client receives `svc_clientdata` message, this function is called before any parsing is done, so that the `client.dll` fills in data from prediction.
*`ps`, `pcd`, `wd` are pointers to current network frame data.
*`pps`, `ppcd`, `pwd` are pointers to predicted frame data.
Called each frame after network entities are processed and after `HUD_CreateEntities`, to let `client.dll` process temporary entities logic.
*`frametime` is the delta between `cl.time` and `cl.oldtime`, i.e. server time.
*`client_time` is `cl.time`
*`gravity` is the synchronized gravity value from the server
*`ppTempEntFree` is a pointer to the head of linked list of free temp entities
*`ppTempEntActive` is a pointer to the head of linked list of active temp entities
*`AddVisibleEntity` is a pointer to function that lets `client.dll` add this entity to the rendering list.
*`TempEntPlaySound` is a pointer to function that's called by `client.dll` when temp entity needs to play predefined hit sound. The `damp` argument of this argument only makes sound to NOT play, if it's zero or negative.
### `void HUD_DrawNormalTriangles( void )`
Called each rendering frame to let `client.dll` draw custom solid triangles through TriAPI or direct OpenGL calls.
### `void HUD_DrawTransparentTriangles( void )`
Called each rendering frame to let `client.dll` draw custom transparent triangles through TriAPI or direct OpenGL calls.
### `struct cl_entity_s *HUD_GetUserEntity( int index )`
Called by engine when beam start/end indices are negative, thus allowing attaching beams to a temporary or client-only entity.
*`index` is the fixed up entity index, as beam start/end indices encode real entity index in low 12 bits (i.e. `beament_start & 0xFFF`).
### `void Demo_ReadBuffer( int size, unsigned char *buffer )`
Called by engine on demo playback, if `client.dll` saved some custom data on demo recording prior.
*`size` is the size of buffer in bytes
*`buffer` is the pointer to custom data stored by `client.dll` in demo
### `void CAM_Think( void )`
Called each frame before rendering starts to let `client.dll` run custom camera logic, like advanced thirdperson follow camera for example.
### `int CL_IsThirdPerson( void )`
Returns non-zero value if camera is in thirdperson mode, lets engine figure out whether add local client entity to the rendering list or not.
### `void CL_CameraOffset( vec3_t offset )`
Not used in the engine.
### `void CL_CreateMove( float frametime, usercmd_t *cmd, int active )`
Called when `usercmd_t` is being created to let `client.dll` record user commands before they are being sent over the network.
*`frametime` is the delta time between previous and current frames.
*`cmd` is the pointer to `usercmd_t` object, where player's intentions and impulses are added.
*`active` is set to `1` when client is finished signing on to the server (as movement commands are being sent even if client is not fully spawned yet).
Called each frame before rendering starts. This is close to the similarly named function found in NQ/QW and lets `client.dll` to run custom view logic.
*`params` is the refdef parameters object. It is also used as return value and might request from the engine to not draw anything (by `onlyClientDraws` field) or to run this multiple times (by `nextview` field)
### `kbutton_t *KB_Find( const char *name )`
Called by engine to find extra keys and their state.
Only few are really used by the engine:
*`in_mlook` for mouse look
*`in_jlook` for joystick look
*`in_graph` for net_graph toggle
Return value: returns pointer to `kbutton_t` if found. `kbutton_t` structure matches the same structure that can be found in NQ and QW.
### `void HUD_DirectorMessage( int size, void *buf )`
> [!IMPORTANT]
> This function is optional.
Called to notify `client.dll` about an `svc_director` message. This feature is used for HLTV, though mods use it to spawn text messages or execute commands (bypassing `svc_stufftext` filter in old `client.dll`) but `svc_director` message structure isn't enforced by engine, so it in theory mods might modify it for their own needs.
*`size` is the size of the payload
*`buf` raw `svc_director` payload
### `void HUD_VoiceStatus( int entindex, qboolean talking )`
> [!IMPORTANT]
> This function is optional.
Called to notify `client.dll` about a client status of using voice chat.
*`entindex` an entity index (client index plus one, because zero is always world). When set to -1, notifies `client.dll` about local client recording. When set to -2, notifies `client.dll` about a loopback (i.e. local client's voice message was sent to server and received back)
*`talking` if true, this client is talking
### `void HUD_ChatInputPosition( int *x, int *y )`
> [!IMPORTANT]
> This function is optional.
When called, returns desired X and Y positions of chat box.
One of technical differences a programmer working with Quake engine might notice is the client.dll file. Historically, it appeared somewhere in between Alpha 0.52 and NetTest1 development and judging by Half-Life SDK 1.0 was meant to handle HUD rendering. The time moved forward, SDK 2.0 finalized `client.dll` API at version 7, added an in-game UI, custom input processing, player movement and weapon prediction, very basic rendering through TriAPI. SDK 2.1 added ability to re-define studio model rendering, and so on.
It somewhat resembles `cgame` module from Quake 3, but more crudely designed and sometimes feels like an afterthought, considering how many engine internal structures it exposes and the main point of incompatibilities with mods, which these days sometimes use `client.dll` as a way to inject custom rendering into the game.
In this document I will try to go through each step, letting you, dear reader, implement your own GoldSrc compatible API in your Quake fork, targetting vanilla Half-Life `client.dll` from latest update, which at the time of writing, is 25-th anniversary update.
Despite that we call it `client.dll`, since SDK 2.4 (unofficial naming, it's the first SDK Valve published on GitHub) it is considered portable and only has SDL2 and VGUI libraries in it's external dependences. It's only called this way to avoid possible misunderstandings with engine developers, who might interpret client as `cl_` prefixed part of Quake engine.
GoldSource exposes a lot of structs to `client.dll`. Some of them are specific to `client.dll` and only used for passing data between engine and client, some of them are used in the engine everywhere, but still exposed in the public SDK. However, many mods rely on internal structs as well, and I will try to shed light on them as well.
When implementing them in C, consider the default to 32-bit systems alignment of 4 bytes and ILP32 data type model.
This file won't have API structs, for that, there should be separate chapters.
## Enums
### Entity types enum
This enum has no real name.
| Value | Description |
|-------|-----------------|
| `0` | Normal entities |
| `1` | Players |
| `2` | Temp entities |
| `3` | Beams |
| `4` | Fragmented entities. |
### edict->solid
It matches QuakeWorld definition.
## `client_data_t`
Used only to pass data to `client.dll` through `HUD_UpdateClientData`.
This structure is similar to the one that can be found in QW, but contains much more data, though most of these fields are not used by the engine, but might be used by mods.
@@ -22,7 +22,7 @@ The other yet unsupported configuration is the big endian.
2) Open `public/build.h` file. Add appropriate checks for your operating system and/or CPU architecture. It shouldn't be hard.
Also, you'll need to build [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d/). It has same `public/build.h` so reflect changes into it. Note that to be compatible with HLSDK proprietary license, it's relicensed as public domain under [Unlicense](https://unlicense.org).
Also, you'll need to build [Half-Life SDK](https://github.com/FWGS/hlsdk-portable/). It has same `public/build.h` so reflect changes into it. Note that to be compatible with HLSDK proprietary license, it's relicensed as public domain under [Unlicense](https://unlicense.org).
We have a library naming scheme that allows us and game creators to distribute binaries for different platforms in one archive. Read `Documentation/extensions/library-naming.md` for more information.
Xash3D FWGS supports both GoldSource-style addon folders and has few own. Each directory can have it's own archives that will be mounted with lower priority than directory itself.
Below is the mounts map, in order of precedence from least important to most important.
|--------------------|------|
| Directory | Note |
|--------------------|------|
| `$game/downloaded` | Always added. Used to store server downloads.|
| `$game` | This is the game directory. |
| `$game/custom` | Always added. Used for user modifications content. |
| `$game_hd` | Added with `fs_mount_hd` set to non-zero value. Used for high definition content, similar to GoldSrc.. |
| `$game_addon` | Added with `fs_mount_addon` set to non-zero value. Used for user modifications content, similar to GoldSrc. |
| `$game_lv` | Added with `fs_mount_lv` set to non-zero value. Used for low-violence content, similar to GoldSrc. |
| `$game_$language` | Added with `fs_mount_l10n` set to non-zero value. Language is controlled with `ui_language` cvar or `-language` command line switch. Used for localization content, similar to GoldSrc. |
@@ -42,3 +42,6 @@ Issue #3: Some mods (like The Specialists, Tyrian, ...) already apply suffixes _
Resolution: On x86 on **Win/Lin/Mac**, don't change anything. Otherwise, strip the _i?86 part and follow the usual scheme.
See discussion: https://github.com/FWGS/xash3d-fwgs/issues/39
Issue #4: When distributing game libraries on Android inside an APK, they couldn't be loaded.
Resolution: Enable `useLegacyPackaging` option in build.gradle, when distributing games in APK. Always force game libraries to have `lib` prefix on Android, regardless if they are packaged in APK or not..
Xash3D FWGS supports lightmapped water, as an extension. It adds three new cvars and new worldspawn key values.
### For level designers:
If you're a level designer and intend to make your level to have lightmapped water, you can put these keyvalues to worldspawn entity description (always first entity in entities list):
| `_litwater` | integer | Set to any non-zero value to enable lightmapped water. Overrides `gl_litwater_force` cvar value. |
| `_litwater_minlight` | integer | Minimal lightmap value water surface will receive. Helps to avoid too dark areas when water isn't properly lit. If not set, defaults to zero. |
| `_litwater_scale` | float | Scales up lightmap value for water surfaces. If not set, defaults to 1.0. |
### For players:
Some of the maps already have computed lightmap for water surfaces and sometimes water has been properly lit but the support hasn't been declared by the level designer.
As a player, you can enable it in `Video options` menu or through console with `gl_litwater_force` cvar. There are also `gl_litwater_minlight` and `gl_litwater_scale` cvars that function similar to keys above. The default values has been set to `192` and `1.25` respectively to slightly avoid issues with maps that wasn't intended to have lightmapped water.
@@ -16,6 +16,7 @@ Only these objects are guaranteed to be available on all targets.
|-------------|-----------|
| `VFileSystem009` | Provides C++ interface to filesystem, binary-compatible with Valve's VFileSystem009. |
| `XashFileSystemXXX` | Provides C interface to filesystem. This interface is unstable and not recommended for generic use, outside of engine internals. For more info about current version look into `filesystem.h`. |
| `MenuFactory` | Returns a `CreateInterface` function pointer (`pfnCreateInterface_t`) for the currently loaded menu library. |
| Length | 2 bytes | uint16_t (LE) | Size of payload in bytes |
| Payload | N bytes | Binary | Command string or response data |
**Notes**:
- Header must be exactly `SBRK` (`53 42 52 4B` in hexadecimal form)
- Maximum frame size: soft limit is 4096 bytes, hard limit is 65535 bytes (due to uint16_t usage)
---
## Session Lifecycle
```
┌──────────────┐
│ IDLE │ ← Initial state, accepts new TCP connections
└──────────────┘
│ sb_gamedir
↓
┌──────────────┐
│ ACTIVE │ ← Session established, rejecting all of other TCP connections
└──────────────┘
│ sb_connect
↓
┌──────────────┐
│ ACTIVE │ ← Client getting auth ticket to connect to game server
└──────────────┘
│ sb_disconnect
↓
┌──────────────┐
│ ... │ ← Client announcing disconnect from game server, could connect somewhere again
└──────────────┘
│
↓
┌──────────────┐
│ ACTIVE │ ← Client shutting down game, terminating broker to reset Steam client state
└──────────────┘
│ sb_terminate
↓
┌──────────────┐
│ RESTARTING │
└──────────────┘
```
---
## Commands
All commands listed below are meant to be sent from client to broker as payload of a frame. The broker will parse the command string and respond accordingly.
XRCON is a TCP-based remote console protocol implemented as a server within the engine. It provides an alternative to the legacy RCON (which operates over UDP as out-of-band packets). XRCON uses a framed binary protocol over a single persistent TCP connection, accepting at most one client at a time.
Key characteristics:
- Based on TCP (stream-oriented, reliable)
- Default port is 27000
- Maximum only one concurrent client
- Binary framed protocol with a 12-byte header + variable-length payload
## Configuration
The XRCON server is controlled by two configuration variables, both restricted to privileged users:
| Variable | Default | Description |
|---|---|---|
| `xrcon_enable` | `0` (disabled) | Master switch; when enabled, the server starts listening for connections |
| `xrcon_address` | `127.0.0.1:27000` | Bind address and port; supports both IPv4 and IPv6. Changing this at runtime triggers a XRCON server restart (stop + rebind) |
By default, XRCON binds only to localhost (`127.0.0.1`), providing a degree of access control. The server will not start listening until explicitly enabled.
## Frame Format
All XRCON messages are encapsulated in a framed binary format. Each frame consists of a fixed 12-byte header followed by a variable-length payload.
### Header (12 bytes)
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | Type | 4-character message type string (null-terminated, occupies 5 bytes in the structure but the 5th byte is padding) |
| 4 | 4 | Version | Protocol version (32-bit unsigned integer, network byte order) |
| 8 | 2 | Length | Total frame length in bytes, including the header (16-bit unsigned integer, network byte order) |
| 10 | 2 | Handle | Handle or sequence number (16-bit unsigned integer, network byte order; currently always zero) |
### Protocol Version
The current protocol version is `0x000000D4` (212 decimal). The server also accepts `0x00D40000` for compatibility with certain third-party clients (e.g., CS2RemoteConsole).
### Maximum Frame Size
- Maximum payload per frame: 4096 bytes
- Maximum total packet size (header + payload): approximately 4136 bytes
| Payload | Variable | Raw command string (null-terminated) |
The command string is injected into the engine's command buffer for execution. There is **no authentication** — any connected client may execute arbitrary commands.
### PRNT — Server Print
**Direction**: Server → Client
Sent by the server to stream console output to the connected client.
| Payload | 77 bytes | All zeros (placeholder / reserved for structured application information) |
This packet currently serves as a placeholder and contains no meaningful data. It may be extended in future versions to carry structured metadata about the server application.
### ADON — Additional Info
**Direction**: Server → Client
Sent by the server immediately after `AINF` during the connection handshake.
| Name Length | 2 bytes | Length of the name string (unsigned 16-bit integer) |
| Name | Variable | Server name / identifier string (e.g., `"HLDS"`) |
This packet carries the server application name, which is a short string identifying the server type (e.g., `"HLDS"` for Half-Life Dedicated Server).
## Security
XRCON has **no built-in authentication or encryption**. There is no password validation or transport-layer security. Any client that can establish a TCP connection to the XRCON port has full command execution access to the engine console.
The only security measures are:
1.**Default localhost binding**: The server binds to `127.0.0.1` by default, accepting connections only from the local machine.
2.**Disabled by default**: The `xrcon_enable` variable defaults to `0`, so the server does not listen unless explicitly enabled.
3.**Privileged variables**: Both configuration variables are restricted to privileged users and cannot be modified through unprivileged console commands or external access.
## Comparison with Legacy RCON
| Feature | XRCON | Legacy RCON |
|---|---|---|
| Transport | TCP (stream) | UDP (datagram, out-of-band) |
| Port | Configurable, default 27000 | Game port (default 27015) |
| Framing | Binary frame header | Plain text over UDP |
| Authentication | None | Password-based |
| Max clients | 1 | Multiple |
| Interaction format | Full console access | Request-response only for submitted command |
| Supported environments | Client and server | Server only |
This feature is still work-in-progress, but for now it's available for all users, and we appreciate any bug-reports and contributions around it.
For connecting to GoldSrc-based servers, use this command:
```
connect ip:port gs
```
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto.
Without this requirement, you will just get "Steam validation rejected" error on connecting.
You need to use [Steam API broker](https://github.com/FWGS/steam-broker) and have purchased Half-Life 1 on your Steam account to be able to join GoldSrc servers.
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
Broker will run on your PC and will be responsible for communicating with Steam client and obtaining auth tickets.
Also, make sure to set that broker as current ticket generator using console or edit `config.cfg` file manually:
```
cl_ticket_generator steam
```
Also, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be
If you want to join GoldSrc servers from other device (Android/iOS or console), make sure to set proper broker IP address with `cl_steam_broker_addr` console variable. Default value assumed that broker is running on the same device as game client.
By the way, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be
solved along with better compatibility with GoldSrc behavior, but may be not - we don't know logic behind this fake client checks.
|Blue Shift |The latest steam release |Uses vgui2 library which xash3d does not support |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/bshift
|Counter Strike |1.6(The latest steam release) |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Sven-Coop |5.0+ |Uses custom GoldSrc engine |
|Area 51 |Update 1 |Uses outdated BSP31 map format and custom HLFX SDK libraries. |You can try [this tool](https://hlfx.ru/forum/showthread.php?threadid=5250) to convert maps but there no warranty if it works.
|Arrange Mod: Rebirth |v150 |No idea yet. |
|Blue Shift |The latest steam release |Uses vgui2 library which xash3d does not support. |Recreated source code here: https://github.com/FWGS/hlsdk-portable/tree/bshift.
|Counter Strike |Beta 6.5- |Uses an old WON HL 1.0.0.16- interface. |
| |1.4 |Has encrypted blob instead of normal client.dll. |You can try [this tool](https://aluigi.altervista.org/papers/hldlldec.zip) to decrypt client.dll but there no warranty if it works.
| |1.5 |Has encrypted blob instead of normal client.dll. |Decrypted blob here: https://csm.dev/threads/cs-1-5-client-dll-decrypted-patched-for-usage.38845.
| |1.6(The latest steam release) |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface. Recreated Client Source Code here: https://github.com/Velaron/cs16-client.
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface. Recreated Client Source Code here: https://github.com/Velaron/cs16-client.
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support. Uses new sequences code on engine-side that was never used in any other mods before. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface.
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface.
|Half-Life: Extended |Day One demo |Uses many hooks to GoldSource engine and version check. |Just wait new version or use more old version.
|Icon of Hell |Beta 0.99 |Uses outdated BSP31 map format and paranoia 2 libraries. |You can try [this tool](https://hlfx.ru/forum/showthread.php?threadid=5250) to convert maps and use Paranoia 2: The Savior 1.51 libraries but there no warranty if it works.
|Paranoia 2: The Savior |All builds older 1.51 |Uses an old renderer interface and engine features. |
|Rebellion |1.0 |Uses an old WON HL 1.0.0.16- interface. |Recreated source code here: https://github.com/FWGS/hlsdk-portable/tree/rebellion.
@@ -16,6 +16,9 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth
## Battle Grounds
Mirrored on github - https://github.com/nekonomicon/BattleGrounds
## Brain Bread
Official github repository - https://github.com/IronOak-Studios/BrainBread
## Bubblemod
Download page on official site(WM snapshot) - [http://www.bubblemod.org/dl_default.php](https://web.archive.org/web/20130717133158/http://www.bubblemod.org/dl_default.php)
@@ -32,18 +35,27 @@ Version 1.9 mirrored on github - https://github.com/solidi/hl-mods/tree/master/c
## Cold Ice Ressurection
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir
## Counter-Life
Available on ModDB - https://www.moddb.com/mods/counter-life/downloads/cl-version-1-source-code
## Cthulhu
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK
## Deathmatch Classic
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc
## Delta Particles
Available on ModDB - https://www.moddb.com/mods/half-life-delta/downloads/delta-particles-full-sources-maps-and-c-code
Xash3D FWGS currently supports four network protocols:
* Version 49, introduced in Xash3D in around 2018.
* Version 48, used in Xash3D FWGS 0.19 and earlier. Deprecated and to be removed in the future.
* GoldSrc version 48, used in current GoldSource version.
* Quake version 15, only used for demo playback for Quake Wrapper mod.
On the server side, we only support Xash3D 49 protocol, but bugcomp `gsmrf` mode can convert GoldSrc 48 messages into Xash3D 49 on the fly, for some mods that directly write engine internal messages.
In the following documents we will only cover version 49, as everything else is either not Xash3D specific or deprecated.
Connectionless protocol defines four common message sources and destinations, they can be:
*`S` for Server
*`C` for Client
*`M` for Master
*`A` for Anything else
All connectionless packets have `\xff\xff\xff\xff` (32-bit integer set to all ones) in it's header. Let's go through each of possible direction in this document.
<!--TOC-->
- [Any](#any)
- [Any to Any](#any-to-any)
- [`A2A_PING` and `A2A_GOLDSRC_PING`](#a2a_ping-and-a2a_goldsrc_ping)
- [`A2A_ACK` and `A2A_GOLDSRC_ACK`](#a2a_ack-and-a2a_goldsrc_ack)
- [Deprecated queries](#deprecated-queries)
- [`A2A_NETINFO`](#a2a_netinfo)
- [`A2A_INFO`](#a2a_info)
- [Any to Client](#any-to-client)
- [`A2C_PRINT` and `A2C_GOLDSRC_PRINT`](#a2c_print-and-a2c_goldsrc_print)
- [Any to Server and Server to Any](#any-to-server-and-server-to-any)
- [GoldSrc server queries](#goldsrc-server-queries)
- [`A2S_GOLDSRC_INFO`](#a2s_goldsrc_info)
- [`A2S_GOLDSRC_PLAYERS`](#a2s_goldsrc_players)
- [`A2S_GOLDSRC_RULES`](#a2s_goldsrc_rules)
- [Any to Master](#any-to-master)
- [`S2M_SCAN_REQUEST`](#s2m_scan_request)
- [Master to Any](#master-to-any)
- [`M2A_SERVERSLIST`](#m2a_serverslist)
- [Master and game server](#master-and-game-server)
- [Server to Master](#server-to-master)
- [`S2M_HEARTBEAT`](#s2m_heartbeat)
- [`S2M_SHUTDOWN`](#s2m_shutdown)
- [`S2M_INFO`](#s2m_info)
- [Master to Server](#master-to-server)
- [`M2S_CHALLENGE`](#m2s_challenge)
- [`M2S_NAT_CONNECT`](#m2s_nat_connect)
- [Client and game server](#client-and-game-server)
- [Client to Server](#client-to-server)
- [`C2S_BANDWIDTHTEST`](#c2s_bandwidthtest)
- [`C2S_GETCHALLENGE`](#c2s_getchallenge)
- [`C2S_CONNECT`](#c2s_connect)
- [Server to Client](#server-to-client)
- [`S2C_BANDWIDTHTEST`](#s2c_bandwidthtest)
- [`S2C_CHALLENGE`](#s2c_challenge)
- [`S2C_CONNECTION`](#s2c_connection)
- [`S2C_ERRORMSG`](#s2c_errormsg)
- [`S2C_REJECT`](#s2c_reject)
<!--TOC-->
## Any
### Any to Any
#### `A2A_PING` and `A2A_GOLDSRC_PING`
Simple ping message.
* Request, in ASCII: `ping` or `i` in GoldSrc format
* Response is always `A2A_ACK` or `A2A_GOLDSRC_ACK`
#### `A2A_ACK` and `A2A_GOLDSRC_ACK`
Simple ack message.
* Request, in ASCII: `ack` or `j` in GoldSrc format
* Response: none
#### Deprecated queries
These text-based Xash protocol queries are deprecated in favor of [GoldSrc server queries](#goldsrc-server-queries), which Xash3D FWGS servers implement as well. New implementations must not send them. The server still responds to `A2A_INFO` for compatibility with older clients, `A2A_NETINFO` is not handled anymore.
##### `A2A_NETINFO`
Used to implement Half-Life's NetAPI.
* Request message, in ASCII: `netinfo <version> <context> <request_id>`
-`version` must be 49, as text.
-`context` can be any 32-bit signed integer value, encoded as text.
-`request_id` see `common/net_api.h`
* Response message, in ASCII: `netinfo <context> <request_id> <response>`
-`context` same as in request.
-`request_id` same as in request.
-`response` is server's response, depending on request type. Always encoded as Quake info string.
Possible requests and response formats:
* Request ID `1` will make server respond with empty response string.
* Request ID `2` makes server respond with all server game rule cvars where the key is cvar name and the value is cvar value. One additional key `rules` with total amount of cvars is added.
* Request ID `3` makes server respond with players list, where:
-`p<id>name` is set to player's name
-`p<id>frags` is set to player's kill count
-`p<id>time` is set to player's total play time
-`players` is total player's list.
- Alternatively, it can respond with `neterror` set to `forbidden` if server does not wish to expose it's player list.
* Request ID `4` makes server to respond with common game details:
-`hostname` is server's name
-`gamedir` is game directory name
-`current` is total player count
-`max` is max players limit
-`map` is server's current level
* On any other server will respond with `neterror` set to `undefined`
* If protocol version doesn't match, server responds with `neterror` set to `protocol`
##### `A2A_INFO`
Used to request server's details.
* Request message, in ASCII: `info <version>`
-`version` must be 49, as text
* Response message, in ASCII: `info\n<response>`
-`response` is Quake info string, otherwise it's an error message.
* Response info string format:
-`p` is set to protocol version (FWGS extension)
-`map` is server's current level
-`dm` set to 1 if current game mode is deathmatch otherwise 0
-`team` set to 1 if current game mode includes teamplay otherwise 0
-`coop` set to 1 if current game mode is cooperative otherwise 0
-`numcl` is total player count
-`maxcl` is max players limit
-`gamedir` is game directory name
-`password` set to 1 if server is protected with password otherwise 0
-`host` is server's name
### Any to Client
#### `A2C_PRINT` and `A2C_GOLDSRC_PRINT`
Simple print message.
* Header: `\xff\xff\xff\xff`
* Request, in ASCII: `print <message>` or `l<message>` in GoldSrc format.
* Response: none
### Any to Server and Server to Any
#### GoldSrc server queries
These match Source Engine Query messages used in GoldSrc and Source engine and implemented for compatibility with existing server browsers and monitoring tools. The client uses them to query GoldSrc servers in the server browser, and as text-based Xash protocol queries are [deprecated](#deprecated-queries), it will use them to query Xash servers as well. Read documentation for them on VDC: https://developer.valvesoftware.com/wiki/Server_queries
Unlike other connectionless messages these are binary: integers are little-endian, floats are 32-bit IEEE 754 and strings are null-terminated.
`A2S_GOLDSRC_PLAYERS` and `A2S_GOLDSRC_RULES` requests carry a 32-bit challenge, `A2S_GOLDSRC_INFO` may have one appended after the query string. When no challenge is known yet, `\xff\xff\xff\xff` is sent in it's place. The server may answer with a challenge instead of the data: byte `A` (`0x41`) followed by a 32-bit challenge value, 9 bytes total with the header. The request is then repeated with the received challenge. Don't confuse this message with textual `S2C_GOLDSRC_CHALLENGE` used during connection, they only share the first byte.
Responses that don't fit into a single packet (usually rules) come from GoldSrc servers split into fragments. Such packets start with `\xfe\xff\xff\xff` instead of `\xff\xff\xff\xff`, followed by a 32-bit sequence number, same in all fragments of one response, and a byte with total fragment count in the lower 4 bits and this fragment's index in the upper 4 bits. Fragment payloads concatenated in index order form a normal `\xff\xff\xff\xff` message. Xash servers never split query responses and send them as single datagrams.
#### `A2S_GOLDSRC_INFO`
Used to request server's details.
* Request: `TSource Engine Query\0`, optionally followed by a 32-bit challenge. Xash servers ignore it.
* Response: byte `I` (`S2A_GOLDSRC_INFO`), followed by:
- byte: protocol version, 48 on GoldSrc, 49 on Xash3D FWGS
- string: server's name
- string: server's current level
- string: game directory name
- string: game description
- int16: Steam AppID, always 0 on Xash servers
- byte: total player count, bots included
- byte: max players limit
- byte: bot count
- byte: server type, `d` for dedicated or `l` for listen server
- byte: server's operating system, `w` for Windows, `l` for Linux, `m` for macOS
- byte: set to 1 if server is protected with password otherwise 0
- byte: set to 1 if server is VAC secured, Xash servers put the `secure` value from gameinfo here
- string: server's version
Same as the Source engine response format but without the extra data flag and its fields.
Legacy GoldSrc servers respond with the obsolete `m` format (`S2A_GOLDSRC_LEGACY_INFO`) instead, see VDC for its layout. Xash servers never send it but the client understands it and assumes protocol 48.
#### `A2S_GOLDSRC_PLAYERS`
Used to request server's player list.
* Request: byte `U` (`0x55`), then a 32-bit challenge.
* Response: byte `D` (`S2A_GOLDSRC_PLAYERS`), followed by a byte with total player count, then for each player:
- float: time in seconds the player is connected, -1.0 for bots on Xash servers
Xash server doesn't respond at all if the player list is empty, the server is protected with password or exposing the player list is disabled with `sv_expose_player_list` cvar.
#### `A2S_GOLDSRC_RULES`
Used to request server's game rules.
* Request: byte `V` (`0x56`), then a 32-bit challenge.
* Response: byte `E` (`S2A_GOLDSRC_RULES`), followed by an int16 with total rule count, then rule name and rule value strings for each.
Only server cvars (`FCVAR_SERVER`) are sent. Values of protected cvars (`FCVAR_PROTECTED`) are replaced with `1` if the value is set otherwise `0`. If there are no cvars to expose, server doesn't respond at all.
### Any to Master
#### `S2M_SCAN_REQUEST`
* Request: `1<region><IP:Port>\0<info>`
- Format of this message is loosely based on https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol
-`info` however adds few additional fields:
-`clver` set to engine's version
-`nat` set to 1 to filter only servers behind NAT and tell master to notify servers about scan
-`commit` set to engine's build commit hash
-`branch` set to engine's build branch
-`os` set to which operating system engine has been built
-`arch` set to which CPU architecture engine has been built
-`buildnum` set to engine's build number
-`key` set to random 32-bit value formatted as hex, used to validate master responses
* Response: `M2A_SERVERSLIST`
### Master to Any
#### `M2A_SERVERSLIST`
* Request: `f\xff<key><reserved><IP:Port>...`
-`key` is random 32-bit value set in `S2M_SCAN_REQUEST`
-`reserved` is single reserved 8-bit byte
- Following is list of IP addresses in binary form: 6-bytes for IPv4 address + port and 18-bytes for IPv6 address + port
- If port is 0, it means the end of list, otherwise it's the last IP used for pagination (not implemented in Xash3D)
* Response: client doesn't make response to master server but might request `A2S_GOLDSRC_INFO` from servers
## Master and game server
### Server to Master
#### `S2M_HEARTBEAT`
Used to update game server information on the master server.
* Request: `q\xff<heartbeat challenge>`
-`heartbeat challenge` is random 32-bit value, used to prevent faked/forged source IP addresses.
* Response: `M2S_CHALLENGE`
#### `S2M_SHUTDOWN`
Used to notify master server about server shutdown, but due to security reasons must be ignored by any master implementation.
* Request: `\x62\x0a`
* Response: none
#### `S2M_INFO`
Game server info response on `M2S_CHALLENGE`.
* Request: `0\n<info>`
-`info` is Quake info string containing server information passed to master server. It contains following fields:
-`protocol` is always 49
-`challenge` is master challenge
-`players` is total player count, without bots
-`max` is max players limits
-`bots` is total bot count
-`gamedir` is set to game directory
-`map` is server's current level
-`type` set to `d` for dedicated or `l` for listen server
-`password` set to `1` if server protected with password set otherwise `0`
-`os` always `w`
-`secure` always `0`
-`lan` always `0`
-`version` engine version
-`region` always `255`
-`product` same as `gamedir`
-`nat` set to `1` if server is behind NAT
* Response: none
### Master to Server
#### `M2S_CHALLENGE`
Master's respoonse on game server's heartbeat message.
-`master challenge` contains 32-bit value, used in server response to prevent faked/forged source IP addresses.
-`heartbat challenge` cotnains 32-bit value, used in heartbeat request to prevent faked/forged source IP addresses.
* Response: `S2M_INFO`.
#### `M2S_NAT_CONNECT`
Master server's message with client IP address and port, used in NAT punching.
* Request: `c <IP:Port>`
* Response: `S2C_INFO` to a specified client address.
## Client and game server
### Client to Server
#### `C2S_BANDWIDTHTEST`
Used to figure out network MTU. The message is optional and server might choose to not implement it or respond with challenge.
* Request, in ASCII: `bandwidth <version> <max_size>`
-`version` must be 49, as text.
-`max_size` is requested maximum packet size.
* Possible responses:
-`S2C_BANDWIDTHTEST`
-`S2C_CHALLENGE`
-`A2A_PRINT` followed by `S2C_REJECT`
-`S2C_ERRORMSG` (as FWGS extension) followed by `A2A_PRINT` and `S2C_REJECT`.
#### `C2S_GETCHALLENGE`
Used to validate client's address to prevent faked/forged source IP addresses.
* Header: `\xff\xff\xff\xff`
* Request, in ASCII: `getchallenge steam`
-`steam` argument is optional and can be ignored by the server, as it's only kept for compatibility with similar GoldSrc 48 message.
* Possible responses:
-`S2C_CHALLENGE`
#### `C2S_CONNECT`
Used to build a connection with the server.
* Header: `\xff\xff\xff\xff`
* Request, in ASCII: `connect <version> <challenge> "<protinfo>" "<userinfo>"`
-`version` must be 49, as text.
-`challenge` must be challenge value, as text.
-`protinfo` is a Quake info string, containing protocol extensions and other connection information.
-`uuid` is this client's unique ID (FWGS extension) hasheed with MD5.
-`qport` is random integer value from 1 to 65535, unique for this engine run.
-`ext` is an integer value OR'ed with requested protocol extensions. Currently only extension is `NET_EXT_SPLITSIZE` with the value of `1`, which tells server to split messages based on `cl_dlmax` value from `userinfo`.
-`userinfo` contains initial user info, encoded as Quake info string.
* Possible responses:
-`A2A_PRINT` followed by `S2C_REJECT`
-`S2C_ERRORMSG` (as FWGS extension) followed by `A2A_PRINT` and `S2C_REJECT`.
-`S2C_CONNECTION`
### Server to Client
#### `S2C_BANDWIDTHTEST`
* Request: `testpacket<crc><blob>`
-`crc` is 32-bit CRC of `blob`
-`blob` random data
* There is no required response to this message
Total message size doesn't exceed request max size.
#### `S2C_CHALLENGE`
* Request, in ASCII: `challenge <value>`
-`value` is challenge value that client must include in it's response
* Response: `C2S_CONNECT`
#### `S2C_CONNECTION`
* Request, in ASCII: `client_connect <protinfo>`
-`protinfo` is an optional Quake info string, contains following optional fields:
-`ext` is an integer value OR'ed with allowed protocol extension. Bit fields match requested in `ext` field in `C2S_CONNECT`
-`cheats` set to 1 if server allows cheats otherwise 0
* Response: there is no out of band from the client but client will proceed to building netchan and switch client-server interaction to it.
#### `S2C_ERRORMSG`
Show client error message. Doesn't mean connection reject, only used for UI.
* Request, in ASCII: `errormsg <message>`
-`message` contains error message
* Response: none
#### `S2C_REJECT`
Client has been rejected in connection.
* Request, in ASCII: `disconnect`
* Response: client can cope, get depressed or mentally tell server to fuck off.
1. Make sure your PSVita is [set up to run homebrew applications](https://vita.hacks.guide/).
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/) by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`) and add it to your `config.txt`, for example:
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/). It is recommended to use kubridge version `0.1`, because other versions aren't tested, we don't know are they suitable or not.
Worth to notice, we got reports that automatic plugins management app EasyPlugin have issues with installing kubridge plugin, so it's better to install it manually: by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`, but could be `ur0:/tai`) and add it to your `config.txt`, for example:
```
*KERNEL
ux0:tai/kubridge.skprx
```
3. Install `libshacccg.suprx` by following [this guide](https://cimmerian.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx).
As online community is growing, we don't want to keep bad or invalid servers on the Internet Games list. It's a common rules for all Xash3D server owners who are using default master server.
1. Breaking master server or clients is prohibited in any way. If you found a serious bug, contact us at contact 'at' fwgs.ru or post an issue at GitHub.
2. Changing settings, exploiting vulnerabilities of clients is prohibited in any way. If you found a serious bug, contact us at contact 'at' fwgs.ru or post an issue at GitHub.
2. Agressive advertisement and spam on other servers is prohibited in any way.
3. If your server is require downloading custom content, it should be available for everyone. Recommended way to deliver custom content is FastDL.
4. It's recommended to keep your server is up-to-date. You may use our public Debian/Ubuntu/Arch Linux [repository](https://github.com/FWGS/xash3d/wiki/How-to-set-up-a-Xash3D-Dedicated-Server-on-Debian-or-Ubuntu) to simplify updating process.
Just follow these rules to not get banned on our master server. Good luck, have fun!
Thanks to mittorn, we have the ability to fully customize the controls in Xash3D. The new config allows you to not only add and change control buttons, but also create custom menus. There is also a built-in visual editor available, which simplifies the customization process without the need for manual file editing.
## Editor mode usage
1. Launch Xash3D and start the game.
2. To enter the edit mode, click on the gear icon (command `touch_enableedit`).
3. In the edit mode, the grid is displayed. The number of cells can be changed with the command `touch_grid_count` (default is 50). The grid can be disabled with the command `touch_grid_enable 0`.
*Touch controls layout editor*

*Touch profiles window*

*Touch buttons parameters window*

## Layout editor features
* **Moving buttons**: click on a button, drag it to the desired location, and release.
* **Resizing buttons**: place your first finger on the top left corner of the button, and use your second finger to resize it.
* **Hiding/showing buttons**: select the button (it will turn red), then use the menu:
* **Close**: closes the editing mode (`touch_disableedit`).
* **Reset**: resets the button to its default values.
* **Hide/Show**: hides or shows the button (`touch_hide <name>` / `touch_show <name>`).
## Working with configuration files / console
All changes made in the visual editor are automatically saved to the touch profile file. The files are located in the `touch_profiles` folder inside game directory. The file name depends on the selected profile.
### Common commands in configuration files
```
// Comment: lines starting with // are ignored.
// Swipe zones for movement. Specify how far you need to swipe to speed up.
// The default values are set to be optimal for a small swipe to immediately walk quickly.
Flags define the behavior of the button. Their values are powers of two:
| Flag | Value | Description |
| --- | --- | --- |
| `TOUCH_FL_HIDE` | 1 | Hides the button (not displayed in the game, but visible in the editor). |
| `TOUCH_FL_NOEDIT` | 2 | Disables editing of the button in the editor. |
| `TOUCH_FL_CLIENT` | 4 | The button is client-side (not saved in the main control file). |
| `TOUCH_FL_MP` | 8 | The button is displayed only in multiplayer. |
| `TOUCH_FL_SP` | 16 | The button is displayed only in singleplayer. |
| `TOUCH_FL_DEF_SHOW` | 32 | The button is always displayed on startup. |
| `TOUCH_FL_DEF_HIDE` | 64 | The button is always hidden on startup. |
| `TOUCH_FL_DRAW_ADDITIVE` | 128 | The button colors are added together in blend mode. |
| `TOUCH_FL_STROKE` | 256 | Enables outline stroke around the button. |
Flags can be combined by adding their values together. For example, `5 = 1 + 4` is the combination of `TOUCH_FL_HIDE` and `TOUCH_FL_CLIENT` flags, which is a hidden client button.
*In the image below, the `spray`, `scores`, `messagemode` buttons are displayed simultaneously with the flag 8 and `loadquick`, `savequick` with the flag 16, and each is displayed in the corresponding game mode.*

## Useful commands
*`touch_hide <pattern>`: hides buttons by pattern.
*`touch_setcommand`: changes the command bound to a button.
*`touch_settexture`: quickly changes the button image.
*`touch_setcolor`: sets the button color.
*`touch_exportconfig`: exports the current configuration, including aspect ratio.
## Usage examples
*`touch_hide menu*` hides all buttons with names starting with `menu`.
*`touch_setcolor "attack" 255 160 0 128` changes the color of the primary fire button from opaque white to translucent orange, similar to the color of the HUD in Half-Life.
*Result of executing this command*

* Example of adding a new button with a custom icon (the `lastinv` command is used - quick change between weapons)

*View of this button in layout editor*

## Tips
* To prevent the `look` and `move` buttons from interfering with editing other elements, place them before the others in the configuration file.
* And vice versa, to make a button appear on top of others, place it at the end of the configuration file.
* You can assign commands to buttons that change other buttons, see the previous section "Usage examples".
* After editing each parameter of each individual button in the Touch Buttons section, do not forget to press Save, otherwise the applied parameters will not be saved.
* To create your own icon for the button, you can use any graphics editor (for Android, Photo Editor by iudesk is suitable). Saving conditions:
* Image format - `.png` with transparency (e.g. alpha channel)
* Aspect ratio / size - 1:1 / 256x256
* Path to the icons location - `touch/gfx` inside game directory.
### Additional links
* [Handy palette for selecting color in RGB format](https://www.rapidtables.com/web/color/RGB_Color.html)
> **Only download Xash3D FWGS from official sources.** Third-party builds, "modded launchers", "optimized" repacks and random mirrors are frequently bundled with malware, miners, spyware and credential stealers. We cannot vouch for anything we did not build. Get official binaries only from the [releases page](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous).
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
@@ -35,15 +39,22 @@ You still needed to copy `valve` directory as all game resources located there.
For additional info, run Xash3D with `-help` command line key.
## Contributing
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html.
### Android
0) Install the APK file.
1) Copy `valve` directory to a folder named `xash` in the Internal storage.
2) Run games from within the app.
## Reporting issues
* Issues are accepted in both English and Russian.
*Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
*They are only accepted if you run legally acquired product (e.g. Half-Life in Steam).
## Contributing code
* Check the CONTRIBUTING.md file.
## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
**NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!**
### Prerequisites
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
@@ -65,24 +76,43 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
* Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install build dependencies by running: `brew install python`.
* Clone the SDL2 repo `$ git clone --recursive https://github.com/libsdl-org/SDL.git -b SDL2` and compile the iOS framework by navigating to SDL/Xcode/SDL and opening the Xcode project.
* Clone this repository: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
### Building
#### Windows (Visual Studio)
0) Open command line.
@@ -99,3 +129,19 @@ If compiling 32-bit on amd64, make sure `PKG_CONFIG_PATH` from the previous step
1) Configure build: `./waf configure` (you need to pass `-8` to compile 64-bit engine on 64-bit x86 processor).
To build you should clone [SDL](https://github.com/libsdl-org/SDL) from `SDL2` branch and [HLSDK-portable](https://github.com/FWGS/hlsdk-portable) `mobile-hacks` branch repositories to 3rdparty folder, after that you should be able to open the project in Android Studio from `android` directory or manually call Gradle to build the APK.
#### iOS/iPadOS (MacOS only)
0) (optional) Examine which build options are available: `./waf --help`.
1) Configure build: `./waf configure --ios --enable-bundled-deps --sdl2 (path/to/SDL2.framework)`, set `--ios-simulator` instead of `--ios` if you want to build for simulator.
2) Compile `./waf build`.
3) Navigate to `build` and copy your compiled SDL2.framework there, then add your game dylibs to `build/ios/libs/(gamedir)/(dlls/cl_dlls)`(You can also run `scripts/ios/buildhlsdk.sh` instead to automatically create an ipa with hlsdk dylibs)
4) Run `scripts/ios/createipa.sh` to create an installable ipa
### Running tests
Tests are enabled with `--enable-tests` passed to `./waf configure` and can be run with `./waf --alltests`.
This builds both standalone unit tests and a separate engine test binary (`xash3d_tests`) that embeds engine-level tests. The engine test binary requires no game assets.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.