Normalizing line endings

This commit is contained in:
Nayruden 2015-11-07 17:08:41 -05:00
parent 5a393ca6fd
commit 7170aceb0a
22 changed files with 4182 additions and 4182 deletions

View File

@ -1,279 +1,279 @@
Title: ULib Readme Title: ULib Readme
*ULib v2.60 (released 00/00/00)* *ULib v2.60 (released 00/00/00)*
ULib is a developer library for GMod 10 (<http://garrysmod.com/>). ULib is a developer library for GMod 10 (<http://garrysmod.com/>).
ULib provides such features as universal physics, user access lists, and much, much more! ULib provides such features as universal physics, user access lists, and much, much more!
Visit our homepage at <http://ulyssesmod.net/>. Visit our homepage at <http://ulyssesmod.net/>.
You can talk to us on our forums at <http://forums.ulyssesmod.net/>. You can talk to us on our forums at <http://forums.ulyssesmod.net/>.
Group: Author Group: Author
ULib is brought to you by.. ULib is brought to you by..
* Brett "Megiddo" Smith - Contact: <megiddo@ulyssesmod.net> * Brett "Megiddo" Smith - Contact: <megiddo@ulyssesmod.net>
* JamminR - Contact: <jamminr@ulyssesmod.net> * JamminR - Contact: <jamminr@ulyssesmod.net>
* Stickly Man! - Contact: <sticklyman@ulyssesmod.net> * Stickly Man! - Contact: <sticklyman@ulyssesmod.net>
* MrPresident - Contact: <mrpresident@ulyssesmod.net> * MrPresident - Contact: <mrpresident@ulyssesmod.net>
Group: Requirements Group: Requirements
ULib requires a working copy of the latest garrysmod, and that's it! ULib requires a working copy of the latest garrysmod, and that's it!
Group: Installation Group: Installation
To install ULib, simply extract the files from the archive to your garrysmod/addons folder. To install ULib, simply extract the files from the archive to your garrysmod/addons folder.
When you've done this, you should have a file structure like this-- When you've done this, you should have a file structure like this--
<garrysmod>/addons/ulib/lua/ULib/init.lua <garrysmod>/addons/ulib/lua/ULib/init.lua
<garrysmod>/addons/ulib/lua/ULib/server/util.lua <garrysmod>/addons/ulib/lua/ULib/server/util.lua
<garrysmod>/addons/ulib/lua/autorun/ulib_init.lua <garrysmod>/addons/ulib/lua/autorun/ulib_init.lua
<garrysmod>/addons/ulib/data/ULib/users.txt <garrysmod>/addons/ulib/data/ULib/users.txt
etc.. etc..
Please note that installation is the same on dedicated servers. Please note that installation is the same on dedicated servers.
You absolutely, positively have to do a full server restart after installing the files. A simple map You absolutely, positively have to do a full server restart after installing the files. A simple map
change will not cut it! change will not cut it!
Group: Usage Group: Usage
Server admins do not "use" ULib, they simply enjoy the benefits it has to offer. Server admins do not "use" ULib, they simply enjoy the benefits it has to offer.
After installing ULib correctly, scripts that take advantage of ULib will take care of the rest. After installing ULib correctly, scripts that take advantage of ULib will take care of the rest.
Rest easy! Rest easy!
Group: Changelog Group: Changelog
v2.60 - *(00/00/00)* v2.60 - *(00/00/00)*
* [ADD] ULib.ucl.getUserInfoFromID for getting user info from an ID. * [ADD] ULib.ucl.getUserInfoFromID for getting user info from an ID.
* [ADD] CAMI support. * [ADD] CAMI support.
* [ADD] "noMount" parameter to file-related APIs. * [ADD] "noMount" parameter to file-related APIs.
* [ADD] ULibGetUser(s)CustomKeyword hooks (Thanks, LuaTenshi). * [ADD] ULibGetUser(s)CustomKeyword hooks (Thanks, LuaTenshi).
* [FIX] The usual random slew of Garry-breakages (Thanks, Fuzzik). * [FIX] The usual random slew of Garry-breakages (Thanks, Fuzzik).
* [FIX] An assumption regarding player authentication that led to a player's group being reset to user sometimes. * [FIX] An assumption regarding player authentication that led to a player's group being reset to user sometimes.
* [FIX] Garry API change for ULib.findinDir (Thanks, ascentechit). * [FIX] Garry API change for ULib.findinDir (Thanks, ascentechit).
* [FIX] Workaround for Garry's odd handling of bot UIDs (Thanks, BurgerLUA). * [FIX] Workaround for Garry's odd handling of bot UIDs (Thanks, BurgerLUA).
* [FIX] Improved how well ULib files handle being autorefreshed. * [FIX] Improved how well ULib files handle being autorefreshed.
* [FIX] Exploitable console command could potentially cause errors and/or crashes. * [FIX] Exploitable console command could potentially cause errors and/or crashes.
* [FIX] Exploit involving file system mounting. * [FIX] Exploit involving file system mounting.
* [CHANGE] Hook system. It's much faster (CPU-wise) and a little easier to use now (Many thanks for input from darkjacky and Divran). * [CHANGE] Hook system. It's much faster (CPU-wise) and a little easier to use now (Many thanks for input from darkjacky and Divran).
v2.52 - *(03/09/15)* v2.52 - *(03/09/15)*
* [ADD] Admin parameter to ULib.unban for overriding purposes (Thanks for the idea, MStruntze). * [ADD] Admin parameter to ULib.unban for overriding purposes (Thanks for the idea, MStruntze).
* [ADD] A list of players is presented when a target string for getUser matches more than one player (Thanks, RhapsodySL). * [ADD] A list of players is presented when a target string for getUser matches more than one player (Thanks, RhapsodySL).
* [FIX] ULib.ucl.registerAccess not allowing an access tag to be registered to no groups. * [FIX] ULib.ucl.registerAccess not allowing an access tag to be registered to no groups.
* [FIX] Several incorrect file I/O calls (Thanks, Q4-Bi). * [FIX] Several incorrect file I/O calls (Thanks, Q4-Bi).
* [FIX] Hook priority being messed up for parent hook when hooks are called recursively (Thanks, NoBrainCZ). * [FIX] Hook priority being messed up for parent hook when hooks are called recursively (Thanks, NoBrainCZ).
* [FIX] Some fiddly-bits with group case-sensitivity (Thanks, BryanFlannery). * [FIX] Some fiddly-bits with group case-sensitivity (Thanks, BryanFlannery).
* [CHANGE] hook.Run to match Garry's changes. * [CHANGE] hook.Run to match Garry's changes.
* [CHANGE] ULib.HOOK_LOCALPLAYERREADY is now called on InitPostEntity instead of OnEntCreate. * [CHANGE] ULib.HOOK_LOCALPLAYERREADY is now called on InitPostEntity instead of OnEntCreate.
v2.51 - *(08/30/13)* v2.51 - *(08/30/13)*
* [FIX] ULib.ucl.userAllow not working on disconnected players (Thanks, JackYack13). * [FIX] ULib.ucl.userAllow not working on disconnected players (Thanks, JackYack13).
* [FIX] Issue with setting groups with capitals in the group name (Thanks, FPtje!). * [FIX] Issue with setting groups with capitals in the group name (Thanks, FPtje!).
* [FIX] Calling SetUserGroup not passing on information to clients (Thanks, Bo98). * [FIX] Calling SetUserGroup not passing on information to clients (Thanks, Bo98).
* [FIX] Garry's File I/O bugs by wrapping all his I/O. * [FIX] Garry's File I/O bugs by wrapping all his I/O.
* [FIX] A user group lower casing that no longer belonged in the code (Thanks, iamalexer). * [FIX] A user group lower casing that no longer belonged in the code (Thanks, iamalexer).
* [FIX] Some issues with casing in ULib commands (Thanks, TheSpy7). * [FIX] Some issues with casing in ULib commands (Thanks, TheSpy7).
* [FIX] Invalid time restrictions throwing an error (Thanks, Scratch). * [FIX] Invalid time restrictions throwing an error (Thanks, Scratch).
* [FIX] A problem with targeting in single player (Effected XGUI. Thanks, bender180). * [FIX] A problem with targeting in single player (Effected XGUI. Thanks, bender180).
* [FIX] A problem with self-target restrictions breaking commands under certain conditions (Thanks, iSnipeu). * [FIX] A problem with self-target restrictions breaking commands under certain conditions (Thanks, iSnipeu).
* [FIX] A bug with being able to update replicated variables after running a listen server and then joining another server. * [FIX] A bug with being able to update replicated variables after running a listen server and then joining another server.
* [REMOVED] Temp garry-patch for reading from the data directory that appears to be fixed now. * [REMOVED] Temp garry-patch for reading from the data directory that appears to be fixed now.
v2.50 - *(01/27/13)* v2.50 - *(01/27/13)*
* [ADD] ULib.pcallError -- Does what global PCallError used to do before it was removed. * [ADD] ULib.pcallError -- Does what global PCallError used to do before it was removed.
* [ADD] Shows reasons to kicked person upon kick or ban (Thanks FPtje!). * [ADD] Shows reasons to kicked person upon kick or ban (Thanks FPtje!).
* [ADD] Operator to target only a specific group, ignoring inheritance ('#'). * [ADD] Operator to target only a specific group, ignoring inheritance ('#').
* [ADD] Operator to target a specific id ('$'). * [ADD] Operator to target a specific id ('$').
* [ADD] ULib.namedQueueFunctionCall to allow scripts to create their own queues separate of the main one. * [ADD] ULib.namedQueueFunctionCall to allow scripts to create their own queues separate of the main one.
* [ADD] The ability to have aliased chat commands. * [ADD] The ability to have aliased chat commands.
* [FIX] The usual assortment of garry breakages. * [FIX] The usual assortment of garry breakages.
* [FIX] Changed away from our custom implementation of datastream to use Garry's new net library. * [FIX] Changed away from our custom implementation of datastream to use Garry's new net library.
* [FIX] Error with returning from invisibility when the player has no weapons (Thanks HellFox). * [FIX] Error with returning from invisibility when the player has no weapons (Thanks HellFox).
* [FIX] "ULibCommandCalled" hook not being called on chat commands (Thanks Adult). * [FIX] "ULibCommandCalled" hook not being called on chat commands (Thanks Adult).
* [CHANGE] Replicated cvars aren't actually relying on source replication anymore since Garry broke it (but they function the same). * [CHANGE] Replicated cvars aren't actually relying on source replication anymore since Garry broke it (but they function the same).
* [CHANGE] Lots of changes to match GM13. * [CHANGE] Lots of changes to match GM13.
* [CHANGE] NumArg now allows for time string format. * [CHANGE] NumArg now allows for time string format.
* [CHANGE] Hook library to match garry's. hook.isInHook was removed, no longer able to support with garry's changes. * [CHANGE] Hook library to match garry's. hook.isInHook was removed, no longer able to support with garry's changes.
v2.42 - *(01/01/12)* v2.42 - *(01/01/12)*
* [FIX] Garry breakages. * [FIX] Garry breakages.
v2.41 - *(09/22/11)* v2.41 - *(09/22/11)*
* [ADD] ULib.ucl.getUserRegisteredID. * [ADD] ULib.ucl.getUserRegisteredID.
* [ADD] ULib.stringTimeToSeconds (Thanks lavacano201014). * [ADD] ULib.stringTimeToSeconds (Thanks lavacano201014).
* [FIX] Now properly kicks users who are banned while joining (Thanks Willdy). * [FIX] Now properly kicks users who are banned while joining (Thanks Willdy).
v2.40 - *(05/13/11)* v2.40 - *(05/13/11)*
* [ADD] ULib.tsayColor and Ulib.tsayError * [ADD] ULib.tsayColor and Ulib.tsayError
* [ADD] Replicated cvars. Nearly a direct port from the UPS implementation, with a few improvements. * [ADD] Replicated cvars. Nearly a direct port from the UPS implementation, with a few improvements.
* [ADD] queueFunctionCall, ported from UPS. * [ADD] queueFunctionCall, ported from UPS.
* [ADD] Player:GetUserGroup(). * [ADD] Player:GetUserGroup().
* [ADD] Player:CheckGroup(), ability to check if a user in a group via inheritance. * [ADD] Player:CheckGroup(), ability to check if a user in a group via inheritance.
* [ADD] ULib.getPlyByUID(). * [ADD] ULib.getPlyByUID().
* [ADD] ULib.clientRPC(), send massive amounts of data to a client with ease. * [ADD] ULib.clientRPC(), send massive amounts of data to a client with ease.
* [ADD] Upgrade script. * [ADD] Upgrade script.
* [ADD] hook.getCurrentHooks(), returns all currently processing hooks. * [ADD] hook.getCurrentHooks(), returns all currently processing hooks.
* [ADD] hook.isInHook( name ), returns if you're in the specified hook or not. * [ADD] hook.isInHook( name ), returns if you're in the specified hook or not.
* [ADD] ULib.splitPort(), ULib.isValidSteamID(), ULib.isValidIP(). * [ADD] ULib.splitPort(), ULib.isValidSteamID(), ULib.isValidIP().
* [ADD] ULib.backupFile(). * [ADD] ULib.backupFile().
* [ADD] ULib.throwBadArg(), useful for argument checking. * [ADD] ULib.throwBadArg(), useful for argument checking.
* [ADD] ULib.checkArg(), useful for argument checking. * [ADD] ULib.checkArg(), useful for argument checking.
* [ADD] ULib.getPicker(), returns a user directly in front of another user. * [ADD] ULib.getPicker(), returns a user directly in front of another user.
* [ADD] Utilities for table inheritance. * [ADD] Utilities for table inheritance.
* [ADD] New 'translation' command system that acts as a wrapper between a user and lua. * [ADD] New 'translation' command system that acts as a wrapper between a user and lua.
* [ADD] New (and very different) command system. * [ADD] New (and very different) command system.
* [ADD] Lots of new hooks. * [ADD] Lots of new hooks.
* [ADD] Support for gatekeeper in ULib.kick. * [ADD] Support for gatekeeper in ULib.kick.
* [ADD] Our own optimized version of datastream, since garry's implementation is always broken. * [ADD] Our own optimized version of datastream, since garry's implementation is always broken.
* [ADD] ULib.getAllReadyPlayers(), useful for sending usermessages to everyone. * [ADD] ULib.getAllReadyPlayers(), useful for sending usermessages to everyone.
* [ADD] Basic spam detection system for ULib commands. * [ADD] Basic spam detection system for ULib commands.
* [FIX] ULib.filesInDir, was completely broken. * [FIX] ULib.filesInDir, was completely broken.
* [FIX] The usual assortment of garry breakages. * [FIX] The usual assortment of garry breakages.
* [FIX] Some case-sensitive issues with the ULib add-command functions. * [FIX] Some case-sensitive issues with the ULib add-command functions.
* [FIX] Attempting to delete misc_registered.txt when it didn't exist. * [FIX] Attempting to delete misc_registered.txt when it didn't exist.
* [FIX] ULib.splitArgs now really properly handles escaped quotes and now unescapes them. * [FIX] ULib.splitArgs now really properly handles escaped quotes and now unescapes them.
* [FIX] Concommands created by ULib removing empty args. * [FIX] Concommands created by ULib removing empty args.
* [FIX] Overflowing command buffer when executing large config files. * [FIX] Overflowing command buffer when executing large config files.
* [FIX] Optimized various functions to support up to 4000 bans (at least!). * [FIX] Optimized various functions to support up to 4000 bans (at least!).
* [FIX] Bug where reloading ban information when a temp ban had less than a minute left made the ban permanent. * [FIX] Bug where reloading ban information when a temp ban had less than a minute left made the ban permanent.
* [FIX] Bug where ULib was reading in bad characters from source bans (Thanks edk141). * [FIX] Bug where ULib was reading in bad characters from source bans (Thanks edk141).
* [CHANGE] Chat hooks are now a high priority due to other aggressive admin mods overriding ULX. * [CHANGE] Chat hooks are now a high priority due to other aggressive admin mods overriding ULX.
* [CHANGE] Rewrote UCL entirely. The upgrade script should take care of bringing over old data into the new system. * [CHANGE] Rewrote UCL entirely. The upgrade script should take care of bringing over old data into the new system.
* [CHANGE] Added the ability to have access tags for each access string. These allow the accesses to have customizable behavior. * [CHANGE] Added the ability to have access tags for each access string. These allow the accesses to have customizable behavior.
* [CHANGE] Access tags now have comments attached to them (for the "what is it?" among us). * [CHANGE] Access tags now have comments attached to them (for the "what is it?" among us).
* [CHANGE] Added lots of keywords (and keyword negation!) to ULib.getUsers and ULib.getUser. * [CHANGE] Added lots of keywords (and keyword negation!) to ULib.getUsers and ULib.getUser.
* [CHANGE] Invisible gets rid of shadows now. * [CHANGE] Invisible gets rid of shadows now.
* [CHANGE] Garry's hook table spec is now more closely followed. (Thanks aVoN!) * [CHANGE] Garry's hook table spec is now more closely followed. (Thanks aVoN!)
* [CHANGE] Moved the hook changes to the shared portion so clients can use the enhanced hooks as well. * [CHANGE] Moved the hook changes to the shared portion so clients can use the enhanced hooks as well.
* [CHANGE] Updated the hooks file to match garry's recent changes. Also increased efficiency in hooks (faster than garry's!) * [CHANGE] Updated the hooks file to match garry's recent changes. Also increased efficiency in hooks (faster than garry's!)
* [CHANGE] Slaps now do a view punch as well. * [CHANGE] Slaps now do a view punch as well.
* [CHANGE] Allow nil access on ULib.addSayCommand so that you can create a command you always have access to. * [CHANGE] Allow nil access on ULib.addSayCommand so that you can create a command you always have access to.
* [CHANGE] ULib.ucl.query always returns true when a nil access string is passed in. * [CHANGE] ULib.ucl.query always returns true when a nil access string is passed in.
* [REMOVE] Ability to have passwords in UCL, don't think it worked anymore and it was never really used. * [REMOVE] Ability to have passwords in UCL, don't think it worked anymore and it was never really used.
* [REMOVE] Immunity no longer exists, since the new UCL has a much better method of doing the same thing. * [REMOVE] Immunity no longer exists, since the new UCL has a much better method of doing the same thing.
* [REMOVE] Some hooks due to garry breakage. * [REMOVE] Some hooks due to garry breakage.
* [REMOVE] Chat sounds on tsay, engine no longer makes sounds so neither should tsay. * [REMOVE] Chat sounds on tsay, engine no longer makes sounds so neither should tsay.
v2.30 - *(06/20/09)* v2.30 - *(06/20/09)*
* [FIX] Umsgs being sent too early in certain circumstances. * [FIX] Umsgs being sent too early in certain circumstances.
* [FIX] Some issues garry introduced in the Jan09 update regarding player initialization. * [FIX] Some issues garry introduced in the Jan09 update regarding player initialization.
* [FIX] ParseKeyValues not unescaping backslashes. * [FIX] ParseKeyValues not unescaping backslashes.
* [CHANGE] Rewrote splitArgs and parseKeyValues. * [CHANGE] Rewrote splitArgs and parseKeyValues.
* [CHANGE] misc_registered.txt now self-destructs on missing or empty groups.txt. * [CHANGE] misc_registered.txt now self-destructs on missing or empty groups.txt.
* [CHANGE] All gamemode.Call refs to hook.Call, thanks aVoN! * [CHANGE] All gamemode.Call refs to hook.Call, thanks aVoN!
* [CHANGE] SetUserGroup now REMOVES any other groups and sets an exclusive group. Sorry about this, but this is for the better. * [CHANGE] SetUserGroup now REMOVES any other groups and sets an exclusive group. Sorry about this, but this is for the better.
v2.21 - *(06/08/08)* v2.21 - *(06/08/08)*
* [ADD] Support for client/server-side only modules. * [ADD] Support for client/server-side only modules.
* [FIX] Bug in ULib.tsay that would incorrectly print to console if the target player was disconnecting. * [FIX] Bug in ULib.tsay that would incorrectly print to console if the target player was disconnecting.
* [FIX] Makes sure that prop protectors don't take ownership of props using physgun reload while a prop is unmovable. * [FIX] Makes sure that prop protectors don't take ownership of props using physgun reload while a prop is unmovable.
* [CHANGE] ULib.getUsers now returns multiple users on an asterisk "*" when enable_keywords is true. "<ALL>" can still be used. (Thanks Kyzer) * [CHANGE] ULib.getUsers now returns multiple users on an asterisk "*" when enable_keywords is true. "<ALL>" can still be used. (Thanks Kyzer)
v2.20 - *(01/26/08)* v2.20 - *(01/26/08)*
* [ADD] ULib now has three shiny new hooks to let you know about client initialization and a new hook to signal a player name change. * [ADD] ULib now has three shiny new hooks to let you know about client initialization and a new hook to signal a player name change.
* [FIX] A possible bug in the physics helpers. * [FIX] A possible bug in the physics helpers.
* [CHANGE] Various things to bring ULib into new engine compatibility. * [CHANGE] Various things to bring ULib into new engine compatibility.
* [CHANGE] Removed all timers dealing with initialization and now rely on flags from the client. This makes the ULib initialization much more dependable. * [CHANGE] Removed all timers dealing with initialization and now rely on flags from the client. This makes the ULib initialization much more dependable.
* [CHANGE] Converted all calls from ULib.consoleCommand( "exec ..." ) to ULib.execFile() to avoid running into the block on "exec" without our module. * [CHANGE] Converted all calls from ULib.consoleCommand( "exec ..." ) to ULib.execFile() to avoid running into the block on "exec" without our module.
* [REMOVE] Removing the module for now, might re-appear in the next version * [REMOVE] Removing the module for now, might re-appear in the next version
v2.10 - *(09/23/07)* v2.10 - *(09/23/07)*
* [ADD] New hook library. Completely backwards compatible, but can now do priorities. (Server-side only) * [ADD] New hook library. Completely backwards compatible, but can now do priorities. (Server-side only)
* [ADD] ULib.parseKeyValues, ULib.makeKeyValues * [ADD] ULib.parseKeyValues, ULib.makeKeyValues
* [ADD] ULib.getSpawnInfo, ULib.Spawn - Enhanced Spawn... will replace original health/armor when called if getSpawnInfo called first. * [ADD] ULib.getSpawnInfo, ULib.Spawn - Enhanced Spawn... will replace original health/armor when called if getSpawnInfo called first.
* [ADD] READDED hexing system to get around garry's ConCommand() blocks. So much is now blocked that it's interferring with normal ULX operations. * [ADD] READDED hexing system to get around garry's ConCommand() blocks. So much is now blocked that it's interferring with normal ULX operations.
* [ADD] Our server module again. This time with only console-executing abilities. This is because garry has blocked much of what we need. Source is included. * [ADD] Our server module again. This time with only console-executing abilities. This is because garry has blocked much of what we need. Source is included.
* [ADD] Custom ban list to store temp bans and additional ban info. Permanent bans are still stored in banned_user.cfg, and the two lists are synchronized. * [ADD] Custom ban list to store temp bans and additional ban info. Permanent bans are still stored in banned_user.cfg, and the two lists are synchronized.
* [FIX] Can now query players from client side. * [FIX] Can now query players from client side.
* [FIX] An exploit in DisallowDelete() that allowed players to still remove the props * [FIX] An exploit in DisallowDelete() that allowed players to still remove the props
* [FIX] Various initialization functions trying to access a disconnected player * [FIX] Various initialization functions trying to access a disconnected player
* [FIX] ULib.csay() sending umsgs to invalid players. * [FIX] ULib.csay() sending umsgs to invalid players.
* [FIX] UCL by clantag not working. * [FIX] UCL by clantag not working.
* [CHANGE] Big changes in ucl.query() and concommand functions. Probably won't be backwards compatible. * [CHANGE] Big changes in ucl.query() and concommand functions. Probably won't be backwards compatible.
* [CHANGE] UCL now uses our new keyvalues functions. It should be backwards compatible with your old data, but we make no promises. If you're having trouble with it, try starting from scratch. * [CHANGE] UCL now uses our new keyvalues functions. It should be backwards compatible with your old data, but we make no promises. If you're having trouble with it, try starting from scratch.
* [CHANGE] ULib.tsay has a wait parameter to send on next frame * [CHANGE] ULib.tsay has a wait parameter to send on next frame
* [CHANGE] subconcommands are now case insensitive * [CHANGE] subconcommands are now case insensitive
* [CHANGE] Csay's now have fade. * [CHANGE] Csay's now have fade.
* [CHANGE] DisallowSpawning() now implements SpawnObject. For example, people can't sit and precache props while in the ulx jail. * [CHANGE] DisallowSpawning() now implements SpawnObject. For example, people can't sit and precache props while in the ulx jail.
* [CHANGE] Say commands are now case insensitive and default to needing a space between command and arg (can flag to use old behavior though) * [CHANGE] Say commands are now case insensitive and default to needing a space between command and arg (can flag to use old behavior though)
* [CHANGE] ULib.ban, and ULib.kickban now accept additional information and pass data to ULib.addBan. * [CHANGE] ULib.ban, and ULib.kickban now accept additional information and pass data to ULib.addBan.
* [CHANGE] Immunity is now an access string instead of a group * [CHANGE] Immunity is now an access string instead of a group
* [CHANGE] Overcoming immunity is no longer bound to superadmins * [CHANGE] Overcoming immunity is no longer bound to superadmins
* [CHANGE] Increased performance of UCL. * [CHANGE] Increased performance of UCL.
* [REMOVED] The vgui panels, derma is the vgui of choice now. * [REMOVED] The vgui panels, derma is the vgui of choice now.
v2.05 - *(06/19/07)* v2.05 - *(06/19/07)*
* [ADD] ply:SetUserGroup() -- Thanks aVoN! * [ADD] ply:SetUserGroup() -- Thanks aVoN!
* [ADD] ply:DisallowVehicles( bool ) * [ADD] ply:DisallowVehicles( bool )
* [FIX] A timer error in UCL, was messing up scoreboard sometimes. * [FIX] A timer error in UCL, was messing up scoreboard sometimes.
* [FIX] Security hole where exploiters could gain superadmin access * [FIX] Security hole where exploiters could gain superadmin access
* [CHANGE] You can assign allow/denies to the default user group, "user" now. (IE, allow guests to slap) * [CHANGE] You can assign allow/denies to the default user group, "user" now. (IE, allow guests to slap)
* [CHANGE] DisallowSpawning now disallows tools that can spawn things. * [CHANGE] DisallowSpawning now disallows tools that can spawn things.
* [REMOVED] Old settings/users.txt stuff, handled by SetUserGroup now * [REMOVED] Old settings/users.txt stuff, handled by SetUserGroup now
v2.04 - *(05/05/07)* v2.04 - *(05/05/07)*
* [ADD] ULib.isSandbox * [ADD] ULib.isSandbox
* [ADD] Player/ent hooks DisallowMoving, DisallowDeleting, DisallowSpawning, DisallowNoclip * [ADD] Player/ent hooks DisallowMoving, DisallowDeleting, DisallowSpawning, DisallowNoclip
* [ADD] Some vgui libs (URoundButton, URoundMenu) * [ADD] Some vgui libs (URoundButton, URoundMenu)
* [FIX] Double printing in console. * [FIX] Double printing in console.
* [CHANGE] Implemented garry's "proper" way of including c-side files. * [CHANGE] Implemented garry's "proper" way of including c-side files.
* [CHANGE] Implemented client side UCL * [CHANGE] Implemented client side UCL
* [CHANGE] Now in addon format * [CHANGE] Now in addon format
* [CHANGE] Slapping noclipped players will take them out of noclip to prevent them flying very far out of the world * [CHANGE] Slapping noclipped players will take them out of noclip to prevent them flying very far out of the world
* [CHANGE] Improved the umsg send/receive functions * [CHANGE] Improved the umsg send/receive functions
* [REMOVED] Hexing system to get around garry's ConCommand() blocks. Very little is blocked now. * [REMOVED] Hexing system to get around garry's ConCommand() blocks. Very little is blocked now.
* [REMOVED] Dll, MOTD functionality is handled by ULX now. * [REMOVED] Dll, MOTD functionality is handled by ULX now.
v2.03 - *(01/10/07)* v2.03 - *(01/10/07)*
* [ADD] ULib module, has functions for motd, concommands, and downloading files. SOURCE CODE! * [ADD] ULib module, has functions for motd, concommands, and downloading files. SOURCE CODE!
* [FIX] Player slap after dead problem. * [FIX] Player slap after dead problem.
v2.02 - *(01/07/07)* v2.02 - *(01/07/07)*
* [ADD] New system for giving files to clients. Strips comments and puts them in a separate folder. * [ADD] New system for giving files to clients. Strips comments and puts them in a separate folder.
* [FIX] Autocompletes aren't handled so hackishly now. This should fix some occasional errors. * [FIX] Autocompletes aren't handled so hackishly now. This should fix some occasional errors.
* [FIX] Lots of general fixes. * [FIX] Lots of general fixes.
v2.01 - *(01/02/07)* v2.01 - *(01/02/07)*
* [FIX] Importing from garry's default user file. * [FIX] Importing from garry's default user file.
* [FIX] All users receiving "you do not have access" message. * [FIX] All users receiving "you do not have access" message.
v2.0 - *(01/01/07)* v2.0 - *(01/01/07)*
* Initial version for GM10 * Initial version for GM10
Group: Developers Group: Developers
To all developers, I sincerely hope you enjoy what ULib has to offer! To all developers, I sincerely hope you enjoy what ULib has to offer!
If you have any suggestions, comments, or complaints, please tell us at <http://forums.ulyssesmod.net/>. If you have any suggestions, comments, or complaints, please tell us at <http://forums.ulyssesmod.net/>.
If you want an overview of what's in ULib, please visit the documentation at <http://ulyssesmod.net/docs/>. If you want an overview of what's in ULib, please visit the documentation at <http://ulyssesmod.net/docs/>.
If you find any bugs, you can report them at <https://github.com/Nayruden/Ulysses/issues>. If you find any bugs, you can report them at <https://github.com/Nayruden/Ulysses/issues>.
All ULib's functions are kept in the table "ULib" to prevent conflicts. All ULib's functions are kept in the table "ULib" to prevent conflicts.
Revisions are kept in the function/variable documentation. If you don't see revisions listed, it hasn't changed since v2.0 Revisions are kept in the function/variable documentation. If you don't see revisions listed, it hasn't changed since v2.0
If you write a script taking advantage of ULib, stick the init script inside ULib/modules. ULib will load your script after If you write a script taking advantage of ULib, stick the init script inside ULib/modules. ULib will load your script after
ULib loads, and will send it to and load it on clients as well. ULib loads, and will send it to and load it on clients as well.
Some important quirks developers should know about -- Some important quirks developers should know about --
* autocomplete - You have to define the autocomplete on the client, so if you pass a string for autocomplete to ULib.concommand, * autocomplete - You have to define the autocomplete on the client, so if you pass a string for autocomplete to ULib.concommand,
it will assume you mean a client function. There's also a delay in the sending of these to the client. it will assume you mean a client function. There's also a delay in the sending of these to the client.
Group: Credits Group: Credits
Thanks to JamminR, who is always there to offer help and advice to those who need it. Thanks to JamminR, who is always there to offer help and advice to those who need it.
Group: License Group: License
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License. This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
Creative Commons Creative Commons
543 Howard Street 543 Howard Street
5th Floor 5th Floor
San Francisco, California 94105 San Francisco, California 94105
USA USA

