Recently, mods (Brutal Half-Life v3 and MMod) started to call this function
every frame as a hacky way to detect presence of some model on the level. I
don't know why they do that, but users (who co-incidentally run engine with
-dev) has been complaining about console spam.
This is why we can't have things.
* No more conversion from liblist.gam to gameinfo.txt. We are using liblist.gam directly now.
gameinfo.txt being native format to Xash3D not only remains, it takes priority over liblist.gam.
* Quake game directories now don't receive autogenerated gameinfo.txt.
* Empty directories don't get gameinfo.txt either, finally making it easier to support HD addon folders.
* If user still wishes to generate gameinfo.txt, there is now command fs_make_gameinfo that creates
gameinfo.txt for currently running game.
* No more creating empty folders for RoDir. They are now created on demand.
On Linux, it uses memfd_create syscall that can be found on Linux 3.17 and
higher. By default memfds are executable, so we set MFD_NOEXEC_SEAL flag to
prevent execution at creation time.
This function is kinda nasty, some mods (like old RCBot builds) expect a slash,
some newer mods (like Sandbot) doesn't. To preserve compatibility with both old
and new mods, just add it as bug compatibility flag.
In API level 21 **and** _FILE_OFFSET_BITS == 64 we don't get fseeko/ftello functions.
To avoid increasing API level, just set _FILE_OFFSET_BITS to some bogus value.
Undefining it doesn't work as opusfile sets it to 64 automatically.
This helps avoid issue when the bzip2 or libogg are compiled before header is
generated for them.
In theory, we shouldn't do that, but I guess dependency calculation through
include directives doesn't work when the file doesn't exist.
Main changes made by me besides engine differences:
* Text color changed to pure white for better readability
* An attempt to draw texture name in full size
The problem is that FCVAR_SERVER flagged cvars get saved to listenserver.cfg.
The game code usually sets sv_zmax value to worldspawn parameters and
listenserver.cfg gets generated before server DLL gets initialized.
This is the first setting I change after installing xash3d-fwgs. Some distros even patch xash3d-fwgs to enable vsync by default (e.g. Batocera).
Let's enable vsync by default here.
frag_message_buf wasn't always freed alongside with fragbuf_t
instead of ensuring frag_message_buf being freed, I turned it into
a flexible array member
By reusing a padding hole in resource_t structure, we put a bit indicating that this archive
was already mounted by filesystem and skip it.
Because we associate this with resource, theoretical use of late precache with archives
will rescan filesystem and allow using newly downloaded assets.
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.
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol.Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol.<br>Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |
| `get_game_dir_full` | Makes server return full path in server's `pfnGetGameDir` API function | Mods targetting engine before HL 1.1.1.1, according to MetaMod [documentation](http://metamod.org/engine_notes.html#GetGameDir) |
after creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description
### ent_fire
Make some actions on entity
`ent_fire <pattern> <command> <args>`
Availiavle commands:
* Set fields (Only set entity field, does not call any functions):
* health
* gravity
* movetype
* solid
* rendermode
* rendercolor (vector)
* renderfx
* renderamt
* hullmin (vector)
* hullmax (vector)
* Actions
* rename: set entity targetname
* settarget: set entity target (only targetnames)
* setmodel: set entity model (does not update)
* set: set key/value by server library
* See game FGD to get list.
* command takes two arguments
* touch: touch entity by current player.
* use: use entity by current player.
* movehere: place entity in player fov.
* drop2floor: place entity to nearest floor surface
* moveup: move entity to 25 units up
* moveup (value): move by y axis relatively to specified value
* Flags (Set/clear specified flag bit, arg is bit number):
* setflag
* clearflag
* setspawnflag
* clearspawnflag
### ent_info
Print information about entity by identificator
`ent_info <identificator>`
### ent_getvars
Set client cvars containing entity information (useful for [[Scripting]]) and call ent_last_cb
`ent_getvars <identificator>`
These cvars are set:
```
ent_last_name
ent_last_num
ent_last_inst
ent_last_origin
ent_last_class
```
### ent_list
Print short information about antities, filtered by pattern
`ent_list <pattern>`
## Syntax description
### \<identificator\>
* !cross: entity under aim
* Instance code: !\<number\>_\<seria\l>
* set by ent_getvars command
* Entity index
* targetname pattern
### \<pattern\>
Pattern is like identificator, but may filter many entities by classname
### (vector)
used by ent_fire command. vector means three float values, entered without quotes
### key/value
All entities parameters may be set by specifiing key and value strings.
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
If value contains spaces, it must be put in quotes:
`ent_fire !cross set origin "0 0 0"`
## Using with scripting
ent_create and ent_getvars commands are setting cvars on client
It can be used with ent_last_cb alias that is executed after setting cvars.
Simple example:
```
ent_create weapon_c4
alias ent_last_cb "ent_fire \$ent_last_inst use"
```
Use weapon_c4 after creating it.
Note that you cannot use many dfferent callbacks at the same time.
You can set entity name by by pattern and create special script, contatning all callbacks.
Example:
example.cfg
```
alias ent_last_cb exec entity_cb.cfg
ent create \<class\> targetname my_ent1_$name
ent_create \<class\> targetname my_ent2_$name
```
entity_cb.cfg
```
if $ent_last_name == my_ent1_$name
:(ent1 actions)
if $ent_last_name == my_ent2_$name
:(ent2 actions)
```
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
## Server side
To enable entity tools on server, set sv_enttools_enable to 1
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
To enable actions on players, set sv_enttools_players to 1.
To enable entity tools for player by nickname, set sv_enttools_godplayer to nickname. Useful to temporary enable from rcon.
To prevent crash on some actions, set host_mapdesign_fatal to 0
For some features described below, you need to enable [console scripting](https://github.com/FWGS/xash3d-fwgs/blob/master/Documentation/extensions/console-scripting.md) with command `cmd_scripting 1` in console.
To get more information about it, check another according page related to console scripting.
## Commands description
### ent_create
Create entity with specified classname and key/values.
After creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description.
### ent_fire
Makes some actions on entity.
`ent_fire <pattern> <command> <args>`
#### Available commands:
Set fields (only set entity field, does not call any functions)
* health
* gravity
* movetype
* solid
* rendermode
* rendercolor (vector)
* renderfx
* renderamt
* hullmin (vector)
* hullmax (vector)
Actions
* rename: set entity targetname
* settarget: set entity target (only targetnames)
* setmodel: set entity model (does not update)
* set: set key/value by server library
* See game FGD to get list.
* command takes two arguments
* touch: touch entity by current player.
* use: use entity by current player.
* movehere: place entity in player fov.
* drop2floor: place entity to nearest floor surface
* moveup: move entity to 25 units up
* moveup (value): move by y axis relatively to specified value
Flags (set/clear specified flag bit, arg is bit number):
* setflag
* clearflag
* setspawnflag
* clearspawnflag
### ent_info
Print information about entity by identificator.
`ent_info <identificator>`
### ent_getvars
Set client cvars containing entity information (useful for [scripting](extensions/console-scripting.md)) and then calls ent_last_cb.
`ent_getvars <identificator>`
These cvars are set:
```
ent_last_name
ent_last_num
ent_last_inst
ent_last_origin
ent_last_class
```
### ent_list
Print short information about antities, filtered by pattern.
`ent_list <pattern>`
## Syntax description
#### \<identificator\>
* !cross: entity under aim
* !\<number\>_\<serial\>: instance code
* Set by ent_getvars command
* Entity index
* Targetname pattern
#### \<pattern\>
Pattern is like identificator, but may filter many entities by classname.
#### (vector)
Used by ent_fire command. vector means three float values, entered without quotes.
#### key/value
All entities parameters may be set by specifiing key and value strings.
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
If value contains spaces, it must be put in quotes:
`ent_fire !cross set origin "0 0 0"`
## Using with scripting
ent_create and ent_getvars commands are setting cvars on client
It can be used with ent_last_cb alias that is executed after setting cvars.
Simple example:
```
ent_create weapon_c4
alias ent_last_cb "ent_fire \$ent_last_inst use"
```
Use weapon_c4 after creating it.
Note that you cannot use many different callbacks at the same time.
You can set entity name by by pattern and create special script, contatning all callbacks.
Example:
> example.cfg
```
alias ent_last_cb exec entity_cb.cfg
ent create \<class\> targetname my_ent1_$name
ent_create \<class\> targetname my_ent2_$name
```
> entity_cb.cfg
```
if $ent_last_name == my_ent1_$name
:(ent1 actions)
if $ent_last_name == my_ent2_$name
:(ent2 actions)
```
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
## Server side configuration
To enable entity tools on server, set sv_enttools_enable to 1
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
@@ -78,12 +78,16 @@ These strings are specific to Xash3D FWGS.
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
| `demomap` | string | Empty string | The name of the demo chapter map (Half-Life Uplink) |
## Note on GoldSrc liblist.gam support
As Xash3D accidentally supports GoldSrc games, it also supports parsing liblist.gam.\
Xash3D will use this file if gameinfo.txt is absent, or if its modification timestamp is older than liblist.gam.
> [!NOTE]
> Starting from January 2025, Xash3D FWGS doesn't automatically generate gameinfo.txt from liblist.gam. The key conversion table still remains but if you wish to use gameinfo.txt instead of liblist.gam, you can execute `fs_make_gameinfo` in console.
For game creators who plan supporting only Xash3D, using this file is not recommended.
The table below defines conversion rules from liblist.gam to gameinfo.txt. Some keys' interpretation does differ from `gameinfo.txt`, in this case a note will be left. If `liblist.gam` key isn't present in this table, it's ignored.
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.
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
Also, 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.
Since IPv6 not as widespread as we would like, NAT (Network Address Translation) still being actively used by many internet service providers in an attempts to
mitigate IPv4 addresses exhaustion. In short, they uses one IPv4 address and doing some tricks with ports to represent many other users behind this address.
But this leads to a problem for users: they cannot accept direct
incoming connections anymore. This means that if you are behind provider's NAT and will try to setup Xash3D FWGS server - nobody will be able to connect to it,
and the server will not show up in servers public list.
## Is it possible to avoid this problem?
In most cases, it is possible to bypass NAT with UDP hole punching, and Xash3D FWGS uses this method too. But this method is not 100% guaranteed to work - it depends
on NAT configurations on both server and client side, and there is no way to control it.
First of all, server should not be behind symmetric NAT. You can check your NAT type on [this page](https://www.checkmynat.com/).
If you get "Symmetric NAT" result in this test, that means you cannot setup publicly available server with internet connection that you are using.
Here is more detailed scheme of different NAT types compatibility, it explains are users with different NAT types can connect to each other or not.
Client NAT type on rows, server NAT type on columns:
| *NAT Type* | Full Cone | Restricted Cone | Port Restricted Cone | Symmetric |
If you are starting server within the game, you need to enable option "*Use NAT Bypass instead of direct mode*" in bottom left corner of screen.
If you are starting dedicated server, you should add console variable `sv_nat 1` to server.cfg file, or add `+sv_nat 1` to server startup parameters.
If you need to connect to server behind NAT, there is separate tab named *NAT* for such servers in server browser. Note that it is useless to add NAT server to favorites,
or somehow trying manually to store it, because it has changing address and port.
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
- [List of mods for Counter Strike(Android only)](#list-of-mods-for-counter-strike)
- [List of mods for Counter Strike](#list-of-mods-for-counter-strike)
- [List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS](#list-of-supported-mods-from-mobile_hacks-branch-of-hlsdk-portable-by-fwgs)
# List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
1. [Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)
Originally this list was written by *Qwertyus*(*Qortez*)
@@ -176,7 +191,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
@@ -379,7 +394,7 @@ Mods:
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
8. [Lost in Black Mesa(first version without HLFX)](https://web.archive.org/web/20160407041812/http://half-life.ru/forum/showthread.php?threadid=13959) (download links dead!)
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
@@ -498,8 +513,8 @@ Mods:
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
Xash3D 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.
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.
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
@@ -11,16 +11,17 @@ Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://ww
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
## Fork features
* Steam Half-Life (HLSDK 2.4) support.
* Steam Half-Life (HLSDK 2.5) support.
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
* Mobility API: better game integration on mobile devices (vibration, touch controls)
* Mobility API: better game integration on mobile devices (vibration, touch controls).
* Different input methods: touch and gamepad in addition to mouse & keyboard.
* TrueType font rendering, as a part of mainui_cpp.
* [A set of small improvements](Documentation/), without broken compatibility.
## Installation & Running
@@ -28,29 +29,28 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
1) Copy engine binaries to some directory.
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
You still needed to copy `valve` directory as all game resources located there.
3) Run the main executable (`xash3d.exe` or AppImage).
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
* Issues are accepted in both English and Russian
* 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.
* Issues are accepted in both English and Russian.
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read https://waf.io/book/
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!
### Prerequisites
If your CPU is x86 compatible, 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.
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.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
#### Windows (Visual Studio)
* Install Visual Studio.
@@ -62,31 +62,40 @@ This repository contains our fork of HLSDK and restored source code for some of
#### GNU/Linux
##### Debian/Ubuntu
*Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this
*Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
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.