A library that contains some functions and optimizations for gmod.
If you need any function, make an issue for it, and I'll look into it.
So currently to get it working on Windows, I would have to redo most of the hooks, and It would also take a good while.
Because of this, I'm not going to make it currently. I'm gonna slowly start adding all symbols and then someday I'm going to redo most hooks.
But for now there won't be a release.
- Download the
ghostinj.dll
,holylib.vdf
andgmsv_holylib_linux.so
from the latest release. - Put the
ghostinj.dll
into the main directory wheresrcds_linux
is located. - Put the
holylib.vdf
into thegarrysmod/addons/
directory. - Put the
gmsv_holylib_linux.so
into thegarrysmod/lua/bin/
directory. - Add
-usegh
to the servers startup params.
If you use a panel like Pterodactyl or something similar, you can use the gamemode field(in most cases) like this:sandbox -usegh
If you already had a ghostinj.dll
, you can rename it to ghostinj2.dll
and it will be loaded by holylib's ghostinj.
- Download the
holylib.vdf
andgmsv_holylib_linux.so
from the latest release. - Put the
holylib.vdf
into thegarrysmod/addons/
directory. - Put the
gmsv_holylib_linux.so
into thegarrysmod/lua/bin/
directory.
- [+] Added entitylist
module.
- - [+] Many pvs.*
function accept now a EntityList
.
- - [+] pas.TestPAS
accepts a EntityList
.
- - [#] Improved pas.FindInPAS
performance by using it internally if it's enabled.
- [+] Added the HolyLib:PreCheckTransmit
, HolyLib:OnPlayerGot[On/Off]Ladder
, HolyLib:OnMoveTypeChange
hook.
- [+] Added HolyLib:OnSourceTVStartNewShot
, HolyLib:OnSourceTVClientDisconnect
hook to sourcetv
module.
- [+] Added INetworkStringTable:GetTable
and HLTVClient:GetTable
functions to sourcetv
and stringtable
module.
- [+] Added pvs.TestPVS
and pvs.FindInPVS
functions to pvs
module.
- [+] Added HolyLib.ExitLadder
and HolyLib.GetLadder
to holylib
module.
- [#] Fixed many issues with the bass
module. It is acutally usable.
- [#] All pvs.FL_EDICT_
enums changed.
- [#] Improved performance by replacing SetTable with RawSet.
- [#] Added missing calls to the deconstructors for CHLTVClient
and CNetworkStringTable
.
- - These missing calls could have caused some bugs or memory leaks.
- [#] Fixed a bug with sourcetv where CHLTVClients
could be NULL while being valid (#15)
You can see all changes here:
https://github.com/RaphaelIT7/gmod-holylib/compare/Release0.6...main
- [#] Cleaned up code a bit
- [#] Switched away from the ILuaBase. All Lua functions now use ILuaInterface.
- Finish 64x (pvs
, sourcetv
, surffix
)
- Find out why ConVars are so broken. (Serverside path
command breaks :<)
- Look into filesystem handle optimization
- Try to fix that one complex NW2 bug. NOTE: It seems to be related to baseline updates (Entity Creation/Deletion)
- Look into StaticPropMgr stuff. May be interresting.
- Add a bind to CAI_NetworkManager::BuildNetworkGraph
or StartRebuild
- Possibly allow on to force workshop download on next level change.
- GO thru everything and use a more consistant codestyle. I created quiet the mess.
Modules
- holylib
- gameevent
- threadpoolfix
- precachefix
- stringtable
- - INetworkStringTable
- pvs
- surffix
- filesystem
- util
- concommand
- vprof
- - VProfCounter
- - VProfNode
- sourcetv
- - HLTVClient
- bitbuf
- - bf_read
- - bf_write
- networking
- steamworks
- systimer
- pas
- voicechat
- - VoiceData
- physenv
- bass
- - IGModAudioChannel
- entitylist
Unfinished Modules
- serverplugins
Issues implemented / fixed
Some things for later
This is most likely cause by the filesystem prediction.
You can use holylib_filesystem_showpredictionerrors
to see any predictions that failed.
You can solve this by setting holylib_filesystem_predictexistance 0
.
The convar was disabled by default now because of this.
Each module has its own convar holylib_enable_[module name]
which allows you to enable/disable specific modules.
You can add -holylib_enable_[module name] 0
to the startup to disable modules on startup.
Every module also has his holylib_debug_[module name]
version and command line option like above, but not all modules use it.
The modules that use that convar have it listed in their ConVars chapter.
All hooks that get called use hook.Run
. Gmod calls gamemode.Call
.
There is -holylib_startdisabled
which will cause all modules to be disabled on startup.
And with holylib_toggledetour
you can block specific detours from being created.
This module contains the HolyLib library.
Player ply - The Player to reconnect.
Returns true
if the player was successfully reconnected.
bool hide - true
to hide the server from the serverlist.
Will just set the hide_server
convar in the future.
HolyLib.FadeClientVolume(Player ply, number fadePercent, number fadeOutSeconds, number holdTime, number fadeInSeconds)
Fades out the clients volume.
Internally just runs soundfade
with the given settings on the client.
Forces all queried commands to be executed/processed.
Returns true
if the given map is valid.
Allows you to create an entity message.
NOTE: If the bitbuf
module is disabled, it will throw a lua error!
Allows you to create any registered usermessage.
NOTE: If the bitbuf
module is disabled, it will throw a lua error!
Finishes the active Entity/Usermessage.
If you don't call this, the message won't be sent! (And the engine might throw a tantrum)
Sends a custom net message to all clients.
This function allows you send any netmessage you want.
You should know what your doing since this function doesn't validate anything.
You can find all valid types in the protocol.h
Same as BroadcastCustomMessage but it only sends it to the specific player.
Invalidates the bone cache of the given entity.
NOTE: Only uses this on Entities that are Animated / Inherit the CBaseAnimating class. Or else it will throw a Lua error.
Sets the SignOnState for the given client.
Returns true
on success.
Forces the player off the ladder.
Returns the Ladder the player is currently on.
Allows you to override the server tags.
Return nothing / nil to not override them.
Example:
hook.Add("HolyLib:GetGModTags", "Example", function()
local tags = {
"gm:sandbox", -- Gamemode name. (Not title!)
"gmc:sandbox", -- Gamemode category
"ver:"..VERSION, -- Server version
"loc:de", -- server location
"hltv:1", -- mark the server as a hltv server.
"gmws:123456789", -- Gamemode workshop id (Do collectons work? idk)
}
return table.concat(tags, " ")
end)
Called before CBaseEntity::PostConstructor
is called.
This should allow you to set the EFL_SERVER_ONLY
flag properly.
Called when a gets onto a ladder -> Direct bind to CFuncLadder::PlayerGotOn
Called when a gets off a ladder -> Direct bind to CFuncLadder::PlayerGotOff
Called when the movetype is about to change.
If you call Entity:SetMoveType
on the current entity inside this hook, it would have no effect.
This module contains additional functions for the gameevent library.
With the Add/Get/RemoveClient* functions you can control the gameevents that are networked to a client which can be useful.
string name(optional) - The event to return the count of listeners for.
If name is not a string, it will return a table containing all events and their listener count:
{
["player_spawn"] = 1
}
NOTE: Can return
nil
on failure.
string name - The event to remove the Lua gameevent listener from.
Returns true
if the listener was successfully removed from the given event.
Returns a table containing all gameevents the given client is listening to.
If not given a player, it will return a table containing all players and the gameevent they're listening to.
Removes the player from listening to the given gameevent.
If the given gameevent is nil
it will remove the player from all gameevents.
Returns true
on success.
Adds the given player to listen to the given event.
Returns true
on success.
Creates the given gameevent.
Can return nil
on failure.
Fires the given gameevent.
If bDontBroadcast
is specified, it won't be networked to players.
Fires the given event for only the given player.
Duplicates the given event.
Blocks/Unblocks the creation of the given gameevent.
Returns the a formated string.
Format: IGameEvent [%s]
%s
-> Gameevent name
Deletes the gameevent internally.
Returns true
if the gameevent is valid.
Returns true
if the gameevent is empty.
Returns true
if the gameevent is reliable.
Returns true
if the gameevent is only local/serverside.
This means it won't be networked to players.
Returns the gameevent name.
Returns the bool for the given key and if not found it returns the fallback.
Returns the int for the given key and if not found it returns the fallback.
Returns the float for the given key and if not found it returns the fallback.
Returns the string for the given key and if not found it returns the fallback.
Sets the bool for the given key.
Sets the int for the given key.
Sets the float for the given key.
Sets the string for the given key.
Called when the client sends the gameevent list it wants to listen to.
Return true
to stop the engine from future processing this list.
NOTE: This and the hook below may be called with a NULL player.
it is caused by the player registering the gameevents before he spawned/got an entity.
Because of this, the third argument was added.
Called after the engine processed the received gameevent list.
If enabled, it will call the gameevent hooks.
My debug stuff :> It'll never be important for you.
This module modifies CThreadPool::ExecuteToPriority
to not call CThreadPool::SuspendExecution
when it doesn't have any jobs.
This is a huge speed improvement for adding searchpaths / mounting legacy addons.
NOTE: This requires the
ghostinj.dll
to be installed!
This module removes the host error when the model or generic precache stringtable overflows.
Instead it will throw a warning.
If these stringtables overflow, expect the models that failed to precache to be an error.
string model - The model that failed to precache.
number idx - The index the model was precache in.
string model - The model that failed to precache.
Return a index number to let the engine fallback to that model or return nil
to just let it become an error model.
string file - The file that failed to precache.
number idx - The index the file was precache in.
string file - The file that failed to precache.
Return a index number to let the engine fallback to that generic or return nil
to just let it be.
Idk if it's a good Idea to play with it's fallback.
The fallback index if a model fails to precache.
-1
= Error Model
0
= Invisible Model
The fallback index if a generic fails to precache.
This module adds a new library called stringtable
, which will contain all functions to handle stringtables,
and it will a hook for when the stringtables are created, since they are created while Lua was already loaded.
NOTE: For now, all functions below are just a bind to their C++ versions -> INetworkStringTable
INetworkStringTable stringtable.CreateStringTable(string tablename, number maxentries, number userdatafixedsize = 0, number userdatanetworkbits = 0)
string tablename - The name for the stringtable we want to create.
number maxentries - The maximal amount of entries.
number userdatafixedsize(default 0
) - The size of the userdata.
number userdatanetworkbits(default 0
) - The networkbits to use for the userdata.
Returns nil
or a INetworkStringTable
.
Nuke all stringtables. BOOOM
string tablename - The table to search for
Returns nil
or the INetworkStringTable
number tableid - The tableid of the table to get
Returns nil
or the INetworkStringTable
Returns the number of stringtables that exist.
INetworkStringTable stringtable.CreateStringTableEx(string tablename, number maxentries, number userdatafixedsize = 0, number userdatanetworkbits = 0, bool bIsFilenames = false )
string tablename - The name for the stringtable we want to create.
number maxentries - The maximal amount of entries.
number userdatafixedsize(default 0
) - The size of the userdata.
number userdatanetworkbits(default 0
) - The networkbits to use for the userdata.
bool bIsFilenames(default false
) - If the stringtable will contain filenames.
INetworkStringTable table - The table to set it on
bool bAllowClientSideAddString - If clients should be able to modify the stringtable.
Returns whether you're allowed to create stringtables.
Returns if the stringtable is locked or not.
Sets whether you're allowed to create stringtable.
Example:
stringtable.AllowCreation(true)
stringtable.CreateStringTable("example", 8192)
stringtable.AllowCreation(false)
NOTE: Please use the
HolyLib:OnStringTableCreation
hook to add custom stringtables.
Deletes that specific stringtable.
This is a metatable that is pushed by this module. It contains the functions listed below
Returns INetworkStringTable [NULL]
if given a invalid table.
Normally returns INetworkStringTable [tableName]
.
Internally implemented and will set the values into the lua table.
Internally seaches first in the metatable table for the key.
If it fails to find it, it will search in the lua table before returning.
If you try to get multiple values from the lua table, just use INetworkStringTable:GetTable()
.
Returns the lua table of this object.
You can store variables into it.
Returns the name of the stringtable
Returns the id of the stringtable
Returns the number of strings this stringtable has
Returns the maximum number of string this stringtable has
ToDo: I have no idea
number tick - The tick to set the stringtable to
Returns the number of strings this stringtable has
number tick - The tick to set the stringtable to
Returns whether or not the stringtable changed since that tick.
bool bIsServer - Weather or not the server is adding this value? (Idk, added it so you have more control.)
string pStr - The string to add
Returns the index of the added string.
number index - The index to get the string from
Returns the string from that index
Returns a table containing all the strings.
string pStr - The string to find the index of
Returns the index of the given string.
Deletes all strings from the stringtable.
If nukePrecache
is true
, it will remove all precache data for the given stringtable.
number maxEntries - The new limit for entries.
Sets the new Entry limit for that stringtable.
The new limit will work but for some stringtables, it might cause issues, where the limits are hardcoded clientside.
A list of known stringtables with hardcoded limits:
modelprecache
-> Limited byCClientState::model_precache
genericprecache
-> Limited byCClientState::generic_precache
soundprecache
-> Limited byCClientState::sound_precache
decalprecache
-> Limited byCClientState::decal_precache
networkvars
-> Limited by the internal net message used.
NOTE: If there are already more entries than the new limit, they won't be removed.
(This could cause issues, so make sure you know what you're doing.)
Deletes the given string at the given index.
Returns true
if the string was deleted.
NOTE: Currently this deletes all strings and readds all except the one at the given index. This is slow and I need to improve it later.
NOTE: This also removes the precache data if you delete something frommodelprecache
or so.
Returns true
if the stringtable is still valid.
Sets the UserData for the given index.
length
is optional and should normally not be used. It could cause crashes is not used correctly!
How this could be useful:
local dataTablePaths = {
"/lua/", -- The order is also important!
-- Add paths that are frequently used to the top so there the first one to be checked for a file.
-- This will improve the performance because it will reduce the number of paths it checks for a file.
"/addons/exampleaddon/lua/", -- Each legacy addon that has a lua folder has it's path.
"/workshop/lua/",
"/workshop/gamemode/",
"/gamemode/",
"/workshop/gamemodes/base/entities/",
"/gamemodes/base/entities/",
"/workshop/gamemodes/sandbox/entities/",
"/gamemodes/sandbox/entities/",
}
local client_lua_files = stringtable.FindTable("client_lua_files")
client_lua_files:SetStringUserData(0, table.concat(dataTablePaths, ";")) -- Set our new datatable paths.
-- Reducing the amount of paths will improve clientside filesystem performance
-- You can see all datapack paths by running "datapack_paths" clientside or printing it like this:
-- print(client_lua_files:GetStringUserData(0))
-- NOTE: Changes to the datatable path will only affect the lcl search path clientside.
Returns the userdata of the given index.
Second return value is the length/size of the data.
Sets the number as userdata for the given string.
Returns the userdata of the given index. It needs to be a int!
Sets the CPrecacheUserData
and sets the flags of it to the given value.
Returns the flags of CPrecacheUserData
.
This module adds these enums
This value is returned if the index of a string is invalid, like if INetworkStringTable:AddString fails.
This module calls these hooks from (hook.Run
)
You can create stringtables inside this hook.
If you want to create stringtables outside this hook, use stringtable.AllowCreation
This adds a bunch of PVS related functions.
Resets the current PVS.
Checks if the given position is inside the current PVS.
Adds the given Origin to the PVS. Gmod already has this function.
Returns the number of clusters that exist.
Returns the cluster id of the given origin.
Returns whether or not the given areas are connected.
We don't validate if you pass valid areas!
Returns the area id of the given origin.
Sets the current PVS to that of the given cluster.
We don't validate if the passed cluster id is valid!
Returns whether or not the given box is inside the PVS.
Adds the given entity index to the PVS
table ents - A sequential table containing all the entities which states flags should be overridden.
bool force - Allows you to set the flags directly. It won't make sure that the value is correct!
Overrides the StateFlag for this Snapshot.
The value will be reset in the next one.
NOTE: If you use force, you should know what your doing or else it might cause a crash.
table ents - A sequential table containing all the entities which states should be set.
bool force - Allows you to set the flags directly. It won't make sure that the value is correct!
Sets the State flag for this entity.
Unlike OverrideStateFlag
, this won't be reset after the snapshot.
NOTE: If you use force, you should know what your doing or else it might cause a crash.
bool force - Allows you to get all flags instead of only the ones for networking.
Returns the state flags for this entity.
table ents - A sequential table containing all the entities that should be removed from being transmitted.
Returns true if the entity or all entities were successfully removed from being transmitted.
NOTE: Only use this function inside the
HolyLib:[Pre/Post]CheckTransmit
hook!
Removes all Entities from being transmitted.
NOTE: Only use this function inside the
HolyLib:[Pre/Post]CheckTransmit
hook!
table ents - A sequential table containing all the entities that should be transmitted.
bool always - If the entity should always be transmitted? (Verify)
Adds the given Entity to be transmitted.
NOTE: Only use this function inside the
HolyLib:[Pre/Post]CheckTransmit
hook!
Returns true
if the baseline is empty.
This should always be the case after a full update.
NOTE: Only use this function inside the
HolyLib:[Pre/Post]CheckTransmit
hook!
REMOVED: This function was removed since I can't get it to work / It would be a bit more complicated than first anticipated.
pvs.SetPreventTransmitBulk(Entity ent / table ents / EntityList list, Player ply or table plys or RecipientFilter filter, bool notransmit)
table ents - A sequential table containing all the entities that should be affected.
table plys - A sequential table containing all the players that it should set it for.
bool notransmit - If the entity should stop being transmitted.
Adds the given Entity to be transmitted.
Returns true
if the given entity / position is inside the PVS of the given origin.
If given a EntityList, it will return a table wich contains the result for each entity.
The key will be the entity and the value is the result.
Returns a table containing all entities that are inside the pvs.
The Entity won't be networked.
The Entity will always be networked.
The Entity will only be networked if it's inside the PVS.
The Entity's ShouldTransmit
function will be called, and its return value will be used.
Called before the transmit checks are done.
Return true
to cancel it.
You could do the transmit stuff yourself inside this hook.
entity ply - The player that everything is transmitted to.
table enitites - The Entities that get transmitted. Only available if holylib_pvs_postchecktransmit
is set to 2
or higher.
NOTE: This hook is only called when
holylib_pvs_postchecktransmit
is enabled!
If enabled, it will add/call the HolyLib:PostCheckTransmit
hook.
If set to 2
it will also pass a table containing all entitites to the hook (The second argument)
This module ports over Momentum Mod's surf fixes.
If enabled, it will enable additional checks to make sure that the player is not stuck in a ramp.
This module contains multiple optimizations for the filesystem.
If enabled, it will check if the file contains a .
after the last /
.
If so it will cause CBaseFileSystem::IsDirectory
to return false since we assume it's a file.
This will cause file.IsDir
to fail on folders with names like these test/test1.23
.
If enabled, it will cause the filesystem to use a cache for the searchpaths.
When you try to open a file with a path like GAME
which has multiple searchpaths, it will check each one until its found.
Now, the first time it searches for it, if it finds it, we add the file and the searchpath to a cache and the next time the same file is searched for, we try to use our cache search path.
This will improve file.Open
, file.Time
and file.Exists
.
The more searchpaths exist, the bigger the improvement for that path will be.
Example (I got 101 legacy addons):
lua_run local a = SysTime() for k=1, 1000 do file.Exists("garrysmod.ver", "GAME") end print(SysTime()-a)
Disabled: 1.907318733
Enabled: 0.035948700999995
You also can test it using the MOD
path. The performance of file.Exists
for any search path and MOD
should be somewhat near each other since, it checks the same amount of searchpaths while this is enabled.
lua_run local a = SysTime() for k=1, 1000 do file.Exists("garrysmod.ver", "GAME") end print(SysTime()-a)
0.033513544999998
lua_run local a = SysTime() for k=1, 1000 do file.Exists("garrysmod.ver", "MOD") end print(SysTime()-a)
0.037827891999996
- If the file doesn't exist, it will still go thru all search paths to search for it again!
- I don't know if this has any bugs, but while using this for ~1 Month on a server, I didn't find any issues.
- It will also improve the
MOD
search path since it also has multiple search paths.
If enabled, it will optimize the CBaseFileSystem::FixPath
function by caching the BASE_PATH
.
If enabled, it will check the searchcache inside CBaseFileSystem::OpenForRead
.
If enabled, it will force the pathID for specific files.
If enabled, it will split each GAME
path into multiple search paths, depending on it's contents.
Then when you try to find a file with the GAME
search path, it will change the pathID to the content path.
Example:
File: cfg/game.cfg
Path: GAME
becomes:
File: cfg/game.cfg
Path: CONTENT_CONFIGS
This will reduce the amount of searchpaths it has to go through which improves performance.
Content paths:
materials/
->CONTENT_MATERIALS
models/
->CONTENT_MODELS
sound/
->CONTENT_SOUNDS
maps/
->CONTENT_MAPS
resource/
->CONTENT_RESOURCE
scripts/
->CONTENT_SCRIPTS
cfg/
->CONTENT_CONFIGS
gamemodes/
->LUA_GAMEMODES
lua/includes/
->LUA_INCLUDES
Does the same for lsv
to save performance.
BUG: This currently breaks workshop addons.
Lua paths:
sandbox/
->LUA_GAMEMODE_SANDBOX
effects/
->LUA_EFFECTS
entities/
->LUA_ENTITIES
weapons/
->LUA_WEAPONS
lua/derma/
->LUA_DERMA
lua/drive/
->LUA_DRIVE
lua/entities/
->LUA_LUA_ENTITIES
vgui/
->LUA_VGUI
postprocess/
->LUA_POSTPROCESS
matproxy/
->LUA_MATPROXY
autorun/
->LUA_AUTORUN
If enabled, it will fallback to the original searchpath if it failed to find something in the split path.
This is quite slow, so disabling this will improve performance to find files that doesn't exist.
If enabled, it will try to predict the path for a file.
Example:
Your loading a model.
First you load the example.mdl
file.
Then you load the example.phy
file.
Here we can check if the example.mdl
file is in the searchcache.
If so, we try to use the searchpath of that file for the .phy
file and since all model files should be in the same folder, this will work for most cases.
If we fail to predict a path, it will end up using one additional search path.
If enabled, it will try to predict the path of a file, but if the file doesn't exist in the predicted path, we'll just say it doesn't exist.
Doesn't rely on holylib_filesystem_predictpath
but it also works with it together.
The logic for prediction is exactly the same as holylib_filesystem_predictpath
but it will just stop checking if it doesn't find a file in the predicted path instead of checking then all other searchpaths.
If enabled, it will fix up weird gamemode paths like sandbox/gamemode/sandbox/gamemode which gmod likes to use.
Currently it fixes these paths:
[Active gamemode]/gamemode/[anything]/[active gamemode]/gamemode/
-> (Example:sandbox/gamemode/spawnmenu/sandbox/gamemode/spawnmenu/
)include/include/
If enabled, it will cache the file handle and return it if needed.
NOTE: This will probably cause issues if you open the same file multiple times.
WARNING: This is a noticeable improvement, but it seems to break .bsp files :/
If enabled, it will print all filesyste suff.
Dumps the searchcache into the console.
ToDo: Allow one to dump it into a file.
Dumps the path for the given searchpath id.
The id is the one listed with each file in the dumped searchcache.
Nukes the searchcache.
Shows all files that were predicted to not exist.
This module also adds a filesystem
library which should generally be faster than gmod's functions, because gmod has some weird / slow things in them.
It also gives you full access to the filesystem and doesn't restrict you to specific directories.
(FSASYNC Enum) filesystem.AsyncRead(string fileName, string gamePath, function callBack(string fileName, string gamePath, FSASYNC status, string content), bool sync)
Reads a file async and calls the callback with the contents.
Creates a directory in the given path.
Deletes the given file.
Returns true
if the given file exists.
table(Files), table(Folders) filesystem.Find(string filePath, string gamePath, string sorting = "nameasc")
Finds and returns a table containing all files and folders in the given path.
Returns true
if the given file is a directory.
Opens the given file or returns nil
on failure.
Renames the given file and returns true
on success.
Returns the size of the given file.
Returns the unix time of the last modification of the given file / folder.
Adds the given folderPath to the gamePath searchpaths.
Removes the given searchpath and returns true
on success.
Removes all searchpaths with that gamePath
Example:
filesystem.RemoveSearchPaths("GAME")
-- Removes all GAME
searchpaths.
Removes all searchpaths.
Returns the full path for the given file or nil
on failure.
Returns the relative path for the given file.
Returns the time the given file was created.
Will return nil
if the file wasn't found.
Returns the time the given file was last accessed.
Will return nil
if the file wasn't found.
This module adds two new functions to the util
library.
Works like util.Compress but it's async and allows you to set the level and dictSize.
The defaults for level and dictSize are the same as gmod's util.Compress.
Instead of making a copy of the data, we keep a reference to it and use it raw!
So please don't modify it while were compressing / decompressing it or else something might break.
Same as above, but uses the default values for level and dictSize.
Works like util.Decompress but it's async.
ignorecycle - If true
it won't throw a lua error when you have a table that is recursive/cycle.
Convers the given table to json.
Unlike Gmod's version, this function will turn the numbers to an integer if they are one/fit one.
The number of threads to use for util.AsyncCompress
.
When changing it, it will wait for all queried jobs to first finish before changing the size.
The number of threads to use for util.AsyncDecompress
.
NOTE: Decompressing seems to be far faster than compressing so it doesn't need as many threads.
This module unblocks quit
and exit
for RunConsoleCommand
.
If enabled, it completely disables the concommand/convar blacklist.
This module adds VProf to gamemode calls, adds two convars and an entire library.
Starts vprof.
Stops vprof.
Returns true
if vprof currently is at it's root node.
Returns the given vprof counter or creates it if it's missing.
Returns the counter by it's index.
Returns nothing if the counter doesn't exist.
Returns the number of counters that exist.
There is a limit on how many counters there can be.
Resets all counters back to 0
.
Returns the time the last frame took.
Returns the peak time of the root node.
Returns the total time of the root node.
Returns the current detail level.
Returns the number of frames it sampled.
Hides/Unhides the given budget group.
Returns the number of budget groups.
There is a limit on how many there can be.
Returns the budget group id by the given name.
Returns the name of the budget group by the given index.
Returns the budget group flags by the index.
Returns the color of the given budget group.
Returns the root node.
Returns the current node.
Returns true
if vprof is enabled.
If vprof is enabled, it will call MarkFrame on the root node.
Enters a new scope.
Leaves the current scope.
Pauses vprof.
Resumes vprof.
Resets vprof.
Resets all peaks.
Terminates vprof and frees the memory of everything.
This will invalidate all VProfCounter
and VProfNode
.
This means that if you try to use one that you stored in lua, it could crash!
NOTE: This should probably never be used.
This object represents a vprof counter.
It internally only contains a string and a pointer to the counter value.
If called on a invalid object, it will return VProfCounter [NULL]
.
Normally returns VProfCounter [name][value]
.
Returns the name of the counter.
Sets the counter to the given value.
Returns the current value of the counter.
Increments the counter by one.
Decrements the counter by one.
This object basicly fully exposes the CVProfNode
class.
If called on a invalid object, it will return VProfNode [NULL]
.
Normally returns VProfNode [name]
.
Returns the name of this node.
Returns the budget group id of the node.
Returns the current time of this node.
Returns the current time of this node but without it's children.
Returns the peak time of this node.
Returns the previous time of this node.
Returns the previous time of this node but without it's children.
Returns the total time of this node.
Returns the total time of this node but without it's children.
Returns the amount of times this node was in scope in this frame.
Returns the child node of this node.
Returns the parent node of this node.
Returns the next sibling of this node.
Returns the previous silbling of this node.
Returns the number of L2 cache misses. Does this even work?
Returns the previous number of L2 cache misses without the children.
Does nothing / returns always 0.
Returns how often this node was in scope.
Returns or creates the VProfNode by the given name.
Returns the set client data.
Marks the frame.
It will move all current times into their previous variants and reset them to 0
.
It will also call MarkFrame on any children or sibling.
Clears the previous time.
Pauses this node.
Resumes this node.
Resets this node.
Resets the peak of this node.
Sets the new budget group by it's id.
Sets the current frametime.
Sets the client data...
Enters the scope.
Exists the scope.
Theses are the CounterGroup_t enums.
If enabled, vprof results will be dumped into a file in the vprof/ folder
Sets the value of sv_stressbots
.
sv_stressbots
is a hidden convar which is very useful for performance tests with bots.
This module adds one function to the cvars
library.
NOTE: The lua library is named
cvar
because thecvars
library is fully declared in Lua and were running before it even exists.
Returns a sequential table with all ConVar's that exist.
Set the convat to the given value.
Returns true
on success.
Unregisters the given convar.
This module plans to add a new sourcetv
library and a new class HLTVPlayer
will allow a SourceTV client to send net messages to the server.
Returns true
if sourcetv is active.
Returns true
if sourcetv is recording.
Returns true
if sourcetv server is the master proxy.
Returns true
if the sourcetv server is a relay.
Returns the number of sourctv clients connected.
Returns the slot of the sourcetv client/bot.
string fileName - The name for the recording.
Returns one of the RECORD_
enums.
Returns the filename of the current recording. or nil
.
Stops the active record.
Returns one of the RECORD_
enums.
If successfully stopped, it will return sourcetv.RECORD_OK
.
Returns a table that contains all HLTV clients. It will return nil
on failure.
Returns the HLTVClient at that slot or nil
on failure.
Fires the gameevent for all hltv clients / broadcasts it.
If allowOverride
is set to true, it internally won't block any events like hltv_cameraman
, hltv_chase
and hltv_fixed
.
Sends the hltv_cameraman
event aall clients and blocks the HLTVDirector
from changing the view.
Call it with 0
/ NULL
to reset it and let the HLTVDirector
take control again.
NOTE: This won't set it for new clients. You have to call it again for thoes.
This is a metatable that is pushed by this module. It contains the functions listed below
Returns the a formated string.
Format: HLTVClient [%i][%s]
%i
-> UserID
%s
-> ClientName
Internally seaches in the metatable table for the key.
Returns the lua table of this object.
You can store variables into it.
NOTE: There is no __newindex function since we can't properly reset the LuaTable.
Returns the name of the client.
Returns the steamid of the client.
NOTE: Currently broken / will return
STEAM_ID_PENDING
Returns the userid of the client.
Returns the slot of the client. Use this for sourcetv.GetClient
.
Reconnects the HLTV client.
Prints the given message into the client's console.
NOTE: It won't add
\n
at the end of the message, so you will need to add it yourself.
Returns true
if the client is still valid.
Sends the given code to the client to be executed.
Returns true
on success.
NOTE: This function was readded back experimentally. It wasn't tested yet. It's still broken but doesn't crash
Fires/sends the gameevent to this specific client.
Sends the hltv_cameraman
event to the specific client and blocks the HLTVDirector
from changing the view.
Call it with 0
/ NULL
to reset it and let the HLTVDirector
take control again.
The recording was started.
SourceTV is not active!
the sourcetv server is not the master!
there already is an active record!
NOTE: Should we allow multiple active record? I think I could implement it. If wanted, make a request for it.
there is no active recording to stop!
The filepath for the recording is invalid!
A file with that name already exists!
Called when a HLTVClient sends a net message to the server.
Example:
util.AddNetworkString("Example")
hook.Add("HolyLib:OnSourceTVNetMessage", "Example", function(client, bf)
local name = util.NetworkIDToString(bf:ReadShort())) -- Reads the header
print(name, bf:ReadString())
end)
---- Client
net.Start("Example")
net.WriteString("Hello World from HLTVClient");
net.SendToServer()
Called when a HLTVClient sends a command.
return true
to tell it that the command was handled in Lua.
Example:
hook.Add("HolyLib:OnSourceTVCommand", "Example", function(client, name, args, argString)
if name == "Example" then
client:ClientPrint("Hello World from HLTVServer\n")
return true
end
end)
Called when SourceTV tries to start a new shot.
Return true
to cancel it.
Called when a client disconnects from the sourcetv server.
NOTE: We pass the playerSlot since passing the HLTVClient object causes weird issues I couldn't fix yet.
If enabled, HLTV Clients can send net messages to the server and HolyLib:OnSourceTVNetMessage
will be called.
If enabled, HLTV Clients can send commands to the server and HolyLib:OnSourceTVCommand
will be called.
This module adds a bf_read
and bf_write
class.
Copies the given buffer into a new one.
Useful if you want to save the data received by a client.
Creates a read buffer from the given data.
Useful if you want to read the userdata of the instancebaseline stringtable.
Create a write buffer with the given size or with the given data.
This class will later be used to read net messages from HLTV clients.
ToDo: Finish the documentation below and make it more detailed.
Returns the a formated string.
Format: bf_read [%i]
%i
-> size of data in bits.
Deletes the buffer internally.
Returns the number of bits left.
Returns the number of bits read.
Returns the size of the data in bits.
Returns the number of bytes left.
Returns the number of bytes read.
Returns the size of the data in bytes.
Returns the current position/bit.
NOTE: This is only available for the 32x!
Returns true
if the buffer is overflowed.
Reads and Angle.
NOTE: This is only available for the 32x!
NOTE: This is only available for the 32x!
NOTE: This is only available for the 32x!
NOTE: This is only available for the 32x!
Reads a number with the given number of bits.
NOTE: This is only available for the 32x!
Reads the given number of bits.
Reads a Vector.
Reads a normalizted Vector.
Reads a byte.
Reads the given number of bytes.
Reads a char.
Reads a float.
Reads a long.
Reads a long long.
Reads one bit.
Reads a number with the given amout of bits.
Reads a short.
Reads a string.
Read a number with the given amount of bits.
Resets the current position and resets the overflow flag.
Sets the current position to the given position.
Returns true
on success.
Sets the current position to the given position relative to the current position.
Basicly newPosition = currentPosition + iPos
Returns true
on success.
Returns the a formated string.
Format: bf_write [%i]
%i
-> size of data in bits.
Deletes the buffer internally.
returns true
if the buffer is still valid.
Returns the written data.
Returns the number of bytes written.
Returns the number of bytes that are unwritten.
Returns the number of bits written.
Returns the number of bits left.
Returns the maximum number of bits that can be written.
Returns true
if the buffer is overflowed.
Resets the buffer.
Returns the debug name.
Sets the debug name.
You should keep a reference to the string.
Seeks to the given bit.
Writes a float.
Writes a char.
Writes a byte.
Writes a long.
Writes a long long.
Writes the given bytes to the buffer.
Writes one bit.
Sets the given bit to the given value.
Writes a short.
Writes a word.
Writes an Angle. (QAngle
internally).
Writes a Vector.
Writes the given number of bits from the data into this buffer.
Returns true
on success.
Writes the given number of bits from the given buffer into this buffer.
Returns true
on success.
NOTE: The current position for the given buffer will change as we internally read from it!
This module tries to optimize anything related to networking.
Currently, this only has one optimization which was ported from sigsegv-mvm into here.
This module adds a few functions related to steam.
Shutdowns the Steam Server.
Starts/Activates the Steam Server.
Returns true
if the Steam Server is connected.
Calls the SV_InitGameServerSteam
function to activate the steam server exactly like the engine does it.
Marks the given client as Authenticated even if they aren't.
Called when our Steam server loses connection to steams servers.
Called when our Steam server successfully connected to steams servers.
This module is just the timer library, but it doesn't use CurTime.
NOTE: Timer repetitions are limited to an unsigned int.
Adjusts the timer with the given name with the new values.
Returns true
if the timer was successfully adjusted.
Does nothing / deprecated.
Creates a timer with the given name.
Returns true
if the given timer exists.
Removes the given timer.
Returns the number of reps left for the given timer.
Returns 0
if the timer wasn't found or the reps are below 0
.
Creates a simple timer.
Returns true
if the given timer was successfully started again.
Returns true
if the given timer was successfully stopped.
Returns the time left until the given timer is executed again.
Returns 0
if the timer wasn't found.
Toggles the given timer.
Returns true
if the timer was activated/started again.
Returns true
if the given timer was successfully paused.
Unpauses the given timer.
Unlike systimer.Start this won't reset the time left until it executes again.
This module plans to add a few PAS related functions like table pas.FindInPAS(Vector pos or Entity ent)
.
If you got an Idea for a function to add, feel free to comment it into its issue.
Returns a sequential table containing all entities in that PAS.
Tests if the give hear position is inside the given pas.
Returns true
if it is.
If given a EntityList, it will return a table wich contains the result for each entity.
The key will be the entity and the value is the result.
Checks if the given pox is inside the PAS.
Returns true
if it is.
This module contains a few things to control the voicechat.
You could probably completly rework the voicechat with this since you could completly handle it in lua.
Sends an empty voice packet.
If playerSlot
isn't specified it will use the player slot of the given player.
Sends the given VoiceData to the given player.
It won't do any processing, it will just send it as it is.
Same as voicechat.SendVoiceData
but broadcasts it to all players.
If given a table it will only send it to thoes players.
Let's the server process the VoiceData like it was received from the client.
This can be a bit performance intense.
NOTE: This will ignore the set player slot!
Returns true
if ply
can hear the targetPly
.
Returns true
if ply
can hear the targetPly
in it's proximity.
VoiceData voicedata.CreateVoiceData(number playerSlot = 0, string data = NULL, number dataLength = NULL)
Creates a new VoiceData object.
NOTE: All Arguments are optional!
VoiceData is a userdata value that is used to manage the voicedata.
Returns VoiceData [%i(Player Slot)][%i(Length/Size)]
.
Garbage collection. Deletes the voice data internally.
Index.
Returns true
if the VoiceData is still valid.
Returns the raw compressed voice data.
Returns the length of the data.
Returns the slot of the player this voicedata is originally from.
number decompressSize - The number of bytes to allocate for decompression.
Returns the uncompressed voice data.
Returns if the VoiceData is in proximity.
Sets the new voice data.
Sets the new length of the data.
Sets the new player slot.
Sets if the VoiceData is in proximity.
Called before the voicedata is processed.
Return true
to stop the engine from processing it.
Example to record and play back voices.
concommand.Add("record_me", function()
hook.Remove("Think", "VoiceChat_Example") -- Doesn't like to play back while recording :^
voiceTbl = {}
voiceStartTick=engine.TickCount()
hook.Add("HolyLib:PreProcessVoiceChat", "VoiceChat_Example", function(ply, voiceData)
if !voiceTbl[ply] then
voiceTbl[ply] = {}
end
voiceTbl[ply][engine.TickCount() - voiceStartTick] = voiceData
-- We save the tick delays since the voice data isn't sent every frame and has random delays.
end)
end)
concommand.Add("stop_record", function()
hook.Remove("HolyLib:PreProcessVoiceChat", "VoiceChat_Example")
end)
concommand.Add("play_me", function(ply)
if !voiceTbl[ply] then
ply:ChatPrint("You first need to record.")
return
end
if !player.GetBots()[1] then
RunConsoleCommand("bot")
end
hook.Remove("HolyLib:PreProcessVoiceChat", "VoiceChat_Example")
voiceIdx = 0
hook.Add("Think", "VoiceChat_Example", function()
if !IsValid(ply) then
hook.Remove("Think", "VoiceChat_Example")
return
end
voiceIdx = voiceIdx + 1
local voiceData = voiceTbl[ply][voiceIdx]
-- We play it back in the exact same tick delays we received it in to not speed it up affect it in any way.
if voiceData then
voicechat.ProcessVoiceData(player.GetBots()[1], voiceData)
end
end)
end)
The Engine's voicechat but in Lua:
hook.Add("HolyLib:PreProcessVoiceChat", "VoiceCHat_Engine", function(pClient, voiceData)
if GetConVar("voice_debugfeedbackfrom"):GetBool() then
print(string.format("Sending voice from: %s - playerslot: %d", pClient:Name(), pClient:EntIndex()))
end
local iLength = voiceData:GetLength()
for _, pDestClient in player.Iterator() do
local bSelf = pDestClient == pClient
local bHearsPlayer = voicechat.IsHearingClient(pDestClient, pClient)
voiceData:SetProximity(voicechat.IsProximityHearingClient(pDestClient, pClient))
if !bHearsPlayer && !bSelf then continue end
voiceData:SetLength(iLength)
if !bHearsPlayer then
-- Still send something, just zero length (this is so the client
-- can display something that shows knows the server knows it's talking).
voiceData:SetLength(0)
end
voicechat.SendVoiceData(pDestClient, voiceData)
end
return true -- Stop Engine handling since we fully handled it
end)
If enabled, the VoiceChat hooks will be called.
This module fixes Facepunch/garrysmod-issues#642 and adds a few small things.
The lag threshold(time in ms) which if exceeded will cause it to call the HolyLib:PhysicsLag
hook.
Returns the lag threshold in ms.
Sets the skiptype for the current simulation.
This is reset after the simulation ended.
Theses are the IVP_SkipType enums.
Let the simulation run normally.
Skip all impact calls.
Skip the entire simulation.
NOTE: Players that collide with props will be randomly teleported!
Called when the physics simulaton is taking longer than the set lag threshold.
You can freeze all props here and then return physenv.IVP_SkipSimulation
to skip the simulation for this tick if someone is trying to crash the server.
This module will add functions related to the bass dll.
Does someone have the bass libs for 2.4.15
? I can't find them :<
.mp3
files most likely won't work.
Since this module is experimental, it's disabled by default.
You can enable it with holylib_enable_bass 1
callback - function(IGMODAudioChannel channel, int errorCode, string error)
Creates a IGMODAudioChannel for the given file.
callback - function(IGMODAudioChannel channel, int errorCode, string error)
Creates a IGMODAudioChannel for the given url.
Returns IGModAudioChannel [NULL]
if invalid.
Else it returns IGModAudioChannel [FileName/URL]
.
ToDo / Doesn nothing yet.
Destorys the audio channel.
Stops the channel.
Pauses the channel.
Plays the channel.
Sets the volume of the channel.
(It's serverside... how does volume even play a role)
Returns the volume of the channel.
Sets the playback rate of the channel.
Returns the playback rate of the channel.
Sets the time of the channel.
Returns the time of the channel.
Returns the buffered time of the channel.
NOTE: If it's playing a file, it will just return the length of it.
Returns the state of the channel.
Sets looping for the channel.
Returns true
if the channel will loop.
Returns true
if were playing a URL.
Returns true
if the channel is a 3D one.
Returns true
if the sound is received in chunks.
Returns true
if the channel is valid.
Returns the filename or URL the channel is playing.
Returns the samplerate of the channel.
Returns the bits per sample.
Returns the average bit rate.
Returns the level of the channel.
First value is left, second is right.
Sets the channel pan.
Returns the channel pan.
Returns the tag of the channel.
Restarts the channel.
Computes the DFT of the sound channel.
What even is that.
This module just adds a lua class.
Only use their functions after entities were created or you might be missing entities in the returned tables!
Creates a new EntityList.
Returns all entities that are in the global entity list.
NOTE: This will only contain networkable / networked entities.
This class should remove some overhead to improve performance since you can pass it to some functions.
It is also used by other modules to improve their performance if they have to loop thru all entities or push entities to lua.
Returns EntityList [NULL]
if given invalid list.
Normally returns EntityList [Entity number]
.
If called, it will free and nuke the entity list.
You should never use it after this was called.
Returns a table with all the entities.
Sets the EntityList from the given table.
Adds the entities from the given table to the Entity list.
Removes the entities that are in the table from the Entity list.
Adds the given entity to the list.
Removes the given entity from the list.
This module adds two new IServerPluginCallbacks
functions:
virtual void OnLuaInit( GarrysMod::Lua::ILuaInterface* LUA )
virtual void OnLuaShutdown( GarrysMod::Lua::ILuaInterface* LUA )
For a plugin to be loaded by HolyLib, you need to expose HolyLib's Interface.
You can expose both HolyLib's and the normal interface since the order of the virtual functions are the same.
This should already work but I never tested it completly yet (Or I forgot that I did test it).
gameevent.GetListeners
-> Facepunch/garrysmod-requests#2377
stringtable.FindTable("modelprecache"):GetNumStrings()
-> Facepunch/garrysmod-requests#82
threadpoolfix
-> Facepunch/garrysmod-issues#5932
HolyLib.Reconnect(ply)
-> Facepunch/garrysmod-requests#2089
pvs.AddEntityToPVS(ent)
-> Facepunch/garrysmod-requests#245
util.AsyncCompress(data, nil, nil, callback)
-> Facepunch/garrysmod-requests#2165
It now throws a warning instead of crashing -> Facepunch/garrysmod-issues#56
HolyLib.Reconnect(ply)
-> Facepunch/garrysmod-requests#2089
concommand
module -> Facepunch/garrysmod-requests#1534
vprof
module -> Facepunch/garrysmod-requests#2374
cvar.GetAll
-> Facepunch/garrysmod-requests#341
sourcetv
module -> Facepunch/garrysmod-requests#2298
bitbuf
module(unfinished) -> Facepunch/garrysmod-requests#594
HLTV
class / sourcetv
module -> Facepunch/garrysmod-requests#2237
surffix
module -> Facepunch/garrysmod-requests#2306
filesystem.TimeCreated
& filesystem.TimeAccessed
-> Facepunch/garrysmod-requests#1633
systimer
module -> Facepunch/garrysmod-requests#1671
pas
module -> Facepunch/garrysmod-requests#140
HolyLib.InvalidateBoneCache
-> Facepunch/garrysmod-requests#1920
HolyLib:PostEntityConstructor
-> Facepunch/garrysmod-requests#2440
physenv
module -> Facepunch/garrysmod-issues#642
Facepunch/garrysmod-requests#1884
(Maybe)Facepunch/garrysmod-requests#132
Facepunch/garrysmod-requests#77
(Maybe)Facepunch/garrysmod-requests#603
Facepunch/garrysmod-requests#439
Facepunch/garrysmod-requests#1323
(Should be possible?)Facepunch/garrysmod-requests#756
(Gonna make a seperate ConVar for it)Facepunch/garrysmod-requests#2120
Facepunch/garrysmod-requests#1472
(Maybe)Facepunch/garrysmod-requests#2129
(Maybe)Facepunch/garrysmod-requests#1962
(Maybe)Facepunch/garrysmod-requests#1699
NW uses a usermessage NetworkedVar
Write order:
- WriteLong -> Entity handle
- Char -> Type ID
- String -> Var name (Planned to change to 12bits key index in next net compact)
- (Value) -> Var value. (Depends on what type it is)
NW2 writes it to the baseline.
Write order:
- 12 bits - Number of net messages networked.
- 1 bit - Magic bool. Idk if true, it wil call
GM:EntityNetworkedVarChanged
(Verify)
loop:
- 12 bits - var key index
- 3 bits - var type
- x bits -var value