View File

@ -1,11 +1,11 @@
"AddonInfo" "AddonInfo"
{ {
"name" "ULib" "name" "ULib"
"version" "2.60" "version" "2.60"
"up_date" "00/00/00" "up_date" "00/00/00"
"author_name" "Team Ulysses" "author_name" "Team Ulysses"
"author_email" "teamulysses@ulyssesmod.net" "author_email" "teamulysses@ulyssesmod.net"
"author_url" "http://www.ulyssesmod.net/" "author_url" "http://www.ulyssesmod.net/"
"info" "Lua Library" "info" "Lua Library"
"override" "0" "override" "0"
} }

View File

@ -1,39 +1,39 @@
Format of admin account in users.txt-- Format of admin account in users.txt--
"<steamid|ip|unique id>" "<steamid|ip|unique id>"
{ {
"group" "superadmin" "group" "superadmin"
"allow" "allow"
{ {
"ulx kick" "ulx kick"
"ulx ban" "ulx ban"
} }
"deny" "deny"
{ {
"ulx cexec" "ulx cexec"
} }
} }
Example of a superadmin: Example of a superadmin:
"STEAM_0:1:123456" "STEAM_0:1:123456"
{ {
"group" "superadmin" "group" "superadmin"
"allow" "allow"
{ {
} }
"deny" "deny"
{ {
} }
} }
Format of group that gets the same allows as a superadmin in groups.txt-- Format of group that gets the same allows as a superadmin in groups.txt--
"<group_name>" "<group_name>"
{ {
"allow" "allow"
{ {
"ulx kick" "ulx kick"
"ulx ban" "ulx ban"
} }
"inherit_from" "superadmin" "inherit_from" "superadmin"
} }

View File

@ -1,35 +1,35 @@
//ATTENTION! This is a default file. DO NOT EDIT THIS FILE!!! //ATTENTION! This is a default file. DO NOT EDIT THIS FILE!!!
//Instead, edit the version in <garrysmod root>/data/ULib/groups.txt if it exists. If it doesn't, copy this file over to create it. //Instead, edit the version in <garrysmod root>/data/ULib/groups.txt if it exists. If it doesn't, copy this file over to create it.
//IF YOU MAKE CHANGES TO THIS FILE THEY WILL BE ERASED! //IF YOU MAKE CHANGES TO THIS FILE THEY WILL BE ERASED!
"operator" "operator"
{ {
"allow" "allow"
{ {
} }
"can_target" "!%admin" "can_target" "!%admin"
} }
"admin" "admin"
{ {
"allow" "allow"
{ {
} }
"inherit_from" "operator" "inherit_from" "operator"
"can_target" "!%superadmin" "can_target" "!%superadmin"
} }
"superadmin" "superadmin"
{ {
"allow" "allow"
{ {
} }
"inherit_from" "admin" "inherit_from" "admin"
} }
"user" "user"
{ {
"allow" "allow"
{ {
} }
} }

View File

@ -1,3 +1,3 @@
//ATTENTION! This is a default file. DO NOT EDIT THIS FILE!!! //ATTENTION! This is a default file. DO NOT EDIT THIS FILE!!!
//Instead, edit the version in <garrysmod root>/data/ULib/users.txt if it exists. If it doesn't, copy this file over to create it. //Instead, edit the version in <garrysmod root>/data/ULib/users.txt if it exists. If it doesn't, copy this file over to create it.
//IF YOU MAKE CHANGES TO THIS FILE THEY WILL BE ERASED! //IF YOU MAKE CHANGES TO THIS FILE THEY WILL BE ERASED!

View File

@ -1,6 +1,6 @@
-- Short and sweet -- Short and sweet
if SERVER then if SERVER then
include( "ulib/init.lua" ) include( "ulib/init.lua" )
else else
include( "ulib/cl_init.lua" ) include( "ulib/cl_init.lua" )
end end

View File

@ -1,63 +1,63 @@
ULib = ULib or {} -- Init table ULib = ULib or {} -- Init table
include( "ulib/shared/defines.lua" ) include( "ulib/shared/defines.lua" )
include( "ulib/shared/misc.lua" ) include( "ulib/shared/misc.lua" )
include( "ulib/shared/util.lua" ) include( "ulib/shared/util.lua" )
include( "ulib/shared/hook.lua" ) include( "ulib/shared/hook.lua" )
include( "ulib/shared/tables.lua" ) include( "ulib/shared/tables.lua" )
include( "ulib/client/commands.lua" ) include( "ulib/client/commands.lua" )
include( "ulib/shared/messages.lua" ) include( "ulib/shared/messages.lua" )
include( "ulib/shared/player.lua" ) include( "ulib/shared/player.lua" )
include( "ulib/client/cl_util.lua" ) include( "ulib/client/cl_util.lua" )
include( "ulib/client/draw.lua" ) include( "ulib/client/draw.lua" )
include( "ulib/shared/commands.lua" ) include( "ulib/shared/commands.lua" )
include( "ulib/shared/sh_ucl.lua" ) include( "ulib/shared/sh_ucl.lua" )
include( "ulib/shared/cami_global.lua" ) include( "ulib/shared/cami_global.lua" )
include( "ulib/shared/cami_ulib.lua" ) include( "ulib/shared/cami_ulib.lua" )
Msg( string.format( "You are running ULib version %.2f.\n", ULib.VERSION ) ) Msg( string.format( "You are running ULib version %.2f.\n", ULib.VERSION ) )
--Shared modules --Shared modules
local files = file.Find( "ulib/modules/*.lua", "LUA" ) local files = file.Find( "ulib/modules/*.lua", "LUA" )
if #files > 0 then if #files > 0 then
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
Msg( "[ULIB] Loading SHARED module: " .. file .. "\n" ) Msg( "[ULIB] Loading SHARED module: " .. file .. "\n" )
include( "ulib/modules/" .. file ) include( "ulib/modules/" .. file )
end end
end end
--Client modules --Client modules
local files = file.Find( "ulib/modules/client/*.lua", "LUA" ) local files = file.Find( "ulib/modules/client/*.lua", "LUA" )
if #files > 0 then if #files > 0 then
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
Msg( "[ULIB] Loading CLIENT module: " .. file .. "\n" ) Msg( "[ULIB] Loading CLIENT module: " .. file .. "\n" )
include( "ulib/modules/client/" .. file ) include( "ulib/modules/client/" .. file )
end end
end end
local needs_auth = {} local needs_auth = {}
local function onEntCreated( ent ) local function onEntCreated( ent )
if ent:IsPlayer() and needs_auth[ ent:UserID() ] then if ent:IsPlayer() and needs_auth[ ent:UserID() ] then
hook.Call( ULib.HOOK_UCLAUTH, _, ent ) -- Because otherwise the server might call this before the player is created hook.Call( ULib.HOOK_UCLAUTH, _, ent ) -- Because otherwise the server might call this before the player is created
needs_auth[ ent:UserID() ] = nil needs_auth[ ent:UserID() ] = nil
end end
end end
hook.Add( "OnEntityCreated", "ULibPlayerAuthCheck", onEntCreated, HOOK_MONITOR_HIGH ) -- Listen for player creations hook.Add( "OnEntityCreated", "ULibPlayerAuthCheck", onEntCreated, HOOK_MONITOR_HIGH ) -- Listen for player creations
local function onInitPostEntity() local function onInitPostEntity()
if LocalPlayer():IsValid() then if LocalPlayer():IsValid() then
hook.Call( ULib.HOOK_LOCALPLAYERREADY, _, LocalPlayer() ) hook.Call( ULib.HOOK_LOCALPLAYERREADY, _, LocalPlayer() )
RunConsoleCommand( "ulib_cl_ready" ) RunConsoleCommand( "ulib_cl_ready" )
end end
end end
hook.Add( "InitPostEntity", "ULibLocalPlayerReady", onInitPostEntity, HOOK_MONITOR_HIGH ) -- Flag server when LocalPlayer() should be valid hook.Add( "InitPostEntity", "ULibLocalPlayerReady", onInitPostEntity, HOOK_MONITOR_HIGH ) -- Flag server when LocalPlayer() should be valid
-- We're trying to make sure that the player auths after the player object is created, this function is part of that check -- We're trying to make sure that the player auths after the player object is created, this function is part of that check
function authPlayerIfReady( ply, userid ) function authPlayerIfReady( ply, userid )
if ply and ply:IsValid() then if ply and ply:IsValid() then
hook.Call( ULib.HOOK_UCLAUTH, _, ply ) -- Call hook hook.Call( ULib.HOOK_UCLAUTH, _, ply ) -- Call hook
else else
needs_auth[ userid ] = true needs_auth[ userid ] = true
end end
end end

View File

@ -1,156 +1,156 @@
--[[ --[[
Title: Utilities Title: Utilities
Some client-side utilties Some client-side utilties
]] ]]
local function ULibRPC() local function ULibRPC()
local fn_string = net.ReadString() local fn_string = net.ReadString()
local args = net.ReadTable() local args = net.ReadTable()
local fn = ULib.findVar( fn_string ) local fn = ULib.findVar( fn_string )
if type( fn ) ~= "function" then return error( "Received bad RPC, invalid function (" .. tostring( fn_string ) .. ")!" ) end if type( fn ) ~= "function" then return error( "Received bad RPC, invalid function (" .. tostring( fn_string ) .. ")!" ) end
-- Since the table length operator can't always be trusted if there are holes in it, find the length by ourself -- Since the table length operator can't always be trusted if there are holes in it, find the length by ourself
local max = 0 local max = 0
for k, v in pairs( args ) do for k, v in pairs( args ) do
local n = tonumber( k ) local n = tonumber( k )
if n and n > max then if n and n > max then
max = n max = n
end end
end end
fn( unpack( args, 1, max ) ) fn( unpack( args, 1, max ) )
end end
net.Receive( "URPC", ULibRPC ) net.Receive( "URPC", ULibRPC )
--[[ --[[
Function: umsgRcv Function: umsgRcv
Receive a umsg sent by ULib.umsgSend Receive a umsg sent by ULib.umsgSend
Parameters: Parameters:
um - The user message object um - The user message object
Returns: Returns:
The variable from the umsg. The variable from the umsg.
]] ]]
function ULib.umsgRcv( um, control ) function ULib.umsgRcv( um, control )
local tv = control or um:ReadChar() local tv = control or um:ReadChar()
local ret -- Our return value local ret -- Our return value
if tv == ULib.TYPE_STRING then if tv == ULib.TYPE_STRING then
ret = um:ReadString() ret = um:ReadString()
elseif tv == ULib.TYPE_FLOAT then elseif tv == ULib.TYPE_FLOAT then
ret = um:ReadFloat() ret = um:ReadFloat()
elseif tv == ULib.TYPE_SHORT then elseif tv == ULib.TYPE_SHORT then
ret = um:ReadShort() ret = um:ReadShort()
elseif tv == ULib.TYPE_LONG then elseif tv == ULib.TYPE_LONG then
ret = um:ReadLong() ret = um:ReadLong()
elseif tv == ULib.TYPE_BOOLEAN then elseif tv == ULib.TYPE_BOOLEAN then
ret = um:ReadBool() ret = um:ReadBool()
elseif tv == ULib.TYPE_ENTITY then elseif tv == ULib.TYPE_ENTITY then
ret = um:ReadEntity() ret = um:ReadEntity()
elseif tv == ULib.TYPE_VECTOR then elseif tv == ULib.TYPE_VECTOR then
ret = um:ReadVector() ret = um:ReadVector()
elseif tv == ULib.TYPE_ANGLE then elseif tv == ULib.TYPE_ANGLE then
ret = um:ReadAngle() ret = um:ReadAngle()
elseif tv == ULib.TYPE_CHAR then elseif tv == ULib.TYPE_CHAR then
ret = um:ReadChar() ret = um:ReadChar()
elseif tv == ULib.TYPE_TABLE_BEGIN then elseif tv == ULib.TYPE_TABLE_BEGIN then
ret = {} ret = {}
while true do -- Yes an infite loop. We have a break inside. while true do -- Yes an infite loop. We have a break inside.
local key = ULib.umsgRcv( um ) local key = ULib.umsgRcv( um )
if key == nil then break end -- Here's our break if key == nil then break end -- Here's our break
ret[ key ] = ULib.umsgRcv( um ) ret[ key ] = ULib.umsgRcv( um )
end end
elseif tv == ULib.TYPE_TABLE_END then elseif tv == ULib.TYPE_TABLE_END then
return nil return nil
elseif tv == ULib.TYPE_NIL then elseif tv == ULib.TYPE_NIL then
return nil return nil
else else
ULib.error( "Unknown type passed to umsgRcv - " .. tv ) ULib.error( "Unknown type passed to umsgRcv - " .. tv )
end end
return ret return ret
end end
-- This will play sounds client side -- This will play sounds client side
local function rcvSound( um ) local function rcvSound( um )
local str = um:ReadString() local str = um:ReadString()
if not ULib.fileExists( "sound/" .. str ) then if not ULib.fileExists( "sound/" .. str ) then
Msg( "[LC ULib ERROR] Received invalid sound\n" ) Msg( "[LC ULib ERROR] Received invalid sound\n" )
return return
end end
if LocalPlayer():IsValid() then if LocalPlayer():IsValid() then
LocalPlayer():EmitSound( Sound( str ) ) LocalPlayer():EmitSound( Sound( str ) )
end end
end end
usermessage.Hook( "ulib_sound", rcvSound ) usermessage.Hook( "ulib_sound", rcvSound )
local cvarinfo = {} -- Stores the client cvar object indexed by name of the server cvar local cvarinfo = {} -- Stores the client cvar object indexed by name of the server cvar
local reversecvar = {} -- Stores the name of server cvars indexed by the client cvar local reversecvar = {} -- Stores the name of server cvars indexed by the client cvar
-- When our client side cvar is changed, notify the server to change it's cvar too. -- When our client side cvar is changed, notify the server to change it's cvar too.
local function clCvarChanged( cl_cvar, oldvalue, newvalue ) local function clCvarChanged( cl_cvar, oldvalue, newvalue )
if not reversecvar[ cl_cvar ] then -- Error if not reversecvar[ cl_cvar ] then -- Error
return return
elseif reversecvar[ cl_cvar ].ignore then -- ignore elseif reversecvar[ cl_cvar ].ignore then -- ignore
reversecvar[ cl_cvar ].ignore = nil reversecvar[ cl_cvar ].ignore = nil
return return
end end
local sv_cvar = reversecvar[ cl_cvar ].sv_cvar local sv_cvar = reversecvar[ cl_cvar ].sv_cvar
RunConsoleCommand( "ulib_update_cvar", sv_cvar, newvalue ) RunConsoleCommand( "ulib_update_cvar", sv_cvar, newvalue )
end end
-- This is the counterpart to <replicatedWithWritableCvar>. See that function for more info. We also add callbacks from here. -- This is the counterpart to <replicatedWithWritableCvar>. See that function for more info. We also add callbacks from here.
local function readCvar( um ) local function readCvar( um )
local sv_cvar = um:ReadString() local sv_cvar = um:ReadString()
local cl_cvar = um:ReadString() local cl_cvar = um:ReadString()
local default_value = um:ReadString() local default_value = um:ReadString()
local current_value = um:ReadString() local current_value = um:ReadString()
cvarinfo[ sv_cvar ] = GetConVar( cl_cvar ) or CreateClientConVar( cl_cvar, default_value, false, false ) -- Make sure it's created one way or another (second case is most common) cvarinfo[ sv_cvar ] = GetConVar( cl_cvar ) or CreateClientConVar( cl_cvar, default_value, false, false ) -- Make sure it's created one way or another (second case is most common)
reversecvar[ cl_cvar ] = { sv_cvar=sv_cvar } reversecvar[ cl_cvar ] = { sv_cvar=sv_cvar }
ULib.queueFunctionCall( function() -- Queued to ensure we don't overload the client console ULib.queueFunctionCall( function() -- Queued to ensure we don't overload the client console
hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, cl_cvar, nil, nil, current_value ) hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, cl_cvar, nil, nil, current_value )
if cvarinfo[ sv_cvar ]:GetString() ~= current_value then if cvarinfo[ sv_cvar ]:GetString() ~= current_value then
reversecvar[ cl_cvar ].ignore = true -- Flag so hook doesn't do anything. Flag is removed at hook. reversecvar[ cl_cvar ].ignore = true -- Flag so hook doesn't do anything. Flag is removed at hook.
RunConsoleCommand( cl_cvar, current_value ) RunConsoleCommand( cl_cvar, current_value )
end end
end ) end )
cvars.AddChangeCallback( cl_cvar, clCvarChanged ) cvars.AddChangeCallback( cl_cvar, clCvarChanged )
end end
usermessage.Hook( "ulib_repWriteCvar", readCvar ) usermessage.Hook( "ulib_repWriteCvar", readCvar )
-- This is called when they've attempted to change a cvar they don't have access to. -- This is called when they've attempted to change a cvar they don't have access to.
local function changeCvar( um ) local function changeCvar( um )
local ply = um:ReadEntity() local ply = um:ReadEntity()
local cl_cvar = um:ReadString() local cl_cvar = um:ReadString()
local oldvalue = um:ReadString() local oldvalue = um:ReadString()
local newvalue = um:ReadString() local newvalue = um:ReadString()
local changed = oldvalue ~= newvalue local changed = oldvalue ~= newvalue
if not reversecvar[ cl_cvar ] then -- Error! if not reversecvar[ cl_cvar ] then -- Error!
return return
end end
local sv_cvar = reversecvar[ cl_cvar ].sv_cvar local sv_cvar = reversecvar[ cl_cvar ].sv_cvar
ULib.queueFunctionCall( function() -- Queued so we won't overload the client console and so that changes are always going to be called via the hook AFTER the initial hook is called ULib.queueFunctionCall( function() -- Queued so we won't overload the client console and so that changes are always going to be called via the hook AFTER the initial hook is called
if changed then if changed then
hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, cl_cvar, ply, oldvalue, newvalue ) hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, cl_cvar, ply, oldvalue, newvalue )
end end
if GetConVarString( cl_cvar ) ~= newvalue then if GetConVarString( cl_cvar ) ~= newvalue then
reversecvar[ cl_cvar ].ignore = true -- Flag so hook doesn't do anything. Flag is removed at hook. reversecvar[ cl_cvar ].ignore = true -- Flag so hook doesn't do anything. Flag is removed at hook.
RunConsoleCommand( cl_cvar, newvalue) RunConsoleCommand( cl_cvar, newvalue)
end end
end ) end )
end end
usermessage.Hook( "ulib_repChangeCvar", changeCvar ) usermessage.Hook( "ulib_repChangeCvar", changeCvar )

View File

@ -1,54 +1,54 @@
--[[ --[[
Title: Draw Title: Draw
Our client-side draw functions Our client-side draw functions
]] ]]
--[[ --[[
Function: csayDraw Function: csayDraw
Draws a csay text on the screen. Draws a csay text on the screen.
Parameters: Parameters:
msg - The message to draw. msg - The message to draw.
color - *(Optional, defaults to 255, 255, 255, 255)* The color of the text color - *(Optional, defaults to 255, 255, 255, 255)* The color of the text
duration - *(Optional, defaults to 5)* The length of the text duration - *(Optional, defaults to 5)* The length of the text
fade - *(Optional, defaults to 0.5)* The length of fade time fade - *(Optional, defaults to 0.5)* The length of fade time
Revisions: Revisions:
v2.10 - Added fade parameter v2.10 - Added fade parameter
]] ]]
function ULib.csayDraw( msg, color, duration, fade ) function ULib.csayDraw( msg, color, duration, fade )
color = color or Color( 255, 255, 255, 255 ) color = color or Color( 255, 255, 255, 255 )
duration = duration or 5 duration = duration or 5
fade = fade or 0.5 fade = fade or 0.5
local start = CurTime() local start = CurTime()
local function drawToScreen() local function drawToScreen()
local alpha = 255 local alpha = 255
local dtime = CurTime() - start local dtime = CurTime() - start
if dtime > duration then -- Our time has come :'( if dtime > duration then -- Our time has come :'(
hook.Remove( "HUDPaint", "CSayHelperDraw" ) hook.Remove( "HUDPaint", "CSayHelperDraw" )
return return
end end
if fade - dtime > 0 then -- beginning fade if fade - dtime > 0 then -- beginning fade
alpha = (fade - dtime) / fade -- 0 to 1 alpha = (fade - dtime) / fade -- 0 to 1
alpha = 1 - alpha -- Reverse alpha = 1 - alpha -- Reverse
alpha = alpha * 255 alpha = alpha * 255
end end
if duration - dtime < fade then -- ending fade if duration - dtime < fade then -- ending fade
alpha = (duration - dtime) / fade -- 0 to 1 alpha = (duration - dtime) / fade -- 0 to 1
alpha = alpha * 255 alpha = alpha * 255
end end
color.a = alpha color.a = alpha
draw.DrawText( msg, "TargetID", ScrW() * 0.5, ScrH() * 0.25, color, TEXT_ALIGN_CENTER ) draw.DrawText( msg, "TargetID", ScrW() * 0.5, ScrH() * 0.25, color, TEXT_ALIGN_CENTER )
end end
hook.Add( "HUDPaint", "CSayHelperDraw", drawToScreen ) hook.Add( "HUDPaint", "CSayHelperDraw", drawToScreen )
end end

View File

@ -1,100 +1,100 @@
if not ULib then if not ULib then
ULib = {} ULib = {}
-- For historical purposes -- For historical purposes
if not ULib.consoleCommand then ULib.consoleCommand = game.ConsoleCommand end if not ULib.consoleCommand then ULib.consoleCommand = game.ConsoleCommand end
file.CreateDir( "ulib" ) file.CreateDir( "ulib" )
Msg( "///////////////////////////////\n" ) Msg( "///////////////////////////////\n" )
Msg( "// Ulysses Library //\n" ) Msg( "// Ulysses Library //\n" )
Msg( "///////////////////////////////\n" ) Msg( "///////////////////////////////\n" )
Msg( "// Loading... //\n" ) Msg( "// Loading... //\n" )
Msg( "// shared/defines.lua //\n" ) Msg( "// shared/defines.lua //\n" )
include( "ulib/shared/defines.lua" ) include( "ulib/shared/defines.lua" )
Msg( "// shared/misc.lua //\n" ) Msg( "// shared/misc.lua //\n" )
include( "ulib/shared/misc.lua" ) include( "ulib/shared/misc.lua" )
Msg( "// shared/util.lua //\n" ) Msg( "// shared/util.lua //\n" )
include( "ulib/shared/util.lua" ) include( "ulib/shared/util.lua" )
Msg( "// shared/hook.lua //\n" ) Msg( "// shared/hook.lua //\n" )
include( "ulib/shared/hook.lua" ) include( "ulib/shared/hook.lua" )
Msg( "// shared/table.lua //\n" ) Msg( "// shared/table.lua //\n" )
include( "ulib/shared/tables.lua" ) include( "ulib/shared/tables.lua" )
Msg( "// shared/player.lua //\n" ) Msg( "// shared/player.lua //\n" )
include( "ulib/shared/player.lua" ) include( "ulib/shared/player.lua" )
Msg( "// server/player.lua //\n" ) Msg( "// server/player.lua //\n" )
include( "ulib/server/player.lua" ) include( "ulib/server/player.lua" )
Msg( "// shared/messages.lua //\n" ) Msg( "// shared/messages.lua //\n" )
include( "ulib/shared/messages.lua" ) include( "ulib/shared/messages.lua" )
Msg( "// shared/commands.lua //\n" ) Msg( "// shared/commands.lua //\n" )
include( "ulib/shared/commands.lua" ) include( "ulib/shared/commands.lua" )
Msg( "// server/concommand.lua //\n" ) Msg( "// server/concommand.lua //\n" )
include( "ulib/server/concommand.lua" ) include( "ulib/server/concommand.lua" )
Msg( "// server/util.lua //\n" ) Msg( "// server/util.lua //\n" )
include( "ulib/server/util.lua" ) include( "ulib/server/util.lua" )
Msg( "// shared/sh_ucl.lua //\n" ) Msg( "// shared/sh_ucl.lua //\n" )
include( "ulib/shared/sh_ucl.lua" ) include( "ulib/shared/sh_ucl.lua" )
Msg( "// server/ucl.lua //\n" ) Msg( "// server/ucl.lua //\n" )
include( "ulib/server/ucl.lua" ) include( "ulib/server/ucl.lua" )
Msg( "// server/phys.lua //\n" ) Msg( "// server/phys.lua //\n" )
include( "ulib/server/phys.lua" ) include( "ulib/server/phys.lua" )
Msg( "// server/player_ext.lua //\n" ) Msg( "// server/player_ext.lua //\n" )
include( "server/player_ext.lua" ) include( "server/player_ext.lua" )
Msg( "// server/entity_ext.lua //\n" ) Msg( "// server/entity_ext.lua //\n" )
include( "server/entity_ext.lua" ) include( "server/entity_ext.lua" )
Msg( "// shared/cami_global.lua //\n" ) Msg( "// shared/cami_global.lua //\n" )
include( "shared/cami_global.lua" ) include( "shared/cami_global.lua" )
Msg( "// shared/cami_ulib.lua //\n" ) Msg( "// shared/cami_ulib.lua //\n" )
include( "shared/cami_ulib.lua" ) include( "shared/cami_ulib.lua" )
Msg( "// Load Complete! //\n" ) Msg( "// Load Complete! //\n" )
Msg( "///////////////////////////////\n" ) Msg( "///////////////////////////////\n" )
AddCSLuaFile( "ulib/cl_init.lua" ) AddCSLuaFile( "ulib/cl_init.lua" )
AddCSLuaFile( "autorun/ulib_init.lua" ) AddCSLuaFile( "autorun/ulib_init.lua" )
local folder = "ulib/shared" local folder = "ulib/shared"
local files = file.Find( folder .. "/" .. "*.lua", "LUA" ) local files = file.Find( folder .. "/" .. "*.lua", "LUA" )
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
AddCSLuaFile( folder .. "/" .. file ) AddCSLuaFile( folder .. "/" .. file )
end end
folder = "ulib/client" folder = "ulib/client"
files = file.Find( folder .. "/" .. "*.lua", "LUA" ) files = file.Find( folder .. "/" .. "*.lua", "LUA" )
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
AddCSLuaFile( folder .. "/" .. file ) AddCSLuaFile( folder .. "/" .. file )
end end
--Shared modules --Shared modules
local files = file.Find( "ulib/modules/*.lua", "LUA" ) local files = file.Find( "ulib/modules/*.lua", "LUA" )
if #files > 0 then if #files > 0 then
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
Msg( "[ULIB] Loading SHARED module: " .. file .. "\n" ) Msg( "[ULIB] Loading SHARED module: " .. file .. "\n" )
include( "ulib/modules/" .. file ) include( "ulib/modules/" .. file )
AddCSLuaFile( "ulib/modules/" .. file ) AddCSLuaFile( "ulib/modules/" .. file )
end end
end end
--Server modules --Server modules
local files = file.Find( "ulib/modules/server/*.lua", "LUA" ) local files = file.Find( "ulib/modules/server/*.lua", "LUA" )
if #files > 0 then if #files > 0 then
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
Msg( "[ULIB] Loading SERVER module: " .. file .. "\n" ) Msg( "[ULIB] Loading SERVER module: " .. file .. "\n" )
include( "ulib/modules/server/" .. file ) include( "ulib/modules/server/" .. file )
end end
end end
--Client modules --Client modules
local files = file.Find( "ulib/modules/client/*.lua", "LUA" ) local files = file.Find( "ulib/modules/client/*.lua", "LUA" )
if #files > 0 then if #files > 0 then
for _, file in ipairs( files ) do for _, file in ipairs( files ) do
Msg( "[ULIB] Loading CLIENT module: " .. file .. "\n" ) Msg( "[ULIB] Loading CLIENT module: " .. file .. "\n" )
AddCSLuaFile( "ulib/modules/client/" .. file ) AddCSLuaFile( "ulib/modules/client/" .. file )
end end
end end
local function clReady( ply ) local function clReady( ply )
ply.ulib_ready = true ply.ulib_ready = true
hook.Call( ULib.HOOK_LOCALPLAYERREADY, _, ply ) hook.Call( ULib.HOOK_LOCALPLAYERREADY, _, ply )
end end
concommand.Add( "ulib_cl_ready", clReady ) -- Called when the c-side player object is ready concommand.Add( "ulib_cl_ready", clReady ) -- Called when the c-side player object is ready
end end

View File

@ -1,3 +1,3 @@
This folder is similar to the lua/autorun folder, except all scripts in this folder are loaded after ULib. This folder is similar to the lua/autorun folder, except all scripts in this folder are loaded after ULib.
Scripts in this directory are shared ( loaded both server and client side ). Scripts in this directory are shared ( loaded both server and client side ).
Scripts in the client and server sub-folders are loaded only on the client and server respectively. Scripts in the client and server sub-folders are loaded only on the client and server respectively.

View File

@ -1,117 +1,117 @@
--[[ --[[
Title: Concommand Helpers Title: Concommand Helpers
Server-side compliment of the shared commands.lua Server-side compliment of the shared commands.lua
]] ]]
--[[ --[[
Table: sayCmds Table: sayCmds
This table holds our say commands. This table holds our say commands.
]] ]]
ULib.sayCmds = ULib.sayCmds or {} ULib.sayCmds = ULib.sayCmds or {}
--[[ --[[
Function: sayCmdCheck Function: sayCmdCheck
Say callback which will check to see if there's a say command being used. *DO NOT CALL DIRECTLY* Say callback which will check to see if there's a say command being used. *DO NOT CALL DIRECTLY*
Parameters: Parameters:
ply - The player. ply - The player.
strText - The text. strText - The text.
bTeam - Team say. bTeam - Team say.
Revisions: Revisions:
v2.10 - Made case-insensitive v2.10 - Made case-insensitive
]] ]]
local function sayCmdCheck( ply, strText, bTeam ) local function sayCmdCheck( ply, strText, bTeam )
local match local match
for str, data in pairs( ULib.sayCmds ) do for str, data in pairs( ULib.sayCmds ) do
local str2 = str local str2 = str
if strText:len() < str:len() then -- Go ahead and allow commands w/o spaces if strText:len() < str:len() then -- Go ahead and allow commands w/o spaces
str2 = string.Trim( str ) str2 = string.Trim( str )
end end
if strText:sub( 1, str2:len() ):lower() == str2 then if strText:sub( 1, str2:len() ):lower() == str2 then
if not match or match:len() <= str:len() then -- Don't rematch if there's a more specific one already. if not match or match:len() <= str:len() then -- Don't rematch if there's a more specific one already.
match = str match = str
end end
end end
end end
if match then -- We've got a winner! if match then -- We've got a winner!
local data = ULib.sayCmds[ match ] local data = ULib.sayCmds[ match ]
local args = string.Trim( strText:sub( match:len() + 1 ) ) -- Strip the caller command out local args = string.Trim( strText:sub( match:len() + 1 ) ) -- Strip the caller command out
local argv = ULib.splitArgs( args ) local argv = ULib.splitArgs( args )
-- ULib command callback -- ULib command callback
if data.__cmd then if data.__cmd then
local return_value = hook.Call( ULib.HOOK_COMMAND_CALLED, _, ply, data.__cmd, argv ) local return_value = hook.Call( ULib.HOOK_COMMAND_CALLED, _, ply, data.__cmd, argv )
if return_value == false then if return_value == false then
return nil return nil
end end
end end
if not ULib.ucl.query( ply, data.access ) then if not ULib.ucl.query( ply, data.access ) then
ULib.tsay( ply, "You do not have access to this command, " .. ply:Nick() .. "." ) ULib.tsay( ply, "You do not have access to this command, " .. ply:Nick() .. "." )
-- Print their name to intimidate them :) -- Print their name to intimidate them :)
return "" -- Block from appearing return "" -- Block from appearing
end end
local fn = data.fn local fn = data.fn
local hide = data.hide local hide = data.hide
ULib.pcallError( fn, ply, match:Trim(), argv, args ) ULib.pcallError( fn, ply, match:Trim(), argv, args )
if hide then return "" end if hide then return "" end
end end
return nil return nil
end end
hook.Add( "PlayerSay", "ULib_saycmd", sayCmdCheck, HOOK_HIGH ) -- High-priority hook.Add( "PlayerSay", "ULib_saycmd", sayCmdCheck, HOOK_HIGH ) -- High-priority
--[[ --[[
Function: addSayCommand Function: addSayCommand
Just like ULib's <concommand()> except that the callback is called when the command is said in chat instead of typed in the console. Just like ULib's <concommand()> except that the callback is called when the command is said in chat instead of typed in the console.
Parameters: Parameters:
say_cmd - A command string for says. IE: "!kick", then when someone says "!kick", it'll call the callback. say_cmd - A command string for says. IE: "!kick", then when someone says "!kick", it'll call the callback.
fn_call - The function to call when the command's called. fn_call - The function to call when the command's called.
access - The access string to associate access with this say command. (IE: "ulx kick"). Remember to call <ULib.ucl.registerAccess()> if the access string isn't being used in a command. access - The access string to associate access with this say command. (IE: "ulx kick"). Remember to call <ULib.ucl.registerAccess()> if the access string isn't being used in a command.
hide_say - *(Optional, defaults to false)* If true, will hide the chat message. Use this if you don't want other people to see the command. hide_say - *(Optional, defaults to false)* If true, will hide the chat message. Use this if you don't want other people to see the command.
nospace - *(Optional, defaults to false)* If true, a space won't be required after the command "IE: !slapbob" vs "!slap bob". nospace - *(Optional, defaults to false)* If true, a space won't be required after the command "IE: !slapbob" vs "!slap bob".
Revisions: Revisions:
v2.10 - Added nospace parameter, made case insensitive v2.10 - Added nospace parameter, made case insensitive
v2.40 - Removed the command help parameter, now accepts nil as access (for always allowed) v2.40 - Removed the command help parameter, now accepts nil as access (for always allowed)
]] ]]
function ULib.addSayCommand( say_cmd, fn_call, access, hide_say, nospace ) function ULib.addSayCommand( say_cmd, fn_call, access, hide_say, nospace )
say_cmd = string.Trim( say_cmd:lower() ) say_cmd = string.Trim( say_cmd:lower() )
if not nospace then if not nospace then
say_cmd = say_cmd .. " " say_cmd = say_cmd .. " "
end end
ULib.sayCmds[ say_cmd ] = { fn=fn_call, hide=hide_say, access=access } ULib.sayCmds[ say_cmd ] = { fn=fn_call, hide=hide_say, access=access }
end end
--[[ --[[
Function: removeSayCommand Function: removeSayCommand
Removes a say command. Removes a say command.
Parameters: Parameters:
say_cmd - The command string for says to remove. say_cmd - The command string for says to remove.
]] ]]
function ULib.removeSayCommand( say_cmd ) function ULib.removeSayCommand( say_cmd )
ULib.sayCmds[ say_cmd ] = nil -- Remove both forms ULib.sayCmds[ say_cmd ] = nil -- Remove both forms
ULib.sayCmds[ say_cmd .. " " ] = nil ULib.sayCmds[ say_cmd .. " " ] = nil
end end

View File

@ -1,192 +1,192 @@
local meta = FindMetaTable( "Entity" ) local meta = FindMetaTable( "Entity" )
-- Return if there's nothing to add on to -- Return if there's nothing to add on to
if not meta then return end if not meta then return end
-- Are you a STOOL author who's angry that your tool isn't on this list? -- Are you a STOOL author who's angry that your tool isn't on this list?
-- Just add this to your code: -- Just add this to your code:
-- if ULib then table.insert( ULib.delWhiteList, "my_stool" ) end -- if ULib then table.insert( ULib.delWhiteList, "my_stool" ) end
ULib.delWhitelist = -- White list for objects that can't be deleted ULib.delWhitelist = -- White list for objects that can't be deleted
{ {
"colour", "colour",
"material", "material",
"paint", "paint",
"hoverball", "hoverball",
"emitter", "emitter",
"elastic", "elastic",
"hydraulic", "hydraulic",
"muscle", "muscle",
"nail", "nail",
"ballsocket", "ballsocket",
"ballsocket_adv", "ballsocket_adv",
"pulley", "pulley",
"rope", "rope",
"slider", "slider",
"weld", "weld",
"winch", "winch",
"balloon", "balloon",
"button", "button",
"duplicator", "duplicator",
"dynamite", "dynamite",
"keepupright", "keepupright",
"lamp", "lamp",
"nocollide", "nocollide",
"thruster", "thruster",
"turret", "turret",
"wheel", "wheel",
"eyeposer", "eyeposer",
"faceposer", "faceposer",
"statue", "statue",
"weld_ez", "weld_ez",
"axis", "axis",
-- Properties -- Properties
"gravity", "gravity",
"collision", "collision",
--"keepupright", -- Already above --"keepupright", -- Already above
"persist", "persist",
} }
-- Are you a STOOL author who's angry that your tool isn't on this list? -- Are you a STOOL author who's angry that your tool isn't on this list?
-- Just add this to your code: -- Just add this to your code:
-- if ULib then table.insert( ULib.moveWhiteList, "my_stool" ) end -- if ULib then table.insert( ULib.moveWhiteList, "my_stool" ) end
ULib.moveWhitelist = -- White list for objects that can't be moved ULib.moveWhitelist = -- White list for objects that can't be moved
{ {
"colour", "colour",
"material", "material",
"paint", "paint",
"duplicator", "duplicator",
"eyeposer", "eyeposer",
"faceposer", "faceposer",
"remover", "remover",
-- Properties -- Properties
--"remover", -- Already above --"remover", -- Already above
"persist", "persist",
} }
function meta:DisallowMoving( bool ) function meta:DisallowMoving( bool )
self.NoMoving = bool self.NoMoving = bool
end end
function meta:DisallowDeleting( bool, callback, no_replication ) function meta:DisallowDeleting( bool, callback, no_replication )
self.NoDeleting = bool self.NoDeleting = bool
self.NoDeletingCallback = callback self.NoDeletingCallback = callback
self.NoReplication = no_replication self.NoReplication = no_replication
end end
local function tool( ply, tr, toolmode, second ) local function tool( ply, tr, toolmode, second )
-- In the case of the nail gun, let's check the entity they're nailing TO first. -- In the case of the nail gun, let's check the entity they're nailing TO first.
if toolmode == "nail" and not second then if toolmode == "nail" and not second then
local tr2 = {} local tr2 = {}
tr2.start = tr.HitPos tr2.start = tr.HitPos
tr2.endpos = tr.HitPos + ply:GetAimVector() * 16 tr2.endpos = tr.HitPos + ply:GetAimVector() * 16
tr2.filter = { ply, tr.Entity } tr2.filter = { ply, tr.Entity }
local trace = util.TraceLine( tr2 ) local trace = util.TraceLine( tr2 )
if trace.Entity and trace.Entity:IsValid() and not trace.Entity:IsPlayer() then if trace.Entity and trace.Entity:IsValid() and not trace.Entity:IsPlayer() then
local ret = tool( ply, trace, toolmode, true ) local ret = tool( ply, trace, toolmode, true )
if ret ~= nil then if ret ~= nil then
return ret return ret
end end
end end
end end
-- In the case of the remover, we have to make sure they're not trying to right click remove one of no delete ents -- In the case of the remover, we have to make sure they're not trying to right click remove one of no delete ents
if toolmode == "remover" and ply:KeyDown( IN_ATTACK2 ) and not ply:KeyDownLast( IN_ATTACK2 ) then if toolmode == "remover" and ply:KeyDown( IN_ATTACK2 ) and not ply:KeyDownLast( IN_ATTACK2 ) then
local ConstrainedEntities = constraint.GetAllConstrainedEntities( tr.Entity ) local ConstrainedEntities = constraint.GetAllConstrainedEntities( tr.Entity )
if ConstrainedEntities then -- If we have anything to worry about if ConstrainedEntities then -- If we have anything to worry about
-- Loop through all the entities in the system -- Loop through all the entities in the system
for _, ent in pairs( ConstrainedEntities ) do for _, ent in pairs( ConstrainedEntities ) do
if ent.NoDeleting then if ent.NoDeleting then
ULib.tsay( ply, "You cannot use a right click delete on this ent because it is constrained to a non-deleteable entity." ) ULib.tsay( ply, "You cannot use a right click delete on this ent because it is constrained to a non-deleteable entity." )
return false return false
end end
end end
end end
end end
if tr.Entity.NoMoving then if tr.Entity.NoMoving then
if not table.HasValue( ULib.moveWhitelist, toolmode ) then if not table.HasValue( ULib.moveWhitelist, toolmode ) then
return false return false
end end
end end
if tr.Entity.NoDeleting then if tr.Entity.NoDeleting then
if not table.HasValue( ULib.delWhitelist, toolmode ) then if not table.HasValue( ULib.delWhitelist, toolmode ) then
return false return false
end end
end end
end end
hook.Add( "CanTool", "ULibEntToolCheck", tool, HOOK_HIGH ) hook.Add( "CanTool", "ULibEntToolCheck", tool, HOOK_HIGH )
local function property( ply, propertymode, ent ) local function property( ply, propertymode, ent )
if ent.NoMoving then if ent.NoMoving then
if not table.HasValue( ULib.moveWhitelist, toolmode ) then if not table.HasValue( ULib.moveWhitelist, toolmode ) then
return false return false
end end
end end
if ent.NoDeleting then if ent.NoDeleting then
if not table.HasValue( ULib.delWhitelist, toolmode ) then if not table.HasValue( ULib.delWhitelist, toolmode ) then
return false return false
end end
end end
end end
hook.Add( "CanProperty", "ULibEntPropertyCheck", property, HOOK_HIGH ) hook.Add( "CanProperty", "ULibEntPropertyCheck", property, HOOK_HIGH )
local function physgun( ply, ent ) local function physgun( ply, ent )
if ent.NoMoving then return false end if ent.NoMoving then return false end
end end
hook.Add( "PhysgunPickup", "ULibEntPhysCheck", physgun, HOOK_HIGH ) hook.Add( "PhysgunPickup", "ULibEntPhysCheck", physgun, HOOK_HIGH )
hook.Add( "CanPlayerUnfreeze", "ULibEntUnfreezeCheck", physgun, HOOK_HIGH ) hook.Add( "CanPlayerUnfreeze", "ULibEntUnfreezeCheck", physgun, HOOK_HIGH )
local function physgunReload( weapon, ply ) local function physgunReload( weapon, ply )
local trace = util.GetPlayerTrace( ply ) local trace = util.GetPlayerTrace( ply )
local tr = util.TraceLine( trace ) local tr = util.TraceLine( trace )
local ent = tr.Entity local ent = tr.Entity
if not ent or not ent:IsValid() or ent:IsWorld() then return end -- Invalid or not interested if not ent or not ent:IsValid() or ent:IsWorld() then return end -- Invalid or not interested
if ent.NoMoving then return false end if ent.NoMoving then return false end
end end
hook.Add( "OnPhysgunReload", "ULibEntPhysReloadCheck", physgunReload, HOOK_HIGH ) hook.Add( "OnPhysgunReload", "ULibEntPhysReloadCheck", physgunReload, HOOK_HIGH )
local function damageCheck( ent ) local function damageCheck( ent )
if ent.NoDeleting then if ent.NoDeleting then
-- return false -- return false
end end
end end
hook.Add( "EntityTakeDamage", "ULibEntDamagedCheck", damageCheck, HOOK_MONITOR_HIGH ) hook.Add( "EntityTakeDamage", "ULibEntDamagedCheck", damageCheck, HOOK_MONITOR_HIGH )
-- This is just in case we have some horribly programmed addon that goes rampant in deleting things -- This is just in case we have some horribly programmed addon that goes rampant in deleting things
local function removedCheck( ent ) local function removedCheck( ent )
if ent.NoDeleting and not ent.NoReplication then if ent.NoDeleting and not ent.NoReplication then
local class = ent:GetClass() local class = ent:GetClass()
local pos = ent:GetPos() local pos = ent:GetPos()
local ang = ent:GetAngles() local ang = ent:GetAngles()
local model = ent:GetModel() local model = ent:GetModel()
local frozen = false local frozen = false
if ent:GetPhysicsObject():IsValid() and not ent:GetPhysicsObject():IsMoveable() then if ent:GetPhysicsObject():IsValid() and not ent:GetPhysicsObject():IsMoveable() then
frozen = true frozen = true
end end
local t = ent:GetTable() local t = ent:GetTable()
ULib.queueFunctionCall( function() -- Create it next frame because 1. Old ent won't be in way and 2. We won't overflow the server while shutting down ULib.queueFunctionCall( function() -- Create it next frame because 1. Old ent won't be in way and 2. We won't overflow the server while shutting down
local ent2 = ents.Create( class ) local ent2 = ents.Create( class )
table.Merge( ent2:GetTable(), t ) table.Merge( ent2:GetTable(), t )
ent2:SetModel( model ) ent2:SetModel( model )
ent2:SetPos( pos ) ent2:SetPos( pos )
ent2:SetAngles( ang ) ent2:SetAngles( ang )
ent2:Spawn() ent2:Spawn()
if frozen then if frozen then
ent2:GetPhysicsObject():EnableMotion( false ) ent2:GetPhysicsObject():EnableMotion( false )
end end
if ent2.NoDeletingCallback then if ent2.NoDeletingCallback then
ent2.NoDeletingCallback( ent, ent2 ) ent2.NoDeletingCallback( ent, ent2 )
end end
end ) end )
end end
end end
hook.Add( "EntityRemoved", "ULibEntRemovedCheck", removedCheck, HOOK_MONITOR_HIGH ) hook.Add( "EntityRemoved", "ULibEntRemovedCheck", removedCheck, HOOK_MONITOR_HIGH )

View File

@ -1,115 +1,115 @@
--[[ --[[
Title: Physics Helpers Title: Physics Helpers
Various functions to make dealing with the HL2 physics engine a little easier. Various functions to make dealing with the HL2 physics engine a little easier.
]] ]]
--[[ --[[
Function: applyAccel Function: applyAccel
Parameters: Parameters:
ent - The entity to apply the acceleration to ent - The entity to apply the acceleration to
magnitude - The amount of acceleration ( Use nil if the magnitude is specified in the direction ) magnitude - The amount of acceleration ( Use nil if the magnitude is specified in the direction )
direction - The direction to apply the acceleration in ( if the magnitude is part of the direction, specify nil for the magnitude ) direction - The direction to apply the acceleration in ( if the magnitude is part of the direction, specify nil for the magnitude )
dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the acceleration ) dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the acceleration )
]] ]]
function ULib.applyAccel( ent, magnitude, direction, dTime ) function ULib.applyAccel( ent, magnitude, direction, dTime )
if dTime == nil then dTime = 1 end if dTime == nil then dTime = 1 end
if magnitude ~= nil then if magnitude ~= nil then
direction:Normalize() direction:Normalize()
else else
magnitude = 1 magnitude = 1
end end
-- Times it by the time elapsed since the last update. -- Times it by the time elapsed since the last update.
local accel = magnitude * dTime local accel = magnitude * dTime
-- Convert our scalar accel to a vector accel -- Convert our scalar accel to a vector accel
accel = direction * accel accel = direction * accel
if ent:GetMoveType() == MOVETYPE_VPHYSICS then if ent:GetMoveType() == MOVETYPE_VPHYSICS then
-- a = f/m , so times by mass to get the force. -- a = f/m , so times by mass to get the force.
local force = accel * ent:GetPhysicsObject():GetMass() local force = accel * ent:GetPhysicsObject():GetMass()
ent:GetPhysicsObject():ApplyForceCenter( force ) ent:GetPhysicsObject():ApplyForceCenter( force )
else else
ent:SetVelocity( accel ) -- As it turns out, SetVelocity() is actually SetAccel() in GM10 ent:SetVelocity( accel ) -- As it turns out, SetVelocity() is actually SetAccel() in GM10
end end
end end
--[[ --[[
Function: applyForce Function: applyForce
Parameters: Parameters:
ent - The entity to apply the force to ent - The entity to apply the force to
magnitude - The amount of force ( Use nil if the magnitude is specified in the direction ) magnitude - The amount of force ( Use nil if the magnitude is specified in the direction )
direction - The direction to apply the force in ( if the magnitude is part of the direction, specify nil for the magnitude ) direction - The direction to apply the force in ( if the magnitude is part of the direction, specify nil for the magnitude )
dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the force ) dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the force )
]] ]]
function ULib.applyForce( ent, magnitude, direction, dTime ) function ULib.applyForce( ent, magnitude, direction, dTime )
if dTime == nil then dTime = 1 end if dTime == nil then dTime = 1 end
if magnitude ~= nil then if magnitude ~= nil then
direction:Normalize() direction:Normalize()
else else
magnitude = 1 magnitude = 1
end end
-- Times it by the time elapsed since the last update. -- Times it by the time elapsed since the last update.
local force = magnitude * dTime local force = magnitude * dTime
-- Convert our scalar force to a vector force -- Convert our scalar force to a vector force
force = direction * force force = direction * force
if ent:GetMoveType() == MOVETYPE_VPHYSICS then if ent:GetMoveType() == MOVETYPE_VPHYSICS then
ent:GetPhysicsObject():ApplyForceCenter( force ) ent:GetPhysicsObject():ApplyForceCenter( force )
else else
-- Because we're not dealing with objects that have vphysics, they might not have a mass. This would cause errors, let's catch them here. -- Because we're not dealing with objects that have vphysics, they might not have a mass. This would cause errors, let's catch them here.
local mass = ent:GetPhysicsObject():GetMass() local mass = ent:GetPhysicsObject():GetMass()
if not mass then if not mass then
mass = 1 mass = 1
Msg( "applyForce was called with a non-physics entity that doesn't have a mass. To continue calculations, we're assuming it has a mass of one. This could very well produce unrealistic looking physics!\n") Msg( "applyForce was called with a non-physics entity that doesn't have a mass. To continue calculations, we're assuming it has a mass of one. This could very well produce unrealistic looking physics!\n")
end end
-- f = m*a, so divide it by mass to get the accel -- f = m*a, so divide it by mass to get the accel
local accel = force * 1/mass local accel = force * 1/mass
ent:SetVelocity( accel ) -- As it turns out, SetVelocity() is actually SetAccel() in GM10 ent:SetVelocity( accel ) -- As it turns out, SetVelocity() is actually SetAccel() in GM10
end end
end end
--[[ --[[
Function: applyAccelInCurDirection Function: applyAccelInCurDirection
Applies an acceleration in the entities current *velocity* direction ( not the entity's heading ). See <applyAccel>. Applies an acceleration in the entities current *velocity* direction ( not the entity's heading ). See <applyAccel>.
Basically makes the entity go faster or slower ( if a negative magnitude is passed ). Basically makes the entity go faster or slower ( if a negative magnitude is passed ).
Parameters: Parameters:
ent - The entity to apply the force to ent - The entity to apply the force to
magnitude - The amount of acceleration magnitude - The amount of acceleration
dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the acceleration ) dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the acceleration )
]] ]]
function ULib.applyAccelInCurDirection( ent, magnitude, dTime ) function ULib.applyAccelInCurDirection( ent, magnitude, dTime )
local direction = ent:GetVelocity( entid ):GetNormalized() local direction = ent:GetVelocity( entid ):GetNormalized()
ULib.applyAccel( entid, magnitude, direction, dTime ) ULib.applyAccel( entid, magnitude, direction, dTime )
end end
--[[ --[[
Function: applyForceInCurDirection Function: applyForceInCurDirection
Applies a force in the entities current *velocity* direction ( not the entity's heading ). See <applyForce>. Applies a force in the entities current *velocity* direction ( not the entity's heading ). See <applyForce>.
Basically makes the entity go faster or slower ( if a negative magnitude is passed ). Basically makes the entity go faster or slower ( if a negative magnitude is passed ).
Parameters: Parameters:
ent - The entity to apply the force to ent - The entity to apply the force to
magnitude - The amount of force magnitude - The amount of force
dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the force ) dTime - *(Optional, defaults to 1)* The time passed since the last update in seconds ( IE: 0.5 for dTime would only apply half the force )
]] ]]
function ULib.applyForceInCurDirection( ent, magnitude, dTime ) function ULib.applyForceInCurDirection( ent, magnitude, dTime )
local direction = ent:GetVelocity( entid ):GetNormalized() local direction = ent:GetVelocity( entid ):GetNormalized()
ULib.applyForce( entid, magnitude, direction, dTime ) ULib.applyForce( entid, magnitude, direction, dTime )
end end

View File

@ -1,491 +1,491 @@
--[[ --[[
Title: Player Title: Player
Holds some helpful player functions. Holds some helpful player functions.
]] ]]
--[[ --[[
Table: slapSounds Table: slapSounds
These are the sounds used for slaps. These are the sounds used for slaps.
]] ]]
local slapSounds = { local slapSounds = {
"physics/body/body_medium_impact_hard1.wav", "physics/body/body_medium_impact_hard1.wav",
"physics/body/body_medium_impact_hard2.wav", "physics/body/body_medium_impact_hard2.wav",
"physics/body/body_medium_impact_hard3.wav", "physics/body/body_medium_impact_hard3.wav",
"physics/body/body_medium_impact_hard5.wav", "physics/body/body_medium_impact_hard5.wav",
"physics/body/body_medium_impact_hard6.wav", "physics/body/body_medium_impact_hard6.wav",
"physics/body/body_medium_impact_soft5.wav", "physics/body/body_medium_impact_soft5.wav",
"physics/body/body_medium_impact_soft6.wav", "physics/body/body_medium_impact_soft6.wav",
"physics/body/body_medium_impact_soft7.wav", "physics/body/body_medium_impact_soft7.wav",
} }
--[[ --[[
Function: slap Function: slap
Slaps an entity, can be a user or any entity. Slaps an entity, can be a user or any entity.
Parameters: Parameters:
ent - The target ent. ent - The target ent.
damage - *(Optional, defaults to 0)* The amount of damage to inflict on the entity. damage - *(Optional, defaults to 0)* The amount of damage to inflict on the entity.
power - *(Optional, defaults to 30)* The power of the slap. power - *(Optional, defaults to 30)* The power of the slap.
nosound - *(Optional, defaults to false)* If true, no sound will be played. nosound - *(Optional, defaults to false)* If true, no sound will be played.
]] ]]
function ULib.slap( ent, damage, power, nosound ) function ULib.slap( ent, damage, power, nosound )
if ent:GetMoveType() == MOVETYPE_OBSERVER then return end -- Nothing we can do. if ent:GetMoveType() == MOVETYPE_OBSERVER then return end -- Nothing we can do.
damage = damage or 0 damage = damage or 0
power = power or 500 power = power or 500
if ent:IsPlayer() then if ent:IsPlayer() then
if not ent:Alive() then if not ent:Alive() then
return -- Nothing we can do. return -- Nothing we can do.
end end
if ent:InVehicle() then if ent:InVehicle() then
ent:ExitVehicle() ent:ExitVehicle()
end end
if ent:GetMoveType() == MOVETYPE_NOCLIP then if ent:GetMoveType() == MOVETYPE_NOCLIP then
ent:SetMoveType( MOVETYPE_WALK ) ent:SetMoveType( MOVETYPE_WALK )
end end
end end
if not nosound then -- Play a slap sound if not nosound then -- Play a slap sound
local sound_num = math.random( #slapSounds ) -- Choose at random local sound_num = math.random( #slapSounds ) -- Choose at random
ent:EmitSound( slapSounds[ sound_num ] ) ent:EmitSound( slapSounds[ sound_num ] )
end end
local direction = Vector( math.random( 20 )-10, math.random( 20 )-10, math.random( 20 )-5 ) -- Make it random, slightly biased to go up. local direction = Vector( math.random( 20 )-10, math.random( 20 )-10, math.random( 20 )-5 ) -- Make it random, slightly biased to go up.
ULib.applyAccel( ent, power, direction ) ULib.applyAccel( ent, power, direction )
local angle_punch_pitch = math.Rand( -20, 20 ) local angle_punch_pitch = math.Rand( -20, 20 )
local angle_punch_yaw = math.sqrt( 20*20 - angle_punch_pitch * angle_punch_pitch ) local angle_punch_yaw = math.sqrt( 20*20 - angle_punch_pitch * angle_punch_pitch )
if math.random( 0, 1 ) == 1 then if math.random( 0, 1 ) == 1 then
angle_punch_yaw = angle_punch_yaw * -1 angle_punch_yaw = angle_punch_yaw * -1
end end
ent:ViewPunch( Angle( angle_punch_pitch, angle_punch_yaw, 0 ) ) ent:ViewPunch( Angle( angle_punch_pitch, angle_punch_yaw, 0 ) )
local newHp = ent:Health() - damage local newHp = ent:Health() - damage
if newHp <= 0 then if newHp <= 0 then
if ent:IsPlayer() then if ent:IsPlayer() then
ent:Kill() ent:Kill()
else else
ent:Fire( "break", 1, 0 ) ent:Fire( "break", 1, 0 )
end end
return return
end end
ent:SetHealth( newHp ) ent:SetHealth( newHp )
end end
--[[ --[[
Function: kick Function: kick
Kicks a user. Kicks a user.
Parameters: Parameters:
ply - The player to kick. ply - The player to kick.
reason - *(Optional)* The reason to give for kicking. reason - *(Optional)* The reason to give for kicking.
]] ]]
function ULib.kick( ply, reason, calling_ply ) function ULib.kick( ply, reason, calling_ply )
if reason and calling_ply ~= nil then if reason and calling_ply ~= nil then
local nick = calling_ply:IsValid() and string.format( "%s(%s)", calling_ply:Nick(), calling_ply:SteamID() ) or "Console" local nick = calling_ply:IsValid() and string.format( "%s(%s)", calling_ply:Nick(), calling_ply:SteamID() ) or "Console"
ply:Kick( string.format( "Kicked by %s (%s)", nick, reason or "[ULX] Kicked from server" ) ) ply:Kick( string.format( "Kicked by %s (%s)", nick, reason or "[ULX] Kicked from server" ) )
else else
ply:Kick( reason or "[ULX] Kicked from server" ) ply:Kick( reason or "[ULX] Kicked from server" )
end end
end end
--[[ --[[
Function: ban Function: ban
Bans a user. Bans a user.
Parameters: Parameters:
ply - The player to ban. ply - The player to ban.
time - *(Optional)* The time in minutes to ban the person for, leave nil or 0 for permaban. time - *(Optional)* The time in minutes to ban the person for, leave nil or 0 for permaban.
reason - *(Optional)* The reason for banning reason - *(Optional)* The reason for banning
admin - *(Optional)* Admin player enacting ban admin - *(Optional)* Admin player enacting ban
Revisions: Revisions:
v2.10 - Added support for custom ban list v2.10 - Added support for custom ban list
]] ]]
function ULib.ban( ply, time, reason, admin ) function ULib.ban( ply, time, reason, admin )
if not time or type( time ) ~= "number" then if not time or type( time ) ~= "number" then
time = 0 time = 0
end end
ULib.addBan( ply:SteamID(), time, reason, ply:Name(), admin ) ULib.addBan( ply:SteamID(), time, reason, ply:Name(), admin )
-- Load our currently banned users so we don't overwrite them -- Load our currently banned users so we don't overwrite them
if ULib.fileExists( "cfg/banned_user.cfg" ) then if ULib.fileExists( "cfg/banned_user.cfg" ) then
ULib.execFile( "cfg/banned_user.cfg" ) ULib.execFile( "cfg/banned_user.cfg" )
end end
end end
--[[ --[[
Function: kickban Function: kickban
Kicks and bans a user. Kicks and bans a user.
Parameters: Parameters:
ply - The player to ban. ply - The player to ban.
time - *(Optional)* The time in minutes to ban the person for, leave nil or 0 for permaban. time - *(Optional)* The time in minutes to ban the person for, leave nil or 0 for permaban.
reason - *(Optional)* The reason for banning reason - *(Optional)* The reason for banning
admin - *(Optional)* Admin player enacting ban admin - *(Optional)* Admin player enacting ban
Revisions: Revisions:
v2.10 - Added support for custom ban list v2.10 - Added support for custom ban list
]] ]]
function ULib.kickban( ply, time, reason, admin ) function ULib.kickban( ply, time, reason, admin )
if not time or type( time ) ~= "number" then if not time or type( time ) ~= "number" then
time = 0 time = 0
end end
ULib.addBan( ply:SteamID(), time, reason, ply:Name(), admin ) ULib.addBan( ply:SteamID(), time, reason, ply:Name(), admin )
-- Load our currently banned users so we don't overwrite them -- Load our currently banned users so we don't overwrite them
if ULib.fileExists( "cfg/banned_user.cfg" ) then if ULib.fileExists( "cfg/banned_user.cfg" ) then
ULib.execFile( "cfg/banned_user.cfg" ) ULib.execFile( "cfg/banned_user.cfg" )
end end
end end
--[[ --[[
Function: addBan Function: addBan
Helper function to store additional data about bans. Helper function to store additional data about bans.
Parameters: Parameters:
steamid - Banned player's steamid steamid - Banned player's steamid
time - Length of ban time - Length of ban
reason - *(Optional)* Reason for banning reason - *(Optional)* Reason for banning
name - *(Optional)* Name of player banned name - *(Optional)* Name of player banned
admin - *(Optional)* Admin player enacting the ban admin - *(Optional)* Admin player enacting the ban
Revisions: Revisions:
2.10 - Initial 2.10 - Initial
2.40 - If the steamid is connected, kicks them with the reason given 2.40 - If the steamid is connected, kicks them with the reason given
]] ]]
function ULib.addBan( steamid, time, reason, name, admin ) function ULib.addBan( steamid, time, reason, name, admin )
local strTime = time ~= 0 and string.format( "for %s minute(s)", time ) or "permanently" local strTime = time ~= 0 and string.format( "for %s minute(s)", time ) or "permanently"
local showReason = string.format( "Banned %s: %s", strTime, reason ) local showReason = string.format( "Banned %s: %s", strTime, reason )
local players = player.GetAll() local players = player.GetAll()
for i=1, #players do for i=1, #players do
if players[ i ]:SteamID() == steamid then if players[ i ]:SteamID() == steamid then
ULib.kick( players[ i ], showReason, admin ) ULib.kick( players[ i ], showReason, admin )
end end
end end
-- Remove all semicolons from the reason to prevent command injection -- Remove all semicolons from the reason to prevent command injection
showReason = string.gsub(showReason, ";", "") showReason = string.gsub(showReason, ";", "")
-- This redundant kick code is to ensure they're kicked -- even if they're joining -- This redundant kick code is to ensure they're kicked -- even if they're joining
game.ConsoleCommand( string.format( "kickid %s %s\n", steamid, showReason or "" ) ) game.ConsoleCommand( string.format( "kickid %s %s\n", steamid, showReason or "" ) )
game.ConsoleCommand( string.format( "banid %f %s kick\n", time, steamid ) ) game.ConsoleCommand( string.format( "banid %f %s kick\n", time, steamid ) )
game.ConsoleCommand( "writeid\n" ) game.ConsoleCommand( "writeid\n" )
local admin_name local admin_name
if admin then if admin then
admin_name = "(Console)" admin_name = "(Console)"
if admin:IsValid() then if admin:IsValid() then
admin_name = string.format( "%s(%s)", admin:Name(), admin:SteamID() ) admin_name = string.format( "%s(%s)", admin:Name(), admin:SteamID() )
end end
end end
local t = {} local t = {}
if ULib.bans[ steamid ] then if ULib.bans[ steamid ] then
t = ULib.bans[ steamid ] t = ULib.bans[ steamid ]
t.modified_admin = admin_name t.modified_admin = admin_name
t.modified_time = os.time() t.modified_time = os.time()
else else
t.admin = admin_name t.admin = admin_name
end end
t.time = t.time or os.time() t.time = t.time or os.time()
if time > 0 then if time > 0 then
t.unban = ( ( time * 60 ) + os.time() ) t.unban = ( ( time * 60 ) + os.time() )
else else
t.unban = 0 t.unban = 0
end end
if reason then if reason then
t.reason = reason t.reason = reason
end end
if name then if name then
t.name = name t.name = name
end end
ULib.bans[ steamid ] = t ULib.bans[ steamid ] = t
ULib.fileWrite( ULib.BANS_FILE, ULib.makeKeyValues( ULib.bans ) ) ULib.fileWrite( ULib.BANS_FILE, ULib.makeKeyValues( ULib.bans ) )
end end
--[[ --[[
Function: unban Function: unban
Unbans the given steamid. Unbans the given steamid.
Parameters: Parameters:
steamid - The steamid to unban. steamid - The steamid to unban.
admin - *(Optional)* Admin player unbanning steamid admin - *(Optional)* Admin player unbanning steamid
Revisions: Revisions:
v2.10 - Initial v2.10 - Initial
]] ]]
function ULib.unban( steamid, admin ) function ULib.unban( steamid, admin )
--Default banlist --Default banlist
if ULib.fileExists( "cfg/banned_user.cfg" ) then if ULib.fileExists( "cfg/banned_user.cfg" ) then
ULib.execFile( "cfg/banned_user.cfg" ) ULib.execFile( "cfg/banned_user.cfg" )
end end
ULib.queueFunctionCall( game.ConsoleCommand, "removeid " .. steamid .. ";writeid\n" ) -- Execute after done loading bans ULib.queueFunctionCall( game.ConsoleCommand, "removeid " .. steamid .. ";writeid\n" ) -- Execute after done loading bans
--ULib banlist --ULib banlist
ULib.bans[ steamid ] = nil ULib.bans[ steamid ] = nil
ULib.fileWrite( ULib.BANS_FILE, ULib.makeKeyValues( ULib.bans ) ) ULib.fileWrite( ULib.BANS_FILE, ULib.makeKeyValues( ULib.bans ) )
end end
local function doInvis() local function doInvis()
local players = player.GetAll() local players = player.GetAll()
local remove = true local remove = true
for _, player in ipairs( players ) do for _, player in ipairs( players ) do
local t = player:GetTable() local t = player:GetTable()
if t.invis then if t.invis then
remove = false remove = false
if player:Alive() and player:GetActiveWeapon():IsValid() then if player:Alive() and player:GetActiveWeapon():IsValid() then
if player:GetActiveWeapon() ~= t.invis.wep then if player:GetActiveWeapon() ~= t.invis.wep then
if t.invis.wep and IsValid( t.invis.wep ) then -- If changed weapon, set the old weapon to be visible. if t.invis.wep and IsValid( t.invis.wep ) then -- If changed weapon, set the old weapon to be visible.
t.invis.wep:SetRenderMode( RENDERMODE_NORMAL ) t.invis.wep:SetRenderMode( RENDERMODE_NORMAL )
t.invis.wep:Fire( "alpha", 255, 0 ) t.invis.wep:Fire( "alpha", 255, 0 )
t.invis.wep:SetMaterial( "" ) t.invis.wep:SetMaterial( "" )
end end
t.invis.wep = player:GetActiveWeapon() t.invis.wep = player:GetActiveWeapon()
ULib.invisible( player, true, t.invis.vis ) ULib.invisible( player, true, t.invis.vis )
end end
end end
end end
end end
if remove then if remove then
hook.Remove( "Think", "InvisThink" ) hook.Remove( "Think", "InvisThink" )
end end
end end
--[[ --[[
Function: invisible Function: invisible
Makes a user invisible Makes a user invisible
Parameters: Parameters:
ply - The player to affect. ply - The player to affect.
bool - Whether they're invisible or not bool - Whether they're invisible or not
visibility - *(Optional, defaults to 0)* A number from 0 to 255 for their visibility. visibility - *(Optional, defaults to 0)* A number from 0 to 255 for their visibility.
Revisions: Revisions:
v2.40 - Removes shadow when invisible v2.40 - Removes shadow when invisible
]] ]]
function ULib.invisible( ply, bool, visibility ) function ULib.invisible( ply, bool, visibility )
if not ply:IsValid() then return end -- This is called on a timer so we need to verify they're still connected if not ply:IsValid() then return end -- This is called on a timer so we need to verify they're still connected
if bool then if bool then
visibility = visibility or 0 visibility = visibility or 0
ply:DrawShadow( false ) ply:DrawShadow( false )
ply:SetMaterial( "models/effects/vol_light001" ) ply:SetMaterial( "models/effects/vol_light001" )
ply:SetRenderMode( RENDERMODE_TRANSALPHA ) ply:SetRenderMode( RENDERMODE_TRANSALPHA )
ply:Fire( "alpha", visibility, 0 ) ply:Fire( "alpha", visibility, 0 )
ply:GetTable().invis = { vis=visibility, wep=ply:GetActiveWeapon() } ply:GetTable().invis = { vis=visibility, wep=ply:GetActiveWeapon() }
if IsValid( ply:GetActiveWeapon() ) then if IsValid( ply:GetActiveWeapon() ) then
ply:GetActiveWeapon():SetRenderMode( RENDERMODE_TRANSALPHA ) ply:GetActiveWeapon():SetRenderMode( RENDERMODE_TRANSALPHA )
ply:GetActiveWeapon():Fire( "alpha", visibility, 0 ) ply:GetActiveWeapon():Fire( "alpha", visibility, 0 )
ply:GetActiveWeapon():SetMaterial( "models/effects/vol_light001" ) ply:GetActiveWeapon():SetMaterial( "models/effects/vol_light001" )
if ply:GetActiveWeapon():GetClass() == "gmod_tool" then if ply:GetActiveWeapon():GetClass() == "gmod_tool" then
ply:DrawWorldModel( false ) -- tool gun has problems ply:DrawWorldModel( false ) -- tool gun has problems
else else
ply:DrawWorldModel( true ) ply:DrawWorldModel( true )
end end
end end
hook.Add( "Think", "InvisThink", doInvis ) hook.Add( "Think", "InvisThink", doInvis )
else else
ply:DrawShadow( true ) ply:DrawShadow( true )
ply:SetMaterial( "" ) ply:SetMaterial( "" )
ply:SetRenderMode( RENDERMODE_NORMAL ) ply:SetRenderMode( RENDERMODE_NORMAL )
ply:Fire( "alpha", 255, 0 ) ply:Fire( "alpha", 255, 0 )
local activeWeapon = ply:GetActiveWeapon() local activeWeapon = ply:GetActiveWeapon()
if IsValid( activeWeapon ) then if IsValid( activeWeapon ) then
activeWeapon:SetRenderMode( RENDERMODE_NORMAL ) activeWeapon:SetRenderMode( RENDERMODE_NORMAL )
activeWeapon:Fire( "alpha", 255, 0 ) activeWeapon:Fire( "alpha", 255, 0 )
activeWeapon:SetMaterial( "" ) activeWeapon:SetMaterial( "" )
end end
ply:GetTable().invis = nil ply:GetTable().invis = nil
end end
end end
--[[ --[[
Function: refreshBans Function: refreshBans
Refreshes the ULib bans. Refreshes the ULib bans.
]] ]]
function ULib.refreshBans() function ULib.refreshBans()
local err local err
if not ULib.fileExists( ULib.BANS_FILE ) then if not ULib.fileExists( ULib.BANS_FILE ) then
ULib.bans = {} ULib.bans = {}
else else
ULib.bans, err = ULib.parseKeyValues( ULib.fileRead( ULib.BANS_FILE ) ) ULib.bans, err = ULib.parseKeyValues( ULib.fileRead( ULib.BANS_FILE ) )
end end
if err then if err then
Msg( "Bans file was not formatted correctly. Attempting to fix and backing up original\n" ) Msg( "Bans file was not formatted correctly. Attempting to fix and backing up original\n" )
if err then if err then
Msg( "Error while reading bans file was: " .. err .. "\n" ) Msg( "Error while reading bans file was: " .. err .. "\n" )
end end
Msg( "Original file was backed up to " .. ULib.backupFile( ULib.BANS_FILE ) .. "\n" ) Msg( "Original file was backed up to " .. ULib.backupFile( ULib.BANS_FILE ) .. "\n" )
ULib.bans = {} ULib.bans = {}
end end
local default_bans = "" local default_bans = ""
if ULib.fileExists( "cfg/banned_user.cfg" ) then if ULib.fileExists( "cfg/banned_user.cfg" ) then
ULib.execFile( "cfg/banned_user.cfg" ) ULib.execFile( "cfg/banned_user.cfg" )
ULib.queueFunctionCall( game.ConsoleCommand, "writeid\n" ) ULib.queueFunctionCall( game.ConsoleCommand, "writeid\n" )
default_bans = ULib.fileRead( "cfg/banned_user.cfg" ) default_bans = ULib.fileRead( "cfg/banned_user.cfg" )
end end
--default_bans = ULib.makePatternSafe( default_bans ) --default_bans = ULib.makePatternSafe( default_bans )
default_bans = string.gsub( default_bans, "banid %d+ ", "" ) default_bans = string.gsub( default_bans, "banid %d+ ", "" )
default_bans = string.Explode( "\n", default_bans:gsub( "\r", "" ) ) default_bans = string.Explode( "\n", default_bans:gsub( "\r", "" ) )
local ban_set = {} local ban_set = {}
for _, v in pairs( default_bans ) do for _, v in pairs( default_bans ) do
if v ~= "" then if v ~= "" then
ban_set[ v ] = true ban_set[ v ] = true
if not ULib.bans[ v ] then if not ULib.bans[ v ] then
ULib.bans[ v ] = { unban = 0 } ULib.bans[ v ] = { unban = 0 }
end end
end end
end end
for k, v in pairs( ULib.bans ) do for k, v in pairs( ULib.bans ) do
if type( v ) == "table" and type( k ) == "string" then if type( v ) == "table" and type( k ) == "string" then
local time = ( v.unban - os.time() ) / 60 local time = ( v.unban - os.time() ) / 60
if time > 0 then if time > 0 then
game.ConsoleCommand( string.format( "banid %f %s\n", time, k ) ) game.ConsoleCommand( string.format( "banid %f %s\n", time, k ) )
elseif math.floor( v.unban ) == 0 then -- We floor it because GM10 has floating point errors that might make it be 0.1e-20 or something dumb. elseif math.floor( v.unban ) == 0 then -- We floor it because GM10 has floating point errors that might make it be 0.1e-20 or something dumb.
if not ban_set[ k ] then if not ban_set[ k ] then
ULib.bans[ k ] = nil ULib.bans[ k ] = nil
end end
else else
ULib.bans[ k ] = nil ULib.bans[ k ] = nil
end end
else else
Msg( "Warning: Bad ban data is being ignored, key = " .. tostring( k ) .. "\n" ) Msg( "Warning: Bad ban data is being ignored, key = " .. tostring( k ) .. "\n" )
ULib.bans[ k ] = nil ULib.bans[ k ] = nil
end end
end end
-- We're queueing this because it will split the load out for VERY large ban files -- We're queueing this because it will split the load out for VERY large ban files
ULib.queueFunctionCall( function() ULib.fileWrite( ULib.BANS_FILE, ULib.makeKeyValues( ULib.bans ) ) end ) ULib.queueFunctionCall( function() ULib.fileWrite( ULib.BANS_FILE, ULib.makeKeyValues( ULib.bans ) ) end )
end end
ULib.pcallError( ULib.refreshBans ) ULib.pcallError( ULib.refreshBans )
--[[ --[[
Function: getSpawnInfo Function: getSpawnInfo
Grabs and returns player information that can be used to respawn player with same health/armor as before the spawn. Grabs and returns player information that can be used to respawn player with same health/armor as before the spawn.
Parameters: Parameters:
ply - The player to grab information for. ply - The player to grab information for.
Returns: Returns:
Updates player object to store health and armor. Has no effect unless ULib.Spawn is used later. Updates player object to store health and armor. Has no effect unless ULib.Spawn is used later.
]] ]]
function ULib.getSpawnInfo( player ) function ULib.getSpawnInfo( player )
local result = {} local result = {}
local t = {} local t = {}
player.ULibSpawnInfo = t player.ULibSpawnInfo = t
t.health = player:Health() t.health = player:Health()
t.armor = player:Armor() t.armor = player:Armor()
if player:GetActiveWeapon():IsValid() then if player:GetActiveWeapon():IsValid() then
t.curweapon = player:GetActiveWeapon():GetClass() t.curweapon = player:GetActiveWeapon():GetClass()
end end
local weapons = player:GetWeapons() local weapons = player:GetWeapons()
local data = {} local data = {}
for _, weapon in ipairs( weapons ) do for _, weapon in ipairs( weapons ) do
printname = weapon:GetClass() printname = weapon:GetClass()
data[ printname ] = {} data[ printname ] = {}
data[ printname ].clip1 = weapon:Clip1() data[ printname ].clip1 = weapon:Clip1()
data[ printname ].clip2 = weapon:Clip2() data[ printname ].clip2 = weapon:Clip2()
data[ printname ].ammo1 = player:GetAmmoCount( weapon:GetPrimaryAmmoType() ) data[ printname ].ammo1 = player:GetAmmoCount( weapon:GetPrimaryAmmoType() )
data[ printname ].ammo2 = player:GetAmmoCount( weapon:GetSecondaryAmmoType() ) data[ printname ].ammo2 = player:GetAmmoCount( weapon:GetSecondaryAmmoType() )
end end
t.data = data t.data = data
end end
-- Helper function for ULib.spawn() -- Helper function for ULib.spawn()
local function doWeapons( player, t ) local function doWeapons( player, t )
if not player:IsValid() then return end -- Drat, missed 'em. if not player:IsValid() then return end -- Drat, missed 'em.
player:StripAmmo() player:StripAmmo()
player:StripWeapons() player:StripWeapons()
for printname, data in pairs( t.data ) do for printname, data in pairs( t.data ) do
player:Give( printname ) player:Give( printname )
local weapon = player:GetWeapon( printname ) local weapon = player:GetWeapon( printname )
weapon:SetClip1( data.clip1 ) weapon:SetClip1( data.clip1 )
weapon:SetClip2( data.clip2 ) weapon:SetClip2( data.clip2 )
player:SetAmmo( data.ammo1, weapon:GetPrimaryAmmoType() ) player:SetAmmo( data.ammo1, weapon:GetPrimaryAmmoType() )
player:SetAmmo( data.ammo2, weapon:GetSecondaryAmmoType() ) player:SetAmmo( data.ammo2, weapon:GetSecondaryAmmoType() )
end end
if t.curweapon then if t.curweapon then
player:SelectWeapon( t.curweapon ) player:SelectWeapon( t.curweapon )
end end
end end
--[[ --[[
Function: spawn Function: spawn
Enhanced spawn player. Can spawn player and return health/armor to status before the spawn. (Only IF ULib.getSpawnInfo was used previously.) Enhanced spawn player. Can spawn player and return health/armor to status before the spawn. (Only IF ULib.getSpawnInfo was used previously.)
Clears previously set values that were stored from ULib.getSpawnInfo. Clears previously set values that were stored from ULib.getSpawnInfo.
Parameters: Parameters:
ply - The player to grab information for. ply - The player to grab information for.
bool - If true, spawn will set player information to values stored using ULib.SpawnInfo bool - If true, spawn will set player information to values stored using ULib.SpawnInfo
Returns: Returns:
Spawns player. Sets health/armor to stored defaults if ULib.getSpawnInfo was used previously. Clears SpawnInfo table afterwards. Spawns player. Sets health/armor to stored defaults if ULib.getSpawnInfo was used previously. Clears SpawnInfo table afterwards.
]] ]]
function ULib.spawn( player, bool ) function ULib.spawn( player, bool )
player:Spawn() player:Spawn()
if bool and player.ULibSpawnInfo then if bool and player.ULibSpawnInfo then
local t = player.ULibSpawnInfo local t = player.ULibSpawnInfo
player:SetHealth( t.health ) player:SetHealth( t.health )
player:SetArmor( t.armor ) player:SetArmor( t.armor )
timer.Simple( 0.1, function() doWeapons( player, t ) end ) timer.Simple( 0.1, function() doWeapons( player, t ) end )
player.ULibSpawnInfo = nil player.ULibSpawnInfo = nil
end end
end end

View File

@ -1,67 +1,67 @@
local meta = FindMetaTable( "Player" ) local meta = FindMetaTable( "Player" )
ULib.spawnWhitelist = -- Tool white list for tools that don't spawn things ULib.spawnWhitelist = -- Tool white list for tools that don't spawn things
{ {
"colour", "colour",
"material", "material",
"paint", "paint",
"ballsocket", "ballsocket",
"ballsocket_adv", "ballsocket_adv",
"weld", "weld",
"keepupright", "keepupright",
"nocollide", "nocollide",
"eyeposer", "eyeposer",
"faceposer", "faceposer",
"statue", "statue",
"weld_ez", "weld_ez",
"axis", "axis",
} }
-- Return if there's nothing to add on to -- Return if there's nothing to add on to
if not meta then return end if not meta then return end
function meta:DisallowNoclip( bool ) function meta:DisallowNoclip( bool )
self.NoNoclip = bool self.NoNoclip = bool
end end
function meta:DisallowSpawning( bool ) function meta:DisallowSpawning( bool )
self.NoSpawning = bool self.NoSpawning = bool
end end
function meta:DisallowVehicles( bool ) function meta:DisallowVehicles( bool )
self.NoVehicles = bool self.NoVehicles = bool
end end
local function tool( ply, tr, toolmode ) local function tool( ply, tr, toolmode )
if ply.NoSpawning then if ply.NoSpawning then
if not table.HasValue( ULib.spawnWhitelist, toolmode ) then if not table.HasValue( ULib.spawnWhitelist, toolmode ) then
return false return false
end end
end end
end end
hook.Add( "CanTool", "ULibPlayerToolCheck", tool, HOOK_HIGH ) hook.Add( "CanTool", "ULibPlayerToolCheck", tool, HOOK_HIGH )
local function noclip( ply ) local function noclip( ply )
if ply.NoNoclip then return false end if ply.NoNoclip then return false end
end end
hook.Add( "PlayerNoClip", "ULibNoclipCheck", noclip, HOOK_HIGH ) hook.Add( "PlayerNoClip", "ULibNoclipCheck", noclip, HOOK_HIGH )
local function spawnblock( ply ) local function spawnblock( ply )
if ply.NoSpawning then return false end if ply.NoSpawning then return false end
end end
hook.Add( "PlayerSpawnObject", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnObject", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerSpawnEffect", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnEffect", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerSpawnProp", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnProp", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerSpawnNPC", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnNPC", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerSpawnVehicle", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnVehicle", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerSpawnRagdoll", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnRagdoll", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerSpawnSENT", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerSpawnSENT", "ULibSpawnBlock", spawnblock )
hook.Add( "PlayerGiveSWEP", "ULibSpawnBlock", spawnblock ) hook.Add( "PlayerGiveSWEP", "ULibSpawnBlock", spawnblock )
local function vehicleblock( ply, ent ) local function vehicleblock( ply, ent )
if ply.NoVehicles then if ply.NoVehicles then
return false return false
end end
end end
hook.Add( "CanPlayerEnterVehicle", "ULibVehicleBlock", vehicleblock, HOOK_HIGH ) hook.Add( "CanPlayerEnterVehicle", "ULibVehicleBlock", vehicleblock, HOOK_HIGH )
hook.Add( "CanDrive", "ULibVehicleDriveBlock", vehicleblock, HOOK_HIGH ) hook.Add( "CanDrive", "ULibVehicleDriveBlock", vehicleblock, HOOK_HIGH )

View File

@ -1,274 +1,274 @@
--[[ --[[
Title: Utilities Title: Utilities
Has some useful server utilities Has some useful server utilities
]] ]]
--[[ --[[
Function: clientRPC Function: clientRPC
Think of this function as if you're calling a client function directly from the server. You state who should run it, what the name of Think of this function as if you're calling a client function directly from the server. You state who should run it, what the name of
the function is, and then a list of parameters to pass to that function on the client. ULib handles the rest. Parameters can be any the function is, and then a list of parameters to pass to that function on the client. ULib handles the rest. Parameters can be any
data type that's allowed on the network and of any size. Send huge tables or strings, it's all the same, and it all works. data type that's allowed on the network and of any size. Send huge tables or strings, it's all the same, and it all works.
Parameters: Parameters:
filter - The Player object, table of Player objects for who you want to send this to, nil sends to everyone. filter - The Player object, table of Player objects for who you want to send this to, nil sends to everyone.
fn - A string of the function to run on the client. Does *not* need to be in the global namespace, "myTable.myFunction" works too. fn - A string of the function to run on the client. Does *not* need to be in the global namespace, "myTable.myFunction" works too.
... - *Optional* The parameters to pass to the function. ... - *Optional* The parameters to pass to the function.
Revisions: Revisions:
v2.40 - Initial. v2.40 - Initial.
]] ]]
function ULib.clientRPC( plys, fn, ... ) function ULib.clientRPC( plys, fn, ... )
ULib.checkArg( 1, "ULib.clientRPC", {"nil","Player","table"}, plys ) ULib.checkArg( 1, "ULib.clientRPC", {"nil","Player","table"}, plys )
ULib.checkArg( 2, "ULib.clientRPC", {"string"}, fn ) ULib.checkArg( 2, "ULib.clientRPC", {"string"}, fn )
net.Start( "URPC" ) net.Start( "URPC" )
net.WriteString( fn ) net.WriteString( fn )
net.WriteTable( {...} ) net.WriteTable( {...} )
if plys then if plys then
net.Send( plys ) net.Send( plys )
else else
net.Broadcast() net.Broadcast()
end end
end end
--[[ --[[
Function: umsgSend Function: umsgSend
Makes sending umsgs a blast. You don't have to bother knowing what type you're sending, just use ULib.umsgRcv() on the client. Makes sending umsgs a blast. You don't have to bother knowing what type you're sending, just use ULib.umsgRcv() on the client.
Note that while you can send tables with this function, you're limited by the max umsg size. If you're sending a large amount of data, Note that while you can send tables with this function, you're limited by the max umsg size. If you're sending a large amount of data,
consider using <clientRPC()> instead. consider using <clientRPC()> instead.
Parameters: Parameters:
v - The value to send. v - The value to send.
queue - *(For use by <clientRPC()> ONLY)* A boolean of whether the messages should be queued with RPC or not. queue - *(For use by <clientRPC()> ONLY)* A boolean of whether the messages should be queued with RPC or not.
]] ]]
function ULib.umsgSend( v, queue ) function ULib.umsgSend( v, queue )
local tv = type( v ) local tv = type( v )
local function call( fn, ... ) local function call( fn, ... )
if queue then if queue then
queueRPC( fn, ... ) queueRPC( fn, ... )
else else
fn( ... ) fn( ... )
end end
end end
if tv == "string" then if tv == "string" then
call( umsg.Char, ULib.TYPE_STRING ) call( umsg.Char, ULib.TYPE_STRING )
call( umsg.String, v ) call( umsg.String, v )
elseif tv == "number" then elseif tv == "number" then
if math.fmod( v, 1 ) ~= 0 then -- It's a float if math.fmod( v, 1 ) ~= 0 then -- It's a float
call( umsg.Char, ULib.TYPE_FLOAT ) call( umsg.Char, ULib.TYPE_FLOAT )
call( umsg.Float, v ) call( umsg.Float, v )
else else
if v <= 127 and v >= -127 then if v <= 127 and v >= -127 then
call( umsg.Char, ULib.TYPE_CHAR ) call( umsg.Char, ULib.TYPE_CHAR )
call( umsg.Char, v ) call( umsg.Char, v )
elseif v < 32767 and v > -32768 then elseif v < 32767 and v > -32768 then
call( umsg.Char, ULib.TYPE_SHORT ) call( umsg.Char, ULib.TYPE_SHORT )
call( umsg.Short, v ) call( umsg.Short, v )
else else
call( umsg.Char, ULib.TYPE_LONG ) call( umsg.Char, ULib.TYPE_LONG )
call( umsg.Long, v ) call( umsg.Long, v )
end end
end end
elseif tv == "boolean" then elseif tv == "boolean" then
call( umsg.Char, ULib.TYPE_BOOLEAN ) call( umsg.Char, ULib.TYPE_BOOLEAN )
call( umsg.Bool, v ) call( umsg.Bool, v )
elseif tv == "Entity" or tv == "Player" then elseif tv == "Entity" or tv == "Player" then
call( umsg.Char, ULib.TYPE_ENTITY ) call( umsg.Char, ULib.TYPE_ENTITY )
call( umsg.Entity, v ) call( umsg.Entity, v )
elseif tv == "Vector" then elseif tv == "Vector" then
call( umsg.Char, ULib.TYPE_VECTOR ) call( umsg.Char, ULib.TYPE_VECTOR )
call( umsg.Vector, v ) call( umsg.Vector, v )
elseif tv == "Angle" then elseif tv == "Angle" then
call( umsg.Char, ULib.TYPE_ANGLE ) call( umsg.Char, ULib.TYPE_ANGLE )
call( umsg.Angle, v ) call( umsg.Angle, v )
elseif tv == "table" then elseif tv == "table" then
call( umsg.Char, ULib.TYPE_TABLE_BEGIN ) call( umsg.Char, ULib.TYPE_TABLE_BEGIN )
for key, value in pairs( v ) do for key, value in pairs( v ) do
ULib.umsgSend( key, queue ) ULib.umsgSend( key, queue )
ULib.umsgSend( value, queue ) ULib.umsgSend( value, queue )
end end
call( umsg.Char, ULib.TYPE_TABLE_END ) call( umsg.Char, ULib.TYPE_TABLE_END )
elseif tv == "nil" then elseif tv == "nil" then
call( umsg.Char, ULib.TYPE_NIL ) call( umsg.Char, ULib.TYPE_NIL )
else else
ULib.error( "Unknown type passed to umsgSend -- " .. tv ) ULib.error( "Unknown type passed to umsgSend -- " .. tv )
end end
end end
--[[ --[[
Function: play3DSound Function: play3DSound
Plays a 3D sound, the further away from the point the player is, the softer the sound will be. Plays a 3D sound, the further away from the point the player is, the softer the sound will be.
Parameters: Parameters:
sound - The sound to play, relative to the sound folder. sound - The sound to play, relative to the sound folder.
vector - The point to play the sound at. vector - The point to play the sound at.
volume - *(Optional, defaults to 1)* The volume to make the sound. volume - *(Optional, defaults to 1)* The volume to make the sound.
pitch - *(Optional, defaults to 1)* The pitch to make the sound, 1 = normal. pitch - *(Optional, defaults to 1)* The pitch to make the sound, 1 = normal.
]] ]]
function ULib.play3DSound( sound, vector, volume, pitch ) function ULib.play3DSound( sound, vector, volume, pitch )
volume = volume or 100 volume = volume or 100
pitch = pitch or 100 pitch = pitch or 100
local ent = ents.Create( "info_null" ) local ent = ents.Create( "info_null" )
if not ent:IsValid() then return end if not ent:IsValid() then return end
ent:SetPos( vector ) ent:SetPos( vector )
ent:Spawn() ent:Spawn()
ent:Activate() ent:Activate()
ent:EmitSound( sound, volume, pitch ) ent:EmitSound( sound, volume, pitch )
end end
--[[ --[[
Function: getAllReadyPlayers Function: getAllReadyPlayers
Similar to player.GetAll(), except it only returns players that have ULib ready to go. Similar to player.GetAll(), except it only returns players that have ULib ready to go.
Revisions: Revisions:
2.40 - Initial 2.40 - Initial
]] ]]
function ULib.getAllReadyPlayers() function ULib.getAllReadyPlayers()
local players = player.GetAll() local players = player.GetAll()
for i=#players, 1, -1 do for i=#players, 1, -1 do
if not players[ i ].ulib_ready then if not players[ i ].ulib_ready then
table.remove( players, i ) table.remove( players, i )
end end
end end
return players return players
end end
ULib.repcvars = ULib.repcvars or {} -- This is used for <ULib.replicatedWithWritableCvar> in order to keep track of valid cvars and access info. ULib.repcvars = ULib.repcvars or {} -- This is used for <ULib.replicatedWithWritableCvar> in order to keep track of valid cvars and access info.
local repcvars = ULib.repcvars local repcvars = ULib.repcvars
local repCvarServerChanged local repCvarServerChanged
--[[ --[[
Function: replicatedWritableCvar Function: replicatedWritableCvar
This function is mainly intended for use with the menus. This function is very similar to creating a replicated cvar with one caveat: This function is mainly intended for use with the menus. This function is very similar to creating a replicated cvar with one caveat:
This function also creates a cvar on the client that can be modified and will be sent back to the server. This function also creates a cvar on the client that can be modified and will be sent back to the server.
Parameters: Parameters:
sv_cvar - The string of server side cvar. sv_cvar - The string of server side cvar.
cl_cvar - The string of the client side cvar. *THIS MUST BE DIFFERENT FROM THE sv_cvar VALUE IF YOU'RE PIGGY BACKING AN EXISTING REPLICATED CVAR (like sv_gravity)*. cl_cvar - The string of the client side cvar. *THIS MUST BE DIFFERENT FROM THE sv_cvar VALUE IF YOU'RE PIGGY BACKING AN EXISTING REPLICATED CVAR (like sv_gravity)*.
default_value - The string of the default value for the cvar. default_value - The string of the default value for the cvar.
save - Boolean of whether or not the value is persistent across map changes. save - Boolean of whether or not the value is persistent across map changes.
This uses garry's way, which has lots of issues. We recommend you watch the cvar for changes and handle saving yourself. This uses garry's way, which has lots of issues. We recommend you watch the cvar for changes and handle saving yourself.
notify - Boolean of whether or not value changes are announced on the server notify - Boolean of whether or not value changes are announced on the server
access - The string of the access required for a client to actually change the value. access - The string of the access required for a client to actually change the value.
Returns: Returns:
The server-side cvar object. The server-side cvar object.
Revisions: Revisions:
v2.40 - Initial. v2.40 - Initial.
v2.50 - Changed to not depend on the replicated cvars themselves due to Garry-breakage. v2.50 - Changed to not depend on the replicated cvars themselves due to Garry-breakage.
]] ]]
function ULib.replicatedWritableCvar( sv_cvar, cl_cvar, default_value, save, notify, access ) function ULib.replicatedWritableCvar( sv_cvar, cl_cvar, default_value, save, notify, access )
sv_cvar = sv_cvar:lower() sv_cvar = sv_cvar:lower()
cl_cvar = cl_cvar:lower() cl_cvar = cl_cvar:lower()
local flags = 0 local flags = 0
if save then if save then
flags = flags + FCVAR_ARCHIVE flags = flags + FCVAR_ARCHIVE
end end
if notify then if notify then
flags = flags + FCVAR_NOTIFY flags = flags + FCVAR_NOTIFY
end end
local cvar_obj = GetConVar( sv_cvar ) or CreateConVar( sv_cvar, default_value, flags ) local cvar_obj = GetConVar( sv_cvar ) or CreateConVar( sv_cvar, default_value, flags )
umsg.Start( "ulib_repWriteCvar" ) -- Send to everyone connected umsg.Start( "ulib_repWriteCvar" ) -- Send to everyone connected
umsg.String( sv_cvar ) umsg.String( sv_cvar )
umsg.String( cl_cvar ) umsg.String( cl_cvar )
umsg.String( default_value ) umsg.String( default_value )
umsg.String( cvar_obj:GetString() ) umsg.String( cvar_obj:GetString() )
umsg.End() umsg.End()
repcvars[ sv_cvar ] = { access=access, default=default_value, cl_cvar=cl_cvar, cvar_obj=cvar_obj } repcvars[ sv_cvar ] = { access=access, default=default_value, cl_cvar=cl_cvar, cvar_obj=cvar_obj }
cvars.AddChangeCallback( sv_cvar, repCvarServerChanged ) cvars.AddChangeCallback( sv_cvar, repCvarServerChanged )
hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, cl_cvar, nil, nil, cvar_obj:GetString() ) hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, cl_cvar, nil, nil, cvar_obj:GetString() )
return cvar_obj return cvar_obj
end end
local function repCvarOnJoin( ply ) local function repCvarOnJoin( ply )
for sv_cvar, v in pairs( repcvars ) do for sv_cvar, v in pairs( repcvars ) do
umsg.Start( "ulib_repWriteCvar", ply ) umsg.Start( "ulib_repWriteCvar", ply )
umsg.String( sv_cvar ) umsg.String( sv_cvar )
umsg.String( v.cl_cvar ) umsg.String( v.cl_cvar )
umsg.String( v.default ) umsg.String( v.default )
umsg.String( v.cvar_obj:GetString() ) umsg.String( v.cvar_obj:GetString() )
umsg.End() umsg.End()
end end
end end
hook.Add( ULib.HOOK_LOCALPLAYERREADY, "ULibSendCvars", repCvarOnJoin ) hook.Add( ULib.HOOK_LOCALPLAYERREADY, "ULibSendCvars", repCvarOnJoin )
local function clientChangeCvar( ply, command, argv ) local function clientChangeCvar( ply, command, argv )
local sv_cvar = argv[ 1 ] local sv_cvar = argv[ 1 ]
local newvalue = argv[ 2 ] local newvalue = argv[ 2 ]
if not sv_cvar or not newvalue or not repcvars[ sv_cvar:lower() ] then -- Bad value, ignore if not sv_cvar or not newvalue or not repcvars[ sv_cvar:lower() ] then -- Bad value, ignore
return return
end end
sv_cvar = sv_cvar:lower() sv_cvar = sv_cvar:lower()
cvar_obj = repcvars[ sv_cvar ].cvar_obj cvar_obj = repcvars[ sv_cvar ].cvar_obj
local oldvalue = cvar_obj:GetString() local oldvalue = cvar_obj:GetString()
if oldvalue == newvalue then return end -- Agreement if oldvalue == newvalue then return end -- Agreement
local access = repcvars[ sv_cvar ].access local access = repcvars[ sv_cvar ].access
if not ply:query( access ) then if not ply:query( access ) then
ULib.tsayError( ply, "You do not have access to this cvar (" .. sv_cvar .. "), " .. ply:Nick() .. "." ) ULib.tsayError( ply, "You do not have access to this cvar (" .. sv_cvar .. "), " .. ply:Nick() .. "." )
umsg.Start( "ulib_repChangeCvar", ply ) umsg.Start( "ulib_repChangeCvar", ply )
umsg.Entity( ply ) umsg.Entity( ply )
umsg.String( repcvars[ sv_cvar ].cl_cvar ) umsg.String( repcvars[ sv_cvar ].cl_cvar )
umsg.String( oldvalue ) umsg.String( oldvalue )
umsg.String( oldvalue ) -- No change umsg.String( oldvalue ) -- No change
umsg.End() umsg.End()
return return
end end
repcvars[ sv_cvar ].ignore = ply -- Flag other hook not to go off. Flag will be removed at hook. repcvars[ sv_cvar ].ignore = ply -- Flag other hook not to go off. Flag will be removed at hook.
RunConsoleCommand( sv_cvar, newvalue ) RunConsoleCommand( sv_cvar, newvalue )
hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, repcvars[ sv_cvar ].cl_cvar, ply, oldvalue, newvalue ) hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, repcvars[ sv_cvar ].cl_cvar, ply, oldvalue, newvalue )
end end
concommand.Add( "ulib_update_cvar", clientChangeCvar, nil, nil, FCVAR_SERVER_CAN_EXECUTE ) concommand.Add( "ulib_update_cvar", clientChangeCvar, nil, nil, FCVAR_SERVER_CAN_EXECUTE )
-- Adding FCVAR_SERVER_CAN_EXECUTE above prevents an odd bug where if a user hosts a listen server, this command gets registered, -- Adding FCVAR_SERVER_CAN_EXECUTE above prevents an odd bug where if a user hosts a listen server, this command gets registered,
-- but when they join another server they can't change any replicated cvars. -- but when they join another server they can't change any replicated cvars.
repCvarServerChanged = function( sv_cvar, oldvalue, newvalue ) repCvarServerChanged = function( sv_cvar, oldvalue, newvalue )
if not repcvars[ sv_cvar ] then -- Bad value or we need to ignore it if not repcvars[ sv_cvar ] then -- Bad value or we need to ignore it
return return
end end
umsg.Start( "ulib_repChangeCvar" ) -- Tell clients to reset to new value umsg.Start( "ulib_repChangeCvar" ) -- Tell clients to reset to new value
umsg.Entity( repcvars[ sv_cvar ].ignore or Entity( 0 ) ) umsg.Entity( repcvars[ sv_cvar ].ignore or Entity( 0 ) )
umsg.String( repcvars[ sv_cvar ].cl_cvar ) umsg.String( repcvars[ sv_cvar ].cl_cvar )
umsg.String( oldvalue ) umsg.String( oldvalue )
umsg.String( newvalue ) umsg.String( newvalue )
umsg.End() umsg.End()
if repcvars[ sv_cvar ].ignore then if repcvars[ sv_cvar ].ignore then
repcvars[ sv_cvar ].ignore = nil repcvars[ sv_cvar ].ignore = nil
else else
hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, repcvars[ sv_cvar ].cl_cvar, Entity( 0 ), oldvalue, newvalue ) hook.Call( ULib.HOOK_REPCVARCHANGED, _, sv_cvar, repcvars[ sv_cvar ].cl_cvar, Entity( 0 ), oldvalue, newvalue )
end end
end end

View File

@ -1,252 +1,252 @@
local gmod = gmod local gmod = gmod
local pairs = pairs local pairs = pairs
local isfunction = isfunction local isfunction = isfunction
local isstring = isstring local isstring = isstring
local isnumber = isnumber local isnumber = isnumber
local math = math local math = math
local IsValid = IsValid local IsValid = IsValid
--[[ --[[
local concommand = concommand local concommand = concommand
local print = print local print = print
local PrintTable = PrintTable local PrintTable = PrintTable
local tostring = tostring local tostring = tostring
local assert = assert local assert = assert
local table = table--]] local table = table--]]
HOOK_MONITOR_HIGH = -2 HOOK_MONITOR_HIGH = -2
HOOK_HIGH = -1 HOOK_HIGH = -1
HOOK_NORMAL = 0 HOOK_NORMAL = 0
HOOK_LOW = 1 HOOK_LOW = 1
HOOK_MONITOR_LOW = 2 HOOK_MONITOR_LOW = 2
if hook.GetULibTable then return end -- Prevent autorefresh reloading this file if hook.GetULibTable then return end -- Prevent autorefresh reloading this file
-- Grab all previous hooks from the pre-existing hook module. -- Grab all previous hooks from the pre-existing hook module.
local OldHooks = hook.GetTable() local OldHooks = hook.GetTable()
module( "hook" ) module( "hook" )
local Hooks = {} local Hooks = {}
local BackwardsHooks = {} -- A table fully to garry's spec for aVoN local BackwardsHooks = {} -- A table fully to garry's spec for aVoN
-- --
-- For access to the Hooks table.. for some reason. -- For access to the Hooks table.. for some reason.
-- --
function GetTable() return BackwardsHooks end function GetTable() return BackwardsHooks end
function GetULibTable() return Hooks end function GetULibTable() return Hooks end
-- --
-- Add a hook -- Add a hook
-- --
function Add( event_name, name, func, priority ) function Add( event_name, name, func, priority )
priority = priority or 0 priority = priority or 0
if ( !isfunction( func ) ) then return end if ( !isfunction( func ) ) then return end
if ( !isstring( event_name ) ) then return end if ( !isstring( event_name ) ) then return end
if ( !isnumber( priority ) ) then return end if ( !isnumber( priority ) ) then return end
priority = math.floor( priority ) priority = math.floor( priority )
if ( priority < -2 ) then priority = -2 end -- math.Clamp may not have been defined yet if ( priority < -2 ) then priority = -2 end -- math.Clamp may not have been defined yet
if ( priority > 2 ) then priority = 2 end if ( priority > 2 ) then priority = 2 end
Remove( event_name, name ) -- This keeps the event name unique, even among the priorities Remove( event_name, name ) -- This keeps the event name unique, even among the priorities
if (Hooks[ event_name ] == nil) then if (Hooks[ event_name ] == nil) then
Hooks[ event_name ] = {[-2]={}, [-1]={}, [0]={}, [1]={}, [2]={}} Hooks[ event_name ] = {[-2]={}, [-1]={}, [0]={}, [1]={}, [2]={}}
BackwardsHooks[ event_name ] = {} BackwardsHooks[ event_name ] = {}
end end
Hooks[ event_name ][ priority ][ name ] = { fn=func, isstring=isstring( name ) } Hooks[ event_name ][ priority ][ name ] = { fn=func, isstring=isstring( name ) }
BackwardsHooks[ event_name ][ name ] = func -- Keep the classic style too so we won't break anything BackwardsHooks[ event_name ][ name ] = func -- Keep the classic style too so we won't break anything
end end
-- --
-- Remove a hook -- Remove a hook
-- --
function Remove( event_name, name ) function Remove( event_name, name )
if ( !isstring( event_name ) ) then return end if ( !isstring( event_name ) ) then return end
if ( !Hooks[ event_name ] ) then return end if ( !Hooks[ event_name ] ) then return end
for i=-2, 2 do for i=-2, 2 do
Hooks[ event_name ][ i ][ name ] = nil Hooks[ event_name ][ i ][ name ] = nil
end end
BackwardsHooks[ event_name ][ name ] = nil BackwardsHooks[ event_name ][ name ] = nil
end end
-- --
-- Run a hook (this replaces Call) -- Run a hook (this replaces Call)
-- --
function Run( name, ... ) function Run( name, ... )
return Call( name, gmod and gmod.GetGamemode() or nil, ... ) return Call( name, gmod and gmod.GetGamemode() or nil, ... )
end end
-- --
-- Called by the engine -- Called by the engine
-- --
function Call( name, gm, ... ) function Call( name, gm, ... )
-- --
-- Run hooks -- Run hooks
-- --
local HookTable = Hooks[ name ] local HookTable = Hooks[ name ]
if ( HookTable != nil ) then if ( HookTable != nil ) then
for i=-2, 2 do for i=-2, 2 do
for k, v in pairs( HookTable[ i ] ) do for k, v in pairs( HookTable[ i ] ) do
if ( v.isstring ) then if ( v.isstring ) then
-- --
-- If it's a string, it's cool -- If it's a string, it's cool
-- --
local a, b, c, d, e, f = v.fn( ... ) local a, b, c, d, e, f = v.fn( ... )
if ( a != nil && i > -2 && i < 2 ) then if ( a != nil && i > -2 && i < 2 ) then
return a, b, c, d, e, f return a, b, c, d, e, f
end end
else else
-- --
-- If the key isn't a string - we assume it to be an entity -- If the key isn't a string - we assume it to be an entity
-- Or panel, or something else that IsValid works on. -- Or panel, or something else that IsValid works on.
-- --
if ( IsValid( k ) ) then if ( IsValid( k ) ) then
-- --
-- If the object is valid - pass it as the first argument (self) -- If the object is valid - pass it as the first argument (self)
-- --
local a, b, c, d, e, f = v.fn( k, ... ) local a, b, c, d, e, f = v.fn( k, ... )
if ( a != nil && i > -2 && i < 2 ) then if ( a != nil && i > -2 && i < 2 ) then
return a, b, c, d, e, f return a, b, c, d, e, f
end end
else else
-- --
-- If the object has become invalid - remove it -- If the object has become invalid - remove it
-- --
HookTable[ i ][ k ] = nil HookTable[ i ][ k ] = nil
end end
end end
end end
end end
end end
-- --
-- Call the gamemode function -- Call the gamemode function
-- --
if ( !gm ) then return end if ( !gm ) then return end
local GamemodeFunction = gm[ name ] local GamemodeFunction = gm[ name ]
if ( GamemodeFunction == nil ) then return end if ( GamemodeFunction == nil ) then return end
return GamemodeFunction( gm, ... ) return GamemodeFunction( gm, ... )
end end
-- Bring in all the old hooks -- Bring in all the old hooks
for event_name, t in pairs( OldHooks ) do for event_name, t in pairs( OldHooks ) do
for name, func in pairs( t ) do for name, func in pairs( t ) do
Add( event_name, name, func ) Add( event_name, name, func )
end end
end end
--[[ --[[
local failed = false local failed = false
local shouldFail = false local shouldFail = false
local i, t local i, t
-- Since the correctness of this file is so important, we've made a little test suite -- Since the correctness of this file is so important, we've made a little test suite
local function appendGenerator( n ) local function appendGenerator( n )
return function( t ) return function( t )
table.insert( t, n ) table.insert( t, n )
end end
end end
local function returnRange() local function returnRange()
return 1, 2, 3, 4, 5, 6, 7, 8 return 1, 2, 3, 4, 5, 6, 7, 8
end end
local function noop() local function noop()
end end
local function err() local function err()
if shouldFail then if shouldFail then
error( "this error is normal!" ) error( "this error is normal!" )
else else
error( "this error is bad!" ) error( "this error is bad!" )
failed = true failed = true
end end
end end
local function doTests( ply, cmd, argv ) local function doTests( ply, cmd, argv )
print( "Being run on client: " .. tostring( CLIENT ) ) print( "Being run on client: " .. tostring( CLIENT ) )
-- First make sure there's no return value leakage... -- First make sure there's no return value leakage...
Add( "LeakageA", "a", returnRange ) Add( "LeakageA", "a", returnRange )
t = { Call( "LeakageA", _ ) } t = { Call( "LeakageA", _ ) }
assert( #t == 6 ) assert( #t == 6 )
for k, v in pairs( t ) do for k, v in pairs( t ) do
assert( k == v ) assert( k == v )
end end
Add( "LeakageB", "a", noop ) Add( "LeakageB", "a", noop )
t = { Call( "LeakageB", _ ) } t = { Call( "LeakageB", _ ) }
assert( #t == 0 ) assert( #t == 0 )
-- Now let's make sure errors are handled correctly... -- Now let's make sure errors are handled correctly...
shouldFail = true shouldFail = true
Add( "ErrCheck", "a", noop ) Add( "ErrCheck", "a", noop )
--Add( "ErrCheck", "b", err ) --Add( "ErrCheck", "b", err )
Add( "ErrCheck", "c", noop ) Add( "ErrCheck", "c", noop )
Add( "ErrCheck", "d", returnRange ) Add( "ErrCheck", "d", returnRange )
t = { Call( "ErrCheck", _ ) } t = { Call( "ErrCheck", _ ) }
assert( #t == 6 ) assert( #t == 6 )
--assert( #Hooks.ErrCheck == 3 and Hooks.ErrCheck[4] == nil ) -- Should have been reduced so that the 'b' got removed --assert( #Hooks.ErrCheck == 3 and Hooks.ErrCheck[4] == nil ) -- Should have been reduced so that the 'b' got removed
shouldFail = false shouldFail = false
t = { Call( "ErrCheck", _ ) } t = { Call( "ErrCheck", _ ) }
assert( #t == 6 ) assert( #t == 6 )
-- Check for override -- Check for override
Add( "ErrCheck", "d", noop, 1 ) -- Different priority, same name should still override Add( "ErrCheck", "d", noop, 1 ) -- Different priority, same name should still override
t = { Call( "ErrCheck", _ ) } t = { Call( "ErrCheck", _ ) }
assert( #t == 0 ) assert( #t == 0 )
-- Check for order and readonly'ness... -- Check for order and readonly'ness...
Add( "Order", "n20a", returnRange, -2 ) Add( "Order", "n20a", returnRange, -2 )
Add( "Order", "a", appendGenerator( 3 ) ) Add( "Order", "a", appendGenerator( 3 ) )
Add( "Order", "n20a", appendGenerator( 1 ), -2 ) Add( "Order", "n20a", appendGenerator( 1 ), -2 )
Add( "Order", "n10a", appendGenerator( 2 ), -1 ) Add( "Order", "n10a", appendGenerator( 2 ), -1 )
Add( "Order", "10a", appendGenerator( 4 ), 1 ) Add( "Order", "10a", appendGenerator( 4 ), 1 )
Add( "Order", "20a", returnRange, 2 ) Add( "Order", "20a", returnRange, 2 )
Add( "Order", "20aa", appendGenerator( 5 ), 2 ) Add( "Order", "20aa", appendGenerator( 5 ), 2 )
t = {} t = {}
Call( "Order", _, t ) Call( "Order", _, t )
print( t, #t ) print( t, #t )
PrintTable( t ) PrintTable( t )
assert( #t == 5 ) assert( #t == 5 )
for k, v in pairs( t ) do for k, v in pairs( t ) do
assert( k == v ) assert( k == v )
end end
Add( "Test", "AAA", function () print( "AAA" ) Remove( "Test", "AAA" ) end ) Add( "Test", "AAA", function () print( "AAA" ) Remove( "Test", "AAA" ) end )
Add( "Test", "BBB", function () print( "BBB" ) end) Add( "Test", "BBB", function () print( "BBB" ) end)
Run( "Test" ) Run( "Test" )
Run( "Test" ) Run( "Test" )
if failed then if failed then
print( "Tests failed!" ) print( "Tests failed!" )
else else
print( "All tests passed!" ) print( "All tests passed!" )
end end
end end
concommand.Add( "run_hook_tests", doTests )--]] concommand.Add( "run_hook_tests", doTests )--]]

View File

@ -1,285 +1,285 @@
--[[ --[[
Title: Messages Title: Messages
Handles messaging like logging, debug, etc. Handles messaging like logging, debug, etc.
]] ]]
--[[ --[[
Function: tsay Function: tsay
Prints a message in talk say as well as in the user's consoles. Prints a message in talk say as well as in the user's consoles.
Parameters: Parameters:
ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client) ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client)
msg - The message to print. msg - The message to print.
wait - *(Optional, defaults to false)* Wait one frame before posting. (Useful to use from things like chat hooks) wait - *(Optional, defaults to false)* Wait one frame before posting. (Useful to use from things like chat hooks)
wasValid - *(INTERNAL USE ONLY)* This is flagged on waiting if the player *was* valid. wasValid - *(INTERNAL USE ONLY)* This is flagged on waiting if the player *was* valid.
Revisions: Revisions:
v2.10 - Initial v2.10 - Initial
]] ]]
function ULib.tsay( ply, msg, wait, wasValid ) function ULib.tsay( ply, msg, wait, wasValid )
ULib.checkArg( 1, "ULib.tsay", {"nil","Player","Entity"}, ply ) ULib.checkArg( 1, "ULib.tsay", {"nil","Player","Entity"}, ply )
ULib.checkArg( 2, "ULib.tsay", "string", msg ) ULib.checkArg( 2, "ULib.tsay", "string", msg )
ULib.checkArg( 3, "ULib.tsay", {"nil","boolean"}, wait ) ULib.checkArg( 3, "ULib.tsay", {"nil","boolean"}, wait )
if wait then ULib.namedQueueFunctionCall( "ULibChats", ULib.tsay, ply, msg, false, ply and ply:IsValid() ) return end -- Call next frame if wait then ULib.namedQueueFunctionCall( "ULibChats", ULib.tsay, ply, msg, false, ply and ply:IsValid() ) return end -- Call next frame
if SERVER and ply and not ply:IsValid() then -- Server console if SERVER and ply and not ply:IsValid() then -- Server console
if wasValid then -- This means we had a valid player that left, so do nothing if wasValid then -- This means we had a valid player that left, so do nothing
return return
end end
Msg( msg .. "\n" ) Msg( msg .. "\n" )
return return
end end
if CLIENT then if CLIENT then
LocalPlayer():ChatPrint( msg ) LocalPlayer():ChatPrint( msg )
return return
end end
if ply then if ply then
ply:ChatPrint( msg ) ply:ChatPrint( msg )
else else
local players = player.GetAll() local players = player.GetAll()
for _, player in ipairs( players ) do for _, player in ipairs( players ) do
player:ChatPrint( msg ) player:ChatPrint( msg )
end end
end end
end end
local serverConsole = {} -- Used in the function below to identify the server console (internal use) local serverConsole = {} -- Used in the function below to identify the server console (internal use)
local function tsayColorCallback( ply, ... ) local function tsayColorCallback( ply, ... )
if CLIENT then if CLIENT then
chat.AddText( ... ) chat.AddText( ... )
return return
end end
if ply and ply ~= serverConsole and not ply:IsValid() then return end -- Player must have left the server if ply and ply ~= serverConsole and not ply:IsValid() then return end -- Player must have left the server
local args = { ... } local args = { ... }
if ply == serverConsole then if ply == serverConsole then
for i=2, #args, 2 do for i=2, #args, 2 do
Msg( args[ i ] ) Msg( args[ i ] )
end end
Msg( "\n" ); Msg( "\n" );
return return
end end
local current_chunk = { size = 0 } local current_chunk = { size = 0 }
local chunks = { current_chunk } local chunks = { current_chunk }
local max_chunk_size = 240 local max_chunk_size = 240
while #args > 0 do while #args > 0 do
local arg = table.remove( args, 1 ) local arg = table.remove( args, 1 )
local typ = type( arg ) local typ = type( arg )
local arg_size = typ == "table" and 4 or #arg + 2 -- Include null in strings, bool in both local arg_size = typ == "table" and 4 or #arg + 2 -- Include null in strings, bool in both
if typ == "string" and current_chunk.size + arg_size > max_chunk_size then -- Split a large string up into multiple messages if typ == "string" and current_chunk.size + arg_size > max_chunk_size then -- Split a large string up into multiple messages
local substr = arg:sub( 1, math.max( 1, max_chunk_size - current_chunk.size - 2 ) ) local substr = arg:sub( 1, math.max( 1, max_chunk_size - current_chunk.size - 2 ) )
if #substr > 0 then if #substr > 0 then
table.insert( current_chunk, substr ) table.insert( current_chunk, substr )
end end
table.insert( args, 1, arg:sub( #substr + 1) ) table.insert( args, 1, arg:sub( #substr + 1) )
current_chunk = { size = 0 } current_chunk = { size = 0 }
table.insert( chunks, current_chunk ) table.insert( chunks, current_chunk )
else else
if current_chunk.size + arg_size > max_chunk_size then if current_chunk.size + arg_size > max_chunk_size then
current_chunk = { size = 0 } current_chunk = { size = 0 }
table.insert( chunks, current_chunk ) table.insert( chunks, current_chunk )
end end
current_chunk.size = current_chunk.size + arg_size current_chunk.size = current_chunk.size + arg_size
table.insert( current_chunk, arg ) table.insert( current_chunk, arg )
end end
end end
for chunk_num=1, #chunks do for chunk_num=1, #chunks do
local chunk = chunks[ chunk_num ] local chunk = chunks[ chunk_num ]
umsg.Start( "tsayc", ply ) umsg.Start( "tsayc", ply )
umsg.Bool( chunk_num == #chunks ) umsg.Bool( chunk_num == #chunks )
umsg.Char( #chunk ) umsg.Char( #chunk )
for i=1, #chunk do for i=1, #chunk do
local arg = chunk[ i ] local arg = chunk[ i ]
if type( arg ) == "string" then if type( arg ) == "string" then
umsg.Bool( true ) umsg.Bool( true )
umsg.String( arg ) umsg.String( arg )
else else
umsg.Bool( false ) umsg.Bool( false )
umsg.Char( arg.r - 128 ) umsg.Char( arg.r - 128 )
umsg.Char( arg.g - 128 ) umsg.Char( arg.g - 128 )
umsg.Char( arg.b - 128 ) umsg.Char( arg.b - 128 )
end end
end end
umsg.End() umsg.End()
end end
end end
if CLIENT then if CLIENT then
local accumulator = {} local accumulator = {}
local function tsayColorHook( um ) local function tsayColorHook( um )
local last = um:ReadBool() local last = um:ReadBool()
local argn = um:ReadChar() local argn = um:ReadChar()
for i=1, argn do for i=1, argn do
if um:ReadBool() then if um:ReadBool() then
table.insert( accumulator, um:ReadString() ) table.insert( accumulator, um:ReadString() )
else else
table.insert( accumulator, Color( um:ReadChar() + 128, um:ReadChar() + 128, um:ReadChar() + 128) ) table.insert( accumulator, Color( um:ReadChar() + 128, um:ReadChar() + 128, um:ReadChar() + 128) )
end end
end end
if last then if last then
chat.AddText( unpack( accumulator ) ) chat.AddText( unpack( accumulator ) )
accumulator = {} accumulator = {}
end end
end end
usermessage.Hook( "tsayc", tsayColorHook ) usermessage.Hook( "tsayc", tsayColorHook )
end end
--[[ --[[
Function: tsayColor Function: tsayColor
Prints a tsay message in color! Prints a tsay message in color!
Parameters: Parameters:
ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client) ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client)
wait - *(Optional, defaults to false)* Wait one frame before posting. (Useful to use from things like chat hooks) wait - *(Optional, defaults to false)* Wait one frame before posting. (Useful to use from things like chat hooks)
... - color arg and text arg ad infinitum, color needs to come before the text it's coloring. ... - color arg and text arg ad infinitum, color needs to come before the text it's coloring.
Revisions: Revisions:
v2.40 - Initial. v2.40 - Initial.
]] ]]
function ULib.tsayColor( ply, wait, ... ) function ULib.tsayColor( ply, wait, ... )
if SERVER and ply and not ply:IsValid() then ply = serverConsole end -- Mark as server if SERVER and ply and not ply:IsValid() then ply = serverConsole end -- Mark as server
if wait then ULib.namedQueueFunctionCall( "ULibChats", tsayColorCallback, ply, ... ) return end -- Call next frame if wait then ULib.namedQueueFunctionCall( "ULibChats", tsayColorCallback, ply, ... ) return end -- Call next frame
tsayColorCallback( ply, ... ) tsayColorCallback( ply, ... )
end end
--[[ --[[
Function: tsayError Function: tsayError
Just like tsay, but prints the string in red Just like tsay, but prints the string in red
Parameters: Parameters:
ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client) ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client)
msg - The message to print. msg - The message to print.
wait - *(Optional, defaults to false)* Wait one frame before posting. (Useful to use from things like chat hooks) wait - *(Optional, defaults to false)* Wait one frame before posting. (Useful to use from things like chat hooks)
Revisions: Revisions:
v2.40 - Initial. v2.40 - Initial.
]] ]]
function ULib.tsayError( ply, msg, wait ) function ULib.tsayError( ply, msg, wait )
return ULib.tsayColor( ply, wait, Color( 255, 140, 39 ), msg ) return ULib.tsayColor( ply, wait, Color( 255, 140, 39 ), msg )
end end
--[[ --[[
Function: csay Function: csay
Prints a message in center of the screen as well as in the user's consoles. Prints a message in center of the screen as well as in the user's consoles.
Parameters: Parameters:
ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client) ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client)
msg - The message to print. msg - The message to print.
color - *(Optional)* The amount of red to use for the text. color - *(Optional)* The amount of red to use for the text.
duration - *(Optional)* The amount of time to show the text. duration - *(Optional)* The amount of time to show the text.
fade - *(Optional, defaults to 0.5)* The length of fade time fade - *(Optional, defaults to 0.5)* The length of fade time
Revisions: Revisions:
v2.10 - Added fade parameter. Fixed it sending the message multiple times. v2.10 - Added fade parameter. Fixed it sending the message multiple times.
v2.40 - Changed to use clientRPC. v2.40 - Changed to use clientRPC.
]] ]]
function ULib.csay( ply, msg, color, duration, fade ) function ULib.csay( ply, msg, color, duration, fade )
if CLIENT then if CLIENT then
ULib.csayDraw( msg, color, duration ) ULib.csayDraw( msg, color, duration )
Msg( msg .. "\n" ) Msg( msg .. "\n" )
return return
end end
ULib.clientRPC( ply, "ULib.csayDraw", msg, color, duration, fade ) ULib.clientRPC( ply, "ULib.csayDraw", msg, color, duration, fade )
ULib.console( ply, msg ) ULib.console( ply, msg )
end end
--[[ --[[
Function: console Function: console
Prints a message in the user's consoles. Prints a message in the user's consoles.
Parameters: Parameters:
ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client) ply - The player to print to, set to nil to send to everyone. (Ignores this param if called on client)
msg - The message to print. msg - The message to print.
]] ]]
function ULib.console( ply, msg ) function ULib.console( ply, msg )
if CLIENT or (ply and not ply:IsValid()) then if CLIENT or (ply and not ply:IsValid()) then
Msg( msg .. "\n" ) Msg( msg .. "\n" )
return return
end end
if ply then if ply then
ply:PrintMessage( HUD_PRINTCONSOLE, msg .. "\n" ) ply:PrintMessage( HUD_PRINTCONSOLE, msg .. "\n" )
else else
local players = player.GetAll() local players = player.GetAll()
for _, player in ipairs( players ) do for _, player in ipairs( players ) do
player:PrintMessage( HUD_PRINTCONSOLE, msg .. "\n" ) player:PrintMessage( HUD_PRINTCONSOLE, msg .. "\n" )
end end
end end
end end
--[[ --[[
Function: error Function: error
Gives an error to console. Gives an error to console.
Parameters: Parameters:
s - The string to use as the error message s - The string to use as the error message
]] ]]
function ULib.error( s ) function ULib.error( s )
if CLIENT then if CLIENT then
Msg( "[LC ULIB ERROR] " .. s .. "\n" ) Msg( "[LC ULIB ERROR] " .. s .. "\n" )
else else
Msg( "[LS ULIB ERROR] " .. s .. "\n" ) Msg( "[LS ULIB ERROR] " .. s .. "\n" )
end end
end end
--[[ --[[
Function: debugFunctionCall Function: debugFunctionCall
Prints a function call, very useful for debugging. Prints a function call, very useful for debugging.
Parameters: Parameters:
name - The name of the function called. name - The name of the function called.
... - all arguments to the function. ... - all arguments to the function.
Revisions: Revisions:
v2.40 - Now uses print instead of Msg, since Msg seems to have a low max length. v2.40 - Now uses print instead of Msg, since Msg seems to have a low max length.
Changed how the variable length params work so you can pass nil followed by more params Changed how the variable length params work so you can pass nil followed by more params
]] ]]
function ULib.debugFunctionCall( name, ... ) function ULib.debugFunctionCall( name, ... )
local args = { ... } local args = { ... }
print( "Function '" .. name .. "' called. Parameters:" ) print( "Function '" .. name .. "' called. Parameters:" )
for i=1, #args do for i=1, #args do
local value = ULib.serialize( args[ i ] ) local value = ULib.serialize( args[ i ] )
print( "[PARAMETER " .. i .. "]: Type=" .. type( args[ i ] ) .. "\tValue=(" .. value .. ")" ) print( "[PARAMETER " .. i .. "]: Type=" .. type( args[ i ] ) .. "\tValue=(" .. value .. ")" )
end end
end end

File diff suppressed because it is too large Load Diff

View File

@ -1,163 +1,163 @@
--[[ --[[
Title: Tables Title: Tables
Some table helpers. Some table helpers.
]] ]]
-- Based off "RecursiveReadOnlyTables" by VeLoSo (http://lua-users.org/wiki/RecursiveReadOnlyTables) -- Based off "RecursiveReadOnlyTables" by VeLoSo (http://lua-users.org/wiki/RecursiveReadOnlyTables)
-- cache the metatables of all existing read-only tables, -- cache the metatables of all existing read-only tables,
-- so our functions can get to them, but user code can't -- so our functions can get to them, but user code can't
local metatable_cache = setmetatable( {}, { __mode = "k" } ) local metatable_cache = setmetatable( {}, { __mode = "k" } )
local function make_getter( real_table ) local function make_getter( real_table )
local function getter( dummy, key ) local function getter( dummy, key )
local ret = real_table[ key ] local ret = real_table[ key ]
if type( ret ) == "table" and not metatable_cache[ ret ] then if type( ret ) == "table" and not metatable_cache[ ret ] then
ret = ULib.makeReadOnly( ret ) ret = ULib.makeReadOnly( ret )
end end
return ret return ret
end end
return getter return getter
end end
local function setter() local function setter()
ULib.error( "Attempt to modify read-only table!" ) ULib.error( "Attempt to modify read-only table!" )
end end
local function make_pairs( real_table ) local function make_pairs( real_table )
local function pairs() local function pairs()
local key, value, cur_key = nil, nil, nil local key, value, cur_key = nil, nil, nil
local function nexter() -- both args dummy local function nexter() -- both args dummy
key, value = next( real_table, cur_key ) key, value = next( real_table, cur_key )
cur_key = key cur_key = key
if type( key ) == "table" and not metatable_cache[ key ] then if type( key ) == "table" and not metatable_cache[ key ] then
key = ULib.makeReadOnly( key ) key = ULib.makeReadOnly( key )
end end
if type( value ) == "table" and not metatable_cache[ value ] then if type( value ) == "table" and not metatable_cache[ value ] then
value = ULib.makeReadOnly( value ) value = ULib.makeReadOnly( value )
end end
return key, value return key, value
end end
return nexter -- values 2 and 3 dummy return nexter -- values 2 and 3 dummy
end end
return pairs return pairs
end end
--[[ --[[
Function: makeReadOnly Function: makeReadOnly
Makes a table and all recursive tables read-only Makes a table and all recursive tables read-only
Parameters: Parameters:
t - The table to make read-only t - The table to make read-only
Returns: Returns:
The table read-only'fied The table read-only'fied
]] ]]
function ULib.makeReadOnly( t ) function ULib.makeReadOnly( t )
local new={} local new={}
local mt={ local mt={
__metatable = "read only table", __metatable = "read only table",
__index = make_getter( t ), __index = make_getter( t ),
__newindex = setter, __newindex = setter,
__pairs = make_pairs( t ), __pairs = make_pairs( t ),
__type = "read-only table" } __type = "read-only table" }
setmetatable( new, mt ) setmetatable( new, mt )
metatable_cache[ new ] = mt metatable_cache[ new ] = mt
return new return new
end end
--[[ --[[
Function: ropairs Function: ropairs
The equivalent of "pairs" for a readonly table, since "pairs" won't work. The equivalent of "pairs" for a readonly table, since "pairs" won't work.
Parameters: Parameters:
t - The table t - The table
]] ]]
function ULib.ropairs( t ) function ULib.ropairs( t )
local mt = metatable_cache[ t ] local mt = metatable_cache[ t ]
if mt==nil then if mt==nil then
ULib.error( "bad argument #1 to 'ropairs' (read-only table expected, got " .. type(t) .. ")" ) ULib.error( "bad argument #1 to 'ropairs' (read-only table expected, got " .. type(t) .. ")" )
end end
return mt.__pairs() return mt.__pairs()
end end
--[[ --[[
Function: findInTable Function: findInTable
Finds a value in a table. As opposed to table.HasValue(), this function will *only* check numeric keys, and will return a number of where the value is. Finds a value in a table. As opposed to table.HasValue(), this function will *only* check numeric keys, and will return a number of where the value is.
Parameters: Parameters:
t - The table to check t - The table to check
check - The value to check if it exists in t. Can be any type. check - The value to check if it exists in t. Can be any type.
init - *(Optional, defaults to 1)* The value to start from. init - *(Optional, defaults to 1)* The value to start from.
last - *(Optional, defaults to the length of the table)* The value to end at. last - *(Optional, defaults to the length of the table)* The value to end at.
recursive - *(Optional, default to false)* If true, it will check any subtables it comes across. recursive - *(Optional, default to false)* If true, it will check any subtables it comes across.
Returns: Returns:
The number of the key where check resides, false if none is found. If init > last it returns false as well. The number of the key where check resides, false if none is found. If init > last it returns false as well.
]] ]]
function ULib.findInTable( t, check, init, last, recursive ) function ULib.findInTable( t, check, init, last, recursive )
init = init or 1 init = init or 1
last = last or #t last = last or #t
if init > last then return false end if init > last then return false end
for i=init, last do for i=init, last do
if t[ i ] == check then return i end if t[ i ] == check then return i end
if type( t[ i ] ) == "table" and recursive then return ULib.findInTable( v, check, 1, recursive ) end if type( t[ i ] ) == "table" and recursive then return ULib.findInTable( v, check, 1, recursive ) end
end end
return false return false
end end
--[[ --[[
Function: matrixTable Function: matrixTable
Splits a table into a number of given columns. Does not change original table. Splits a table into a number of given columns. Does not change original table.
Parameters: Parameters:
t - The table to split t - The table to split
columns, The number of columns to create columns, The number of columns to create
Returns: Returns:
The new table with the column being the first key and the row being the second key. The new table with the column being the first key and the row being the second key.
Revisions: Revisions:
v2.10 - Initial v2.10 - Initial
]] ]]
function ULib.matrixTable( t, columns ) function ULib.matrixTable( t, columns )
local baserows = math.floor( #t / columns ) local baserows = math.floor( #t / columns )
local remainder = math.fmod( #t, columns ) local remainder = math.fmod( #t, columns )
local nt = {} -- New table after we process local nt = {} -- New table after we process
local curn = 1 -- What value to grab next from our old table local curn = 1 -- What value to grab next from our old table
for i=1, columns do for i=1, columns do
local numtograb = baserows local numtograb = baserows
if i <= remainder then if i <= remainder then
numtograb = baserows + 1 numtograb = baserows + 1
end end
nt[ i ] = {} nt[ i ] = {}
for n=0, numtograb - 1 do for n=0, numtograb - 1 do
table.insert( nt[ i ], t[ curn + n ] ) table.insert( nt[ i ], t[ curn + n ] )
end end
curn = curn + numtograb curn = curn + numtograb
end end
return nt return nt
end end

File diff suppressed because it is too large Load Diff