Removed files for dead branch: sourcemod-1.1.0
--HG-- branch : sourcemod-1.1.0
This commit is contained in:
parent
02931c94cf
commit
e175cce776
21
NOTICE.txt
21
NOTICE.txt
@ -1,21 +0,0 @@
|
|||||||
We now use svn:keywords "Id" on all .c/.cpp/.h/.sp/.inc files. Please make sure your client is configured properly.
|
|
||||||
|
|
||||||
WINDOWS:
|
|
||||||
Open your Application Data folder.
|
|
||||||
Windows XP/2000: C:\Documents and Settings\<user>\Application Data
|
|
||||||
Windows Vista: C:\Users\<user>\AppData\Roaming
|
|
||||||
|
|
||||||
Now go to Subversion. Open the "config" file with a text editor.
|
|
||||||
|
|
||||||
LINUX:
|
|
||||||
Open ~/.subversion/config with your favorite text editor.
|
|
||||||
|
|
||||||
Under [miscellany], uncomment this line:
|
|
||||||
# enable-auto-props = yes
|
|
||||||
|
|
||||||
Under [auto-props], add these lines:
|
|
||||||
*.c = svn:keywords=Id
|
|
||||||
*.cpp = svn:keywords=Id
|
|
||||||
*.h = svn:keywords=Id
|
|
||||||
*.sp = svn:keywords=Id
|
|
||||||
*.inc = svn:keywords=Id
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
Groups
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Allowed properties for a group:
|
|
||||||
*
|
|
||||||
* "flags" - Flag string.
|
|
||||||
* "immunity" - Immunity level number, or a group name.
|
|
||||||
* If the group name is a number, prepend it with an
|
|
||||||
* '@' symbol similar to admins_simple.ini. Users
|
|
||||||
* will only inherit the level number if it's higher
|
|
||||||
* than their current value.
|
|
||||||
*/
|
|
||||||
"Default"
|
|
||||||
{
|
|
||||||
"immunity" "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
"Full Admins"
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* You can override commands and command groups here.
|
|
||||||
* Specify a command name or group and either "allow" or "deny"
|
|
||||||
* Examples:
|
|
||||||
* ":CSDM" "allow"
|
|
||||||
* "csdm_enable" "deny"
|
|
||||||
*/
|
|
||||||
Overrides
|
|
||||||
{
|
|
||||||
}
|
|
||||||
"flags" "abcdefghiz"
|
|
||||||
|
|
||||||
/* Largish number for lots of in-between values. */
|
|
||||||
"immunity" "99"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
/**
|
|
||||||
* There is no reason to edit this file. Core uses this to map each named
|
|
||||||
* access type to a given ASCII character. The names are all pre-defined.
|
|
||||||
*/
|
|
||||||
Levels
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* These are the default role flag mappings.
|
|
||||||
* You can assign new letters for custom purposes, however you should
|
|
||||||
* not change the default names, as SourceMod hardcodes these.
|
|
||||||
*/
|
|
||||||
Flags
|
|
||||||
{
|
|
||||||
"reservation" "a" //Reserved slots
|
|
||||||
"generic" "b" //Generic admin, required for admins
|
|
||||||
"kick" "c" //Kick other players
|
|
||||||
"ban" "d" //Banning other players
|
|
||||||
"unban" "e" //Removing bans
|
|
||||||
"slay" "f" //Slaying other players
|
|
||||||
"changemap" "g" //Changing the map
|
|
||||||
"cvars" "h" //Changing cvars
|
|
||||||
"config" "i" //Changing configs
|
|
||||||
"chat" "j" //Special chat privileges
|
|
||||||
"vote" "k" //Voting
|
|
||||||
"password" "l" //Password the server
|
|
||||||
"rcon" "m" //Remote console
|
|
||||||
"cheats" "n" //Change sv_cheats and related commands
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom flags can be used by plugins, but they can also be used to
|
|
||||||
* for you to expand on the previous groups, using Overrides.
|
|
||||||
*/
|
|
||||||
|
|
||||||
"custom1" "o"
|
|
||||||
"custom2" "p"
|
|
||||||
"custom3" "q"
|
|
||||||
"custom4" "r"
|
|
||||||
"custom5" "s"
|
|
||||||
"custom6" "t"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Root is a magic access flag that grants all permissions.
|
|
||||||
* This should only be given to trusted administrators.
|
|
||||||
* Root users can target anyone regardless of immunity,
|
|
||||||
* however, they themselves are not automatically immune.
|
|
||||||
*/
|
|
||||||
"root" "z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
Overrides
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* By default, commands are registered with three pieces of information:
|
|
||||||
* 1)Command Name (for example, "csdm_enable")
|
|
||||||
* 2)Command Group Name (for example, "CSDM")
|
|
||||||
* 3)Command Level (for example, "changemap")
|
|
||||||
*
|
|
||||||
* You can override the default flags assigned to individual commands or command groups in this way.
|
|
||||||
* To override a group, use the "@" character before the name. Example:
|
|
||||||
* Examples:
|
|
||||||
* "@CSDM" "b" // Override the CSDM group to 'b' flag
|
|
||||||
* "csdm_enable" "bgi" // Override the csdm_enable command to 'bgi' flags
|
|
||||||
*
|
|
||||||
* Note that for overrides, order is important. In the above example, csdm_enable overwrites
|
|
||||||
* any setting that csdm_enable previously had.
|
|
||||||
*
|
|
||||||
* You can make a command completely public by using an empty flag string.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
/**
|
|
||||||
* List config files here (relative to moddir) to have them added to the exec config menu list
|
|
||||||
* Left side is the filename, right side is the text to be added to the menu
|
|
||||||
*/
|
|
||||||
Configs
|
|
||||||
{
|
|
||||||
"cfg/server.cfg" "Standard Server Setup"
|
|
||||||
"cfg/sourcemod/sm_warmode_on.cfg" "War Mode On"
|
|
||||||
"cfg/sourcemod/sm_warmode_off.cfg" "War Mode Off"
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
// adminmenu_maplist.ini
|
|
||||||
//
|
|
||||||
// List maps here to be added to the map and votemap sections of the admin menu
|
|
||||||
//
|
|
||||||
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/**
|
|
||||||
* The default sorting is designed to look familiar to Mani's admin menu.
|
|
||||||
* You may re-order items here for your own menu. Any items not explicitly
|
|
||||||
* sorted will be sorted by their final translated phrases for each given client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
"Menu"
|
|
||||||
{
|
|
||||||
"PlayerCommands"
|
|
||||||
{
|
|
||||||
"item" "sm_slay"
|
|
||||||
"item" "sm_slap"
|
|
||||||
"item" "sm_kick"
|
|
||||||
"item" "sm_ban"
|
|
||||||
"item" "sm_gag"
|
|
||||||
"item" "sm_burn"
|
|
||||||
}
|
|
||||||
|
|
||||||
"ServerCommands"
|
|
||||||
{
|
|
||||||
"item" "sm_map"
|
|
||||||
"item" "sm_execcfg"
|
|
||||||
"item" "sm_reloadadmins"
|
|
||||||
}
|
|
||||||
|
|
||||||
"VotingCommands"
|
|
||||||
{
|
|
||||||
"item" "sm_cancelvote"
|
|
||||||
"item" "sm_votemap"
|
|
||||||
"item" "sm_votekick"
|
|
||||||
"item" "sm_voteban"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* USE THIS SECTION TO DECLARE DETAILED ADMIN PROPERTIES.
|
|
||||||
*
|
|
||||||
* Each admin should have its own "Admin" section, followed by a name.
|
|
||||||
* The name does not have to be unique.
|
|
||||||
*
|
|
||||||
* Available properties: (Anything else is filtered as custom)
|
|
||||||
* "auth" - REQUIRED - Auth method to use. Built-in methods are:
|
|
||||||
* "steam" - Steam based authentication
|
|
||||||
* "name" - Name based authentication
|
|
||||||
* "ip" - IP based authentication
|
|
||||||
* Anything else is treated as custom.
|
|
||||||
* Note: Only one auth method is allowed per entry.
|
|
||||||
*
|
|
||||||
* "identity" - REQUIRED - Identification string, for example, a steamid or name.
|
|
||||||
* Note: Only one identity is allowed per entry.
|
|
||||||
*
|
|
||||||
* "password" - Optional password to require.
|
|
||||||
* "group" - Adds one group to the user's group table.
|
|
||||||
* "flags" - Adds one or more flags to the user's permissions.
|
|
||||||
* "immunity" - Sets the user's immunity level (0 = no immunity).
|
|
||||||
* Immunity can be any value. Admins with higher
|
|
||||||
* values cannot be targetted. See sm_immunity_mode
|
|
||||||
* to tweak the rules. Default value is 0.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
"BAILOPAN"
|
|
||||||
{
|
|
||||||
"auth" "steam"
|
|
||||||
"identity" "STEAM_0:1:16"
|
|
||||||
"flags" "abcdef"
|
|
||||||
}
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
Admins
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
//
|
|
||||||
// READ THIS CAREFULLY! SEE BOTTOM FOR EXAMPLES
|
|
||||||
//
|
|
||||||
// For each admin, you need three settings:
|
|
||||||
// "identity" "permissions" "password"
|
|
||||||
//
|
|
||||||
// For the Identity, you can use a SteamID or Name. To use an IP address, prepend a ! character.
|
|
||||||
// For the Permissions, you can use a flag string and an optional password.
|
|
||||||
//
|
|
||||||
// PERMISSIONS:
|
|
||||||
// Flag definitions are in "admin_levels.cfg"
|
|
||||||
// You can combine flags into a string like this:
|
|
||||||
// "abcdefgh"
|
|
||||||
//
|
|
||||||
// If you want to specify a group instead of a flag, use an @ symbol. Example:
|
|
||||||
// "@Full Admins"
|
|
||||||
//
|
|
||||||
// You can also specify immunity values. Two examples:
|
|
||||||
// "83:abcdefg" //Immunity is 83, flags are abcefgh
|
|
||||||
// "6:@Full Admins" //Immunity is 6, group is "Full Admins"
|
|
||||||
//
|
|
||||||
// Immunity values can be any number. An admin cannot target an admin with
|
|
||||||
// a higher access value (see sm_immunity_mode to tweak the rules). Default
|
|
||||||
// immunity value is 0 (no immunity).
|
|
||||||
//
|
|
||||||
// PASSWORDS:
|
|
||||||
// Passwords are generally not needed unless you have name-based authentication.
|
|
||||||
// In this case, admins must type this in their console:
|
|
||||||
//
|
|
||||||
// setinfo "KEY" "PASSWORD"
|
|
||||||
//
|
|
||||||
// Where KEY is the "PassInfoVar" setting in your core.cfg file, and "PASSWORD"
|
|
||||||
// is their password. With name based authentication, this must be done before
|
|
||||||
// changing names or connecting. Otherwise, SourceMod will automatically detect
|
|
||||||
// the password being set.
|
|
||||||
//
|
|
||||||
////////////////////////////////
|
|
||||||
// Examples: (do not put // in front of real lines, as // means 'comment')
|
|
||||||
//
|
|
||||||
// "STEAM_0:1:16" "bce" //kick, ban, slay for this steam ID, no immunity
|
|
||||||
// "!127.0.0.1" "99:z" //all permissions for this ip, immunity value is 99
|
|
||||||
// "BAILOPAN" "abc" "Gab3n" //name BAILOPAN, password "Gab3n": gets reservation, kick, ban
|
|
||||||
//
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
//This file re-enables a server from "war mode" by unlocking plugin loading
|
|
||||||
//and refreshing the plugins list.
|
|
||||||
sm plugins load_unlock
|
|
||||||
sm plugins refresh
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
|
||||||
//any more plugins from being loaded.
|
|
||||||
sm plugins unload_all
|
|
||||||
sm plugins load basebans.smx
|
|
||||||
sm plugins load basecommands.smx
|
|
||||||
sm plugins load admin-flatfile.smx
|
|
||||||
sm plugins load adminhelp.smx
|
|
||||||
sm plugins load adminmenu.smx
|
|
||||||
sm plugins load_lock
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
// SourceMod Configuration File
|
|
||||||
// This file is automatically executed by SourceMod every mapchange.
|
|
||||||
|
|
||||||
|
|
||||||
// Specifies how admin activity should be relayed to users. Add up the values
|
|
||||||
// below to get the functionality you want.
|
|
||||||
// 1: Show admin activity to non-admins anonymously.
|
|
||||||
// 2: If 1 is specified, admin names will be shown.
|
|
||||||
// 4: Show admin activity to admins anonymously.
|
|
||||||
// 8: If 4 is specified, admin names will be shown.
|
|
||||||
// 16: Always show admin names to root users.
|
|
||||||
// --
|
|
||||||
// Default: 13 (1+4+8)
|
|
||||||
sm_show_activity 13
|
|
||||||
|
|
||||||
// Specifies whether menu sounds are enabled for menus created by SourceMod.
|
|
||||||
// Menu sounds can be further configured in addons/sourcemod/configs/core.cfg.
|
|
||||||
// --
|
|
||||||
// Default: 1
|
|
||||||
sm_menu_sounds 1
|
|
||||||
|
|
||||||
// Specifies how long of a delay, in seconds, should be used in between votes
|
|
||||||
// that are "public" or can be spammed. Whether or not this delay is obeyed
|
|
||||||
// is dependent on the menu/command.
|
|
||||||
// --
|
|
||||||
// Default: 30
|
|
||||||
sm_vote_delay 30
|
|
||||||
|
|
||||||
// Default datetime formatting rules when displaying to clients.
|
|
||||||
// For full options, see: http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html
|
|
||||||
// --
|
|
||||||
// Default: %m/%d/%Y - %H:%M:%S
|
|
||||||
// 12 hour format: %m/%d/%Y - %I:%M:%S %p
|
|
||||||
sm_datetime_format "%m/%d/%Y - %H:%M:%S"
|
|
||||||
|
|
||||||
// Sets how SourceMod should check immunity levels when administrators target
|
|
||||||
// each other.
|
|
||||||
// 0: Ignore immunity levels (except for specific group immunities).
|
|
||||||
// 1: Protect from admins of lower access only.
|
|
||||||
// 2: Protect from admins of equal to or lower access.
|
|
||||||
// 3: Same as 2, except admins with no immunity can affect each other.
|
|
||||||
// --
|
|
||||||
// Default: 1
|
|
||||||
sm_immunity_mode 1
|
|
||||||
|
|
||||||
// Sets how many seconds SourceMod should adjust time values for incorrect
|
|
||||||
// server clocks. This can be positive or negative and will affect every
|
|
||||||
// system time in SourceMod, including logging stamps.
|
|
||||||
// --
|
|
||||||
// Default: 0
|
|
||||||
sm_time_adjustment 0
|
|
||||||
|
|
||||||
// Specifies the amount of time that is allowed between chat messages. This
|
|
||||||
// includes the say and say_team commands. If a client sends a message faster
|
|
||||||
// than this time, they receive a flood token. When the client has accumulated
|
|
||||||
// 3 or more tokens, a warning message is shown instead of the chat message.
|
|
||||||
// --
|
|
||||||
// Requires: antiflood.smx
|
|
||||||
// Default: 0.75
|
|
||||||
sm_flood_time 0.75
|
|
||||||
|
|
||||||
// Specifies how the reserved slots plugin operates. Valid values are:
|
|
||||||
// 0 : Public slots are used in preference to reserved slots. Reserved slots are freed before public slots.
|
|
||||||
// 1 : If someone with reserve access joins into a reserved slot, the player with the highest latency and
|
|
||||||
// no reserved slot access (spectator players are selected first) is kicked to make room. Thus, the reserved
|
|
||||||
// slots always remains free. The only situation where the reserved slot(s) can become properly occupied is
|
|
||||||
// if the server is full with reserve slot access clients.
|
|
||||||
// --
|
|
||||||
// Requires: reservedslots.smx
|
|
||||||
// Default: 0
|
|
||||||
sm_reserve_type 0
|
|
||||||
|
|
||||||
// Specifies the number of reserved player slots. Users with the reservation
|
|
||||||
// admin flag set will be able to join the server when there are no public slots
|
|
||||||
// remaining. If someone does not have this flag, they will be kicked.
|
|
||||||
// (Public slots are defined as: maxplayers - number of reserved slots)
|
|
||||||
// --
|
|
||||||
// Requires: reservedslots.smx
|
|
||||||
// Default: 0
|
|
||||||
sm_reserved_slots 0
|
|
||||||
|
|
||||||
// Specifies whether or not reserved slots will be hidden (subtracted from max
|
|
||||||
// slot count). Valid values are 0 (visible) or 1 (hidden).
|
|
||||||
// --
|
|
||||||
// Requires: reservedslots.smx
|
|
||||||
// Default: 0
|
|
||||||
sm_hide_slots 0
|
|
||||||
|
|
||||||
// Specifies whether or not non-admins can send messages to admins using
|
|
||||||
// say_team @<message>. Valid values are 0 (disabled) or 1 (enabled)
|
|
||||||
// --
|
|
||||||
// Required: basechat.smx
|
|
||||||
// Default: 1
|
|
||||||
sm_chat_mode 1
|
|
||||||
|
|
||||||
// Specifies whether or not "timeleft" will automaticly be triggered every
|
|
||||||
// x seconds. Valid values are 0 (disabled) to 1800 seconds.
|
|
||||||
// --
|
|
||||||
// Required: basetriggers.smx
|
|
||||||
// Default: 0
|
|
||||||
sm_timeleft_interval 0
|
|
||||||
|
|
||||||
// Specifies whether or not chat triggers are broadcast to the server or just
|
|
||||||
// the player who requested the info trigger. Valid values are 0 (Disabled) or
|
|
||||||
// 1 (Enabled)
|
|
||||||
// --
|
|
||||||
// Required: basetriggers.smx
|
|
||||||
// Default: 1
|
|
||||||
sm_trigger_show 1
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
/**
|
|
||||||
* This file is used to set various options that are important to SourceMod's core.
|
|
||||||
* If this file is missing or an option in this file is missing, then the default values will be used.
|
|
||||||
*/
|
|
||||||
"Core"
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Relative path to SourceMod's base directory. This is relative to the game/mod directory.
|
|
||||||
* Only change this if you have installed SourceMod in a non-default location.
|
|
||||||
*
|
|
||||||
* The default value is "addons/sourcemod"
|
|
||||||
*/
|
|
||||||
"BasePath" "addons/sourcemod"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This option determines if SourceMod logging is enabled.
|
|
||||||
*
|
|
||||||
* "on" - Logging is enabled (default)
|
|
||||||
* "off" - Logging is disabled
|
|
||||||
*/
|
|
||||||
"Logging" "on"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This option determines how SourceMod logging should be handled.
|
|
||||||
*
|
|
||||||
* "daily" - New log file is created for each day (default)
|
|
||||||
* "map" - New log file is created for each map change
|
|
||||||
* "game" - Use game's log files
|
|
||||||
*/
|
|
||||||
"LogMode" "daily"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Language that multilingual enabled plugins and extensions will use to print messages.
|
|
||||||
* Only languages listed in languages.cfg are valid.
|
|
||||||
*
|
|
||||||
* The default value is "en"
|
|
||||||
*/
|
|
||||||
"ServerLang" "en"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String to use as the public chat trigger. Set an empty string to disable.
|
|
||||||
*/
|
|
||||||
"PublicChatTrigger" "!"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String to use as the silent chat trigger. Set an empty string to disable.
|
|
||||||
*/
|
|
||||||
"SilentChatTrigger" "/"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Password setinfo key that clients must set. You must change this in order for
|
|
||||||
* passwords to work, for security reasons.
|
|
||||||
*/
|
|
||||||
"PassInfoVar" "_password"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the sound that gets played when an item is selected from a menu.
|
|
||||||
*/
|
|
||||||
"MenuItemSound" "buttons/button14.wav"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the sound that gets played when an "Exit" button is selected
|
|
||||||
* from a menu.
|
|
||||||
*/
|
|
||||||
"MenuExitSound" "buttons/combine_button7.wav"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the sound that gets played when an "Exit Back" button is selected
|
|
||||||
* from a menu. This is the special "Back" button that is intended to roll back
|
|
||||||
* to a previous menu.
|
|
||||||
*/
|
|
||||||
"MenuExitBackSound" "buttons/combine_button7.wav"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables whether SourceMod reads a client's cl_language cvar to set
|
|
||||||
* their language for server-side phrase translation.
|
|
||||||
*
|
|
||||||
* "on" - Translate using the client's language (default)
|
|
||||||
* "off" - Translate using default server's language
|
|
||||||
*/
|
|
||||||
"AllowClLanguageVar" "On"
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
"Databases"
|
|
||||||
{
|
|
||||||
"driver_default" "mysql"
|
|
||||||
|
|
||||||
"default"
|
|
||||||
{
|
|
||||||
"driver" "default"
|
|
||||||
"host" "localhost"
|
|
||||||
"database" "sourcemod"
|
|
||||||
"user" "root"
|
|
||||||
"pass" ""
|
|
||||||
//"timeout" "0"
|
|
||||||
//"port" "0"
|
|
||||||
}
|
|
||||||
|
|
||||||
"storage-local"
|
|
||||||
{
|
|
||||||
"driver" "sqlite"
|
|
||||||
"database" "sourcemod-local"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
/* Add group options to be added to 'group' or 'groupplayer' type submenus
|
|
||||||
* The left side is the name that will show in the menu, right is the command that will be fired
|
|
||||||
*/
|
|
||||||
|
|
||||||
Groups
|
|
||||||
{
|
|
||||||
"All" "@all"
|
|
||||||
"Bots" "@bots"
|
|
||||||
"Alive" "@alive"
|
|
||||||
"Dead" "@dead"
|
|
||||||
"Humans" "@humans"
|
|
||||||
"Current aim" "@aim"
|
|
||||||
|
|
||||||
/* You can enable these if you are using Counter-Strike Source and running the cstrike extension */
|
|
||||||
// "Terrorists" "@t"
|
|
||||||
// "Counter-Terrorists" "@ct"
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,389 +0,0 @@
|
|||||||
"Commands"
|
|
||||||
{
|
|
||||||
"Fun Commands"
|
|
||||||
{
|
|
||||||
"admin" "sm_ban"
|
|
||||||
"Set Player Speed"
|
|
||||||
{
|
|
||||||
"cmd" "sm_speed #1 #2"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Edit"
|
|
||||||
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Speed Multiplier"
|
|
||||||
"1" "1.0"
|
|
||||||
"1." "Normal"
|
|
||||||
"2" "0.8"
|
|
||||||
"2." "80%"
|
|
||||||
"3" "0.5"
|
|
||||||
"3." "Half"
|
|
||||||
"4" "1.5"
|
|
||||||
"4." "50% Boost"
|
|
||||||
"5" "2.0"
|
|
||||||
"5." "Double"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Give Player Weapon"
|
|
||||||
{
|
|
||||||
"cmd" "sm_weapon #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "player"
|
|
||||||
"title" "Player to Give to"
|
|
||||||
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Weapon:"
|
|
||||||
"1" "weapon_ak47"
|
|
||||||
"1." "Ak-47"
|
|
||||||
"2" "weapon_m4a1"
|
|
||||||
"2." "M4A1"
|
|
||||||
"3" "weapon_deagle"
|
|
||||||
"3." "Desert Eagle"
|
|
||||||
"4" "weapon_mp5"
|
|
||||||
"4." "MP5"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Set Player Armour"
|
|
||||||
{
|
|
||||||
"cmd" "sm_armour #1 #2"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Edit"
|
|
||||||
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Armour:"
|
|
||||||
"1" "0"
|
|
||||||
"2" "20"
|
|
||||||
"3" "50"
|
|
||||||
"4" "80"
|
|
||||||
"5" "100"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Set Player HP"
|
|
||||||
{
|
|
||||||
"cmd" "sm_hp #1 #2"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Edit"
|
|
||||||
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "HP:"
|
|
||||||
"1" "1"
|
|
||||||
"2" "20"
|
|
||||||
"3" "50"
|
|
||||||
"4" "80"
|
|
||||||
"5" "100"
|
|
||||||
"6" "150"
|
|
||||||
"7" "200"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Bury Player"
|
|
||||||
{
|
|
||||||
"cmd" "sm_bury #1"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Bury"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"UnBury Player"
|
|
||||||
{
|
|
||||||
"cmd" "sm_unbury #1"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to UnBury"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Respawn Player"
|
|
||||||
{
|
|
||||||
"cmd" "sm_respawn #1"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Respawn"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Disarm Player"
|
|
||||||
{
|
|
||||||
"cmd" "sm_disarm #1"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Disarm"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Burn and Disarm"
|
|
||||||
{
|
|
||||||
"cmd" "sm_burn #1 #2;sm_disarm #1"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Burn"
|
|
||||||
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Time:"
|
|
||||||
"1" "0"
|
|
||||||
"2" "5"
|
|
||||||
"3" "10"
|
|
||||||
"4" "20"
|
|
||||||
"5" "30"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Set Player Gravity"
|
|
||||||
{
|
|
||||||
"cmd" "sm_gravity #1 #2"
|
|
||||||
"execute" "player"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
"method" "name"
|
|
||||||
"title" "Player/Team to Edit"
|
|
||||||
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Speed Multiplier"
|
|
||||||
"1" "1.0"
|
|
||||||
"1." "Normal"
|
|
||||||
"2" "0.8"
|
|
||||||
"2." "80%"
|
|
||||||
"3" "0.5"
|
|
||||||
"3." "Half"
|
|
||||||
"4" "1.5"
|
|
||||||
"4." "50% Boost"
|
|
||||||
"5" "0.25"
|
|
||||||
"5." "Quarter"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Set Player No-Clip"
|
|
||||||
{
|
|
||||||
"cmd" "sm_noclip #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"1" "1"
|
|
||||||
"1." "On"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Set Player God"
|
|
||||||
{
|
|
||||||
"cmd" "sm_god #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"1" "1"
|
|
||||||
"1." "On"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Set Player NightVision"
|
|
||||||
{
|
|
||||||
"cmd" "sm_nv #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"1" "1"
|
|
||||||
"1." "Give"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Take"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Set Player Helmet"
|
|
||||||
{
|
|
||||||
"cmd" "sm_helmet #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"1" "1"
|
|
||||||
"1." "Give"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Take"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Set Player Defuse Kit"
|
|
||||||
{
|
|
||||||
"cmd" "sm_defuser #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "groupplayer"
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"1" "1"
|
|
||||||
"1." "Give"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Take"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
"ServerCommands"
|
|
||||||
{
|
|
||||||
"Extend Map"
|
|
||||||
{
|
|
||||||
"cmd" "sm_extend #1"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Extend for:"
|
|
||||||
"1" "5"
|
|
||||||
"1." "5 Minutes"
|
|
||||||
"2" "10"
|
|
||||||
"2." "10 Minutes"
|
|
||||||
"3" "15"
|
|
||||||
"3." "15 Minutes"
|
|
||||||
"4" "20"
|
|
||||||
"4." "20 Minutes"
|
|
||||||
"5" "30"
|
|
||||||
"5." "Half an Hour"
|
|
||||||
"6" "45"
|
|
||||||
"6." "45 Minutes"
|
|
||||||
"7" "60"
|
|
||||||
"7." "An Hour"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"Cvars"
|
|
||||||
{
|
|
||||||
"admin" "sm_kick"
|
|
||||||
"Timelimit"
|
|
||||||
{
|
|
||||||
"cmd" "mp_timelimit #1"
|
|
||||||
"execute" "server"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Timelimit:"
|
|
||||||
"1" "20"
|
|
||||||
"2" "40"
|
|
||||||
"3" "60"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Friendly Fire"
|
|
||||||
{
|
|
||||||
"cmd" "mp_friendlyfire #1"
|
|
||||||
"execute" "server"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Friendly Fire:"
|
|
||||||
"1" "1"
|
|
||||||
"1." "On"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Show Damage Done"
|
|
||||||
{
|
|
||||||
"cmd" "sm_showdamage #1"
|
|
||||||
"admin" "sm_csay"
|
|
||||||
"execute" "server"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Show Damage Done:"
|
|
||||||
"1" "1"
|
|
||||||
"1." "On"
|
|
||||||
"2" "0"
|
|
||||||
"2." "Off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Team management"
|
|
||||||
{
|
|
||||||
"Team Player"
|
|
||||||
{
|
|
||||||
"cmd" "sm_team #1 #2"
|
|
||||||
"1"
|
|
||||||
{
|
|
||||||
"type" "player"
|
|
||||||
}
|
|
||||||
"2"
|
|
||||||
{
|
|
||||||
"type" "list"
|
|
||||||
"title" "Team:"
|
|
||||||
"1" "1"
|
|
||||||
"1." "Spectators"
|
|
||||||
"2" "2"
|
|
||||||
"2." "Terrorists"
|
|
||||||
"3" "3"
|
|
||||||
"3." "Counter-Terrorists"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Switch Team"
|
|
||||||
{
|
|
||||||
"cmd" "sm_teamswap"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,6 +0,0 @@
|
|||||||
"Languages"
|
|
||||||
{
|
|
||||||
"en" "English"
|
|
||||||
"es" "Español"
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
/**
|
|
||||||
* Each sub-section of "Plugins" should have a title which specifies a plugin filename.
|
|
||||||
* Filenames have a wildcard of *. Appending .smx is not required.
|
|
||||||
* If the filename has no explicit path, it will be patched to any sub-path in the plugins folder.
|
|
||||||
*
|
|
||||||
* Available properties for plugins are:
|
|
||||||
* "pause" - Whether or not the plugin should load paused - "yes" or "no" (defualt)
|
|
||||||
* "lifetime" - Lifetime of the plugin. Options:
|
|
||||||
* "mapsync" - Plugins should be reloaded on mapchange if changed (default)
|
|
||||||
* "global" - Plugin will never be unloaded or updated
|
|
||||||
* "blockload" - Plugin will always be blocked from loading. Implicit (automatic) loads
|
|
||||||
* produce no error, but explicit (manual) loads will show an error message.
|
|
||||||
* (Options are one of "yes" or "no")
|
|
||||||
*
|
|
||||||
* You can also have an "Options" section declaring options to pass onto the JIT:
|
|
||||||
* "debug" - Whether or not to load the plugin in debug mode
|
|
||||||
*/
|
|
||||||
|
|
||||||
"Plugins"
|
|
||||||
{
|
|
||||||
"*"
|
|
||||||
{
|
|
||||||
"pause" "no"
|
|
||||||
"lifetime" "mapsync"
|
|
||||||
|
|
||||||
"Options"
|
|
||||||
{
|
|
||||||
"debug" "no"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
|
|
||||||
CREATE TABLE sm_admins (
|
|
||||||
id int(10) unsigned NOT NULL auto_increment,
|
|
||||||
authtype enum('steam','name','ip') NOT NULL,
|
|
||||||
identity varchar(65) NOT NULL,
|
|
||||||
password varchar(65),
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
name varchar(65) NOT NULL,
|
|
||||||
immunity int(10) unsigned NOT NULL,
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_groups (
|
|
||||||
id int(10) unsigned NOT NULL auto_increment,
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
name varchar(120) NOT NULL,
|
|
||||||
immunity_level int(1) unsigned NOT NULL,
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_group_immunity (
|
|
||||||
group_id int(10) unsigned NOT NULL,
|
|
||||||
other_id int(10) unsigned NOT NULL,
|
|
||||||
PRIMARY KEY (group_id, other_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_group_overrides (
|
|
||||||
group_id int(10) unsigned NOT NULL,
|
|
||||||
type enum('command','group') NOT NULL,
|
|
||||||
name varchar(32) NOT NULL,
|
|
||||||
access enum('allow','deny') NOT NULL,
|
|
||||||
PRIMARY KEY (group_id, type, name)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_overrides (
|
|
||||||
type enum('command','group') NOT NULL,
|
|
||||||
name varchar(32) NOT NULL,
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
PRIMARY KEY (type,name)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_admins_groups (
|
|
||||||
admin_id int(10) unsigned NOT NULL,
|
|
||||||
group_id int(10) unsigned NOT NULL,
|
|
||||||
inherit_order int(10) NOT NULL,
|
|
||||||
PRIMARY KEY (admin_id, group_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS sm_config (
|
|
||||||
cfg_key varchar(32) NOT NULL,
|
|
||||||
cfg_value varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (cfg_key)
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409') ON DUPLICATE KEY UPDATE cfg_value = '1.0.0.1409';
|
|
||||||
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
ALTER TABLE sm_admins ADD immunity INT UNSIGNED NOT NULL;
|
|
||||||
|
|
||||||
ALTER TABLE sm_groups ADD immunity_level INT UNSIGNED NOT NULL;
|
|
||||||
UPDATE sm_groups SET immunity_level = 2 WHERE immunity = 'default';
|
|
||||||
UPDATE sm_groups SET immunity_level = 1 WHERE immunity = 'global';
|
|
||||||
ALTER TABLE sm_groups DROP immunity;
|
|
||||||
|
|
||||||
CREATE TABLE sm_config (
|
|
||||||
cfg_key varchar(32) NOT NULL,
|
|
||||||
cfg_value varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (cfg_key)
|
|
||||||
);
|
|
||||||
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409') ON DUPLICATE KEY UPDATE cfg_value = '1.0.0.1409';
|
|
||||||
|
|
||||||
Binary file not shown.
@ -1,54 +0,0 @@
|
|||||||
|
|
||||||
CREATE TABLE sm_admins (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
authtype varchar(16) NOT NULL CHECK(authtype IN ('steam', 'ip', 'name')),
|
|
||||||
identity varchar(65) NOT NULL,
|
|
||||||
password varchar(65),
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
name varchar(65) NOT NULL,
|
|
||||||
immunity INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_groups (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
name varchar(120) NOT NULL,
|
|
||||||
immunity_level INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_group_immunity (
|
|
||||||
group_id INTEGER NOT NULL,
|
|
||||||
other_id INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY (group_id, other_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_group_overrides (
|
|
||||||
group_id INTEGER NOT NULL,
|
|
||||||
type varchar(16) NOT NULL CHECK (type IN ('command', 'group')),
|
|
||||||
name varchar(32) NOT NULL,
|
|
||||||
access varchar(16) NOT NULL CHECK (access IN ('allow', 'deny')),
|
|
||||||
PRIMARY KEY (group_id, type, name)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_overrides (
|
|
||||||
type varchar(16) NOT NULL CHECK (type IN ('command', 'group')),
|
|
||||||
name varchar(32) NOT NULL,
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
PRIMARY KEY (type,name)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE sm_admins_groups (
|
|
||||||
admin_id INTEGER NOT NULL,
|
|
||||||
group_id INTEGER NOT NULL,
|
|
||||||
inherit_order int(10) NOT NULL,
|
|
||||||
PRIMARY KEY (admin_id, group_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS sm_config (
|
|
||||||
cfg_key varchar(32) NOT NULL,
|
|
||||||
cfg_value varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (cfg_key)
|
|
||||||
);
|
|
||||||
|
|
||||||
REPLACE INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409');
|
|
||||||
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
|
|
||||||
ALTER TABLE sm_admins ADD immunity INTEGER DEFAULT 0 NOT NULL;
|
|
||||||
|
|
||||||
CREATE TABLE _sm_groups_temp (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
flags varchar(30) NOT NULL,
|
|
||||||
name varchar(120) NOT NULL,
|
|
||||||
immunity_level INTEGER DEFAULT 0 NOT NULL
|
|
||||||
);
|
|
||||||
INSERT INTO _sm_groups_temp (id, flags, name) SELECT id, flags, name FROM sm_groups;
|
|
||||||
UPDATE _sm_groups_temp SET immunity_level = 2 WHERE id IN (SELECT g.id FROM sm_groups g WHERE g.immunity = 'global');
|
|
||||||
UPDATE _sm_groups_temp SET immunity_level = 1 WHERE id IN (SELECT g.id FROM sm_groups g WHERE g.immunity = 'default');
|
|
||||||
DROP TABLE sm_groups;
|
|
||||||
ALTER TABLE _sm_groups_temp RENAME TO sm_groups;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS sm_config (
|
|
||||||
cfg_key varchar(32) NOT NULL,
|
|
||||||
cfg_value varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (cfg_key)
|
|
||||||
);
|
|
||||||
|
|
||||||
REPLACE INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409');
|
|
||||||
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ADTFactory.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
|
|
||||||
ADTFactory g_AdtFactory;
|
|
||||||
|
|
||||||
const char *ADTFactory::GetInterfaceName()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_ADTFACTORY_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ADTFactory::GetInterfaceVersion()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_ADTFACTORY_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADTFactory::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
IBasicTrie *ADTFactory::CreateBasicTrie()
|
|
||||||
{
|
|
||||||
return new BaseTrie();
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseTrie::BaseTrie()
|
|
||||||
{
|
|
||||||
m_pTrie = sm_trie_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseTrie::~BaseTrie()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_pTrie);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseTrie::Insert(const char *key, void *value)
|
|
||||||
{
|
|
||||||
return sm_trie_insert(m_pTrie, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseTrie::Retrieve(const char *key, void **value)
|
|
||||||
{
|
|
||||||
return sm_trie_retrieve(m_pTrie, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseTrie::Delete(const char *key)
|
|
||||||
{
|
|
||||||
return sm_trie_delete(m_pTrie, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseTrie::Clear()
|
|
||||||
{
|
|
||||||
sm_trie_clear(m_pTrie);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseTrie::Destroy()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseTrie::Replace(const char *key, void *value)
|
|
||||||
{
|
|
||||||
return sm_trie_replace(m_pTrie, key, value);
|
|
||||||
}
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
|
||||||
|
|
||||||
#include <IADTFactory.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sm_trie.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class BaseTrie : public IBasicTrie
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseTrie();
|
|
||||||
virtual ~BaseTrie();
|
|
||||||
virtual bool Insert(const char *key, void *value);
|
|
||||||
virtual bool Replace(const char *key, void *value);
|
|
||||||
virtual bool Retrieve(const char *key, void **value);
|
|
||||||
virtual bool Delete(const char *key);
|
|
||||||
virtual void Clear();
|
|
||||||
virtual void Destroy();
|
|
||||||
private:
|
|
||||||
Trie *m_pTrie;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ADTFactory :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IADTFactory
|
|
||||||
{
|
|
||||||
public: //SMInterface
|
|
||||||
const char *GetInterfaceName();
|
|
||||||
unsigned int GetInterfaceVersion();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
public: //IADTFactory
|
|
||||||
IBasicTrie *CreateBasicTrie();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
|
||||||
|
|
||||||
1732
core/AdminCache.cpp
1732
core/AdminCache.cpp
File diff suppressed because it is too large
Load Diff
@ -1,201 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
|
||||||
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include <sm_trie.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <IAdminSystem.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include <IForwardSys.h>
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
#define GRP_MAGIC_SET 0xDEADFADE
|
|
||||||
#define GRP_MAGIC_UNSET 0xFACEFACE
|
|
||||||
#define USR_MAGIC_SET 0xDEADFACE
|
|
||||||
#define USR_MAGIC_UNSET 0xFADEDEAD
|
|
||||||
|
|
||||||
struct AdminGroup
|
|
||||||
{
|
|
||||||
uint32_t magic; /* Magic flag, for memory validation (ugh) */
|
|
||||||
unsigned int immunity_level; /* Immunity level */
|
|
||||||
/* Immune from target table (-1 = nonexistent)
|
|
||||||
* [0] = number of entries
|
|
||||||
* [1...N] = immune targets
|
|
||||||
*/
|
|
||||||
int immune_table;
|
|
||||||
Trie *pCmdTable; /* Command override table (can be NULL) */
|
|
||||||
Trie *pCmdGrpTable; /* Command group override table (can be NULL) */
|
|
||||||
int next_grp; /* Next group in the chain */
|
|
||||||
int prev_grp; /* Previous group in the chain */
|
|
||||||
int nameidx; /* Name */
|
|
||||||
FlagBits addflags; /* Additive flags */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AuthMethod
|
|
||||||
{
|
|
||||||
String name;
|
|
||||||
Trie *table;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UserAuth
|
|
||||||
{
|
|
||||||
unsigned int index; /* Index into auth table */
|
|
||||||
int identidx; /* Index into the string table */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AdminUser
|
|
||||||
{
|
|
||||||
uint32_t magic; /* Magic flag, for memory validation */
|
|
||||||
FlagBits flags; /* Flags */
|
|
||||||
FlagBits eflags; /* Effective flags */
|
|
||||||
int nameidx; /* Name index */
|
|
||||||
int password; /* Password index */
|
|
||||||
unsigned int grp_count; /* Number of groups */
|
|
||||||
unsigned int grp_size; /* Size of groups table */
|
|
||||||
int grp_table; /* Group table itself */
|
|
||||||
int next_user; /* Next user in the list */
|
|
||||||
int prev_user; /* Previous user in the list */
|
|
||||||
UserAuth auth; /* Auth method for this user */
|
|
||||||
unsigned int immunity_level; /* Immunity level */
|
|
||||||
unsigned int serialchange; /* Serial # for changes */
|
|
||||||
};
|
|
||||||
|
|
||||||
class AdminCache :
|
|
||||||
public IAdminSystem,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AdminCache();
|
|
||||||
~AdminCache();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModStartup(bool late);
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
void OnSourceModPluginsLoaded();
|
|
||||||
public: //IAdminSystem
|
|
||||||
/** Command cache stuff */
|
|
||||||
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
|
|
||||||
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
|
|
||||||
void UnsetCommandOverride(const char *cmd, OverrideType type);
|
|
||||||
/** Group cache stuff */
|
|
||||||
GroupId AddGroup(const char *group_name);
|
|
||||||
GroupId FindGroupByName(const char *group_name);
|
|
||||||
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
|
|
||||||
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
|
|
||||||
FlagBits GetGroupAddFlags(GroupId id);
|
|
||||||
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
|
|
||||||
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
|
|
||||||
void InvalidateGroup(GroupId id);
|
|
||||||
void AddGroupImmunity(GroupId id, GroupId other_id);
|
|
||||||
unsigned int GetGroupImmunityCount(GroupId id);
|
|
||||||
GroupId GetGroupImmunity(GroupId id, unsigned int number);
|
|
||||||
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
|
|
||||||
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
|
|
||||||
void DumpAdminCache(AdminCachePart part, bool rebuild);
|
|
||||||
void AddAdminListener(IAdminListener *pListener);
|
|
||||||
void RemoveAdminListener(IAdminListener *pListener);
|
|
||||||
/** User stuff */
|
|
||||||
void RegisterAuthIdentType(const char *name);
|
|
||||||
AdminId CreateAdmin(const char *name);
|
|
||||||
const char *GetAdminName(AdminId id);
|
|
||||||
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
|
|
||||||
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
|
|
||||||
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
|
|
||||||
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
|
|
||||||
bool AdminInheritGroup(AdminId id, GroupId gid);
|
|
||||||
unsigned int GetAdminGroupCount(AdminId id);
|
|
||||||
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
|
|
||||||
void SetAdminPassword(AdminId id, const char *password);
|
|
||||||
const char *GetAdminPassword(AdminId id);
|
|
||||||
AdminId FindAdminByIdentity(const char *auth, const char *identity);
|
|
||||||
bool InvalidateAdmin(AdminId id);
|
|
||||||
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
|
|
||||||
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
|
|
||||||
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
|
|
||||||
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
|
|
||||||
bool CheckAdminFlags(AdminId id, FlagBits bits);
|
|
||||||
bool CanAdminTarget(AdminId id, AdminId target);
|
|
||||||
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
|
|
||||||
bool FindFlag(const char *str, AdminFlag *pFlag);
|
|
||||||
bool FindFlag(char c, AdminFlag *pAdmFlag);
|
|
||||||
FlagBits ReadFlagString(const char *flags, const char **end);
|
|
||||||
unsigned int GetAdminSerialChange(AdminId id);
|
|
||||||
bool CanAdminUseCommand(int client, const char *cmd);
|
|
||||||
const char *GetGroupName(GroupId gid);
|
|
||||||
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
|
|
||||||
unsigned int GetGroupImmunityLevel(GroupId gid);
|
|
||||||
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
|
|
||||||
unsigned int GetAdminImmunityLevel(AdminId id);
|
|
||||||
bool CheckAccess(int client,
|
|
||||||
const char *cmd,
|
|
||||||
FlagBits flags,
|
|
||||||
bool override_only);
|
|
||||||
public:
|
|
||||||
bool IsValidAdmin(AdminId id);
|
|
||||||
private:
|
|
||||||
void _UnsetCommandOverride(const char *cmd);
|
|
||||||
void _UnsetCommandGroupOverride(const char *group);
|
|
||||||
void InvalidateGroupCache();
|
|
||||||
void InvalidateAdminCache(bool unlink_admins);
|
|
||||||
void DumpCommandOverrideCache(OverrideType type);
|
|
||||||
Trie *GetMethodByIndex(unsigned int index);
|
|
||||||
bool GetMethodIndex(const char *name, unsigned int *_index);
|
|
||||||
void NameFlag(const char *str, AdminFlag flag);
|
|
||||||
public:
|
|
||||||
BaseStringTable *m_pStrings;
|
|
||||||
BaseMemTable *m_pMemory;
|
|
||||||
Trie *m_pCmdOverrides;
|
|
||||||
Trie *m_pCmdGrpOverrides;
|
|
||||||
int m_FirstGroup;
|
|
||||||
int m_LastGroup;
|
|
||||||
int m_FreeGroupList;
|
|
||||||
Trie *m_pGroups;
|
|
||||||
List<IAdminListener *> m_hooks;
|
|
||||||
List<AuthMethod> m_AuthMethods;
|
|
||||||
Trie *m_pAuthTables;
|
|
||||||
IForward *m_pCacheFwd;
|
|
||||||
int m_FirstUser;
|
|
||||||
int m_LastUser;
|
|
||||||
int m_FreeUserList;
|
|
||||||
bool m_InvalidatingAdmins;
|
|
||||||
bool m_destroying;
|
|
||||||
Trie *m_pLevelNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern AdminCache g_Admins;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
|
||||||
@ -1,259 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "CDataPack.h"
|
|
||||||
|
|
||||||
#define DATAPACK_INITIAL_SIZE 512
|
|
||||||
|
|
||||||
CDataPack::CDataPack()
|
|
||||||
{
|
|
||||||
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
|
|
||||||
m_capacity = DATAPACK_INITIAL_SIZE;
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
CDataPack::~CDataPack()
|
|
||||||
{
|
|
||||||
free(m_pBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::Initialize()
|
|
||||||
{
|
|
||||||
m_curptr = m_pBase;
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::CheckSize(size_t typesize)
|
|
||||||
{
|
|
||||||
if (m_curptr - m_pBase + typesize <= m_capacity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t pos = m_curptr - m_pBase;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
m_capacity *= 2;
|
|
||||||
m_pBase = (char *)realloc(m_pBase, m_capacity);
|
|
||||||
m_curptr = m_pBase + pos;
|
|
||||||
} while (m_curptr - m_pBase + typesize > m_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::ResetSize()
|
|
||||||
{
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(size_t) + size);
|
|
||||||
size_t pos = m_curptr - m_pBase;
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = size;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
if (addr)
|
|
||||||
{
|
|
||||||
*addr = m_curptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += size;
|
|
||||||
m_size += sizeof(size_t) + size;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackCell(cell_t cell)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(size_t) + sizeof(cell_t));
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = sizeof(cell_t);
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
*(cell_t *)m_curptr = cell;
|
|
||||||
m_curptr += sizeof(cell_t);
|
|
||||||
|
|
||||||
m_size += sizeof(size_t) + sizeof(cell_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackFloat(float val)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(size_t) + sizeof(float));
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = sizeof(float);
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
*(float *)m_curptr = val;
|
|
||||||
m_curptr += sizeof(float);
|
|
||||||
|
|
||||||
m_size += sizeof(size_t) + sizeof(float);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackString(const char *string)
|
|
||||||
{
|
|
||||||
size_t len = strlen(string);
|
|
||||||
size_t maxsize = sizeof(size_t) + len + 1;
|
|
||||||
CheckSize(maxsize);
|
|
||||||
|
|
||||||
// Pack the string length first for buffer overrun checking.
|
|
||||||
*(size_t *)m_curptr = len;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
// Now pack the string.
|
|
||||||
memcpy(m_curptr, string, len);
|
|
||||||
m_curptr[len] = '\0';
|
|
||||||
m_curptr += len + 1;
|
|
||||||
|
|
||||||
m_size += maxsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::Reset() const
|
|
||||||
{
|
|
||||||
m_curptr = m_pBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CDataPack::GetPosition() const
|
|
||||||
{
|
|
||||||
return static_cast<size_t>(m_curptr - m_pBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDataPack::SetPosition(size_t pos) const
|
|
||||||
{
|
|
||||||
if (pos > m_size-1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_curptr = m_pBase + pos;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t CDataPack::ReadCell() const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
|
||||||
m_curptr += sizeof(cell_t);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
float CDataPack::ReadFloat() const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(size_t) + sizeof(float)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
float val = *reinterpret_cast<float *>(m_curptr);
|
|
||||||
m_curptr += sizeof(float);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDataPack::IsReadable(size_t bytes) const
|
|
||||||
{
|
|
||||||
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CDataPack::ReadString(size_t *len) const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(size_t)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t real_len = *(size_t *)m_curptr;
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
char *str = (char *)m_curptr;
|
|
||||||
|
|
||||||
if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
*len = real_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += real_len + 1;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *CDataPack::GetMemory() const
|
|
||||||
{
|
|
||||||
return m_curptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *CDataPack::ReadMemory(size_t *size) const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(size_t)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bytecount = *(size_t *)m_curptr;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
if (!IsReadable(bytecount))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ptr = m_curptr;
|
|
||||||
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
*size = bytecount;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += bytecount;
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
|
||||||
|
|
||||||
#include <IDataPack.h>
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class CDataPack : public IDataPack
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CDataPack();
|
|
||||||
~CDataPack();
|
|
||||||
public: //IDataReader
|
|
||||||
void Reset() const;
|
|
||||||
size_t GetPosition() const;
|
|
||||||
bool SetPosition(size_t pos) const;
|
|
||||||
cell_t ReadCell() const;
|
|
||||||
float ReadFloat() const;
|
|
||||||
bool IsReadable(size_t bytes) const;
|
|
||||||
const char *ReadString(size_t *len) const;
|
|
||||||
void *GetMemory() const;
|
|
||||||
void *ReadMemory(size_t *size) const;
|
|
||||||
public: //IDataPack
|
|
||||||
void ResetSize();
|
|
||||||
void PackCell(cell_t cell);
|
|
||||||
void PackFloat(float val);
|
|
||||||
void PackString(const char *string);
|
|
||||||
size_t CreateMemory(size_t size, void **addr);
|
|
||||||
public:
|
|
||||||
void Initialize();
|
|
||||||
private:
|
|
||||||
void CheckSize(size_t sizetype);
|
|
||||||
private:
|
|
||||||
char *m_pBase;
|
|
||||||
mutable char *m_curptr;
|
|
||||||
size_t m_capacity;
|
|
||||||
size_t m_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
|
||||||
191
core/CellArray.h
191
core/CellArray.h
@ -1,191 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
extern HandleType_t htCellArray;
|
|
||||||
|
|
||||||
class CellArray
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~CellArray()
|
|
||||||
{
|
|
||||||
free(m_Data);
|
|
||||||
}
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
cell_t *push()
|
|
||||||
{
|
|
||||||
if (!GrowIfNeeded(1))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
cell_t *arr = &m_Data[m_Size * m_BlockSize];
|
|
||||||
m_Size++;
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
cell_t *at(size_t b) const
|
|
||||||
{
|
|
||||||
return &m_Data[b * m_BlockSize];
|
|
||||||
}
|
|
||||||
size_t blocksize() const
|
|
||||||
{
|
|
||||||
return m_BlockSize;
|
|
||||||
}
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
m_Size = 0;
|
|
||||||
}
|
|
||||||
bool swap(size_t item1, size_t item2)
|
|
||||||
{
|
|
||||||
/* Make sure there is extra space available */
|
|
||||||
if (!GrowIfNeeded(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t *pri = at(item1);
|
|
||||||
cell_t *alt = at(item2);
|
|
||||||
|
|
||||||
/* Get our temporary array 1 after the limit */
|
|
||||||
cell_t *temp = &m_Data[m_Size * m_BlockSize];
|
|
||||||
|
|
||||||
memcpy(temp, pri, sizeof(cell_t) * m_BlockSize);
|
|
||||||
memcpy(pri, alt, sizeof(cell_t) * m_BlockSize);
|
|
||||||
memcpy(alt, temp, sizeof(cell_t) * m_BlockSize);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void remove(size_t index)
|
|
||||||
{
|
|
||||||
/* If we're at the end, take the easy way out */
|
|
||||||
if (index == m_Size - 1)
|
|
||||||
{
|
|
||||||
m_Size--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, it's time to move stuff! */
|
|
||||||
size_t remaining_indexes = (m_Size - 1) - index;
|
|
||||||
cell_t *src = at(index + 1);
|
|
||||||
cell_t *dest = at(index);
|
|
||||||
memmove(dest, src, sizeof(cell_t) * m_BlockSize * remaining_indexes);
|
|
||||||
|
|
||||||
m_Size--;
|
|
||||||
}
|
|
||||||
cell_t *insert_at(size_t index)
|
|
||||||
{
|
|
||||||
/* Make sure it'll fit */
|
|
||||||
if (!GrowIfNeeded(1))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* move everything up */
|
|
||||||
cell_t *src = at(index);
|
|
||||||
cell_t *dst = at(index + 1);
|
|
||||||
memmove(dst, src, sizeof(cell_t) * m_BlockSize * m_Size);
|
|
||||||
|
|
||||||
m_Size++;
|
|
||||||
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
bool resize(size_t count)
|
|
||||||
{
|
|
||||||
if (count <= m_Size)
|
|
||||||
{
|
|
||||||
m_Size = count;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!GrowIfNeeded(count - m_Size))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Size = count;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CellArray *clone()
|
|
||||||
{
|
|
||||||
CellArray *array = new CellArray(m_BlockSize);
|
|
||||||
array->m_AllocSize = m_AllocSize;
|
|
||||||
array->m_Size = m_Size;
|
|
||||||
array->m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
|
||||||
memcpy(array->m_Data, m_Data, sizeof(cell_t) * m_BlockSize * m_Size);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t *base()
|
|
||||||
{
|
|
||||||
return m_Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool GrowIfNeeded(size_t count)
|
|
||||||
{
|
|
||||||
/* Shortcut out if we can store this */
|
|
||||||
if (m_Size + count <= m_AllocSize)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/* Set a base allocation size of 8 items */
|
|
||||||
if (!m_AllocSize)
|
|
||||||
{
|
|
||||||
m_AllocSize = 8;
|
|
||||||
}
|
|
||||||
/* If it's not enough, keep doubling */
|
|
||||||
while (m_Size + count > m_AllocSize)
|
|
||||||
{
|
|
||||||
m_AllocSize *= 2;
|
|
||||||
}
|
|
||||||
/* finally, allocate the new block */
|
|
||||||
if (m_Data)
|
|
||||||
{
|
|
||||||
m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
|
||||||
} else {
|
|
||||||
m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
|
||||||
}
|
|
||||||
return (m_Data != NULL);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
cell_t *m_Data;
|
|
||||||
size_t m_BlockSize;
|
|
||||||
size_t m_AllocSize;
|
|
||||||
size_t m_Size;
|
|
||||||
};
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
|
|
||||||
|
|
||||||
#include <irecipientfilter.h>
|
|
||||||
#include <sp_vm_types.h>
|
|
||||||
|
|
||||||
class CellRecipientFilter : public IRecipientFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CellRecipientFilter() : m_IsReliable(false), m_IsInitMessage(false), m_Size(0) {}
|
|
||||||
~CellRecipientFilter() {}
|
|
||||||
public: //IRecipientFilter
|
|
||||||
bool IsReliable() const;
|
|
||||||
bool IsInitMessage() const;
|
|
||||||
int GetRecipientCount() const;
|
|
||||||
int GetRecipientIndex(int slot) const;
|
|
||||||
public:
|
|
||||||
void Initialize(const cell_t *ptr, size_t count);
|
|
||||||
void SetToReliable(bool isreliable);
|
|
||||||
void SetToInit(bool isinitmsg);
|
|
||||||
void Reset();
|
|
||||||
private:
|
|
||||||
cell_t m_Players[255];
|
|
||||||
bool m_IsReliable;
|
|
||||||
bool m_IsInitMessage;
|
|
||||||
size_t m_Size;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void CellRecipientFilter::Reset()
|
|
||||||
{
|
|
||||||
m_IsReliable = false;
|
|
||||||
m_IsInitMessage = false;
|
|
||||||
m_Size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool CellRecipientFilter::IsReliable() const
|
|
||||||
{
|
|
||||||
return m_IsReliable;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool CellRecipientFilter::IsInitMessage() const
|
|
||||||
{
|
|
||||||
return m_IsInitMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int CellRecipientFilter::GetRecipientCount() const
|
|
||||||
{
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
|
||||||
{
|
|
||||||
if ((slot < 0) || (slot >= GetRecipientCount()))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return static_cast<int>(m_Players[slot]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
|
||||||
{
|
|
||||||
m_IsInitMessage = isinitmsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CellRecipientFilter::SetToReliable(bool isreliable)
|
|
||||||
{
|
|
||||||
m_IsReliable = isreliable;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CellRecipientFilter::Initialize(const cell_t *ptr, size_t count)
|
|
||||||
{
|
|
||||||
memcpy(m_Players, ptr, count * sizeof(cell_t));
|
|
||||||
m_Size = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
|
|
||||||
@ -1,340 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include "ChatTriggers.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "ConCmdManager.h"
|
|
||||||
#include <IPlayerHelpers.h>
|
|
||||||
|
|
||||||
/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
|
|
||||||
* While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
|
|
||||||
* can technically be compiled against any MM:S version after 1.4.2.
|
|
||||||
*/
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
|
||||||
#else
|
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#if SH_IMPL_VERSION >= 5
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#elif SH_IMPL_VERSION == 4
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#elif SH_IMPL_VERSION == 3
|
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#endif //SH_IMPL_VERSION
|
|
||||||
#endif //ORANGEBOX_BUILD
|
|
||||||
|
|
||||||
ChatTriggers g_ChatTriggers;
|
|
||||||
|
|
||||||
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
|
|
||||||
m_bTriggerWasSilent(false), m_ReplyTo(SM_REPLY_CONSOLE)
|
|
||||||
{
|
|
||||||
m_PubTrigger = sm_strdup("!");
|
|
||||||
m_PrivTrigger = sm_strdup("/");
|
|
||||||
m_PubTriggerSize = 1;
|
|
||||||
m_PrivTriggerSize = 1;
|
|
||||||
m_bIsChatTrigger = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatTriggers::~ChatTriggers()
|
|
||||||
{
|
|
||||||
delete [] m_PubTrigger;
|
|
||||||
m_PubTrigger = NULL;
|
|
||||||
delete [] m_PrivTrigger;
|
|
||||||
m_PrivTrigger = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength)
|
|
||||||
{
|
|
||||||
if (strcmp(key, "PublicChatTrigger") == 0)
|
|
||||||
{
|
|
||||||
delete [] m_PubTrigger;
|
|
||||||
m_PubTrigger = sm_strdup(value);
|
|
||||||
m_PubTriggerSize = strlen(m_PubTrigger);
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
} else if (strcmp(key, "SilentChatTrigger") == 0) {
|
|
||||||
delete [] m_PrivTrigger;
|
|
||||||
m_PrivTrigger = sm_strdup(value);
|
|
||||||
m_PrivTriggerSize = strlen(m_PrivTrigger);
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModGameInitialized()
|
|
||||||
{
|
|
||||||
unsigned int total = 2;
|
|
||||||
ConCommandBase *pCmd = icvar->GetCommands();
|
|
||||||
const char *name;
|
|
||||||
while (pCmd)
|
|
||||||
{
|
|
||||||
if (pCmd->IsCommand())
|
|
||||||
{
|
|
||||||
name = pCmd->GetName();
|
|
||||||
if (!m_pSayCmd && strcmp(name, "say") == 0)
|
|
||||||
{
|
|
||||||
m_pSayCmd = (ConCommand *)pCmd;
|
|
||||||
if (--total == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (!m_pSayTeamCmd && strcmp(name, "say_team") == 0) {
|
|
||||||
m_pSayTeamCmd = (ConCommand *)pCmd;
|
|
||||||
if (--total == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pCmd = const_cast<ConCommandBase *>(pCmd->GetNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pSayCmd)
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
}
|
|
||||||
if (m_pSayTeamCmd)
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
if (m_pSayTeamCmd)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
|
||||||
}
|
|
||||||
if (m_pSayCmd)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
|
|
||||||
{
|
|
||||||
#else
|
|
||||||
void ChatTriggers::OnSayCommand_Pre()
|
|
||||||
{
|
|
||||||
CCommand command;
|
|
||||||
#endif
|
|
||||||
int client = g_ConCmds.GetCommandClient();
|
|
||||||
m_bIsChatTrigger = false;
|
|
||||||
|
|
||||||
/* The server console cannot do this */
|
|
||||||
if (client == 0)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *args = command.ArgS();
|
|
||||||
|
|
||||||
if (!args)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle quoted string sets */
|
|
||||||
bool is_quoted = false;
|
|
||||||
if (args[0] == '"')
|
|
||||||
{
|
|
||||||
args++;
|
|
||||||
is_quoted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_trigger = false;
|
|
||||||
bool is_silent = false;
|
|
||||||
|
|
||||||
/* Check for either trigger */
|
|
||||||
if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
|
|
||||||
{
|
|
||||||
is_trigger = true;
|
|
||||||
args = &args[m_PubTriggerSize];
|
|
||||||
} else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0) {
|
|
||||||
is_trigger = true;
|
|
||||||
is_silent = true;
|
|
||||||
args = &args[m_PrivTriggerSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_trigger)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if this is actually a command!
|
|
||||||
*/
|
|
||||||
if (!PreProcessTrigger(engine->PEntityOfEntIndex(client), args, is_quoted))
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bIsChatTrigger = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We'll execute it in post.
|
|
||||||
*/
|
|
||||||
m_bWillProcessInPost = true;
|
|
||||||
m_bTriggerWasSilent = is_silent;
|
|
||||||
|
|
||||||
/* If we're silent, block */
|
|
||||||
if (is_silent)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, let the command continue */
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
|
||||||
#else
|
|
||||||
void ChatTriggers::OnSayCommand_Post()
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
m_bIsChatTrigger = false;
|
|
||||||
if (m_bWillProcessInPost)
|
|
||||||
{
|
|
||||||
/* Reset this for re-entrancy */
|
|
||||||
m_bWillProcessInPost = false;
|
|
||||||
|
|
||||||
/* Execute the cached command */
|
|
||||||
int client = g_ConCmds.GetCommandClient();
|
|
||||||
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
|
||||||
serverpluginhelpers->ClientCommand(engine->PEntityOfEntIndex(client), m_ToExecute);
|
|
||||||
SetReplyTo(old);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
|
|
||||||
{
|
|
||||||
/* Extract a command. This is kind of sloppy. */
|
|
||||||
char cmd_buf[64];
|
|
||||||
size_t cmd_len = 0;
|
|
||||||
const char *inptr = args;
|
|
||||||
while (*inptr != '\0'
|
|
||||||
&& !textparsers->IsWhitespace(inptr)
|
|
||||||
&& *inptr != '"'
|
|
||||||
&& cmd_len < sizeof(cmd_buf) - 1)
|
|
||||||
{
|
|
||||||
cmd_buf[cmd_len++] = *inptr++;
|
|
||||||
}
|
|
||||||
cmd_buf[cmd_len] = '\0';
|
|
||||||
|
|
||||||
if (cmd_len == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if we have this registered */
|
|
||||||
bool prepended = false;
|
|
||||||
if (!g_ConCmds.LookForSourceModCommand(cmd_buf))
|
|
||||||
{
|
|
||||||
/* Check if we had an "sm_" prefix */
|
|
||||||
if (strncmp(cmd_buf, "sm_", 3) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now, prepend. Don't worry about the buffers. This will
|
|
||||||
* work because the sizes are limited from earlier.
|
|
||||||
*/
|
|
||||||
char new_buf[80];
|
|
||||||
strcpy(new_buf, "sm_");
|
|
||||||
strncopy(&new_buf[3], cmd_buf, sizeof(new_buf)-3);
|
|
||||||
|
|
||||||
/* Recheck */
|
|
||||||
if (!g_ConCmds.LookForSourceModCommand(new_buf))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
prepended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if we need to do extra string manipulation */
|
|
||||||
if (is_quoted || prepended)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/* Check if we need to prepend sm_ */
|
|
||||||
if (prepended)
|
|
||||||
{
|
|
||||||
len = UTIL_Format(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
|
|
||||||
} else {
|
|
||||||
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we need to strip a quote */
|
|
||||||
if (is_quoted)
|
|
||||||
{
|
|
||||||
if (m_ToExecute[len-1] == '"')
|
|
||||||
{
|
|
||||||
m_ToExecute[--len] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
|
|
||||||
{
|
|
||||||
unsigned int old = m_ReplyTo;
|
|
||||||
|
|
||||||
m_ReplyTo = reply;
|
|
||||||
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ChatTriggers::GetReplyTo()
|
|
||||||
{
|
|
||||||
return m_ReplyTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatTriggers::IsChatTrigger()
|
|
||||||
{
|
|
||||||
return m_bIsChatTrigger;
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CHAT_TRIGGERS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CHAT_TRIGGERS_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include <IGameHelpers.h>
|
|
||||||
#include <compat_wrappers.h>
|
|
||||||
|
|
||||||
class ChatTriggers : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ChatTriggers();
|
|
||||||
~ChatTriggers();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModGameInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength);
|
|
||||||
private: //ConCommand
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void OnSayCommand_Pre(const CCommand &command);
|
|
||||||
void OnSayCommand_Post(const CCommand &command);
|
|
||||||
#else
|
|
||||||
void OnSayCommand_Pre();
|
|
||||||
void OnSayCommand_Post();
|
|
||||||
#endif
|
|
||||||
public:
|
|
||||||
unsigned int GetReplyTo();
|
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
|
||||||
bool IsChatTrigger();
|
|
||||||
private:
|
|
||||||
bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
|
|
||||||
private:
|
|
||||||
ConCommand *m_pSayCmd;
|
|
||||||
ConCommand *m_pSayTeamCmd;
|
|
||||||
char *m_PubTrigger;
|
|
||||||
size_t m_PubTriggerSize;
|
|
||||||
char *m_PrivTrigger;
|
|
||||||
size_t m_PrivTriggerSize;
|
|
||||||
bool m_bWillProcessInPost;
|
|
||||||
bool m_bTriggerWasSilent;
|
|
||||||
bool m_bIsChatTrigger;
|
|
||||||
unsigned int m_ReplyTo;
|
|
||||||
char m_ToExecute[300];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ChatTriggers g_ChatTriggers;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CHAT_TRIGGERS_H_
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,161 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <IRootConsoleMenu.h>
|
|
||||||
#include <IAdminSystem.h>
|
|
||||||
#include "concmd_cleaner.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
enum CmdType
|
|
||||||
{
|
|
||||||
Cmd_Server,
|
|
||||||
Cmd_Console,
|
|
||||||
Cmd_Admin,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AdminCmdInfo
|
|
||||||
{
|
|
||||||
AdminCmdInfo()
|
|
||||||
{
|
|
||||||
cmdGrpId = -1;
|
|
||||||
flags = 0;
|
|
||||||
eflags = 0;
|
|
||||||
}
|
|
||||||
int cmdGrpId; /* index into cmdgroup string table */
|
|
||||||
FlagBits flags; /* default flags */
|
|
||||||
FlagBits eflags; /* effective flags */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CmdHook
|
|
||||||
{
|
|
||||||
CmdHook()
|
|
||||||
{
|
|
||||||
pf = NULL;
|
|
||||||
pAdmin = NULL;
|
|
||||||
}
|
|
||||||
IPluginFunction *pf; /* function hook */
|
|
||||||
String helptext; /* help text */
|
|
||||||
AdminCmdInfo *pAdmin; /* admin requirements, if any */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ConCmdInfo
|
|
||||||
{
|
|
||||||
ConCmdInfo()
|
|
||||||
{
|
|
||||||
sourceMod = false;
|
|
||||||
pCmd = NULL;
|
|
||||||
}
|
|
||||||
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
|
||||||
ConCommand *pCmd; /**< Pointer to the command itself */
|
|
||||||
List<CmdHook *> srvhooks; /**< Hooks as a server command */
|
|
||||||
List<CmdHook *> conhooks; /**< Hooks as a console command */
|
|
||||||
AdminCmdInfo admin; /**< Admin info, if any */
|
|
||||||
bool is_admin_set; /**< Whether or not admin info is set */
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConCmdManager :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IRootConsoleCommand,
|
|
||||||
public IPluginsListener,
|
|
||||||
public IConCommandTracker
|
|
||||||
{
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
friend void CommandCallback(const CCommand &command);
|
|
||||||
#else
|
|
||||||
friend void CommandCallback();
|
|
||||||
#endif
|
|
||||||
public:
|
|
||||||
ConCmdManager();
|
|
||||||
~ConCmdManager();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: //IPluginsListener
|
|
||||||
void OnPluginDestroyed(IPlugin *plugin);
|
|
||||||
public: //IRootConsoleCommand
|
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
|
||||||
public: //IConCommandTracker
|
|
||||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
|
||||||
public:
|
|
||||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
|
||||||
bool AddConsoleCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
|
||||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
|
||||||
const char *name,
|
|
||||||
const char *group,
|
|
||||||
int adminflags,
|
|
||||||
const char *description,
|
|
||||||
int flags);
|
|
||||||
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
|
|
||||||
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
|
||||||
bool LookForSourceModCommand(const char *cmd);
|
|
||||||
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
|
|
||||||
bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
|
|
||||||
private:
|
|
||||||
void InternalDispatch(const CCommand &command);
|
|
||||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
|
||||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
|
|
||||||
void SetCommandClient(int client);
|
|
||||||
void AddToCmdList(ConCmdInfo *info);
|
|
||||||
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
|
|
||||||
void RemoveConCmds(List<CmdHook *> &cmdlist);
|
|
||||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
|
||||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
|
||||||
public:
|
|
||||||
inline int GetCommandClient()
|
|
||||||
{
|
|
||||||
return m_CmdClient;
|
|
||||||
}
|
|
||||||
inline const List<ConCmdInfo *> & GetCommandList()
|
|
||||||
{
|
|
||||||
return m_CmdList;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
Trie *m_pCmds; /* command lookup */
|
|
||||||
Trie *m_pCmdGrps; /* command group lookup */
|
|
||||||
List<ConCmdInfo *> m_CmdList; /* command list */
|
|
||||||
int m_CmdClient; /* current client */
|
|
||||||
BaseStringTable m_Strings; /* string table */
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ConCmdManager g_ConCmds;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
|
||||||
@ -1,823 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ConVarManager.h"
|
|
||||||
#include "HalfLife2.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include <sm_trie_tpl.h>
|
|
||||||
|
|
||||||
ConVarManager g_ConVarManager;
|
|
||||||
|
|
||||||
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
|
|
||||||
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
|
||||||
typedef List<const ConVar *> ConVarList;
|
|
||||||
KTrie<ConVarInfo *> convar_cache;
|
|
||||||
|
|
||||||
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ConVarManager::~ConVarManager()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Episode 2 has this function by default, but the older versions do not.
|
|
||||||
*/
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
|
||||||
if (g_SMAPI->GetGameDLLVersion() >= 6)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsDLLQueryHooked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleAccess sec;
|
|
||||||
|
|
||||||
/* Set up access rights for the 'ConVar' handle type */
|
|
||||||
sec.access[HandleAccess_Read] = 0;
|
|
||||||
sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
|
||||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
|
||||||
|
|
||||||
/* Create the 'ConVar' handle type */
|
|
||||||
m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
|
||||||
|
|
||||||
/* Add the 'convars' option to the 'sm' console command */
|
|
||||||
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
List<ConVarInfo *>::iterator iter = m_ConVars.begin();
|
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
|
||||||
|
|
||||||
/* Iterate list of ConVarInfo structures, remove every one of them */
|
|
||||||
while (iter != m_ConVars.end())
|
|
||||||
{
|
|
||||||
ConVarInfo *pInfo = (*iter);
|
|
||||||
|
|
||||||
iter = m_ConVars.erase(iter);
|
|
||||||
|
|
||||||
g_HandleSys.FreeHandle(pInfo->handle, &sec);
|
|
||||||
if (pInfo->pChangeForward != NULL)
|
|
||||||
{
|
|
||||||
g_Forwards.ReleaseForward(pInfo->pChangeForward);
|
|
||||||
}
|
|
||||||
if (pInfo->sourceMod)
|
|
||||||
{
|
|
||||||
/* If we created it, we won't be tracking it, therefore it is
|
|
||||||
* safe to remove everything in one go.
|
|
||||||
*/
|
|
||||||
META_UNREGCVAR(pInfo->pVar);
|
|
||||||
delete [] pInfo->pVar->GetName();
|
|
||||||
delete [] pInfo->pVar->GetHelpText();
|
|
||||||
delete [] pInfo->pVar->GetDefault();
|
|
||||||
delete pInfo->pVar;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If we didn't create it, we might be tracking it. Also,
|
|
||||||
* it could be unreadable.
|
|
||||||
*/
|
|
||||||
UntrackConCommandBase(pInfo->pVar, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* It's not safe to read the name here, so we simply delete the
|
|
||||||
* the info struct and clear the lookup cache at the end.
|
|
||||||
*/
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
convar_cache.clear();
|
|
||||||
|
|
||||||
/* Unhook things */
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsDLLQueryHooked = false;
|
|
||||||
}
|
|
||||||
else if (m_bIsVSPQueryHooked)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsVSPQueryHooked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the 'convars' option from the 'sm' console command */
|
|
||||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
|
||||||
|
|
||||||
/* Remove the 'ConVar' handle type */
|
|
||||||
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Orange Box will never use this.
|
|
||||||
*/
|
|
||||||
void ConVarManager::OnSourceModVSPReceived()
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Don't bother if the DLL is already hooked.
|
|
||||||
*/
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For later MM:S versions, use the updated API, since it's cleaner. */
|
|
||||||
#if defined METAMOD_PLAPI_VERSION
|
|
||||||
int engine = g_SMAPI->GetSourceEngineBuild();
|
|
||||||
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (g_HL2.IsOriginalEngine() || vsp_version < 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsVSPQueryHooked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
|
||||||
{
|
|
||||||
ConVarInfo **pLookup = convar_cache.retrieve(name);
|
|
||||||
if (pLookup != NULL)
|
|
||||||
{
|
|
||||||
*pVar = *pLookup;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
|
|
||||||
{
|
|
||||||
/* Only check convars that have not been created by SourceMod's core */
|
|
||||||
ConVarInfo *pInfo;
|
|
||||||
if (!convar_cache_lookup(name, &pInfo))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
|
||||||
|
|
||||||
/* Remove it from our cache */
|
|
||||||
m_ConVars.remove(pInfo);
|
|
||||||
convar_cache.remove(name);
|
|
||||||
|
|
||||||
/* Now make sure no plugins are referring to this pointer */
|
|
||||||
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
|
|
||||||
while (pl_iter->MorePlugins())
|
|
||||||
{
|
|
||||||
IPlugin *pl = pl_iter->GetPlugin();
|
|
||||||
|
|
||||||
ConVarList *pConVarList;
|
|
||||||
if (pl->GetProperty("ConVarList", (void **)&pConVarList, true)
|
|
||||||
&& pConVarList != NULL)
|
|
||||||
{
|
|
||||||
pConVarList->remove(pInfo->pVar);
|
|
||||||
}
|
|
||||||
|
|
||||||
pl_iter->NextPlugin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free resources */
|
|
||||||
g_HandleSys.FreeHandle(pInfo->handle, &sec);
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
|
||||||
{
|
|
||||||
ConVarList *pConVarList;
|
|
||||||
|
|
||||||
/* If plugin has a convar list, free its memory */
|
|
||||||
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
|
||||||
{
|
|
||||||
delete pConVarList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
|
||||||
{
|
|
||||||
int argcount = command.ArgC();
|
|
||||||
if (argcount >= 3)
|
|
||||||
{
|
|
||||||
/* Get plugin index that was passed */
|
|
||||||
int id = atoi(command.Arg(2));
|
|
||||||
|
|
||||||
/* Get plugin object */
|
|
||||||
CPlugin *plugin = g_PluginSys.GetPluginByOrder(id);
|
|
||||||
|
|
||||||
if (!plugin)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get plugin name */
|
|
||||||
const sm_plugininfo_t *plinfo = plugin->GetPublicInfo();
|
|
||||||
const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename();
|
|
||||||
|
|
||||||
ConVarList *pConVarList;
|
|
||||||
ConVarList::iterator iter;
|
|
||||||
|
|
||||||
/* If no convar list... */
|
|
||||||
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
|
||||||
|
|
||||||
/* Iterate convar list and display each one */
|
|
||||||
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
|
||||||
{
|
|
||||||
const ConVar *pConVar = (*iter);
|
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display usage of subcommand */
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max)
|
|
||||||
{
|
|
||||||
ConVar *pConVar = NULL;
|
|
||||||
ConVarInfo *pInfo = NULL;
|
|
||||||
Handle_t hndl = 0;
|
|
||||||
|
|
||||||
/* Find out if the convar exists already */
|
|
||||||
pConVar = icvar->FindVar(name);
|
|
||||||
|
|
||||||
/* If the convar already exists... */
|
|
||||||
if (pConVar)
|
|
||||||
{
|
|
||||||
/* Add convar to plugin's list */
|
|
||||||
AddConVarToPluginList(pContext, pConVar);
|
|
||||||
|
|
||||||
/* First find out if we already have a handle to it */
|
|
||||||
if (convar_cache_lookup(name, &pInfo))
|
|
||||||
{
|
|
||||||
return pInfo->handle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Create and initialize ConVarInfo structure */
|
|
||||||
pInfo = new ConVarInfo();
|
|
||||||
pInfo->sourceMod = false;
|
|
||||||
pInfo->pChangeForward = NULL;
|
|
||||||
pInfo->origCallback = pConVar->GetCallback();
|
|
||||||
pInfo->pVar = pConVar;
|
|
||||||
|
|
||||||
/* If we don't, then create a new handle from the convar */
|
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
|
||||||
if (hndl == BAD_HANDLE)
|
|
||||||
{
|
|
||||||
delete pInfo;
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->handle = hndl;
|
|
||||||
|
|
||||||
/* Insert struct into caches */
|
|
||||||
m_ConVars.push_back(pInfo);
|
|
||||||
convar_cache.insert(name, pInfo);
|
|
||||||
TrackConCommandBase(pConVar, this);
|
|
||||||
|
|
||||||
return hndl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To prevent creating a convar that has the same name as a console command... ugh */
|
|
||||||
ConCommandBase *pBase = icvar->GetCommands();
|
|
||||||
|
|
||||||
while (pBase)
|
|
||||||
{
|
|
||||||
if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
|
|
||||||
{
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create and initialize ConVarInfo structure */
|
|
||||||
pInfo = new ConVarInfo();
|
|
||||||
pInfo->handle = hndl;
|
|
||||||
pInfo->sourceMod = true;
|
|
||||||
pInfo->pChangeForward = NULL;
|
|
||||||
pInfo->origCallback = NULL;
|
|
||||||
|
|
||||||
/* Create a handle from the new convar */
|
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
|
||||||
if (hndl == BAD_HANDLE)
|
|
||||||
{
|
|
||||||
delete pInfo;
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->handle = hndl;
|
|
||||||
|
|
||||||
/* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
|
|
||||||
pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
|
|
||||||
pInfo->pVar = pConVar;
|
|
||||||
|
|
||||||
/* Add convar to plugin's list */
|
|
||||||
AddConVarToPluginList(pContext, pConVar);
|
|
||||||
|
|
||||||
/* Insert struct into caches */
|
|
||||||
m_ConVars.push_back(pInfo);
|
|
||||||
convar_cache.insert(name, pInfo);
|
|
||||||
|
|
||||||
return hndl;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t ConVarManager::FindConVar(const char *name)
|
|
||||||
{
|
|
||||||
ConVar *pConVar = NULL;
|
|
||||||
ConVarInfo *pInfo;
|
|
||||||
Handle_t hndl;
|
|
||||||
|
|
||||||
/* Search for convar */
|
|
||||||
pConVar = icvar->FindVar(name);
|
|
||||||
|
|
||||||
/* If it doesn't exist, then return an invalid handle */
|
|
||||||
if (!pConVar)
|
|
||||||
{
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At this point, the convar exists. So, find out if we already have a handle */
|
|
||||||
if (convar_cache_lookup(name, &pInfo))
|
|
||||||
{
|
|
||||||
return pInfo->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create and initialize ConVarInfo structure */
|
|
||||||
pInfo = new ConVarInfo();
|
|
||||||
pInfo->sourceMod = false;
|
|
||||||
pInfo->pChangeForward = NULL;
|
|
||||||
pInfo->origCallback = pConVar->GetCallback();
|
|
||||||
pInfo->pVar = pConVar;
|
|
||||||
|
|
||||||
/* If we don't have a handle, then create a new one */
|
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
|
||||||
if (hndl == BAD_HANDLE)
|
|
||||||
{
|
|
||||||
delete pInfo;
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->handle = hndl;
|
|
||||||
|
|
||||||
/* Insert struct into our caches */
|
|
||||||
m_ConVars.push_back(pInfo);
|
|
||||||
convar_cache.insert(name, pInfo);
|
|
||||||
TrackConCommandBase(pConVar, this);
|
|
||||||
|
|
||||||
return hndl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
|
|
||||||
{
|
|
||||||
ConVarInfo *pInfo;
|
|
||||||
IChangeableForward *pForward;
|
|
||||||
|
|
||||||
/* Find the convar in the lookup trie */
|
|
||||||
if (convar_cache_lookup(pConVar->GetName(), &pInfo))
|
|
||||||
{
|
|
||||||
/* Get the forward */
|
|
||||||
pForward = pInfo->pChangeForward;
|
|
||||||
|
|
||||||
/* If forward does not exist, create it */
|
|
||||||
if (!pForward)
|
|
||||||
{
|
|
||||||
pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
|
|
||||||
pInfo->pChangeForward = pForward;
|
|
||||||
|
|
||||||
/* Install our own callback */
|
|
||||||
pConVar->InstallChangeCallback(OnConVarChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add function to forward's list */
|
|
||||||
pForward->AddFunction(pFunction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
|
|
||||||
{
|
|
||||||
ConVarInfo *pInfo;
|
|
||||||
IChangeableForward *pForward;
|
|
||||||
IPluginContext *pContext = pFunction->GetParentContext();
|
|
||||||
|
|
||||||
/* Find the convar in the lookup trie */
|
|
||||||
if (convar_cache_lookup(pConVar->GetName(), &pInfo))
|
|
||||||
{
|
|
||||||
/* Get the forward */
|
|
||||||
pForward = pInfo->pChangeForward;
|
|
||||||
|
|
||||||
/* If the forward doesn't exist, we can't unhook anything */
|
|
||||||
if (!pForward)
|
|
||||||
{
|
|
||||||
pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the function from the forward's list */
|
|
||||||
if (!pForward->RemoveFunction(pFunction))
|
|
||||||
{
|
|
||||||
pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the forward now has 0 functions in it... */
|
|
||||||
if (pForward->GetFunctionCount() == 0)
|
|
||||||
{
|
|
||||||
/* Free this forward */
|
|
||||||
g_Forwards.ReleaseForward(pForward);
|
|
||||||
pInfo->pChangeForward = NULL;
|
|
||||||
|
|
||||||
/* Put back the original convar callback */
|
|
||||||
pConVar->InstallChangeCallback(pInfo->origCallback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
|
|
||||||
{
|
|
||||||
QueryCvarCookie_t cookie;
|
|
||||||
|
|
||||||
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
cookie = engine->StartQueryCvarValue(pPlayer, name);
|
|
||||||
}
|
|
||||||
else if (m_bIsVSPQueryHooked)
|
|
||||||
{
|
|
||||||
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return InvalidQueryCvarCookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConVarQuery query = {cookie, pCallback, hndl};
|
|
||||||
m_ConVarQueries.push_back(query);
|
|
||||||
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar)
|
|
||||||
{
|
|
||||||
ConVarList *pConVarList;
|
|
||||||
ConVarList::iterator iter;
|
|
||||||
bool inserted = false;
|
|
||||||
const char *orig = pConVar->GetName();
|
|
||||||
|
|
||||||
IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
|
||||||
|
|
||||||
/* Check plugin for an existing convar list */
|
|
||||||
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
|
||||||
{
|
|
||||||
pConVarList = new ConVarList();
|
|
||||||
plugin->SetProperty("ConVarList", pConVarList);
|
|
||||||
}
|
|
||||||
else if (pConVarList->find(pConVar) != pConVarList->end())
|
|
||||||
{
|
|
||||||
/* If convar is already in list, then don't add it */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert convar into list which is sorted alphabetically */
|
|
||||||
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
|
||||||
{
|
|
||||||
if (strcmp(orig, (*iter)->GetName()) < 0)
|
|
||||||
{
|
|
||||||
pConVarList->insert(iter, pConVar);
|
|
||||||
inserted = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!inserted)
|
|
||||||
{
|
|
||||||
pConVarList->push_back(pConVar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void ConVarManager::OnConVarChanged(IConVar *pIConVar, const char *oldValue, float flOldValue)
|
|
||||||
#else
|
|
||||||
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* If the values are the same, exit early in order to not trigger callbacks */
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
ConVar *pConVar = (ConVar *)pIConVar;
|
|
||||||
#endif
|
|
||||||
if (strcmp(pConVar->GetString(), oldValue) == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConVarInfo *pInfo;
|
|
||||||
|
|
||||||
/* Find the convar in the lookup trie */
|
|
||||||
if (!convar_cache_lookup(pConVar->GetName(), &pInfo))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FnChangeCallback_t origCallback = pInfo->origCallback;
|
|
||||||
IChangeableForward *pForward = pInfo->pChangeForward;
|
|
||||||
|
|
||||||
/* If there was a change callback installed previously, call it */
|
|
||||||
if (origCallback)
|
|
||||||
{
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
origCallback(pConVar, oldValue, flOldValue);
|
|
||||||
#else
|
|
||||||
origCallback(pConVar, oldValue);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now call forwards in plugins that have hooked this */
|
|
||||||
pForward->PushCell(pInfo->handle);
|
|
||||||
pForward->PushString(oldValue);
|
|
||||||
pForward->PushString(reinterpret_cast<ConVar *>(pConVar)->GetString());
|
|
||||||
pForward->Execute(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConVarManager::IsQueryingSupported()
|
|
||||||
{
|
|
||||||
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
|
||||||
{
|
|
||||||
IPluginFunction *pCallback = NULL;
|
|
||||||
cell_t value = 0;
|
|
||||||
List<ConVarQuery>::iterator iter;
|
|
||||||
|
|
||||||
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
|
|
||||||
{
|
|
||||||
ConVarQuery &query = (*iter);
|
|
||||||
if (query.cookie == cookie)
|
|
||||||
{
|
|
||||||
pCallback = query.pCallback;
|
|
||||||
value = query.value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCallback)
|
|
||||||
{
|
|
||||||
cell_t ret;
|
|
||||||
|
|
||||||
pCallback->PushCell(cookie);
|
|
||||||
pCallback->PushCell(engine->IndexOfEdict(pPlayer));
|
|
||||||
pCallback->PushCell(result);
|
|
||||||
pCallback->PushString(cvarName);
|
|
||||||
|
|
||||||
if (result == eQueryCvarValueStatus_ValueIntact)
|
|
||||||
{
|
|
||||||
pCallback->PushString(cvarValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pCallback->PushString("\0");
|
|
||||||
}
|
|
||||||
|
|
||||||
pCallback->PushCell(value);
|
|
||||||
pCallback->Execute(&ret);
|
|
||||||
|
|
||||||
m_ConVarQueries.erase(iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
|
|
||||||
{
|
|
||||||
ConVarInfo *pInfo;
|
|
||||||
HandleError error;
|
|
||||||
|
|
||||||
if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
|
|
||||||
{
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pVar)
|
|
||||||
{
|
|
||||||
*pVar = pInfo->pVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_YamagramState = 0;
|
|
||||||
|
|
||||||
void _YamagramPrinterTwoPointOhOh(int yamagram)
|
|
||||||
{
|
|
||||||
switch (yamagram)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
g_RootMenu.ConsolePrint("Answer the following questions correctly and Gaben may not eat you after all.");
|
|
||||||
g_RootMenu.ConsolePrint("You will be given one hint in the form of my patented yamagrams.");
|
|
||||||
g_RootMenu.ConsolePrint("Type sm_nana to see the last question.");
|
|
||||||
g_RootMenu.ConsolePrint("Type sm_nana <answer> to attempt an answer of the question.");
|
|
||||||
g_RootMenu.ConsolePrint("-------------------------------");
|
|
||||||
_YamagramPrinterTwoPointOhOh(1);
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
g_RootMenu.ConsolePrint("Question Ichi (1)");
|
|
||||||
g_RootMenu.ConsolePrint("One can turn into a cow by doing what action?");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: AGE SANS GRIT");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
g_RootMenu.ConsolePrint("Question Ni (2)");
|
|
||||||
g_RootMenu.ConsolePrint("What kind of hat should you wear when using the Internet?");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: BRR MOOSE");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
g_RootMenu.ConsolePrint("Question San (3)");
|
|
||||||
g_RootMenu.ConsolePrint("Who is the lead developer of SourceMod?");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: VEAL BANDANA DID RIP SOON");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
g_RootMenu.ConsolePrint("Question Yon (4)");
|
|
||||||
g_RootMenu.ConsolePrint("A terrible translation of 'SVN Revision' to Japanese romaji might be ...");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: I TAKE IN AN AIR OK");
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
g_RootMenu.ConsolePrint("Question Go (5)");
|
|
||||||
g_RootMenu.ConsolePrint("What is a fundamental concept in the game of Go?");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: AD LADEN THIEF");
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
g_RootMenu.ConsolePrint("Question Roku (6)");
|
|
||||||
g_RootMenu.ConsolePrint("Why am I asking all these strange questions?");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: CHUBBY TITAN EATS EWE WAGE DATA");
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
g_RootMenu.ConsolePrint("Question Nana (7)");
|
|
||||||
g_RootMenu.ConsolePrint("What is my name?");
|
|
||||||
g_RootMenu.ConsolePrint("Hint: AD MODE LAG US");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_YamagramState = yamagram;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void _IntExt_CallYamagrams(const CCommand &cmd)
|
|
||||||
{
|
|
||||||
#else
|
|
||||||
void _IntExt_CallYamagrams()
|
|
||||||
{
|
|
||||||
CCommand cmd;
|
|
||||||
#endif
|
|
||||||
bool correct = false;
|
|
||||||
const char *arg = cmd.ArgS();
|
|
||||||
|
|
||||||
if (!arg || arg[0] == '\0')
|
|
||||||
{
|
|
||||||
_YamagramPrinterTwoPointOhOh(s_YamagramState);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (s_YamagramState)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
correct = !strcasecmp(arg, "eating grass");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
correct = !strcasecmp(arg, "sombrero");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
correct = !strcasecmp(arg, "david bailopan anderson");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
correct = !strcasecmp(arg, "kaitei no kairan");
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
correct = !strcasecmp(arg, "life and death");
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
correct = !strcasecmp(arg, "because gabe wanted it that way");
|
|
||||||
if (correct)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("Congratulations, you have answered 6 of my questions.");
|
|
||||||
g_RootMenu.ConsolePrint("However, I have one final question for you. It wouldn't be nana without it.");
|
|
||||||
g_RootMenu.ConsolePrint("-------------------------------");
|
|
||||||
_YamagramPrinterTwoPointOhOh(7);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
correct = !strcasecmp(arg, "damaged soul");
|
|
||||||
if (correct)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("You don't know how lucky you are to still be alive!");
|
|
||||||
g_RootMenu.ConsolePrint("Congratulations. You have answered all 7 questions correctly.");
|
|
||||||
g_RootMenu.ConsolePrint("The SourceMod Dev Team will be at your door with anti-Gaben grenades");
|
|
||||||
g_RootMenu.ConsolePrint("within seconds. You will also be provided with a rocket launcher,");
|
|
||||||
g_RootMenu.ConsolePrint("just in case Alfred decides to strike you with a blitzkrieg in retaliation.");
|
|
||||||
|
|
||||||
s_YamagramState = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_YamagramState > 0)
|
|
||||||
{
|
|
||||||
if (correct)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("Correct! You are one step closer to avoiding the deadly jaws of Gaben.");
|
|
||||||
g_RootMenu.ConsolePrint("-------------------------------");
|
|
||||||
s_YamagramState++;
|
|
||||||
} else {
|
|
||||||
g_RootMenu.ConsolePrint("Wrong! You better be more careful. Gaben may be at your door at any minute.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_YamagramPrinterTwoPointOhOh(s_YamagramState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _IntExt_EnableYamagrams()
|
|
||||||
{
|
|
||||||
static ConCommand *pCmd = NULL;
|
|
||||||
if (!pCmd)
|
|
||||||
{
|
|
||||||
pCmd = new ConCommand("sm_nana", _IntExt_CallYamagrams, "Try these yamagrams!", FCVAR_GAMEDLL);
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Warning: Gaben has been alerted of your actions. You may be eaten.");
|
|
||||||
} else {
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Gaben has already been alerted of your actions...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void _IntExt_OnHostnameChanged(IConVar *pConVar, const char *oldValue, float flOldValue)
|
|
||||||
#else
|
|
||||||
void _IntExt_OnHostnameChanged(ConVar *pConVar, char const *oldValue)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (strcmp(oldValue, "Good morning, DS-san.") == 0
|
|
||||||
&& strcmp(reinterpret_cast<ConVar *>(pConVar)->GetString(), "Good night, talking desk lamp.") == 0)
|
|
||||||
{
|
|
||||||
_IntExt_EnableYamagrams();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,154 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CONVARMANAGER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CONVARMANAGER_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <IPluginSys.h>
|
|
||||||
#include <IForwardSys.h>
|
|
||||||
#include <IHandleSys.h>
|
|
||||||
#include <IRootConsoleMenu.h>
|
|
||||||
#include <compat_wrappers.h>
|
|
||||||
#include "concmd_cleaner.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds SourceMod-specific information about a convar
|
|
||||||
*/
|
|
||||||
struct ConVarInfo
|
|
||||||
{
|
|
||||||
Handle_t handle; /**< Handle to self */
|
|
||||||
bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
|
|
||||||
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
|
||||||
FnChangeCallback_t origCallback; /**< The original callback function */
|
|
||||||
ConVar *pVar; /**< The actual convar */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds information about a client convar query
|
|
||||||
*/
|
|
||||||
struct ConVarQuery
|
|
||||||
{
|
|
||||||
QueryCvarCookie_t cookie; /**< Cookie that identifies query */
|
|
||||||
IPluginFunction *pCallback; /**< Function that will be called when query is finished */
|
|
||||||
cell_t value; /**< Optional value passed to query function */
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConVarManager :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IHandleTypeDispatch,
|
|
||||||
public IPluginsListener,
|
|
||||||
public IRootConsoleCommand,
|
|
||||||
public IConCommandTracker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConVarManager();
|
|
||||||
~ConVarManager();
|
|
||||||
public: // SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
void OnSourceModVSPReceived();
|
|
||||||
public: // IHandleTypeDispatch
|
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
|
||||||
public: // IPluginsListener
|
|
||||||
void OnPluginUnloaded(IPlugin *plugin);
|
|
||||||
public: //IRootConsoleCommand
|
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
|
||||||
public: //IConCommandTracker
|
|
||||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a convar and return a handle to it.
|
|
||||||
*/
|
|
||||||
Handle_t CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal,
|
|
||||||
const char *description, int flags, bool hasMin, float min, bool hasMax, float max);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Searches for a convar and returns a handle to it
|
|
||||||
*/
|
|
||||||
Handle_t FindConVar(const char* name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a function to call when the specified convar changes.
|
|
||||||
*/
|
|
||||||
void HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a function from the forward that will be called when the specified convar changes.
|
|
||||||
*/
|
|
||||||
void UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a query to find the value of a client convar.
|
|
||||||
*/
|
|
||||||
QueryCvarCookie_t QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback,
|
|
||||||
Handle_t hndl);
|
|
||||||
|
|
||||||
bool IsQueryingSupported();
|
|
||||||
|
|
||||||
HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Adds a convar to a plugin's list.
|
|
||||||
*/
|
|
||||||
static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static callback that Valve's ConVar object executes when the convar's value changes.
|
|
||||||
*/
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
static void OnConVarChanged(IConVar *pConVar, const char *oldValue, float flOldValue);
|
|
||||||
#else
|
|
||||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for when StartQueryCvarValue() has finished.
|
|
||||||
*/
|
|
||||||
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
|
|
||||||
const char *cvarName, const char *cvarValue);
|
|
||||||
private:
|
|
||||||
HandleType_t m_ConVarType;
|
|
||||||
List<ConVarInfo *> m_ConVars;
|
|
||||||
List<ConVarQuery> m_ConVarQueries;
|
|
||||||
bool m_bIsDLLQueryHooked;
|
|
||||||
bool m_bIsVSPQueryHooked;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ConVarManager g_ConVarManager;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CONVARMANAGER_H_
|
|
||||||
|
|
||||||
@ -1,420 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include "CoreConfig.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_version.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
|
||||||
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
|
|
||||||
#elif defined PLATFORM_LINUX
|
|
||||||
ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IForward *g_pOnServerCfg = NULL;
|
|
||||||
IForward *g_pOnConfigsExecuted = NULL;
|
|
||||||
CoreConfig g_CoreConfig;
|
|
||||||
bool g_bConfigsExecd = false;
|
|
||||||
|
|
||||||
void CoreConfig::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
|
|
||||||
g_pOnServerCfg = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
|
||||||
g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreConfig::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
g_RootMenu.RemoveRootConsoleCommand("config", this);
|
|
||||||
g_Forwards.ReleaseForward(g_pOnServerCfg);
|
|
||||||
g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreConfig::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
g_bConfigsExecd = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
|
||||||
{
|
|
||||||
int argcount = command.ArgC();
|
|
||||||
if (argcount >= 4)
|
|
||||||
{
|
|
||||||
const char *option = command.Arg(2);
|
|
||||||
const char *value = command.Arg(3);
|
|
||||||
|
|
||||||
char error[255];
|
|
||||||
|
|
||||||
ConfigResult res = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));
|
|
||||||
|
|
||||||
if (res == ConfigResult_Reject)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\" (%s)", option, value, error);
|
|
||||||
} else if (res == ConfigResult_Ignore) {
|
|
||||||
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
|
||||||
} else {
|
|
||||||
g_RootMenu.ConsolePrint("Config option \"%s\" successfully set to \"%s.\"", option, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreConfig::Initialize()
|
|
||||||
{
|
|
||||||
SMCError err;
|
|
||||||
char filePath[PLATFORM_MAX_PATH];
|
|
||||||
|
|
||||||
/* Try to get command line value of core config convar */
|
|
||||||
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
|
||||||
|
|
||||||
/* If sm_corecfgfile not specified on command line, use default value */
|
|
||||||
if (!corecfg)
|
|
||||||
{
|
|
||||||
corecfg = sm_corecfgfile.GetDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Format path to config file */
|
|
||||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
|
||||||
|
|
||||||
/* Parse config file */
|
|
||||||
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
|
|
||||||
{
|
|
||||||
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
|
||||||
const char *error = textparsers->GetSMCErrorString(err);
|
|
||||||
g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
ConfigResult err = SetConfigOption(key, value, ConfigSource_File, error, sizeof(error));
|
|
||||||
|
|
||||||
if (err == ConfigResult_Reject)
|
|
||||||
{
|
|
||||||
/* This is a fatal error */
|
|
||||||
g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength)
|
|
||||||
{
|
|
||||||
ConfigResult result;
|
|
||||||
|
|
||||||
/* Notify! */
|
|
||||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
|
||||||
while (pBase)
|
|
||||||
{
|
|
||||||
if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
pBase = pBase->m_pGlobalClassNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SM_AreConfigsExecuted()
|
|
||||||
{
|
|
||||||
return g_bConfigsExecd;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsPathSepChar(char c)
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
return (c == '\\' || c == '/');
|
|
||||||
#elif defined PLATFORM_LINUX
|
|
||||||
return (c == '/');
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
|
||||||
{
|
|
||||||
bool will_create = false;
|
|
||||||
|
|
||||||
/* See if we should be creating */
|
|
||||||
if (can_create && cfg->create)
|
|
||||||
{
|
|
||||||
will_create = true;
|
|
||||||
|
|
||||||
/* If the folder does not exist, attempt to create it.
|
|
||||||
* We're awfully nice.
|
|
||||||
*/
|
|
||||||
const char *folder = cfg->folder.c_str();
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
|
||||||
char build[PLATFORM_MAX_PATH];
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "cfg/%s", folder);
|
|
||||||
|
|
||||||
if (!g_LibSys.IsPathDirectory(path))
|
|
||||||
{
|
|
||||||
char *cur_ptr = path;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
g_LibSys.PathFormat(path, sizeof(path), "%s", folder);
|
|
||||||
len = g_SourceMod.BuildPath(Path_Game, build, sizeof(build), "cfg");
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Find next suitable path */
|
|
||||||
char *next_ptr = cur_ptr;
|
|
||||||
while (*next_ptr != '\0')
|
|
||||||
{
|
|
||||||
if (IsPathSepChar(*next_ptr))
|
|
||||||
{
|
|
||||||
*next_ptr = '\0';
|
|
||||||
next_ptr++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
next_ptr++;
|
|
||||||
}
|
|
||||||
if (*next_ptr == '\0')
|
|
||||||
{
|
|
||||||
next_ptr = NULL;
|
|
||||||
}
|
|
||||||
len += g_LibSys.PathFormat(&build[len],
|
|
||||||
sizeof(build)-len,
|
|
||||||
"/%s",
|
|
||||||
cur_ptr);
|
|
||||||
if (!g_LibSys.CreateFolder(build))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cur_ptr = next_ptr;
|
|
||||||
} while (cur_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the file exists. */
|
|
||||||
char file[PLATFORM_MAX_PATH];
|
|
||||||
char local[PLATFORM_MAX_PATH];
|
|
||||||
|
|
||||||
if (cfg->folder.size())
|
|
||||||
{
|
|
||||||
g_LibSys.PathFormat(local,
|
|
||||||
sizeof(local),
|
|
||||||
"%s/%s.cfg",
|
|
||||||
cfg->folder.c_str(),
|
|
||||||
cfg->autocfg.c_str());
|
|
||||||
} else {
|
|
||||||
g_LibSys.PathFormat(local,
|
|
||||||
sizeof(local),
|
|
||||||
"%s.cfg",
|
|
||||||
cfg->autocfg.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, file, sizeof(file), "cfg/%s", local);
|
|
||||||
|
|
||||||
bool file_exists = g_LibSys.IsPathFile(file);
|
|
||||||
if (!file_exists && will_create)
|
|
||||||
{
|
|
||||||
List<const ConVar *> *convars = NULL;
|
|
||||||
if (pl->GetProperty("ConVarList", (void **)&convars, false) && convars)
|
|
||||||
{
|
|
||||||
/* Attempt to create it */
|
|
||||||
FILE *fp = fopen(file, "wt");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SVN_FULL_VERSION);
|
|
||||||
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
|
||||||
fprintf(fp, "\n\n");
|
|
||||||
|
|
||||||
List<const ConVar *>::iterator iter;
|
|
||||||
float x;
|
|
||||||
for (iter = convars->begin(); iter != convars->end(); iter++)
|
|
||||||
{
|
|
||||||
const ConVar *cvar = (*iter);
|
|
||||||
|
|
||||||
if ((cvar->GetFlags() & FCVAR_DONTRECORD) == FCVAR_DONTRECORD)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char descr[255];
|
|
||||||
char *dptr = descr;
|
|
||||||
|
|
||||||
/* Print comments until there is no more */
|
|
||||||
strncopy(descr, cvar->GetHelpText(), sizeof(descr));
|
|
||||||
while (*dptr != '\0')
|
|
||||||
{
|
|
||||||
/* Find the next line */
|
|
||||||
char *next_ptr = dptr;
|
|
||||||
while (*next_ptr != '\0')
|
|
||||||
{
|
|
||||||
if (*next_ptr == '\n')
|
|
||||||
{
|
|
||||||
*next_ptr = '\0';
|
|
||||||
next_ptr++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
next_ptr++;
|
|
||||||
}
|
|
||||||
fprintf(fp, "// %s\n", dptr);
|
|
||||||
dptr = next_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "// -\n");
|
|
||||||
fprintf(fp, "// Default: \"%s\"\n", cvar->GetDefault());
|
|
||||||
if (cvar->GetMin(x))
|
|
||||||
{
|
|
||||||
fprintf(fp, "// Minimum: \"%02f\"\n", x);
|
|
||||||
}
|
|
||||||
if (cvar->GetMax(x))
|
|
||||||
{
|
|
||||||
fprintf(fp, "// Maximum: \"%02f\"\n", x);
|
|
||||||
}
|
|
||||||
fprintf(fp, "%s \"%s\"\n", cvar->GetName(), cvar->GetDefault());
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
file_exists = true;
|
|
||||||
can_create = false;
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_exists)
|
|
||||||
{
|
|
||||||
char cmd[255];
|
|
||||||
UTIL_Format(cmd, sizeof(cmd), "exec %s\n", local);
|
|
||||||
engine->ServerCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return can_create;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM_DoSingleExecFwds(IPluginContext *ctx)
|
|
||||||
{
|
|
||||||
IPluginFunction *pf;
|
|
||||||
|
|
||||||
if ((pf = ctx->GetFunctionByName("OnServerCfg")) != NULL)
|
|
||||||
{
|
|
||||||
pf->Execute(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pf = ctx->GetFunctionByName("OnConfigsExecuted")) != NULL)
|
|
||||||
{
|
|
||||||
pf->Execute(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
|
||||||
{
|
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
|
||||||
while (iter->MorePlugins())
|
|
||||||
{
|
|
||||||
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
|
|
||||||
if (plugin->GetSerial() == serial)
|
|
||||||
{
|
|
||||||
SM_DoSingleExecFwds(plugin->GetBaseContext());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iter->NextPlugin();
|
|
||||||
}
|
|
||||||
iter->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM_ExecuteForPlugin(IPluginContext *ctx)
|
|
||||||
{
|
|
||||||
CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
|
|
||||||
|
|
||||||
unsigned int num = plugin->GetConfigCount();
|
|
||||||
if (!num)
|
|
||||||
{
|
|
||||||
SM_DoSingleExecFwds(ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool can_create = true;
|
|
||||||
for (unsigned int i=0; i<num; i++)
|
|
||||||
{
|
|
||||||
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
|
||||||
}
|
|
||||||
char cmd[255];
|
|
||||||
UTIL_Format(cmd, sizeof(cmd), "sm internal 2 %d\n", plugin->GetSerial());
|
|
||||||
engine->ServerCommand(cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM_ExecuteAllConfigs()
|
|
||||||
{
|
|
||||||
if (g_bConfigsExecd)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
|
|
||||||
|
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
|
||||||
while (iter->MorePlugins())
|
|
||||||
{
|
|
||||||
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
|
|
||||||
unsigned int num = plugin->GetConfigCount();
|
|
||||||
bool can_create = true;
|
|
||||||
for (unsigned int i=0; i<num; i++)
|
|
||||||
{
|
|
||||||
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
|
||||||
}
|
|
||||||
iter->NextPlugin();
|
|
||||||
}
|
|
||||||
iter->Release();
|
|
||||||
|
|
||||||
engine->ServerCommand("sm internal 1\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM_ConfigsExecuted_Global()
|
|
||||||
{
|
|
||||||
if (g_bConfigsExecd)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_bConfigsExecd = true;
|
|
||||||
|
|
||||||
g_pOnServerCfg->Execute(NULL);
|
|
||||||
g_pOnConfigsExecuted->Execute(NULL);
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CORECONFIG_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CORECONFIG_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include <IRootConsoleMenu.h>
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class CoreConfig :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public ITextListener_SMC,
|
|
||||||
public IRootConsoleCommand
|
|
||||||
{
|
|
||||||
public: // SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
public: // ITextListener_SMC
|
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
|
||||||
public: // IRootConsoleCommand
|
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Initializes CoreConfig by reading from core.cfg file
|
|
||||||
*/
|
|
||||||
void Initialize();
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Sets configuration option by notifying SourceMod components that rely on core.cfg
|
|
||||||
*/
|
|
||||||
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern bool SM_AreConfigsExecuted();
|
|
||||||
extern void SM_ExecuteAllConfigs();
|
|
||||||
extern void SM_ExecuteForPlugin(IPluginContext *ctx);
|
|
||||||
extern void SM_ConfigsExecuted_Global();
|
|
||||||
extern void SM_ConfigsExecuted_Plugin(unsigned int serial);
|
|
||||||
|
|
||||||
extern CoreConfig g_CoreConfig;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CORECONFIG_H_
|
|
||||||
@ -1,145 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined CRAZY_DEBUG
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "Tlhelp32.h"
|
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "minidump.h"
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
MiniDumpWriteDump2(
|
|
||||||
IN HANDLE hProcess,
|
|
||||||
IN DWORD ProcessId,
|
|
||||||
IN HANDLE hFile,
|
|
||||||
IN MINIDUMP_TYPE DumpType,
|
|
||||||
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
|
|
||||||
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
|
|
||||||
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DumpType = (MINIDUMP_TYPE)((int)DumpType|MiniDumpWithFullMemory|MiniDumpWithHandleData);
|
|
||||||
return MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType, ExceptionParam, UserStreamParam, CallbackParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
FARPROC WINAPI GetProcAddress2(HMODULE hModule, LPCSTR lpProcName)
|
|
||||||
{
|
|
||||||
if (strcmp(lpProcName, "MiniDumpWriteDump") == 0)
|
|
||||||
{
|
|
||||||
return (FARPROC)MiniDumpWriteDump2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetProcAddress(hModule, lpProcName);
|
|
||||||
}
|
|
||||||
|
|
||||||
class CrazyWindowsDebugger : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
HANDLE hModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
|
||||||
MODULEENTRY32 me32;
|
|
||||||
|
|
||||||
me32.dwSize = sizeof(MODULEENTRY32);
|
|
||||||
|
|
||||||
if (!Module32First(hModuleList, &me32))
|
|
||||||
{
|
|
||||||
Error("Could not initialize crazy debugger!");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (strcasecmp(me32.szModule, "steam.dll") == 0)
|
|
||||||
{
|
|
||||||
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)me32.modBaseAddr;
|
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
{
|
|
||||||
Error("[SM] Could not detect steam.dll with valid DOS signature");
|
|
||||||
}
|
|
||||||
char *base = (char *)dos;
|
|
||||||
IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
|
|
||||||
if (nt->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
|
||||||
Error("[SM] Could not detect steam.dll with valid NT signature");
|
|
||||||
}
|
|
||||||
IMAGE_IMPORT_DESCRIPTOR *desc =
|
|
||||||
(IMAGE_IMPORT_DESCRIPTOR *)
|
|
||||||
(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
|
||||||
if (base == (char *)desc)
|
|
||||||
{
|
|
||||||
Error("[SM] Could not find the steam.dll IAT");
|
|
||||||
}
|
|
||||||
while (desc->Name)
|
|
||||||
{
|
|
||||||
if (desc->FirstThunk != 0)
|
|
||||||
{
|
|
||||||
IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
|
|
||||||
DWORD *iat = (DWORD *)(base + desc->FirstThunk);
|
|
||||||
while (data->u1.Function)
|
|
||||||
{
|
|
||||||
if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
|
|
||||||
{
|
|
||||||
IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
|
|
||||||
if (strcmp((char *)import->Name, "GetProcAddress") == 0)
|
|
||||||
{
|
|
||||||
DWORD oldprot, oldprot2;
|
|
||||||
VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
|
|
||||||
*iat = (DWORD)GetProcAddress2;
|
|
||||||
VirtualProtect(iat, 4, oldprot, &oldprot2);
|
|
||||||
found = true;
|
|
||||||
goto _end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data++;
|
|
||||||
iat++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (Module32Next(hModuleList, &me32));
|
|
||||||
|
|
||||||
_end:
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
Error("Could not find steam.dll's GetProcAddress IAT entry");
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hModuleList);
|
|
||||||
}
|
|
||||||
} s_CrazyDebugger;
|
|
||||||
#endif
|
|
||||||
@ -1,719 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Database.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "ExtensionSys.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "ThreadSupport.h"
|
|
||||||
|
|
||||||
#define DBPARSE_LEVEL_NONE 0
|
|
||||||
#define DBPARSE_LEVEL_MAIN 1
|
|
||||||
#define DBPARSE_LEVEL_DATABASE 2
|
|
||||||
|
|
||||||
DBManager g_DBMan;
|
|
||||||
static bool s_OneTimeThreaderErrorMsg = false;
|
|
||||||
|
|
||||||
DBManager::DBManager()
|
|
||||||
: m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
HandleAccess sec;
|
|
||||||
|
|
||||||
g_HandleSys.InitAccessDefaults(NULL, &sec);
|
|
||||||
sec.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;
|
|
||||||
sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
|
|
||||||
|
|
||||||
m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
|
||||||
m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
|
||||||
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
|
|
||||||
|
|
||||||
m_pConfigLock = g_pThreader->MakeMutex();
|
|
||||||
m_pThinkLock = g_pThreader->MakeMutex();
|
|
||||||
m_pQueueLock = g_pThreader->MakeMutex();
|
|
||||||
|
|
||||||
g_PluginSys.AddPluginsListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
SMCError err;
|
|
||||||
SMCStates states = {0, 0};
|
|
||||||
|
|
||||||
/* We lock and don't give up the lock until we're done.
|
|
||||||
* This way the thread's search won't be searching through a
|
|
||||||
* potentially empty/corrupt list, which would be very bad.
|
|
||||||
*/
|
|
||||||
m_pConfigLock->Lock();
|
|
||||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
|
||||||
if (err != SMCError_Custom)
|
|
||||||
{
|
|
||||||
const char *txt = textparsers->GetSMCErrorString(err);
|
|
||||||
g_Logger.LogError("[SM] Line %d: %s", states.line, txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_pConfigLock->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
KillWorkerThread();
|
|
||||||
g_PluginSys.RemovePluginsListener(this);
|
|
||||||
m_pConfigLock->DestroyThis();
|
|
||||||
m_pThinkLock->DestroyThis();
|
|
||||||
m_pQueueLock->DestroyThis();
|
|
||||||
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
|
||||||
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DBManager::GetInterfaceVersion()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_DBI_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *DBManager::GetInterfaceName()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_DBI_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnHandleDestroy(HandleType_t type, void *object)
|
|
||||||
{
|
|
||||||
if (type == m_DriverType)
|
|
||||||
{
|
|
||||||
/* Ignore */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_HandleSys.TypeCheck(type, m_DatabaseType))
|
|
||||||
{
|
|
||||||
IDatabase *pdb = (IDatabase *)object;
|
|
||||||
pdb->Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::ReadSMC_ParseStart()
|
|
||||||
{
|
|
||||||
m_confs.clear();
|
|
||||||
m_ParseLevel = 0;
|
|
||||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
|
||||||
m_StrTab.Reset();
|
|
||||||
m_DefDriver.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfDbInfo s_CurInfo;
|
|
||||||
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
|
||||||
{
|
|
||||||
if (m_ParseLevel)
|
|
||||||
{
|
|
||||||
m_ParseLevel++;
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_NONE)
|
|
||||||
{
|
|
||||||
if (strcmp(name, "Databases") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
|
||||||
} else {
|
|
||||||
m_ParseLevel++;
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
|
||||||
s_CurInfo = ConfDbInfo();
|
|
||||||
s_CurInfo.name = m_StrTab.AddString(name);
|
|
||||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
|
||||||
m_ParseLevel++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
if (m_ParseLevel)
|
|
||||||
{
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_MAIN)
|
|
||||||
{
|
|
||||||
if (strcmp(key, "driver_default") == 0)
|
|
||||||
{
|
|
||||||
m_DefDriver.assign(value);
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
|
||||||
if (strcmp(key, "driver") == 0)
|
|
||||||
{
|
|
||||||
if (strcmp(value, "default") != 0)
|
|
||||||
{
|
|
||||||
s_CurInfo.driver = m_StrTab.AddString(value);
|
|
||||||
}
|
|
||||||
} else if (strcmp(key, "database") == 0) {
|
|
||||||
s_CurInfo.database = m_StrTab.AddString(value);
|
|
||||||
} else if (strcmp(key, "host") == 0) {
|
|
||||||
s_CurInfo.host = m_StrTab.AddString(value);
|
|
||||||
} else if (strcmp(key, "user") == 0) {
|
|
||||||
s_CurInfo.user = m_StrTab.AddString(value);
|
|
||||||
} else if (strcmp(key, "pass") == 0) {
|
|
||||||
s_CurInfo.pass = m_StrTab.AddString(value);
|
|
||||||
} else if (strcmp(key, "timeout") == 0) {
|
|
||||||
s_CurInfo.info.maxTimeout = atoi(value);
|
|
||||||
} else if (strcmp(key, "port") == 0) {
|
|
||||||
s_CurInfo.info.port = atoi(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSIGN_VAR(var) \
|
|
||||||
if (s_CurInfo.var == -1) { \
|
|
||||||
s_CurInfo.info.var = ""; \
|
|
||||||
} else { \
|
|
||||||
s_CurInfo.info.var = m_StrTab.GetString(s_CurInfo.var); \
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
|
||||||
{
|
|
||||||
if (m_ParseLevel)
|
|
||||||
{
|
|
||||||
m_ParseLevel--;
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
|
||||||
{
|
|
||||||
/* Set all of the info members to either a blank string
|
|
||||||
* or the string pointer from the string table.
|
|
||||||
*/
|
|
||||||
ASSIGN_VAR(driver);
|
|
||||||
ASSIGN_VAR(database);
|
|
||||||
ASSIGN_VAR(host);
|
|
||||||
ASSIGN_VAR(user);
|
|
||||||
ASSIGN_VAR(pass);
|
|
||||||
|
|
||||||
/* Save it.. */
|
|
||||||
m_confs.push_back(s_CurInfo);
|
|
||||||
|
|
||||||
/* Go up one level */
|
|
||||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
|
||||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
|
||||||
return SMCResult_Halt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
#undef ASSIGN_VAR
|
|
||||||
|
|
||||||
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
|
|
||||||
{
|
|
||||||
ConfDbInfo *pInfo = GetDatabaseConf(name);
|
|
||||||
|
|
||||||
if (!pInfo)
|
|
||||||
{
|
|
||||||
if (pdr)
|
|
||||||
{
|
|
||||||
*pdr = NULL;
|
|
||||||
}
|
|
||||||
*pdb = NULL;
|
|
||||||
UTIL_Format(error, maxlength, "Configuration \"%s\" not found", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *dname = pInfo->info.driver;
|
|
||||||
if (!pInfo->realDriver)
|
|
||||||
{
|
|
||||||
/* Try to assign a real driver pointer */
|
|
||||||
if (pInfo->info.driver[0] == '\0')
|
|
||||||
{
|
|
||||||
if (!m_pDefault && m_DefDriver.size() > 0)
|
|
||||||
{
|
|
||||||
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
|
|
||||||
}
|
|
||||||
dname = m_DefDriver.size() ? m_DefDriver.c_str() : "default";
|
|
||||||
pInfo->realDriver = m_pDefault;
|
|
||||||
} else {
|
|
||||||
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pInfo->realDriver)
|
|
||||||
{
|
|
||||||
if (pdr)
|
|
||||||
{
|
|
||||||
*pdr = pInfo->realDriver;
|
|
||||||
}
|
|
||||||
*pdb = pInfo->realDriver->Connect(&pInfo->info, persistent, error, maxlength);
|
|
||||||
return (*pdb != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdr)
|
|
||||||
{
|
|
||||||
*pdr = NULL;
|
|
||||||
}
|
|
||||||
*pdb = NULL;
|
|
||||||
|
|
||||||
UTIL_Format(error, maxlength, "Driver \"%s\" not found", dname);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::AddDriver(IDBDriver *pDriver)
|
|
||||||
{
|
|
||||||
/* Let's kill the worker. Join the thread and let the queries flush.
|
|
||||||
* This is kind of stupid but we just want to unload safely.
|
|
||||||
* Rather than recreate the worker, we'll wait until someone throws
|
|
||||||
* another query through.
|
|
||||||
*/
|
|
||||||
KillWorkerThread();
|
|
||||||
|
|
||||||
m_drivers.push_back(pDriver);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::RemoveDriver(IDBDriver *pDriver)
|
|
||||||
{
|
|
||||||
/* Again, we're forced to kill the worker. How rude!
|
|
||||||
* Doing this flushes the queue, and thus we don't need to
|
|
||||||
* clean anything else.
|
|
||||||
*/
|
|
||||||
KillWorkerThread();
|
|
||||||
|
|
||||||
for (size_t i=0; i<m_drivers.size(); i++)
|
|
||||||
{
|
|
||||||
if (m_drivers[i] == pDriver)
|
|
||||||
{
|
|
||||||
m_drivers.erase(m_drivers.iterAt(i));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure NOTHING references this! */
|
|
||||||
List<ConfDbInfo>::iterator iter;
|
|
||||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
|
||||||
{
|
|
||||||
ConfDbInfo &db = (*iter);
|
|
||||||
if (db.realDriver == pDriver)
|
|
||||||
{
|
|
||||||
db.realDriver = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now that the driver is gone, we have to test the think queue.
|
|
||||||
* Whatever happens therein is up to the db op!
|
|
||||||
*/
|
|
||||||
Queue<IDBThreadOperation *>::iterator qiter = m_ThinkQueue.begin();
|
|
||||||
Queue<IDBThreadOperation *> templist;
|
|
||||||
while (qiter != m_ThinkQueue.end())
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = (*qiter);
|
|
||||||
if (op->GetDriver() == pDriver)
|
|
||||||
{
|
|
||||||
templist.push(op);
|
|
||||||
qiter = m_ThinkQueue.erase(qiter);
|
|
||||||
} else {
|
|
||||||
qiter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (qiter = templist.begin();
|
|
||||||
qiter != templist.end();
|
|
||||||
qiter++)
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = (*qiter);
|
|
||||||
op->CancelThinkPart();
|
|
||||||
op->Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IDBDriver *DBManager::GetDefaultDriver()
|
|
||||||
{
|
|
||||||
if (!m_pDefault && m_DefDriver.size() > 0)
|
|
||||||
{
|
|
||||||
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_pDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t DBManager::CreateHandle(DBHandleType dtype, void *ptr, IdentityToken_t *pToken)
|
|
||||||
{
|
|
||||||
HandleType_t type = 0;
|
|
||||||
|
|
||||||
if (dtype == DBHandle_Driver)
|
|
||||||
{
|
|
||||||
type = m_DriverType;
|
|
||||||
} else if (dtype == DBHandle_Database) {
|
|
||||||
type = m_DatabaseType;
|
|
||||||
} else {
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(type, ptr, pToken, g_pCoreIdent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleError DBManager::ReadHandle(Handle_t hndl, DBHandleType dtype, void **ptr)
|
|
||||||
{
|
|
||||||
HandleType_t type = 0;
|
|
||||||
|
|
||||||
if (dtype == DBHandle_Driver)
|
|
||||||
{
|
|
||||||
type = m_DriverType;
|
|
||||||
} else if (dtype == DBHandle_Database) {
|
|
||||||
type = m_DatabaseType;
|
|
||||||
} else {
|
|
||||||
return HandleError_Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(hndl, type, &sec, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleError DBManager::ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token)
|
|
||||||
{
|
|
||||||
HandleSecurity sec(token, g_pCoreIdent);
|
|
||||||
return g_HandleSys.FreeHandle(hndl, &sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DBManager::GetDriverCount()
|
|
||||||
{
|
|
||||||
return (unsigned int)m_drivers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
IDBDriver *DBManager::GetDriver(unsigned int index)
|
|
||||||
{
|
|
||||||
if (index >= m_drivers.size())
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_drivers[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
|
||||||
{
|
|
||||||
ConfDbInfo *info = GetDatabaseConf(name);
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &info->info;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
|
|
||||||
{
|
|
||||||
List<ConfDbInfo>::iterator iter;
|
|
||||||
|
|
||||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
|
||||||
{
|
|
||||||
ConfDbInfo &conf = (*iter);
|
|
||||||
if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
|
|
||||||
{
|
|
||||||
return &conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDBDriver *DBManager::FindOrLoadDriver(const char *name)
|
|
||||||
{
|
|
||||||
size_t last_size = m_drivers.size();
|
|
||||||
for (size_t i=0; i<last_size; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(m_drivers[i]->GetIdentifier(), name) == 0)
|
|
||||||
{
|
|
||||||
return m_drivers[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char filename[PLATFORM_MAX_PATH];
|
|
||||||
UTIL_Format(filename, sizeof(filename), "dbi.%s.ext", name);
|
|
||||||
|
|
||||||
IExtension *pExt = g_Extensions.LoadAutoExtension(filename);
|
|
||||||
if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* last_size is now gauranteed to be a valid index.
|
|
||||||
* The identifier must match the name.
|
|
||||||
*/
|
|
||||||
if (strcmp(m_drivers[last_size]->GetIdentifier(), name) == 0)
|
|
||||||
{
|
|
||||||
return m_drivers[last_size];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::KillWorkerThread()
|
|
||||||
{
|
|
||||||
if (m_pWorker)
|
|
||||||
{
|
|
||||||
m_pWorker->Stop(false);
|
|
||||||
g_pThreader->DestroyWorker(m_pWorker);
|
|
||||||
m_pWorker = NULL;
|
|
||||||
s_OneTimeThreaderErrorMsg = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static IdentityToken_t *s_pAddBlock = NULL;
|
|
||||||
|
|
||||||
bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
|
||||||
{
|
|
||||||
if (s_pAddBlock && op->GetOwner() == s_pAddBlock)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_pWorker)
|
|
||||||
{
|
|
||||||
m_pWorker = g_pThreader->MakeWorker(this, true);
|
|
||||||
if (!m_pWorker)
|
|
||||||
{
|
|
||||||
if (!s_OneTimeThreaderErrorMsg)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unable to create db threader (error unknown)");
|
|
||||||
s_OneTimeThreaderErrorMsg = true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!m_pWorker->Start())
|
|
||||||
{
|
|
||||||
if (!s_OneTimeThreaderErrorMsg)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unable to start db threader (error unknown)");
|
|
||||||
s_OneTimeThreaderErrorMsg = true;
|
|
||||||
}
|
|
||||||
g_pThreader->DestroyWorker(m_pWorker);
|
|
||||||
m_pWorker = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add to the queue */
|
|
||||||
{
|
|
||||||
m_pQueueLock->Lock();
|
|
||||||
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
|
|
||||||
queue.push(op);
|
|
||||||
m_pQueueLock->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the thread */
|
|
||||||
m_pWorker->MakeThread(this);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnWorkerStart(IThreadWorker *pWorker)
|
|
||||||
{
|
|
||||||
m_drSafety.clear();
|
|
||||||
for (size_t i=0; i<m_drivers.size(); i++)
|
|
||||||
{
|
|
||||||
if (m_drivers[i]->IsThreadSafe())
|
|
||||||
{
|
|
||||||
m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety());
|
|
||||||
} else {
|
|
||||||
m_drSafety.push_back(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnWorkerStop(IThreadWorker *pWorker)
|
|
||||||
{
|
|
||||||
for (size_t i=0; i<m_drivers.size(); i++)
|
|
||||||
{
|
|
||||||
if (m_drSafety[i])
|
|
||||||
{
|
|
||||||
m_drivers[i]->ShutdownThreadSafety();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_drSafety.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::RunThread(IThreadHandle *pThread)
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = NULL;
|
|
||||||
|
|
||||||
/* Get something from the queue */
|
|
||||||
{
|
|
||||||
m_pQueueLock->Lock();
|
|
||||||
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
|
|
||||||
if (!queue.empty())
|
|
||||||
{
|
|
||||||
op = queue.first();
|
|
||||||
queue.pop();
|
|
||||||
}
|
|
||||||
m_pQueueLock->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* whoa. hi. did we get something? we should have. */
|
|
||||||
if (!op)
|
|
||||||
{
|
|
||||||
/* wtf? */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
op->RunThreadPart();
|
|
||||||
|
|
||||||
m_pThinkLock->Lock();
|
|
||||||
m_ThinkQueue.push(op);
|
|
||||||
m_pThinkLock->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::RunFrame()
|
|
||||||
{
|
|
||||||
/* Don't bother if we're empty */
|
|
||||||
if (!m_ThinkQueue.size())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dump one thing per-frame so the server stays sane. */
|
|
||||||
m_pThinkLock->Lock();
|
|
||||||
IDBThreadOperation *op = m_ThinkQueue.first();
|
|
||||||
m_ThinkQueue.pop();
|
|
||||||
m_pThinkLock->Unlock();
|
|
||||||
op->RunThinkPart();
|
|
||||||
op->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnTerminate(IThreadHandle *pThread, bool cancel)
|
|
||||||
{
|
|
||||||
/* Do nothing */
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
|
|
||||||
{
|
|
||||||
s_pAddBlock = pToken;
|
|
||||||
|
|
||||||
/* Kill the thread so we can flush everything into the think queue... */
|
|
||||||
KillWorkerThread();
|
|
||||||
|
|
||||||
/* Run all of the think operations.
|
|
||||||
* Unlike the driver unloading example, we'll let these calls go through,
|
|
||||||
* since a plugin unloading is far more normal.
|
|
||||||
*/
|
|
||||||
Queue<IDBThreadOperation *>::iterator iter = m_ThinkQueue.begin();
|
|
||||||
Queue<IDBThreadOperation *> templist;
|
|
||||||
while (iter != m_ThinkQueue.end())
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = (*iter);
|
|
||||||
if (op->GetOwner() == pToken)
|
|
||||||
{
|
|
||||||
templist.push(op);
|
|
||||||
iter = m_ThinkQueue.erase(iter);
|
|
||||||
} else {
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iter = templist.begin();
|
|
||||||
iter != templist.end();
|
|
||||||
iter++)
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = (*iter);
|
|
||||||
op->RunThinkPart();
|
|
||||||
op->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
s_pAddBlock = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnPluginUnloaded(IPlugin *plugin)
|
|
||||||
{
|
|
||||||
/* Kill the thread so we can flush everything into the think queue... */
|
|
||||||
KillWorkerThread();
|
|
||||||
|
|
||||||
/* Mark the plugin as being unloaded so future database calls will ignore threading... */
|
|
||||||
plugin->SetProperty("DisallowDBThreads", NULL);
|
|
||||||
|
|
||||||
/* Run all of the think operations.
|
|
||||||
* Unlike the driver unloading example, we'll let these calls go through,
|
|
||||||
* since a plugin unloading is far more normal.
|
|
||||||
*/
|
|
||||||
Queue<IDBThreadOperation *>::iterator iter = m_ThinkQueue.begin();
|
|
||||||
Queue<IDBThreadOperation *> templist;
|
|
||||||
while (iter != m_ThinkQueue.end())
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = (*iter);
|
|
||||||
if (op->GetOwner() == plugin->GetIdentity())
|
|
||||||
{
|
|
||||||
templist.push(op);
|
|
||||||
iter = m_ThinkQueue.erase(iter);
|
|
||||||
} else {
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iter = templist.begin();
|
|
||||||
iter != templist.end();
|
|
||||||
iter++)
|
|
||||||
{
|
|
||||||
IDBThreadOperation *op = (*iter);
|
|
||||||
op->RunThinkPart();
|
|
||||||
op->Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::LockConfig()
|
|
||||||
{
|
|
||||||
m_pConfigLock->Lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::UnlockConfig()
|
|
||||||
{
|
|
||||||
m_pConfigLock->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *DBManager::GetDefaultDriverName()
|
|
||||||
{
|
|
||||||
return m_DefDriver.c_str();
|
|
||||||
}
|
|
||||||
149
core/Database.h
149
core/Database.h
@ -1,149 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_DATABASE_MANAGER_H_
|
|
||||||
#define _INCLUDE_DATABASE_MANAGER_H_
|
|
||||||
|
|
||||||
#include <IDBDriver.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include <IThreader.h>
|
|
||||||
#include "sm_simple_prioqueue.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
struct ConfDbInfo
|
|
||||||
{
|
|
||||||
ConfDbInfo() : name(-1), driver(-1), host(-1), user(-1), pass(-1),
|
|
||||||
database(-1), realDriver(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
int name;
|
|
||||||
int driver;
|
|
||||||
int host;
|
|
||||||
int user;
|
|
||||||
int pass;
|
|
||||||
int database;
|
|
||||||
IDBDriver *realDriver;
|
|
||||||
DatabaseInfo info;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DBManager :
|
|
||||||
public IDBManager,
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IHandleTypeDispatch,
|
|
||||||
public ITextListener_SMC,
|
|
||||||
public IThread,
|
|
||||||
public IThreadWorkerCallbacks,
|
|
||||||
public IPluginsListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DBManager();
|
|
||||||
public:
|
|
||||||
const char *GetInterfaceName();
|
|
||||||
unsigned int GetInterfaceVersion();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
void OnSourceModIdentityDropped(IdentityToken_t *pToken);
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: //IHandleTypeDispatch
|
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
|
||||||
public: //IDBManager
|
|
||||||
void AddDriver(IDBDriver *pDrivera);
|
|
||||||
void RemoveDriver(IDBDriver *pDriver);
|
|
||||||
const DatabaseInfo *FindDatabaseConf(const char *name);
|
|
||||||
bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
|
|
||||||
unsigned int GetDriverCount();
|
|
||||||
IDBDriver *GetDriver(unsigned int index);
|
|
||||||
Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken);
|
|
||||||
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
|
|
||||||
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
|
|
||||||
public: //ITextListener_SMC
|
|
||||||
void ReadSMC_ParseStart();
|
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
|
||||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
|
||||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
|
||||||
public: //IThread
|
|
||||||
void RunThread(IThreadHandle *pThread);
|
|
||||||
void OnTerminate(IThreadHandle *pThread, bool cancel);
|
|
||||||
public: //IThreadWorkerCallbacks
|
|
||||||
void OnWorkerStart(IThreadWorker *pWorker);
|
|
||||||
void OnWorkerStop(IThreadWorker *pWorker);
|
|
||||||
public: //IPluginsListener
|
|
||||||
void OnPluginUnloaded(IPlugin *plugin);
|
|
||||||
public:
|
|
||||||
ConfDbInfo *GetDatabaseConf(const char *name);
|
|
||||||
IDBDriver *FindOrLoadDriver(const char *name);
|
|
||||||
IDBDriver *GetDefaultDriver();
|
|
||||||
const char *GetDefaultDriverName();
|
|
||||||
bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio);
|
|
||||||
void LockConfig();
|
|
||||||
void UnlockConfig();
|
|
||||||
void RunFrame();
|
|
||||||
inline HandleType_t GetDatabaseType()
|
|
||||||
{
|
|
||||||
return m_DatabaseType;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void KillWorkerThread();
|
|
||||||
private:
|
|
||||||
CVector<IDBDriver *> m_drivers;
|
|
||||||
|
|
||||||
/* Threading stuff */
|
|
||||||
PrioQueue<IDBThreadOperation *> m_OpQueue;
|
|
||||||
Queue<IDBThreadOperation *> m_ThinkQueue;
|
|
||||||
CVector<bool> m_drSafety; /* which drivers are safe? */
|
|
||||||
IThreadWorker *m_pWorker; /* Worker thread object */
|
|
||||||
IMutex *m_pConfigLock; /* Configuration lock */
|
|
||||||
IMutex *m_pQueueLock; /* Queue safety lock */
|
|
||||||
IMutex *m_pThinkLock; /* Think-queue lock */
|
|
||||||
|
|
||||||
List<ConfDbInfo> m_confs;
|
|
||||||
HandleType_t m_DriverType;
|
|
||||||
HandleType_t m_DatabaseType;
|
|
||||||
String m_DefDriver;
|
|
||||||
BaseStringTable m_StrTab;
|
|
||||||
char m_Filename[PLATFORM_MAX_PATH];
|
|
||||||
unsigned int m_ParseLevel;
|
|
||||||
unsigned int m_ParseState;
|
|
||||||
IDBDriver *m_pDefault;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern DBManager g_DBMan;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_DATABASE_MANAGER_H_
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "DebugReporter.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
|
|
||||||
DebugReport g_DbgReporter;
|
|
||||||
|
|
||||||
/* I'm really lazy. This should probably be exported to ISourcePawnEngine someday,
|
|
||||||
* but we need to make sure the JIT will deal with the version bump.
|
|
||||||
*/
|
|
||||||
extern const char *GetSourcePawnErrorMessage(int error);
|
|
||||||
|
|
||||||
void DebugReport::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_pSourcePawn->SetDebugListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char buffer[512];
|
|
||||||
|
|
||||||
va_start(ap, message);
|
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
|
||||||
const char *error = GetSourcePawnErrorMessage(err);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Logger.LogError("[SM] %s", buffer);
|
|
||||||
|
|
||||||
if (func_idx != -1)
|
|
||||||
{
|
|
||||||
if (func_idx & 1)
|
|
||||||
{
|
|
||||||
func_idx >>= 1;
|
|
||||||
sp_public_t *function;
|
|
||||||
if (ctx->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr, int err, const char *message, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char buffer[512];
|
|
||||||
|
|
||||||
va_start(ap, message);
|
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
|
|
||||||
const char *error = GetSourcePawnErrorMessage(err);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Logger.LogError("[SM] %s", buffer);
|
|
||||||
|
|
||||||
IPluginDebugInfo *pDebug;
|
|
||||||
if ((pDebug = pContext->GetDebugInfo()) == NULL)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
|
||||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
|
||||||
_GetPluginIndex(pContext));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *name;
|
|
||||||
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
|
|
||||||
{
|
|
||||||
const char *lastname;
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
|
||||||
int n_err = error->GetErrorCode();
|
|
||||||
|
|
||||||
if (n_err != SP_ERROR_NATIVE)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
|
|
||||||
n_err,
|
|
||||||
error->GetErrorString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lastname=error->GetLastNative(NULL)) != NULL)
|
|
||||||
{
|
|
||||||
const char *custerr;
|
|
||||||
if ((custerr=error->GetCustomErrorString()) != NULL)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error->DebugInfoAvailable())
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
|
||||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
|
||||||
_GetPluginIndex(ctx));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallStackInfo stk_info;
|
|
||||||
int i = 0;
|
|
||||||
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
|
||||||
while (error->GetTraceInfo(&stk_info))
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
|
|
||||||
i++,
|
|
||||||
stk_info.line,
|
|
||||||
stk_info.filename,
|
|
||||||
stk_info.function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
|
||||||
{
|
|
||||||
int id = 1;
|
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
|
||||||
|
|
||||||
for (; iter->MorePlugins(); iter->NextPlugin(), id++)
|
|
||||||
{
|
|
||||||
IPlugin *pl = iter->GetPlugin();
|
|
||||||
if (pl->GetBaseContext() == ctx)
|
|
||||||
{
|
|
||||||
iter->Release();
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iter->Release();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
|
|
||||||
|
|
||||||
#include "sp_vm_api.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
class DebugReport :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IDebugListener
|
|
||||||
{
|
|
||||||
public: // SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
public: // IDebugListener
|
|
||||||
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
|
|
||||||
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
|
||||||
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
|
||||||
private:
|
|
||||||
int _GetPluginIndex(IPluginContext *ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern DebugReport g_DbgReporter;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
|
|
||||||
|
|
||||||
@ -1,449 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EventManager.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
|
|
||||||
EventManager g_EventManager;
|
|
||||||
|
|
||||||
SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool);
|
|
||||||
|
|
||||||
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
|
||||||
typedef List<EventHook *> EventHookList;
|
|
||||||
|
|
||||||
EventManager::EventManager() : m_EventType(0)
|
|
||||||
{
|
|
||||||
/* Create an event lookup trie */
|
|
||||||
m_EventHooks = sm_trie_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
EventManager::~EventManager()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_EventHooks);
|
|
||||||
|
|
||||||
/* Free memory used by EventInfo structs if any */
|
|
||||||
CStack<EventInfo *>::iterator iter;
|
|
||||||
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
|
|
||||||
{
|
|
||||||
delete (*iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_FreeEvents.popall();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
/* Add a hook for IGameEventManager2::FireEvent() */
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
|
|
||||||
|
|
||||||
HandleAccess sec;
|
|
||||||
|
|
||||||
/* Handle access security for 'GameEvent' handle type */
|
|
||||||
sec.access[HandleAccess_Read] = 0;
|
|
||||||
sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
|
||||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
|
||||||
|
|
||||||
/* Create the 'GameEvent' handle type */
|
|
||||||
m_EventType = g_HandleSys.CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
/* Remove hook for IGameEventManager2::FireEvent() */
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
|
|
||||||
|
|
||||||
/* Remove the 'GameEvent' handle type */
|
|
||||||
g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
|
|
||||||
|
|
||||||
/* Remove ourselves as listener for events */
|
|
||||||
gameevents->RemoveListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::OnHandleDestroy(HandleType_t type, void *object)
|
|
||||||
{
|
|
||||||
EventInfo *pInfo = static_cast<EventInfo *>(object);
|
|
||||||
|
|
||||||
/* Should only free event when created by a plugin */
|
|
||||||
if (pInfo->pOwner)
|
|
||||||
{
|
|
||||||
/* Free IGameEvent */
|
|
||||||
gameevents->FreeEvent(pInfo->pEvent);
|
|
||||||
|
|
||||||
/* Add EventInfo struct to free event stack */
|
|
||||||
m_FreeEvents.push(pInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::OnPluginUnloaded(IPlugin *plugin)
|
|
||||||
{
|
|
||||||
EventHookList *pHookList;
|
|
||||||
EventHookList::iterator iter;
|
|
||||||
EventHook *pHook;
|
|
||||||
|
|
||||||
// If plugin has an event hook list...
|
|
||||||
if (plugin->GetProperty("EventHooks", reinterpret_cast<void **>(&pHookList), true))
|
|
||||||
{
|
|
||||||
for (iter = pHookList->begin(); iter != pHookList->end(); iter++)
|
|
||||||
{
|
|
||||||
pHook = (*iter);
|
|
||||||
|
|
||||||
if (--pHook->refCount == 0)
|
|
||||||
{
|
|
||||||
if (pHook->pPreHook)
|
|
||||||
{
|
|
||||||
g_Forwards.ReleaseForward(pHook->pPreHook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pHook->pPostHook)
|
|
||||||
{
|
|
||||||
g_Forwards.ReleaseForward(pHook->pPostHook);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pHook;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pHookList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IGameEventListener2::FireGameEvent */
|
|
||||||
void EventManager::FireGameEvent(IGameEvent *pEvent)
|
|
||||||
{
|
|
||||||
/* Not going to do anything here.
|
|
||||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
|
||||||
}
|
|
||||||
|
|
||||||
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
|
||||||
{
|
|
||||||
EventHook *pHook;
|
|
||||||
|
|
||||||
/* If we aren't listening to this event... */
|
|
||||||
if (!gameevents->FindListener(this, name))
|
|
||||||
{
|
|
||||||
/* Then add ourselves */
|
|
||||||
if (!gameevents->AddListener(this, name, true))
|
|
||||||
{
|
|
||||||
/* If event doesn't exist... */
|
|
||||||
return EventHookErr_InvalidEvent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a hook structure does not exist... */
|
|
||||||
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
|
|
||||||
{
|
|
||||||
EventHookList *pHookList;
|
|
||||||
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
|
||||||
|
|
||||||
/* Check plugin for an existing EventHook list */
|
|
||||||
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
|
|
||||||
{
|
|
||||||
pHookList = new EventHookList();
|
|
||||||
plugin->SetProperty("EventHooks", pHookList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create new GameEventHook structure */
|
|
||||||
pHook = new EventHook();
|
|
||||||
|
|
||||||
if (mode == EventHookMode_Pre)
|
|
||||||
{
|
|
||||||
/* Create forward for a pre hook */
|
|
||||||
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
|
|
||||||
/* Add to forward list */
|
|
||||||
pHook->pPreHook->AddFunction(pFunction);
|
|
||||||
} else {
|
|
||||||
/* Create forward for a post hook */
|
|
||||||
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
|
||||||
/* Should we copy data from a pre hook to the post hook? */
|
|
||||||
pHook->postCopy = (mode == EventHookMode_Post);
|
|
||||||
/* Add to forward list */
|
|
||||||
pHook->pPostHook->AddFunction(pFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increase reference count */
|
|
||||||
pHook->refCount++;
|
|
||||||
|
|
||||||
/* Add hook structure to hook lists */
|
|
||||||
pHookList->push_back(pHook);
|
|
||||||
sm_trie_insert(m_EventHooks, name, pHook);
|
|
||||||
|
|
||||||
return EventHookErr_Okay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hook structure already exists at this point */
|
|
||||||
|
|
||||||
if (mode == EventHookMode_Pre)
|
|
||||||
{
|
|
||||||
/* Create pre hook forward if necessary */
|
|
||||||
if (!pHook->pPreHook)
|
|
||||||
{
|
|
||||||
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add plugin function to forward list */
|
|
||||||
pHook->pPreHook->AddFunction(pFunction);
|
|
||||||
} else {
|
|
||||||
/* Create post hook forward if necessary */
|
|
||||||
if (!pHook->pPostHook)
|
|
||||||
{
|
|
||||||
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If postCopy is false, then we may want to set it to true */
|
|
||||||
if (!pHook->postCopy)
|
|
||||||
{
|
|
||||||
pHook->postCopy = (mode == EventHookMode_Post);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add plugin function to forward list */
|
|
||||||
pHook->pPostHook->AddFunction(pFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increase reference count */
|
|
||||||
pHook->refCount++;
|
|
||||||
|
|
||||||
return EventHookErr_Okay;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
|
||||||
{
|
|
||||||
EventHook *pHook;
|
|
||||||
IChangeableForward **pEventForward;
|
|
||||||
|
|
||||||
/* If hook does not exist at all */
|
|
||||||
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
|
|
||||||
{
|
|
||||||
return EventHookErr_NotActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One forward to rule them all */
|
|
||||||
if (mode == EventHookMode_Pre)
|
|
||||||
{
|
|
||||||
pEventForward = &pHook->pPreHook;
|
|
||||||
} else {
|
|
||||||
pEventForward = &pHook->pPostHook;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove function from forward's list */
|
|
||||||
if (*pEventForward == NULL || !(*pEventForward)->RemoveFunction(pFunction))
|
|
||||||
{
|
|
||||||
return EventHookErr_InvalidCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If forward's list contains 0 functions now, free it */
|
|
||||||
if ((*pEventForward)->GetFunctionCount() == 0)
|
|
||||||
{
|
|
||||||
g_Forwards.ReleaseForward(*pEventForward);
|
|
||||||
*pEventForward = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrement reference count */
|
|
||||||
if (--pHook->refCount == 0)
|
|
||||||
{
|
|
||||||
/* If reference count is now 0, free hook structure */
|
|
||||||
|
|
||||||
EventHookList *pHookList;
|
|
||||||
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
|
||||||
|
|
||||||
/* Get plugin's event hook list */
|
|
||||||
if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
|
|
||||||
{
|
|
||||||
return EventHookErr_NotActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the event was actually being hooked */
|
|
||||||
if (pHookList->find(pHook) == pHookList->end())
|
|
||||||
{
|
|
||||||
return EventHookErr_NotActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove current structure from plugin's list */
|
|
||||||
pHookList->remove(pHook);
|
|
||||||
|
|
||||||
/* Delete entry in trie */
|
|
||||||
sm_trie_delete(m_EventHooks, name);
|
|
||||||
|
|
||||||
/* And finally free structure memory */
|
|
||||||
delete pHook;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EventHookErr_Okay;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name, bool force)
|
|
||||||
{
|
|
||||||
EventInfo *pInfo;
|
|
||||||
IGameEvent *pEvent = gameevents->CreateEvent(name, force);
|
|
||||||
|
|
||||||
if (pEvent)
|
|
||||||
{
|
|
||||||
if (m_FreeEvents.empty())
|
|
||||||
{
|
|
||||||
pInfo = new EventInfo();
|
|
||||||
} else {
|
|
||||||
pInfo = m_FreeEvents.front();
|
|
||||||
m_FreeEvents.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pInfo->pEvent = pEvent;
|
|
||||||
pInfo->pOwner = pContext->GetIdentity();
|
|
||||||
|
|
||||||
return pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
|
|
||||||
{
|
|
||||||
/* Actually fire event now */
|
|
||||||
gameevents->FireEvent(pInfo->pEvent, bDontBroadcast);
|
|
||||||
|
|
||||||
/* IGameEvent is free at this point, so no one owns this */
|
|
||||||
pInfo->pOwner = NULL;
|
|
||||||
|
|
||||||
/* Add EventInfo struct to free event stack */
|
|
||||||
m_FreeEvents.push(pInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventManager::CancelCreatedEvent(EventInfo *pInfo)
|
|
||||||
{
|
|
||||||
/* Free event from IGameEventManager2 */
|
|
||||||
gameevents->FreeEvent(pInfo->pEvent);
|
|
||||||
|
|
||||||
/* IGameEvent is free at this point, so no one owns this */
|
|
||||||
pInfo->pOwner = NULL;
|
|
||||||
|
|
||||||
/* Add EventInfo struct to free event stack */
|
|
||||||
m_FreeEvents.push(pInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IGameEventManager2::FireEvent hook */
|
|
||||||
bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|
||||||
{
|
|
||||||
EventHook *pHook;
|
|
||||||
IChangeableForward *pForward;
|
|
||||||
const char *name;
|
|
||||||
cell_t res = Pl_Continue;
|
|
||||||
|
|
||||||
/* Get the event name, we're going to need this for passing to post hooks */
|
|
||||||
name = pEvent->GetName();
|
|
||||||
|
|
||||||
m_EventNames.push(name);
|
|
||||||
|
|
||||||
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
|
|
||||||
{
|
|
||||||
pForward = pHook->pPreHook;
|
|
||||||
|
|
||||||
if (pForward)
|
|
||||||
{
|
|
||||||
EventInfo info = { pEvent, NULL };
|
|
||||||
|
|
||||||
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
|
||||||
pForward->PushCell(hndl);
|
|
||||||
pForward->PushString(name);
|
|
||||||
pForward->PushCell(bDontBroadcast);
|
|
||||||
pForward->Execute(&res, NULL);
|
|
||||||
|
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pHook->postCopy)
|
|
||||||
{
|
|
||||||
pHook->pEventCopy = gameevents->DuplicateEvent(pEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
gameevents->FreeEvent(pEvent);
|
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IGameEventManager2::FireEvent post hook */
|
|
||||||
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
|
||||||
{
|
|
||||||
IGameEvent *pEventCopy = NULL;
|
|
||||||
EventHook *pHook;
|
|
||||||
IChangeableForward *pForward;
|
|
||||||
const char *name;
|
|
||||||
Handle_t hndl = 0;
|
|
||||||
|
|
||||||
name = m_EventNames.front();
|
|
||||||
|
|
||||||
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
|
|
||||||
{
|
|
||||||
pForward = pHook->pPostHook;
|
|
||||||
|
|
||||||
if (pForward)
|
|
||||||
{
|
|
||||||
EventInfo info = { pHook->pEventCopy, NULL };
|
|
||||||
|
|
||||||
if (pHook->postCopy)
|
|
||||||
{
|
|
||||||
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
|
||||||
|
|
||||||
pForward->PushCell(hndl);
|
|
||||||
} else {
|
|
||||||
pForward->PushCell(BAD_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pForward->PushString(name);
|
|
||||||
pForward->PushCell(bDontBroadcast);
|
|
||||||
pForward->Execute(NULL);
|
|
||||||
|
|
||||||
if (pHook->postCopy)
|
|
||||||
{
|
|
||||||
/* Free handle */
|
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
|
||||||
|
|
||||||
/* Free event structure */
|
|
||||||
gameevents->FreeEvent(pEventCopy);
|
|
||||||
pHook->pEventCopy = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_EventNames.pop();
|
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
||||||
}
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include <IHandleSys.h>
|
|
||||||
#include <IForwardSys.h>
|
|
||||||
#include <IPluginSys.h>
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
struct EventInfo
|
|
||||||
{
|
|
||||||
IGameEvent *pEvent;
|
|
||||||
IdentityToken_t *pOwner;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EventHook
|
|
||||||
{
|
|
||||||
EventHook()
|
|
||||||
{
|
|
||||||
pPreHook = NULL;
|
|
||||||
pPostHook = NULL;
|
|
||||||
postCopy = false;
|
|
||||||
pEventCopy = NULL;
|
|
||||||
refCount = 0;
|
|
||||||
}
|
|
||||||
IChangeableForward *pPreHook;
|
|
||||||
IChangeableForward *pPostHook;
|
|
||||||
bool postCopy;
|
|
||||||
IGameEvent *pEventCopy;
|
|
||||||
unsigned int refCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EventHookMode
|
|
||||||
{
|
|
||||||
EventHookMode_Pre,
|
|
||||||
EventHookMode_Post,
|
|
||||||
EventHookMode_PostNoCopy
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EventHookError
|
|
||||||
{
|
|
||||||
EventHookErr_Okay = 0, /**< No error */
|
|
||||||
EventHookErr_InvalidEvent, /**< Specified event does not exist */
|
|
||||||
EventHookErr_NotActive, /**< Specified event has no active hook */
|
|
||||||
EventHookErr_InvalidCallback, /**< Specified event does not fire specified callback */
|
|
||||||
};
|
|
||||||
|
|
||||||
class EventManager :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IHandleTypeDispatch,
|
|
||||||
public IPluginsListener,
|
|
||||||
public IGameEventListener2
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EventManager();
|
|
||||||
~EventManager();
|
|
||||||
public: // SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: // IHandleTypeDispatch
|
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
|
||||||
public: // IPluginsListener
|
|
||||||
void OnPluginUnloaded(IPlugin *plugin);
|
|
||||||
public: // IGameEventListener2
|
|
||||||
void FireGameEvent(IGameEvent *pEvent);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Get the 'GameEvent' handle type ID.
|
|
||||||
*/
|
|
||||||
inline HandleType_t GetHandleType()
|
|
||||||
{
|
|
||||||
return m_EventType;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
EventHookError HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
|
|
||||||
EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
|
|
||||||
EventInfo *CreateEvent(IPluginContext *pContext, const char *name, bool force=false);
|
|
||||||
void FireEvent(EventInfo *pInfo, bool bDontBroadcast=false);
|
|
||||||
void CancelCreatedEvent(EventInfo *pInfo);
|
|
||||||
private: // IGameEventManager2 hooks
|
|
||||||
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);
|
|
||||||
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
|
|
||||||
private:
|
|
||||||
HandleType_t m_EventType;
|
|
||||||
Trie *m_EventHooks;
|
|
||||||
CStack<EventInfo *> m_FreeEvents;
|
|
||||||
CStack<const char *> m_EventNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern EventManager g_EventManager;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_EVENTMANAGER_H_
|
|
||||||
@ -1,664 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "GameConfigs.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "HalfLife2.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "MemoryUtils.h"
|
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sm_crc32.h"
|
|
||||||
|
|
||||||
#if defined PLATFORM_LINUX
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GameConfigManager g_GameConfigs;
|
|
||||||
IGameConfig *g_pGameConf = NULL;
|
|
||||||
char g_Game[256];
|
|
||||||
char g_GameDesc[256] = {'!', '\0'};
|
|
||||||
|
|
||||||
#define PSTATE_NONE 0
|
|
||||||
#define PSTATE_GAMES 1
|
|
||||||
#define PSTATE_GAMEDEFS 2
|
|
||||||
#define PSTATE_GAMEDEFS_OFFSETS 3
|
|
||||||
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
|
|
||||||
#define PSTATE_GAMEDEFS_KEYS 5
|
|
||||||
#define PSTATE_GAMEDEFS_SUPPORTED 6
|
|
||||||
#define PSTATE_GAMEDEFS_SIGNATURES 7
|
|
||||||
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 8
|
|
||||||
#define PSTATE_GAMEDEFS_CRC 9
|
|
||||||
#define PSTATE_GAMEDEFS_CRC_BINARY 10
|
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
#define PLATFORM_NAME "windows"
|
|
||||||
#define PLATFORM_SERVER_BINARY "server.dll"
|
|
||||||
#elif defined PLATFORM_LINUX
|
|
||||||
#define PLATFORM_NAME "linux"
|
|
||||||
#define PLATFORM_SERVER_BINARY "server_i486.so"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct TempSigInfo
|
|
||||||
{
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
library[0] = '\0';
|
|
||||||
sig[0] = '\0';
|
|
||||||
}
|
|
||||||
char sig[512];
|
|
||||||
char library[64];
|
|
||||||
} s_TempSig;
|
|
||||||
unsigned int s_ServerBinCRC;
|
|
||||||
bool s_ServerBinCRC_Ok = false;
|
|
||||||
|
|
||||||
CGameConfig::CGameConfig(const char *file)
|
|
||||||
{
|
|
||||||
m_pFile = sm_strdup(file);
|
|
||||||
m_pOffsets = sm_trie_create();
|
|
||||||
m_pProps = sm_trie_create();
|
|
||||||
m_pKeys = sm_trie_create();
|
|
||||||
m_pSigs = sm_trie_create();
|
|
||||||
m_pStrings = new BaseStringTable(512);
|
|
||||||
m_RefCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGameConfig::~CGameConfig()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_pOffsets);
|
|
||||||
sm_trie_destroy(m_pProps);
|
|
||||||
sm_trie_destroy(m_pKeys);
|
|
||||||
sm_trie_destroy(m_pSigs);
|
|
||||||
delete [] m_pFile;
|
|
||||||
delete m_pStrings;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
|
||||||
{
|
|
||||||
if (m_IgnoreLevel)
|
|
||||||
{
|
|
||||||
m_IgnoreLevel++;
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_ParseState)
|
|
||||||
{
|
|
||||||
case PSTATE_NONE:
|
|
||||||
{
|
|
||||||
if (strcmp(name, "Games") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMES;
|
|
||||||
} else {
|
|
||||||
m_IgnoreLevel++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMES:
|
|
||||||
{
|
|
||||||
if ((strcmp(name, "*") == 0)
|
|
||||||
|| (strcmp(name, "#default") == 0)
|
|
||||||
|| (strcasecmp(name, g_Game) == 0)
|
|
||||||
|| (strcasecmp(name, g_GameDesc) == 0))
|
|
||||||
{
|
|
||||||
bShouldBeReadingDefault = true;
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
|
||||||
strncopy(m_Game, name, sizeof(m_Game));
|
|
||||||
} else {
|
|
||||||
m_IgnoreLevel++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS:
|
|
||||||
{
|
|
||||||
if (strcmp(name, "Offsets") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "Keys") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_KEYS;
|
|
||||||
}
|
|
||||||
else if ((strcmp(name, "#supported") == 0)
|
|
||||||
&& (strcmp(m_Game, "#default") == 0))
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
|
|
||||||
/* Ignore this section unless we get a game. */
|
|
||||||
bShouldBeReadingDefault = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "Signatures") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, "CRC") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_CRC;
|
|
||||||
bShouldBeReadingDefault = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_IgnoreLevel++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_OFFSETS:
|
|
||||||
{
|
|
||||||
m_Prop[0] = '\0';
|
|
||||||
m_Class[0] = '\0';
|
|
||||||
strncopy(m_offset, name, sizeof(m_offset));
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES:
|
|
||||||
{
|
|
||||||
strncopy(m_offset, name, sizeof(m_offset));
|
|
||||||
s_TempSig.Reset();
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_CRC:
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
error[0] = '\0';
|
|
||||||
if (strcmp(name, "server") != 0)
|
|
||||||
{
|
|
||||||
UTIL_Format(error, sizeof(error), "Unrecognized library \"%s\"", name);
|
|
||||||
}
|
|
||||||
else if (!s_ServerBinCRC_Ok)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "bin/" PLATFORM_SERVER_BINARY);
|
|
||||||
if ((fp = fopen(path, "rb")) == NULL)
|
|
||||||
{
|
|
||||||
UTIL_Format(error, sizeof(error), "Could not open binary: %s", path);
|
|
||||||
} else {
|
|
||||||
size_t size;
|
|
||||||
void *buffer;
|
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
size = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
|
|
||||||
buffer = malloc(size);
|
|
||||||
fread(buffer, size, 1, fp);
|
|
||||||
s_ServerBinCRC = UTIL_CRC32(buffer, size);
|
|
||||||
free(buffer);
|
|
||||||
s_ServerBinCRC_Ok = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error[0] != '\0')
|
|
||||||
{
|
|
||||||
m_IgnoreLevel = 1;
|
|
||||||
g_Logger.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_pFile);
|
|
||||||
g_Logger.LogError("[SM] %s", error);
|
|
||||||
} else {
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* No sub-sections allowed:
|
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
|
||||||
case PSTATE_GAMEDEFS_KEYS:
|
|
||||||
case PSTATE_GAMEDEFS_SUPPORTED:
|
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
|
||||||
case PSTATE_GAMEDEFS_CRC_BINARY:
|
|
||||||
*/
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* If we don't know what we got, start ignoring */
|
|
||||||
m_IgnoreLevel++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
if (m_IgnoreLevel)
|
|
||||||
{
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == PSTATE_GAMEDEFS_OFFSETS_OFFSET)
|
|
||||||
{
|
|
||||||
if (strcmp(key, "class") == 0)
|
|
||||||
{
|
|
||||||
strncopy(m_Class, value, sizeof(m_Class));
|
|
||||||
} else if (strcmp(key, "prop") == 0) {
|
|
||||||
strncopy(m_Prop, value, sizeof(m_Prop));
|
|
||||||
} else if (strcmp(key, PLATFORM_NAME) == 0) {
|
|
||||||
int val = atoi(value);
|
|
||||||
sm_trie_replace(m_pOffsets, m_offset, (void *)val);
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
|
|
||||||
int id = m_pStrings->AddString(value);
|
|
||||||
sm_trie_replace(m_pKeys, key, (void *)id);
|
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
|
|
||||||
if (strcmp(key, "game") == 0
|
|
||||||
&& (strcasecmp(value, g_Game) == 0 || strcasecmp(value, g_GameDesc) == 0))
|
|
||||||
{
|
|
||||||
bShouldBeReadingDefault = true;
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
|
|
||||||
if (strcmp(key, PLATFORM_NAME) == 0)
|
|
||||||
{
|
|
||||||
strncopy(s_TempSig.sig, value, sizeof(s_TempSig.sig));
|
|
||||||
} else if (strcmp(key, "library") == 0) {
|
|
||||||
strncopy(s_TempSig.library, value, sizeof(s_TempSig.library));
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) {
|
|
||||||
if (strcmp(key, PLATFORM_NAME) == 0
|
|
||||||
&& s_ServerBinCRC_Ok
|
|
||||||
&& !bShouldBeReadingDefault)
|
|
||||||
{
|
|
||||||
unsigned int crc = 0;
|
|
||||||
sscanf(value, "%08X", &crc);
|
|
||||||
if (s_ServerBinCRC == crc)
|
|
||||||
{
|
|
||||||
bShouldBeReadingDefault = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|
||||||
{
|
|
||||||
if (m_IgnoreLevel)
|
|
||||||
{
|
|
||||||
m_IgnoreLevel--;
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_ParseState)
|
|
||||||
{
|
|
||||||
case PSTATE_GAMES:
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_NONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS:
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMES;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_KEYS:
|
|
||||||
case PSTATE_GAMEDEFS_OFFSETS:
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
|
||||||
{
|
|
||||||
/* Parse the offset... */
|
|
||||||
if (m_Class[0] != '\0'
|
|
||||||
&& m_Prop[0] != '\0')
|
|
||||||
{
|
|
||||||
SendProp *pProp = g_HL2.FindInSendTable(m_Class, m_Prop);
|
|
||||||
if (pProp)
|
|
||||||
{
|
|
||||||
int val = pProp->GetOffset();
|
|
||||||
sm_trie_replace(m_pOffsets, m_offset, (void *)val);
|
|
||||||
sm_trie_replace(m_pProps, m_offset, pProp);
|
|
||||||
} else {
|
|
||||||
/* Check if it's a non-default game and no offsets exist */
|
|
||||||
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
|
|
||||||
&& (!sm_trie_retrieve(m_pOffsets, m_offset, NULL)))
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
|
||||||
m_Class,
|
|
||||||
m_Prop,
|
|
||||||
m_pFile,
|
|
||||||
m_Game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_CRC:
|
|
||||||
case PSTATE_GAMEDEFS_SUPPORTED:
|
|
||||||
{
|
|
||||||
if (!bShouldBeReadingDefault)
|
|
||||||
{
|
|
||||||
/* If we shouldn't read the rest of this section, set the ignore level. */
|
|
||||||
m_IgnoreLevel = 1;
|
|
||||||
m_ParseState = PSTATE_GAMES;
|
|
||||||
} else {
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_CRC_BINARY:
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_CRC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES:
|
|
||||||
{
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
|
||||||
{
|
|
||||||
if (s_TempSig.library[0] == '\0')
|
|
||||||
{
|
|
||||||
/* assume server */
|
|
||||||
strncopy(s_TempSig.library, "server", sizeof(s_TempSig.library));
|
|
||||||
}
|
|
||||||
void *addrInBase = NULL;
|
|
||||||
if (strcmp(s_TempSig.library, "server") == 0)
|
|
||||||
{
|
|
||||||
addrInBase = (void *)g_SMAPI->GetServerFactory(false);
|
|
||||||
} else if (strcmp(s_TempSig.library, "engine") == 0) {
|
|
||||||
addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
|
|
||||||
}
|
|
||||||
void *final_addr = NULL;
|
|
||||||
if (addrInBase == NULL)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
|
||||||
s_TempSig.library,
|
|
||||||
m_pFile);
|
|
||||||
} else {
|
|
||||||
#if defined PLATFORM_LINUX
|
|
||||||
if (s_TempSig.sig[0] == '@')
|
|
||||||
{
|
|
||||||
Dl_info info;
|
|
||||||
/* GNU only: returns 0 on error, inconsistent! >:[ */
|
|
||||||
if (dladdr(addrInBase, &info) != 0)
|
|
||||||
{
|
|
||||||
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
|
||||||
dlclose(handle);
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
|
||||||
s_TempSig.library,
|
|
||||||
m_pFile);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
|
|
||||||
s_TempSig.library,
|
|
||||||
m_pFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (final_addr)
|
|
||||||
{
|
|
||||||
goto skip_find;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* First, preprocess the signature */
|
|
||||||
char real_sig[255];
|
|
||||||
size_t real_bytes;
|
|
||||||
size_t length;
|
|
||||||
|
|
||||||
real_bytes = 0;
|
|
||||||
length = strlen(s_TempSig.sig);
|
|
||||||
|
|
||||||
for (size_t i=0; i<length; i++)
|
|
||||||
{
|
|
||||||
if (real_bytes >= sizeof(real_sig))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
real_sig[real_bytes++] = s_TempSig.sig[i];
|
|
||||||
if (s_TempSig.sig[i] == '\\'
|
|
||||||
&& s_TempSig.sig[i+1] == 'x')
|
|
||||||
{
|
|
||||||
if (i + 3 >= length)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Get the hex part */
|
|
||||||
char s_byte[3];
|
|
||||||
int r_byte;
|
|
||||||
s_byte[0] = s_TempSig.sig[i+2];
|
|
||||||
s_byte[1] = s_TempSig.sig[i+3];
|
|
||||||
s_byte[2] = '\0';
|
|
||||||
/* Read it as an integer */
|
|
||||||
sscanf(s_byte, "%x", &r_byte);
|
|
||||||
/* Save the value */
|
|
||||||
real_sig[real_bytes-1] = r_byte;
|
|
||||||
/* Adjust index */
|
|
||||||
i += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (real_bytes >= 1)
|
|
||||||
{
|
|
||||||
final_addr = g_MemUtils.FindPattern(addrInBase, real_sig, real_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined PLATFORM_LINUX
|
|
||||||
skip_find:
|
|
||||||
#endif
|
|
||||||
sm_trie_replace(m_pSigs, m_offset, final_addr);
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|
||||||
{
|
|
||||||
SMCError err;
|
|
||||||
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s.txt", m_pFile);
|
|
||||||
/* Backwards compatibility */
|
|
||||||
if (!g_LibSys.PathExists(path))
|
|
||||||
{
|
|
||||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize parse states */
|
|
||||||
m_IgnoreLevel = 0;
|
|
||||||
bShouldBeReadingDefault = true;
|
|
||||||
m_ParseState = PSTATE_NONE;
|
|
||||||
/* Reset cached data */
|
|
||||||
m_pStrings->Reset();
|
|
||||||
sm_trie_clear(m_pOffsets);
|
|
||||||
sm_trie_clear(m_pProps);
|
|
||||||
sm_trie_clear(m_pKeys);
|
|
||||||
|
|
||||||
if ((err=textparsers->ParseFile_SMC(path, this, NULL))
|
|
||||||
!= SMCError_Okay)
|
|
||||||
{
|
|
||||||
if (error && (err != SMCError_Custom))
|
|
||||||
{
|
|
||||||
const char *str = textparsers->GetSMCErrorString(err);
|
|
||||||
snprintf(error, maxlength, "%s", str);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CGameConfig::GetOffset(const char *key, int *value)
|
|
||||||
{
|
|
||||||
void *obj;
|
|
||||||
|
|
||||||
if (!sm_trie_retrieve(m_pOffsets, key, &obj))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*value = (int)obj;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CGameConfig::GetKeyValue(const char *key)
|
|
||||||
{
|
|
||||||
void *obj;
|
|
||||||
if (!sm_trie_retrieve(m_pKeys, key, &obj))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return m_pStrings->GetString((int)obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
SendProp *CGameConfig::GetSendProp(const char *key)
|
|
||||||
{
|
|
||||||
SendProp *pProp;
|
|
||||||
|
|
||||||
if (!sm_trie_retrieve(m_pProps, key, (void **)&pProp))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pProp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CGameConfig::GetMemSig(const char *key, void **addr)
|
|
||||||
{
|
|
||||||
return sm_trie_retrieve(m_pSigs, key, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGameConfig::IncRefCount()
|
|
||||||
{
|
|
||||||
m_RefCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CGameConfig::DecRefCount()
|
|
||||||
{
|
|
||||||
m_RefCount--;
|
|
||||||
return m_RefCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameConfigManager::GameConfigManager()
|
|
||||||
{
|
|
||||||
m_pLookup = sm_trie_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
GameConfigManager::~GameConfigManager()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_pLookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameConfigManager::OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
|
|
||||||
|
|
||||||
strncopy(g_Game, g_SourceMod.GetGameFolderName(), sizeof(g_Game));
|
|
||||||
strncopy(g_GameDesc + 1, SERVER_CALL(GetGameDescription)(), sizeof(g_GameDesc) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameConfigManager::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
/* NOW initialize the game file */
|
|
||||||
CGameConfig *pGameConf = (CGameConfig *)g_pGameConf;
|
|
||||||
|
|
||||||
char error[255];
|
|
||||||
if (!pGameConf->Reparse(error, sizeof(error)))
|
|
||||||
{
|
|
||||||
/* :TODO: log */
|
|
||||||
}
|
|
||||||
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameConfigManager::OnSourceModAllShutdown()
|
|
||||||
{
|
|
||||||
CloseGameConfigFile(g_pGameConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength)
|
|
||||||
{
|
|
||||||
CGameConfig *pConfig;
|
|
||||||
|
|
||||||
if (sm_trie_retrieve(m_pLookup, file, (void **)&pConfig))
|
|
||||||
{
|
|
||||||
pConfig->IncRefCount();
|
|
||||||
*_pConfig = pConfig;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pConfig = new CGameConfig(file);
|
|
||||||
|
|
||||||
/* :HACKHACK: Don't parse the main config file */
|
|
||||||
bool retval = true;
|
|
||||||
if (_pConfig != &g_pGameConf)
|
|
||||||
{
|
|
||||||
retval = pConfig->Reparse(error, maxlength);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_cfgs.push_back(pConfig);
|
|
||||||
sm_trie_insert(m_pLookup, file, pConfig);
|
|
||||||
|
|
||||||
pConfig->IncRefCount();
|
|
||||||
|
|
||||||
*_pConfig = pConfig;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg)
|
|
||||||
{
|
|
||||||
CGameConfig *pConfig = (CGameConfig *)cfg;
|
|
||||||
|
|
||||||
if (pConfig->DecRefCount() == 0)
|
|
||||||
{
|
|
||||||
sm_trie_delete(m_pLookup, pConfig->m_pFile);
|
|
||||||
delete pConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern HandleType_t g_GameConfigsType;
|
|
||||||
|
|
||||||
IGameConfig *GameConfigManager::ReadHandle(Handle_t hndl, IdentityToken_t *ident, HandleError *err)
|
|
||||||
{
|
|
||||||
HandleSecurity sec(ident, g_pCoreIdent);
|
|
||||||
IGameConfig *conf = NULL;
|
|
||||||
HandleError _err = g_HandleSys.ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&conf);
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
*err = _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
|
||||||
|
|
||||||
#include <IGameConfigs.h>
|
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class SendProp;
|
|
||||||
|
|
||||||
class CGameConfig :
|
|
||||||
public ITextListener_SMC,
|
|
||||||
public IGameConfig
|
|
||||||
{
|
|
||||||
friend class GameConfigManager;
|
|
||||||
public:
|
|
||||||
CGameConfig(const char *file);
|
|
||||||
~CGameConfig();
|
|
||||||
public:
|
|
||||||
bool Reparse(char *error, size_t maxlength);
|
|
||||||
public: //ITextListener_SMC
|
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
|
||||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
|
||||||
public: //IGameConfig
|
|
||||||
const char *GetKeyValue(const char *key);
|
|
||||||
bool GetOffset(const char *key, int *value);
|
|
||||||
SendProp *GetSendProp(const char *key);
|
|
||||||
bool GetMemSig(const char *key, void **addr);
|
|
||||||
public:
|
|
||||||
void IncRefCount();
|
|
||||||
unsigned int DecRefCount();
|
|
||||||
private:
|
|
||||||
BaseStringTable *m_pStrings;
|
|
||||||
char *m_pFile;
|
|
||||||
Trie *m_pOffsets;
|
|
||||||
Trie *m_pProps;
|
|
||||||
Trie *m_pKeys;
|
|
||||||
Trie *m_pSigs;
|
|
||||||
unsigned int m_RefCount;
|
|
||||||
/* Parse states */
|
|
||||||
int m_ParseState;
|
|
||||||
unsigned int m_IgnoreLevel;
|
|
||||||
char m_Class[64];
|
|
||||||
char m_Prop[64];
|
|
||||||
char m_offset[64];
|
|
||||||
char m_Game[256];
|
|
||||||
bool bShouldBeReadingDefault;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GameConfigManager :
|
|
||||||
public IGameConfigManager,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GameConfigManager();
|
|
||||||
~GameConfigManager();
|
|
||||||
public: //IGameConfigManager
|
|
||||||
bool LoadGameConfigFile(const char *file, IGameConfig **pConfig, char *error, size_t maxlength);
|
|
||||||
void CloseGameConfigFile(IGameConfig *cfg);
|
|
||||||
IGameConfig *ReadHandle(Handle_t hndl,
|
|
||||||
IdentityToken_t *ident,
|
|
||||||
HandleError *err);
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModStartup(bool late);
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModAllShutdown();
|
|
||||||
private:
|
|
||||||
List<CGameConfig *> m_cfgs;
|
|
||||||
Trie *m_pLookup;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern GameConfigManager g_GameConfigs;
|
|
||||||
extern IGameConfig *g_pGameConf;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
|
||||||
@ -1,441 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "HalfLife2.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "UserMessages.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "GameConfigs.h"
|
|
||||||
#include <compat_wrappers.h>
|
|
||||||
|
|
||||||
CHalfLife2 g_HL2;
|
|
||||||
ConVar *sv_lan = NULL;
|
|
||||||
|
|
||||||
namespace SourceHook
|
|
||||||
{
|
|
||||||
template<>
|
|
||||||
int HashFunction<datamap_t *>(datamap_t * const &k)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<int>(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
int Compare<datamap_t *>(datamap_t * const &k1, datamap_t * const &k2)
|
|
||||||
{
|
|
||||||
return (k1-k2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHalfLife2::CHalfLife2()
|
|
||||||
{
|
|
||||||
m_pClasses = sm_trie_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
CHalfLife2::~CHalfLife2()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_pClasses);
|
|
||||||
|
|
||||||
List<DataTableInfo *>::iterator iter;
|
|
||||||
DataTableInfo *pInfo;
|
|
||||||
for (iter=m_Tables.begin(); iter!=m_Tables.end(); iter++)
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
sm_trie_destroy(pInfo->lookup);
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Tables.clear();
|
|
||||||
|
|
||||||
THash<datamap_t *, DataMapTrie>::iterator h_iter;
|
|
||||||
for (h_iter=m_Maps.begin(); h_iter!=m_Maps.end(); h_iter++)
|
|
||||||
{
|
|
||||||
if (h_iter->val.trie)
|
|
||||||
{
|
|
||||||
sm_trie_destroy(h_iter->val.trie);
|
|
||||||
h_iter->val.trie = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Maps.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
|
|
||||||
bool is_original_engine = false;
|
|
||||||
|
|
||||||
void CHalfLife2::OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
/* The Ship currently is the only known game to use an older version of the engine */
|
|
||||||
#if defined METAMOD_PLAPI_VERSION
|
|
||||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
|
||||||
#else
|
|
||||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
is_original_engine = true;
|
|
||||||
}
|
|
||||||
else if (g_pSharedChangeInfo == NULL)
|
|
||||||
{
|
|
||||||
g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHalfLife2::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
m_MsgTextMsg = g_UserMsgs.GetMessageIndex("TextMsg");
|
|
||||||
m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText");
|
|
||||||
m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu");
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined METAMOD_PLAPI_VERSION
|
|
||||||
bool CHalfLife2::IsOriginalEngine()
|
|
||||||
{
|
|
||||||
return is_original_engine;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
|
|
||||||
{
|
|
||||||
return engine->GetChangeAccessor( (const edict_t *)this );
|
|
||||||
}
|
|
||||||
|
|
||||||
SendProp *UTIL_FindInSendTable(SendTable *pTable, const char *name)
|
|
||||||
{
|
|
||||||
const char *pname;
|
|
||||||
int props = pTable->GetNumProps();
|
|
||||||
SendProp *prop;
|
|
||||||
|
|
||||||
for (int i=0; i<props; i++)
|
|
||||||
{
|
|
||||||
prop = pTable->GetProp(i);
|
|
||||||
pname = prop->GetName();
|
|
||||||
if (pname && strcmp(name, pname) == 0)
|
|
||||||
{
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
if (prop->GetDataTable())
|
|
||||||
{
|
|
||||||
if ((prop=UTIL_FindInSendTable(prop->GetDataTable(), name)) != NULL)
|
|
||||||
{
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
|
|
||||||
{
|
|
||||||
while (pMap)
|
|
||||||
{
|
|
||||||
for (int i=0; i<pMap->dataNumFields; i++)
|
|
||||||
{
|
|
||||||
if (pMap->dataDesc[i].fieldName == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
|
|
||||||
{
|
|
||||||
return &(pMap->dataDesc[i]);
|
|
||||||
}
|
|
||||||
if (pMap->dataDesc[i].td)
|
|
||||||
{
|
|
||||||
typedescription_t *_td;
|
|
||||||
if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
|
|
||||||
{
|
|
||||||
return _td;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pMap = pMap->baseMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerClass *CHalfLife2::FindServerClass(const char *classname)
|
|
||||||
{
|
|
||||||
DataTableInfo *pInfo = _FindServerClass(classname);
|
|
||||||
if (!pInfo)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pInfo->sc;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
|
|
||||||
{
|
|
||||||
DataTableInfo *pInfo = NULL;
|
|
||||||
|
|
||||||
if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
|
|
||||||
{
|
|
||||||
ServerClass *sc = gamedll->GetAllServerClasses();
|
|
||||||
while (sc)
|
|
||||||
{
|
|
||||||
if (strcmp(classname, sc->GetName()) == 0)
|
|
||||||
{
|
|
||||||
pInfo = new DataTableInfo;
|
|
||||||
pInfo->lookup = sm_trie_create();
|
|
||||||
pInfo->sc = sc;
|
|
||||||
sm_trie_insert(m_pClasses, classname, pInfo);
|
|
||||||
m_Tables.push_back(pInfo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sc = sc->m_pNext;
|
|
||||||
}
|
|
||||||
if (!pInfo)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
|
|
||||||
{
|
|
||||||
DataTableInfo *pInfo = _FindServerClass(classname);
|
|
||||||
|
|
||||||
if (!pInfo)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendProp *pProp = NULL;
|
|
||||||
if (!sm_trie_retrieve(pInfo->lookup, offset, (void **)&pProp))
|
|
||||||
{
|
|
||||||
if ((pProp = UTIL_FindInSendTable(pInfo->sc->m_pTable, offset)) != NULL)
|
|
||||||
{
|
|
||||||
sm_trie_insert(pInfo->lookup, offset, pProp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pProp;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
|
|
||||||
{
|
|
||||||
typedescription_t *td = NULL;
|
|
||||||
DataMapTrie &val = m_Maps[pMap];
|
|
||||||
|
|
||||||
if (!val.trie)
|
|
||||||
{
|
|
||||||
val.trie = sm_trie_create();
|
|
||||||
}
|
|
||||||
if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
|
|
||||||
{
|
|
||||||
if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
|
|
||||||
{
|
|
||||||
sm_trie_insert(val.trie, offset, td);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return td;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
|
|
||||||
{
|
|
||||||
if (g_pSharedChangeInfo != NULL)
|
|
||||||
{
|
|
||||||
if (offset)
|
|
||||||
{
|
|
||||||
pEdict->StateChanged(offset);
|
|
||||||
} else {
|
|
||||||
pEdict->StateChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
|
||||||
{
|
|
||||||
bf_write *pBitBuf = NULL;
|
|
||||||
cell_t players[] = {client};
|
|
||||||
|
|
||||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBitBuf->WriteByte(dest);
|
|
||||||
pBitBuf->WriteString(msg);
|
|
||||||
g_UserMsgs.EndMessage();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
|
||||||
{
|
|
||||||
bf_write *pBitBuf = NULL;
|
|
||||||
cell_t players[] = {client};
|
|
||||||
|
|
||||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *pre_byte = g_pGameConf->GetKeyValue("HintTextPreByte");
|
|
||||||
if (pre_byte != NULL && strcmp(pre_byte, "yes") == 0)
|
|
||||||
{
|
|
||||||
pBitBuf->WriteByte(1);
|
|
||||||
}
|
|
||||||
pBitBuf->WriteString(msg);
|
|
||||||
g_UserMsgs.EndMessage();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
|
|
||||||
{
|
|
||||||
bf_write *pBitBuf = NULL;
|
|
||||||
KeyValues *SubKey = NULL;
|
|
||||||
int count = 0;
|
|
||||||
cell_t players[] = {client};
|
|
||||||
|
|
||||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data)
|
|
||||||
{
|
|
||||||
SubKey = data->GetFirstSubKey();
|
|
||||||
while (SubKey)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
SubKey = SubKey->GetNextKey();
|
|
||||||
}
|
|
||||||
SubKey = data->GetFirstSubKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
pBitBuf->WriteString(name);
|
|
||||||
pBitBuf->WriteByte((show) ? 1 : 0);
|
|
||||||
pBitBuf->WriteByte(count);
|
|
||||||
while (SubKey)
|
|
||||||
{
|
|
||||||
pBitBuf->WriteString(SubKey->GetName());
|
|
||||||
pBitBuf->WriteString(SubKey->GetString());
|
|
||||||
SubKey = SubKey->GetNextKey();
|
|
||||||
}
|
|
||||||
g_UserMsgs.EndMessage();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHalfLife2::AddToFakeCliCmdQueue(int client, int userid, const char *cmd)
|
|
||||||
{
|
|
||||||
DelayedFakeCliCmd *pFake;
|
|
||||||
|
|
||||||
if (m_FreeCmds.empty())
|
|
||||||
{
|
|
||||||
pFake = new DelayedFakeCliCmd;
|
|
||||||
} else {
|
|
||||||
pFake = m_FreeCmds.front();
|
|
||||||
m_FreeCmds.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pFake->client = client;
|
|
||||||
pFake->userid = userid;
|
|
||||||
pFake->cmd.assign(cmd);
|
|
||||||
|
|
||||||
m_CmdQueue.push(pFake);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHalfLife2::ProcessFakeCliCmdQueue()
|
|
||||||
{
|
|
||||||
while (!m_CmdQueue.empty())
|
|
||||||
{
|
|
||||||
DelayedFakeCliCmd *pFake = m_CmdQueue.first();
|
|
||||||
|
|
||||||
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
|
|
||||||
{
|
|
||||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
|
|
||||||
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_CmdQueue.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CHalfLife2::IsLANServer()
|
|
||||||
{
|
|
||||||
sv_lan = icvar->FindVar("sv_lan");
|
|
||||||
|
|
||||||
if (!sv_lan)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sv_lan->GetInt() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHalfLife2::PushCommandStack(const CCommand *cmd)
|
|
||||||
{
|
|
||||||
CachedCommandInfo info;
|
|
||||||
|
|
||||||
info.args = cmd;
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
|
||||||
strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_CommandStack.push(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CCommand *CHalfLife2::PeekCommandStack()
|
|
||||||
{
|
|
||||||
if (m_CommandStack.empty())
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_CommandStack.front().args;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHalfLife2::PopCommandStack()
|
|
||||||
{
|
|
||||||
m_CommandStack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CHalfLife2::CurrentCommandName()
|
|
||||||
{
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
return m_CommandStack.front().args->Arg(0);
|
|
||||||
#else
|
|
||||||
return m_CommandStack.front().cmd;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
127
core/HalfLife2.h
127
core/HalfLife2.h
@ -1,127 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
|
||||||
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <sh_tinyhash.h>
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sm_queue.h"
|
|
||||||
#include <IGameHelpers.h>
|
|
||||||
#include <KeyValues.h>
|
|
||||||
|
|
||||||
class CCommand;
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
#define HUD_PRINTTALK 3
|
|
||||||
#define HUD_PRINTCENTER 4
|
|
||||||
|
|
||||||
struct DataTableInfo
|
|
||||||
{
|
|
||||||
ServerClass *sc;
|
|
||||||
Trie *lookup;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DataMapTrie
|
|
||||||
{
|
|
||||||
DataMapTrie() : trie(NULL) {}
|
|
||||||
Trie *trie;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DelayedFakeCliCmd
|
|
||||||
{
|
|
||||||
String cmd;
|
|
||||||
int client;
|
|
||||||
int userid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CachedCommandInfo
|
|
||||||
{
|
|
||||||
const CCommand *args;
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
|
||||||
char cmd[300];
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class CHalfLife2 :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IGameHelpers
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CHalfLife2();
|
|
||||||
~CHalfLife2();
|
|
||||||
public:
|
|
||||||
void OnSourceModStartup(bool late);
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
/*void OnSourceModAllShutdown();*/
|
|
||||||
public: //IGameHelpers
|
|
||||||
SendProp *FindInSendTable(const char *classname, const char *offset);
|
|
||||||
datamap_t *GetDataMap(CBaseEntity *pEntity);
|
|
||||||
ServerClass *FindServerClass(const char *classname);
|
|
||||||
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
|
|
||||||
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
|
||||||
bool TextMsg(int client, int dest, const char *msg);
|
|
||||||
bool HintTextMsg(int client, const char *msg);
|
|
||||||
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
|
||||||
bool IsLANServer();
|
|
||||||
public:
|
|
||||||
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
|
||||||
void ProcessFakeCliCmdQueue();
|
|
||||||
public:
|
|
||||||
void PushCommandStack(const CCommand *cmd);
|
|
||||||
void PopCommandStack();
|
|
||||||
const CCommand *PeekCommandStack();
|
|
||||||
const char *CurrentCommandName();
|
|
||||||
#if !defined METAMOD_PLAPI_VERSION
|
|
||||||
bool IsOriginalEngine();
|
|
||||||
#endif
|
|
||||||
private:
|
|
||||||
DataTableInfo *_FindServerClass(const char *classname);
|
|
||||||
private:
|
|
||||||
Trie *m_pClasses;
|
|
||||||
List<DataTableInfo *> m_Tables;
|
|
||||||
THash<datamap_t *, DataMapTrie> m_Maps;
|
|
||||||
int m_MsgTextMsg;
|
|
||||||
int m_HinTextMsg;
|
|
||||||
int m_VGUIMenu;
|
|
||||||
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
|
||||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
|
||||||
CStack<CachedCommandInfo> m_CommandStack;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CHalfLife2 g_HL2;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
|
||||||
507
core/Logger.cpp
507
core/Logger.cpp
@ -1,507 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "systems/LibrarySys.h"
|
|
||||||
#include "TimerSys.h"
|
|
||||||
#include "sm_version.h"
|
|
||||||
|
|
||||||
Logger g_Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* :TODO: This should be creating the log folder if it doesn't exist
|
|
||||||
*/
|
|
||||||
|
|
||||||
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength)
|
|
||||||
{
|
|
||||||
if (strcasecmp(key, "Logging") == 0)
|
|
||||||
{
|
|
||||||
bool state;
|
|
||||||
|
|
||||||
if (strcasecmp(value, "on") == 0)
|
|
||||||
{
|
|
||||||
state = true;
|
|
||||||
} else if (strcasecmp(value, "off") == 0) {
|
|
||||||
state = false;
|
|
||||||
} else {
|
|
||||||
UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
|
||||||
return ConfigResult_Reject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source == ConfigSource_Console)
|
|
||||||
{
|
|
||||||
state ? EnableLogging() : DisableLogging();
|
|
||||||
} else {
|
|
||||||
m_InitialState = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
} else if (strcasecmp(key, "LogMode") == 0) {
|
|
||||||
if (strcasecmp(value, "daily") == 0)
|
|
||||||
{
|
|
||||||
m_Mode = LoggingMode_Daily;
|
|
||||||
} else if (strcasecmp(value, "map") == 0) {
|
|
||||||
m_Mode = LoggingMode_PerMap;
|
|
||||||
} else if (strcasecmp(value, "game") == 0) {
|
|
||||||
m_Mode = LoggingMode_Game;
|
|
||||||
} else {
|
|
||||||
UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]");
|
|
||||||
return ConfigResult_Reject;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
InitLogger(m_Mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::OnSourceModAllShutdown()
|
|
||||||
{
|
|
||||||
CloseLogger();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
MapChange(mapName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::_NewMapFile()
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append "Log file closed" to previous log file */
|
|
||||||
_CloseFile();
|
|
||||||
|
|
||||||
char _filename[256];
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
|
|
||||||
FILE *fp = fopen(_filename, "r");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
|
|
||||||
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
|
||||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
|
||||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
|
||||||
LogFatal("[SM] Logging has been disabled.");
|
|
||||||
m_Active = false;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
char date[32];
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SVN_FULL_VERSION);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::_CloseFile()
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = NULL;
|
|
||||||
if (!m_NrmFileName.empty())
|
|
||||||
{
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
LogMessage("Log file closed.");
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
m_NrmFileName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_ErrMapStart)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
LogError("Error log file session closed.");
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
m_ErrFileName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::InitLogger(LoggingMode mode)
|
|
||||||
{
|
|
||||||
m_Mode = mode;
|
|
||||||
m_Active = m_InitialState;
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
m_CurDay = curtime->tm_mday;
|
|
||||||
|
|
||||||
char _filename[256];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrFileName.assign(_filename);
|
|
||||||
|
|
||||||
switch (m_Mode)
|
|
||||||
{
|
|
||||||
case LoggingMode_PerMap:
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
m_DelayedStart = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LoggingMode_Daily:
|
|
||||||
{
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
m_DailyPrintHdr = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* do nothing... */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::CloseLogger()
|
|
||||||
{
|
|
||||||
_CloseFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, msg);
|
|
||||||
LogToOpenFileEx(fp, msg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[3072];
|
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
|
||||||
|
|
||||||
char date[32];
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
|
|
||||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
|
||||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogMessage(const char *vafmt, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Mode == LoggingMode_Game)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
_PrintToGameLog(vafmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_DelayedStart)
|
|
||||||
{
|
|
||||||
m_DelayedStart = false;
|
|
||||||
_NewMapFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
FILE *fp = NULL;
|
|
||||||
if (m_Mode == LoggingMode_PerMap)
|
|
||||||
{
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
_NewMapFile();
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
goto print_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (m_CurDay != curtime->tm_mday)
|
|
||||||
{
|
|
||||||
char _filename[256];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
m_CurDay = curtime->tm_mday;
|
|
||||||
m_DailyPrintHdr = true;
|
|
||||||
}
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
if (m_DailyPrintHdr)
|
|
||||||
{
|
|
||||||
char date[32];
|
|
||||||
m_DailyPrintHdr = false;
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SVN_FULL_VERSION);
|
|
||||||
}
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fclose(fp);
|
|
||||||
} else {
|
|
||||||
goto print_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
print_error:
|
|
||||||
char error[255];
|
|
||||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
|
||||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
|
||||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
|
||||||
LogFatal("[SM] Logging has been disabled.");
|
|
||||||
m_Active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogError(const char *vafmt, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
if (curtime->tm_mday != m_CurDay)
|
|
||||||
{
|
|
||||||
char _filename[256];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrFileName.assign(_filename);
|
|
||||||
m_CurDay = curtime->tm_mday;
|
|
||||||
m_ErrMapStart = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
if (!m_ErrMapStart)
|
|
||||||
{
|
|
||||||
char date[32];
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
|
||||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrMapStart = true;
|
|
||||||
}
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
|
||||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
|
||||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
|
||||||
LogFatal("[SM] Logging has been disabled.");
|
|
||||||
m_Active = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::MapChange(const char *mapname)
|
|
||||||
{
|
|
||||||
m_CurMapName.assign(mapname);
|
|
||||||
|
|
||||||
switch (m_Mode)
|
|
||||||
{
|
|
||||||
case LoggingMode_Daily:
|
|
||||||
{
|
|
||||||
LogMessage("-------- Mapchange to %s --------", mapname);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LoggingMode_PerMap:
|
|
||||||
{
|
|
||||||
_NewMapFile();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* Do nothing... */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ErrMapStart)
|
|
||||||
{
|
|
||||||
LogError("Error log file session closed.");
|
|
||||||
}
|
|
||||||
m_ErrMapStart = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
char msg[3072];
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
|
|
||||||
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
|
|
||||||
|
|
||||||
msg[len++] = '\n';
|
|
||||||
msg[len] = '\0';
|
|
||||||
|
|
||||||
engine->LogPrint(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Logger::GetLogFileName(LogType type) const
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case LogType_Normal:
|
|
||||||
{
|
|
||||||
return m_NrmFileName.c_str();
|
|
||||||
}
|
|
||||||
case LogType_Error:
|
|
||||||
{
|
|
||||||
return m_ErrFileName.c_str();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggingMode Logger::GetLoggingMode() const
|
|
||||||
{
|
|
||||||
return m_Mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::EnableLogging()
|
|
||||||
{
|
|
||||||
if (m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_Active = true;
|
|
||||||
LogMessage("[SM] Logging enabled manually by user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::DisableLogging()
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LogMessage("[SM] Logging disabled manually by user.");
|
|
||||||
m_Active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogFatal(const char *msg, ...)
|
|
||||||
{
|
|
||||||
/* :TODO: make this print all pretty-like
|
|
||||||
* In fact, the pretty log printing function should be abstracted.
|
|
||||||
* It's already implemented twice which is bad.
|
|
||||||
*/
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
|
||||||
|
|
||||||
FILE *fp = fopen(path, "at");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
m_Active = true;
|
|
||||||
va_start(ap, msg);
|
|
||||||
LogToOpenFileEx(fp, msg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
m_Active = false;
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
103
core/Logger.h
103
core/Logger.h
@ -1,103 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
enum LogType
|
|
||||||
{
|
|
||||||
LogType_Normal,
|
|
||||||
LogType_Error
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LoggingMode
|
|
||||||
{
|
|
||||||
LoggingMode_Daily,
|
|
||||||
LoggingMode_PerMap,
|
|
||||||
LoggingMode_Game
|
|
||||||
};
|
|
||||||
|
|
||||||
class Logger : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
|
||||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
|
||||||
m_InitialState(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public: //SMGlobalClass
|
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength);
|
|
||||||
void OnSourceModStartup(bool late);
|
|
||||||
void OnSourceModAllShutdown();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
public:
|
|
||||||
void InitLogger(LoggingMode mode);
|
|
||||||
void CloseLogger();
|
|
||||||
void EnableLogging();
|
|
||||||
void DisableLogging();
|
|
||||||
void LogMessage(const char *msg, ...);
|
|
||||||
void LogError(const char *msg, ...);
|
|
||||||
void LogFatal(const char *msg, ...);
|
|
||||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
|
||||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
|
||||||
void MapChange(const char *mapname);
|
|
||||||
const char *GetLogFileName(LogType type) const;
|
|
||||||
LoggingMode GetLoggingMode() const;
|
|
||||||
private:
|
|
||||||
void _CloseFile();
|
|
||||||
void _NewMapFile();
|
|
||||||
void _PrintToGameLog(const char *fmt, va_list ap);
|
|
||||||
private:
|
|
||||||
String m_NrmFileName;
|
|
||||||
String m_ErrFileName;
|
|
||||||
String m_CurMapName;
|
|
||||||
LoggingMode m_Mode;
|
|
||||||
int m_CurDay;
|
|
||||||
bool m_ErrMapStart;
|
|
||||||
bool m_Active;
|
|
||||||
bool m_DelayedStart;
|
|
||||||
bool m_DailyPrintHdr;
|
|
||||||
bool m_InitialState;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Logger g_Logger;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
#(C)2004-2006 SourceMM Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
SMM_BASE = ../../sourcemm
|
|
||||||
HL2SDK = ../../hl2sdk
|
|
||||||
SMSDK = ..
|
|
||||||
SRCDS = ~/srcds
|
|
||||||
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
|
|
||||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
|
|
||||||
GCC4_FLAGS = -fvisibility=hidden
|
|
||||||
GCC4_CPP_FLAGS = -fvisibility-inlines-hidden
|
|
||||||
DEBUG_FLAGS = -g -ggdb3
|
|
||||||
CPP = gcc-4.1
|
|
||||||
BINARY = sourcemod.2.ep1.so
|
|
||||||
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
|
|
||||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
|
||||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
|
||||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
|
||||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
|
||||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
|
||||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
|
|
||||||
frame_hooks.cpp concmd_cleaner.cpp
|
|
||||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
|
||||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
|
||||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
|
||||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp \
|
|
||||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
|
||||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp
|
|
||||||
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
|
|
||||||
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
|
|
||||||
systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \
|
|
||||||
vm/sp_vm_function.cpp
|
|
||||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
|
||||||
OBJECTS_C = zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
|
|
||||||
zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
|
|
||||||
zlib/uncompr.c zlib/zutil.c
|
|
||||||
|
|
||||||
LINK = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so -lpthread -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE = -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
|
||||||
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_BASE) -I$(SMM_BASE)/sourcehook -I$(SMM_BASE)/sourcemm \
|
|
||||||
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions \
|
|
||||||
-Isystems
|
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
|
||||||
BIN_DIR = Debug
|
|
||||||
CFLAGS = $(DEBUG_FLAGS)
|
|
||||||
else
|
|
||||||
BIN_DIR = Release
|
|
||||||
CFLAGS = $(OPT_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-uninitialized -Werror -fPIC -mfpmath=sse -msse -DSOURCEMOD_BUILD -DSM_DEFAULT_THREADER
|
|
||||||
CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
|
||||||
CFLAGS += $(GCC4_FLAGS)
|
|
||||||
CPPFLAGS += $(GCC4_CPP_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.ox)
|
|
||||||
OBJ_LINUX_C := $(OBJECTS_C:%.c=$(BIN_DIR)/%.oc)
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.ox: %.cpp
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.oc: %.c
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
all:
|
|
||||||
mkdir -p $(BIN_DIR)/systems
|
|
||||||
mkdir -p $(BIN_DIR)/vm
|
|
||||||
mkdir -p $(BIN_DIR)/zlib
|
|
||||||
mkdir -p $(BIN_DIR)/thread
|
|
||||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
|
||||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
|
||||||
$(MAKE) -f Makefile.ep1 sourcemod
|
|
||||||
|
|
||||||
sourcemod: $(OBJ_LINUX) $(OBJ_LINUX_C)
|
|
||||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(OBJ_LINUX_C) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
$(MAKE) -f Makefile.ep1 all DEBUG=true
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf Release/*.ox
|
|
||||||
rm -rf Release/systems/*.ox
|
|
||||||
rm -rf Release/zlib/*.oc
|
|
||||||
rm -rf Release/vm/*.ox
|
|
||||||
rm -rf Release/thread/*.ox
|
|
||||||
rm -rf Release/$(BINARY)
|
|
||||||
rm -rf Debug/*.ox
|
|
||||||
rm -rf Debug/systems/*.ox
|
|
||||||
rm -rf Debug/zlib/*.oc
|
|
||||||
rm -rf Debug/vm/*.ox
|
|
||||||
rm -rf Debug/thread/*.ox
|
|
||||||
rm -rf Debug/$(BINARY)
|
|
||||||
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
#(C)2004-2006 SourceMM Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
SMM_BASE = ../../sourcemm
|
|
||||||
HL2SDK = ../../hl2sdk-ob
|
|
||||||
SMSDK = ..
|
|
||||||
SRCDS = ~/srcds
|
|
||||||
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
|
|
||||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
|
|
||||||
GCC4_FLAGS = -fvisibility=hidden
|
|
||||||
GCC4_CPP_FLAGS = -fvisibility-inlines-hidden
|
|
||||||
DEBUG_FLAGS = -g -ggdb3
|
|
||||||
CPP = gcc-4.1
|
|
||||||
BINARY = sourcemod.2.ep2.so
|
|
||||||
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
|
|
||||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
|
||||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
|
||||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
|
||||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
|
||||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
|
||||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
|
|
||||||
frame_hooks.cpp bitbuf.cpp concmd_cleaner.cpp
|
|
||||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
|
||||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
|
||||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
|
||||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp \
|
|
||||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
|
||||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp
|
|
||||||
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
|
|
||||||
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
|
|
||||||
systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \
|
|
||||||
vm/sp_vm_function.cpp
|
|
||||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
|
||||||
OBJECTS_C = zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
|
|
||||||
zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
|
|
||||||
zlib/uncompr.c zlib/zutil.c
|
|
||||||
|
|
||||||
LINK = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so -lpthread -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE = -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
|
||||||
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_BASE) -I$(SMM_BASE)/sourcehook -I$(SMM_BASE)/sourcemm \
|
|
||||||
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions \
|
|
||||||
-Isystems
|
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
|
||||||
BIN_DIR = Debug
|
|
||||||
CFLAGS = $(DEBUG_FLAGS)
|
|
||||||
else
|
|
||||||
BIN_DIR = Release
|
|
||||||
CFLAGS = $(OPT_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-uninitialized -Werror -fPIC -mfpmath=sse -msse -DSOURCEMOD_BUILD -DSM_DEFAULT_THREADER -DORANGEBOX_BUILD
|
|
||||||
CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
|
||||||
CFLAGS += $(GCC4_FLAGS)
|
|
||||||
CPPFLAGS += $(GCC4_CPP_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.ox)
|
|
||||||
OBJ_LINUX_C := $(OBJECTS_C:%.c=$(BIN_DIR)/%.oc)
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.ox: %.cpp
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.oc: %.c
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
all:
|
|
||||||
mkdir -p $(BIN_DIR)/systems
|
|
||||||
mkdir -p $(BIN_DIR)/vm
|
|
||||||
mkdir -p $(BIN_DIR)/zlib
|
|
||||||
mkdir -p $(BIN_DIR)/thread
|
|
||||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
|
||||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
|
||||||
ln -sf $(HL2SDK)/tier1/bitbuf.cpp bitbuf.cpp
|
|
||||||
$(MAKE) -f Makefile.ep2 sourcemod
|
|
||||||
|
|
||||||
sourcemod: $(OBJ_LINUX) $(OBJ_LINUX_C)
|
|
||||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(OBJ_LINUX_C) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
$(MAKE) -f Makefile.ep2 all DEBUG=true
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf Release/*.ox
|
|
||||||
rm -rf Release/systems/*.ox
|
|
||||||
rm -rf Release/zlib/*.oc
|
|
||||||
rm -rf Release/vm/*.ox
|
|
||||||
rm -rf Release/thread/*.ox
|
|
||||||
rm -rf Release/$(BINARY)
|
|
||||||
rm -rf Debug/*.ox
|
|
||||||
rm -rf Debug/systems/*.ox
|
|
||||||
rm -rf Debug/zlib/*.oc
|
|
||||||
rm -rf Debug/vm/*.ox
|
|
||||||
rm -rf Debug/thread/*.ox
|
|
||||||
rm -rf Debug/$(BINARY)
|
|
||||||
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
#(C)2004-2006 SourceMM Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
SMM_BASE = ../../sourcemm-1.4.2
|
|
||||||
HL2SDK = ../../hl2sdk
|
|
||||||
SMSDK = ..
|
|
||||||
SRCDS = ~/srcds
|
|
||||||
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
|
|
||||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
|
|
||||||
GCC4_FLAGS = -fvisibility=hidden
|
|
||||||
GCC4_CPP_FLAGS = -fvisibility-inlines-hidden
|
|
||||||
DEBUG_FLAGS = -g -ggdb3
|
|
||||||
CPP = gcc-4.1
|
|
||||||
BINARY = sourcemod.1.ep1.so
|
|
||||||
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
|
|
||||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
|
||||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
|
||||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
|
||||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
|
||||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
|
||||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
|
|
||||||
frame_hooks.cpp concmd_cleaner.cpp
|
|
||||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
|
||||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
|
||||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
|
||||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp \
|
|
||||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
|
||||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp
|
|
||||||
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
|
|
||||||
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
|
|
||||||
systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \
|
|
||||||
vm/sp_vm_function.cpp
|
|
||||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
|
||||||
OBJECTS_C = zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
|
|
||||||
zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
|
|
||||||
zlib/uncompr.c zlib/zutil.c
|
|
||||||
|
|
||||||
LINK = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so -lpthread -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE = -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
|
||||||
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_BASE) -I$(SMM_BASE)/sourcehook -I$(SMM_BASE)/sourcemm \
|
|
||||||
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions \
|
|
||||||
-Isystems
|
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
|
||||||
BIN_DIR = Debug
|
|
||||||
CFLAGS = $(DEBUG_FLAGS)
|
|
||||||
else
|
|
||||||
BIN_DIR = Release
|
|
||||||
CFLAGS = $(OPT_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-uninitialized -Werror -fPIC -mfpmath=sse -msse -DSOURCEMOD_BUILD -DSM_DEFAULT_THREADER
|
|
||||||
CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
|
||||||
CFLAGS += $(GCC4_FLAGS)
|
|
||||||
CPPFLAGS += $(GCC4_CPP_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.ox)
|
|
||||||
OBJ_LINUX_C := $(OBJECTS_C:%.c=$(BIN_DIR)/%.oc)
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.ox: %.cpp
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.oc: %.c
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
all:
|
|
||||||
mkdir -p $(BIN_DIR)/systems
|
|
||||||
mkdir -p $(BIN_DIR)/vm
|
|
||||||
mkdir -p $(BIN_DIR)/zlib
|
|
||||||
mkdir -p $(BIN_DIR)/thread
|
|
||||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
|
||||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
|
||||||
$(MAKE) -f Makefile.orig sourcemod
|
|
||||||
|
|
||||||
sourcemod: $(OBJ_LINUX) $(OBJ_LINUX_C)
|
|
||||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(OBJ_LINUX_C) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
$(MAKE) -f Makefile.orig all DEBUG=true
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf Release/*.ox
|
|
||||||
rm -rf Release/systems/*.ox
|
|
||||||
rm -rf Release/zlib/*.oc
|
|
||||||
rm -rf Release/vm/*.ox
|
|
||||||
rm -rf Release/thread/*.ox
|
|
||||||
rm -rf Release/$(BINARY)
|
|
||||||
rm -rf Debug/*.ox
|
|
||||||
rm -rf Debug/systems/*.ox
|
|
||||||
rm -rf Debug/zlib/*.oc
|
|
||||||
rm -rf Debug/vm/*.ox
|
|
||||||
rm -rf Debug/thread/*.ox
|
|
||||||
rm -rf Debug/$(BINARY)
|
|
||||||
|
|
||||||
@ -1,220 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "MemoryUtils.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#ifdef PLATFORM_LINUX
|
|
||||||
#include <string.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MemoryUtils g_MemUtils;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
MemoryUtils::MemoryUtils()
|
|
||||||
{
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
|
||||||
|
|
||||||
SYSTEM_INFO info;
|
|
||||||
GetSystemInfo(&info);
|
|
||||||
|
|
||||||
m_PageSize = info.dwPageSize;
|
|
||||||
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
|
|
||||||
m_PageSize = sysconf(_SC_PAGE_SIZE);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void MemoryUtils::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
|
|
||||||
{
|
|
||||||
DynLibInfo lib;
|
|
||||||
bool found;
|
|
||||||
char *ptr, *end;
|
|
||||||
|
|
||||||
memset(&lib, 0, sizeof(DynLibInfo));
|
|
||||||
|
|
||||||
if (!GetLibraryInfo(libPtr, lib))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = reinterpret_cast<char *>(lib.baseAddress);
|
|
||||||
end = ptr + lib.memorySize;
|
|
||||||
|
|
||||||
while (ptr < end)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
for (register size_t i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
|
|
||||||
{
|
|
||||||
found = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|
||||||
{
|
|
||||||
unsigned long baseAddr;
|
|
||||||
|
|
||||||
if (libPtr == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION info;
|
|
||||||
IMAGE_DOS_HEADER *dos;
|
|
||||||
IMAGE_NT_HEADERS *pe;
|
|
||||||
IMAGE_FILE_HEADER *file;
|
|
||||||
IMAGE_OPTIONAL_HEADER *opt;
|
|
||||||
|
|
||||||
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
baseAddr = reinterpret_cast<unsigned long>(info.AllocationBase);
|
|
||||||
|
|
||||||
/* All this is for our insane sanity checks :o */
|
|
||||||
dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr);
|
|
||||||
pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew);
|
|
||||||
file = &pe->FileHeader;
|
|
||||||
opt = &pe->OptionalHeader;
|
|
||||||
|
|
||||||
/* Check PE magic and signature */
|
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check architecture, which is 32-bit/x86 right now
|
|
||||||
* Should change this for 64-bit if Valve gets their act together
|
|
||||||
*/
|
|
||||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For our purposes, this must be a dynamic library */
|
|
||||||
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, we can do this */
|
|
||||||
lib.memorySize = opt->SizeOfImage;
|
|
||||||
|
|
||||||
#elif defined PLATFORM_LINUX
|
|
||||||
|
|
||||||
Dl_info info;
|
|
||||||
Elf32_Ehdr *file;
|
|
||||||
Elf32_Phdr *phdr;
|
|
||||||
uint16_t phdrCount;
|
|
||||||
|
|
||||||
if (!dladdr(libPtr, &info))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.dli_fbase || !info.dli_fname)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is for our insane sanity checks :o */
|
|
||||||
baseAddr = reinterpret_cast<unsigned long>(info.dli_fbase);
|
|
||||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
|
||||||
|
|
||||||
/* Check ELF magic */
|
|
||||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check ELF version */
|
|
||||||
if (file->e_ident[EI_VERSION] != EV_CURRENT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
|
||||||
* Should change this for 64-bit if Valve gets their act together
|
|
||||||
*/
|
|
||||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For our purposes, this must be a dynamic library/shared object */
|
|
||||||
if (file->e_type != ET_DYN)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
phdrCount = file->e_phnum;
|
|
||||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
|
||||||
|
|
||||||
/* Add up the memory sizes of segments marked as PT_LOAD as those are the only ones that should be in memory */
|
|
||||||
for (uint16_t i = 0; i < phdrCount; i++)
|
|
||||||
{
|
|
||||||
Elf32_Phdr &hdr = phdr[i];
|
|
||||||
|
|
||||||
if (hdr.p_type == PT_LOAD)
|
|
||||||
{
|
|
||||||
lib.memorySize += hdr.p_memsz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
|
||||||
|
|
||||||
#include <IMemoryUtils.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
struct DynLibInfo
|
|
||||||
{
|
|
||||||
void *baseAddress;
|
|
||||||
size_t memorySize;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MemoryUtils :
|
|
||||||
public IMemoryUtils,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public: // SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
public: // IMemoryUtils
|
|
||||||
void *FindPattern(const void *libPtr, const char *pattern, size_t len);
|
|
||||||
private:
|
|
||||||
bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern MemoryUtils g_MemUtils;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
|
||||||
@ -1,747 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "MenuManager.h"
|
|
||||||
#include "MenuVoting.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#include "MenuStyle_Valve.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
|
|
||||||
MenuManager g_Menus;
|
|
||||||
VoteMenuHandler s_VoteHandler;
|
|
||||||
|
|
||||||
ConVar sm_menu_sounds("sm_menu_sounds", "1", 0, "Sets whether SourceMod menus play trigger sounds");
|
|
||||||
|
|
||||||
MenuManager::MenuManager()
|
|
||||||
{
|
|
||||||
m_Styles.push_back(&g_ValveMenuStyle);
|
|
||||||
SetDefaultStyle(&g_ValveMenuStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
|
|
||||||
HandleAccess access;
|
|
||||||
g_HandleSys.InitAccessDefaults(NULL, &access);
|
|
||||||
|
|
||||||
/* Deny cloning to menus */
|
|
||||||
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
|
||||||
m_MenuType = g_HandleSys.CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
|
||||||
|
|
||||||
/* Also deny deletion to styles */
|
|
||||||
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
|
||||||
m_StyleType = g_HandleSys.CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::OnSourceModAllShutdown()
|
|
||||||
{
|
|
||||||
g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
|
|
||||||
g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
|
|
||||||
{
|
|
||||||
if (type == m_MenuType)
|
|
||||||
{
|
|
||||||
IBaseMenu *menu = (IBaseMenu *)object;
|
|
||||||
menu->Destroy(false);
|
|
||||||
} else if (type == m_StyleType) {
|
|
||||||
/* Do nothing */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
|
|
||||||
{
|
|
||||||
if (m_MenuType == NO_HANDLE_TYPE)
|
|
||||||
{
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
|
||||||
{
|
|
||||||
if (m_StyleType == NO_HANDLE_TYPE)
|
|
||||||
{
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
|
||||||
{
|
|
||||||
HandleSecurity sec;
|
|
||||||
|
|
||||||
sec.pIdentity = g_pCoreIdent;
|
|
||||||
sec.pOwner = NULL;
|
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(handle, m_MenuType, &sec, (void **)menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
|
||||||
{
|
|
||||||
HandleSecurity sec;
|
|
||||||
|
|
||||||
sec.pIdentity = g_pCoreIdent;
|
|
||||||
sec.pOwner = g_pCoreIdent;
|
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(handle, m_StyleType, &sec, (void **)style);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MenuManager::SetDefaultStyle(IMenuStyle *style)
|
|
||||||
{
|
|
||||||
if (!style)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pDefaultStyle = style;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuStyle *MenuManager::GetStyle(unsigned int index)
|
|
||||||
{
|
|
||||||
if (index >= GetStyleCount())
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_Styles[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::AddStyle(IMenuStyle *style)
|
|
||||||
{
|
|
||||||
m_Styles.push_back(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MenuManager::GetStyleCount()
|
|
||||||
{
|
|
||||||
return (unsigned int)m_Styles.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuStyle *MenuManager::FindStyleByName(const char *name)
|
|
||||||
{
|
|
||||||
unsigned int count = GetStyleCount();
|
|
||||||
for (unsigned int i=0; i<count; i++)
|
|
||||||
{
|
|
||||||
IMenuStyle *ptr = GetStyle(i);
|
|
||||||
if (strcasecmp(ptr->GetStyleName(), name) == 0)
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsSlotItem(IMenuPanel *display,
|
|
||||||
unsigned int style)
|
|
||||||
{
|
|
||||||
if (!display->CanDrawItem(style))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((style & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (style & ITEMDRAW_RAWLINE)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder order)
|
|
||||||
{
|
|
||||||
IBaseMenu *menu = md.menu;
|
|
||||||
|
|
||||||
if (!menu)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned int position;
|
|
||||||
ItemDrawInfo draw;
|
|
||||||
} drawItems[10];
|
|
||||||
|
|
||||||
/* Figure out how many items to draw */
|
|
||||||
IMenuStyle *style = menu->GetDrawStyle();
|
|
||||||
unsigned int pgn = menu->GetPagination();
|
|
||||||
unsigned int maxItems = style->GetMaxPageItems();
|
|
||||||
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
|
|
||||||
|
|
||||||
if (pgn != MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
maxItems = pgn;
|
|
||||||
}
|
|
||||||
else if (exitButton)
|
|
||||||
{
|
|
||||||
maxItems--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is very not allowed! */
|
|
||||||
if (maxItems < 2)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int totalItems = menu->GetItemCount();
|
|
||||||
unsigned int startItem = 0;
|
|
||||||
|
|
||||||
/* For pagination, find the starting point. */
|
|
||||||
if (pgn != MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
if (order == ItemOrder_Ascending)
|
|
||||||
{
|
|
||||||
startItem = md.lastItem;
|
|
||||||
/* This shouldn't happen with well-coded menus.
|
|
||||||
* If the item is out of bounds, switch the order to
|
|
||||||
* Items_Descending and make us start from the top.
|
|
||||||
*/
|
|
||||||
if (startItem >= totalItems)
|
|
||||||
{
|
|
||||||
startItem = totalItems - 1;
|
|
||||||
order = ItemOrder_Descending;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (order == ItemOrder_Descending)
|
|
||||||
{
|
|
||||||
startItem = md.firstItem;
|
|
||||||
/* This shouldn't happen with well-coded menus.
|
|
||||||
* If searching backwards doesn't give us enough room,
|
|
||||||
* start from the beginning and change to ascending.
|
|
||||||
*/
|
|
||||||
if (startItem <= maxItems)
|
|
||||||
{
|
|
||||||
startItem = 0;
|
|
||||||
order = ItemOrder_Ascending;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get our Display pointer and initialize some crap */
|
|
||||||
IMenuPanel *panel = menu->CreatePanel();
|
|
||||||
IMenuHandler *mh = md.mh;
|
|
||||||
bool foundExtra = false;
|
|
||||||
unsigned int extraItem = 0;
|
|
||||||
|
|
||||||
if (panel == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We keep searching until:
|
|
||||||
* 1) There are no more items
|
|
||||||
* 2) We reach one OVER the maximum number of slot items
|
|
||||||
* 3) We have reached maxItems and pagination is MENU_NO_PAGINATION
|
|
||||||
*/
|
|
||||||
unsigned int i = startItem;
|
|
||||||
unsigned int foundItems = 0;
|
|
||||||
while (totalItems)
|
|
||||||
{
|
|
||||||
ItemDrawInfo &dr = drawItems[foundItems].draw;
|
|
||||||
/* Is the item valid? */
|
|
||||||
if (menu->GetItemInfo(i, &dr) != NULL)
|
|
||||||
{
|
|
||||||
/* Ask the user to change the style, if necessary */
|
|
||||||
mh->OnMenuDrawItem(menu, client, i, dr.style);
|
|
||||||
/* Check if it's renderable */
|
|
||||||
if (IsSlotItem(panel, dr.style))
|
|
||||||
{
|
|
||||||
/* If we've already found the max number of items,
|
|
||||||
* This means we should just cancel out and log our
|
|
||||||
* "last item."
|
|
||||||
*/
|
|
||||||
if (foundItems >= maxItems)
|
|
||||||
{
|
|
||||||
foundExtra = true;
|
|
||||||
extraItem = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
drawItems[foundItems++].position = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If there's no pagination, stop once the menu is full. */
|
|
||||||
if (pgn == MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
/* If we've filled up, then stop */
|
|
||||||
if (foundItems >= maxItems)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If we're descending and this is the first item, stop */
|
|
||||||
if (order == ItemOrder_Descending)
|
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
/* If we're ascending and this is the last item, stop */
|
|
||||||
else if (order == ItemOrder_Ascending)
|
|
||||||
{
|
|
||||||
if (i >= totalItems - 1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There were no items to draw! */
|
|
||||||
if (!foundItems)
|
|
||||||
{
|
|
||||||
panel->DeleteThis();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool displayPrev = false;
|
|
||||||
bool displayNext = false;
|
|
||||||
|
|
||||||
/* This is an annoying process.
|
|
||||||
* Skip it for non-paginated menus, which get special treatment.
|
|
||||||
*/
|
|
||||||
if (pgn != MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
if (foundExtra)
|
|
||||||
{
|
|
||||||
if (order == ItemOrder_Descending)
|
|
||||||
{
|
|
||||||
displayPrev = true;
|
|
||||||
md.firstItem = extraItem;
|
|
||||||
}
|
|
||||||
else if (order == ItemOrder_Ascending)
|
|
||||||
{
|
|
||||||
displayNext = true;
|
|
||||||
md.lastItem = extraItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int lastItem = 0;
|
|
||||||
ItemDrawInfo dr;
|
|
||||||
/* Find the last feasible item to search from. */
|
|
||||||
if (order == ItemOrder_Descending)
|
|
||||||
{
|
|
||||||
lastItem = drawItems[0].position;
|
|
||||||
if (lastItem >= totalItems - 1)
|
|
||||||
{
|
|
||||||
goto skip_search;
|
|
||||||
}
|
|
||||||
while (++lastItem < totalItems)
|
|
||||||
{
|
|
||||||
if (menu->GetItemInfo(lastItem, &dr) != NULL)
|
|
||||||
{
|
|
||||||
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
|
||||||
if (IsSlotItem(panel, dr.style))
|
|
||||||
{
|
|
||||||
displayNext = true;
|
|
||||||
md.lastItem = lastItem;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (order == ItemOrder_Ascending)
|
|
||||||
{
|
|
||||||
lastItem = drawItems[0].position;
|
|
||||||
if (lastItem == 0)
|
|
||||||
{
|
|
||||||
goto skip_search;
|
|
||||||
}
|
|
||||||
lastItem--;
|
|
||||||
while (lastItem != 0)
|
|
||||||
{
|
|
||||||
if (menu->GetItemInfo(lastItem, &dr) != NULL)
|
|
||||||
{
|
|
||||||
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
|
||||||
if (IsSlotItem(panel, dr.style))
|
|
||||||
{
|
|
||||||
displayPrev = true;
|
|
||||||
md.firstItem = lastItem;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastItem--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_search:
|
|
||||||
|
|
||||||
/* Draw the item according to the order */
|
|
||||||
menu_slots_t *slots = md.slots;
|
|
||||||
unsigned int position = 0; /* Keep track of the last position */
|
|
||||||
if (order == ItemOrder_Ascending)
|
|
||||||
{
|
|
||||||
md.item_on_page = drawItems[0].position;
|
|
||||||
for (unsigned int i = 0; i < foundItems; i++)
|
|
||||||
{
|
|
||||||
ItemDrawInfo &dr = drawItems[i].draw;
|
|
||||||
if ((position = mh->OnMenuDisplayItem(menu, client, panel, drawItems[i].position, dr)) == 0)
|
|
||||||
{
|
|
||||||
position = panel->DrawItem(dr);
|
|
||||||
}
|
|
||||||
if (position != 0)
|
|
||||||
{
|
|
||||||
slots[position].item = drawItems[i].position;
|
|
||||||
slots[position].type = ItemSel_Item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (order == ItemOrder_Descending)
|
|
||||||
{
|
|
||||||
unsigned int i = foundItems;
|
|
||||||
/* NOTE: There will always be at least one item because
|
|
||||||
* of the check earlier.
|
|
||||||
*/
|
|
||||||
md.item_on_page = drawItems[foundItems - 1].position;
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
ItemDrawInfo &dr = drawItems[i].draw;
|
|
||||||
if ((position = mh->OnMenuDisplayItem(menu, client, panel, drawItems[i].position, dr)) == 0)
|
|
||||||
{
|
|
||||||
position = panel->DrawItem(dr);
|
|
||||||
}
|
|
||||||
if (position != 0)
|
|
||||||
{
|
|
||||||
slots[position].item = drawItems[i].position;
|
|
||||||
slots[position].type = ItemSel_Item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now, we need to check if we need to add anything extra */
|
|
||||||
if (pgn != MENU_NO_PAGINATION || exitButton)
|
|
||||||
{
|
|
||||||
bool canDrawDisabled = panel->CanDrawItem(ITEMDRAW_DISABLED|ITEMDRAW_CONTROL);
|
|
||||||
bool exitBackButton = false;
|
|
||||||
char text[50];
|
|
||||||
|
|
||||||
if (pgn != MENU_NO_PAGINATION
|
|
||||||
&& (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXITBACK)
|
|
||||||
{
|
|
||||||
exitBackButton = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate how many items we are allowed for control stuff */
|
|
||||||
unsigned int padding = style->GetMaxPageItems() - maxItems;
|
|
||||||
|
|
||||||
/* Add the number of available slots */
|
|
||||||
padding += (maxItems - foundItems);
|
|
||||||
|
|
||||||
/* Someday, if we are able to re-enable this, we will be very lucky men. */
|
|
||||||
#if 0
|
|
||||||
if (!style->FeatureExists(MenuStyleFeature_ImplicitExit))
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
/* Even if we don't draw an exit button, we invalidate the slot. */
|
|
||||||
padding--;
|
|
||||||
#if 0
|
|
||||||
} else {
|
|
||||||
/* Otherwise, we don't draw anything and leave the slot available */
|
|
||||||
exitButton = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pgn != MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
/* Subtract two slots for the displayNext/displayPrev padding */
|
|
||||||
padding -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have an "Exit Back" button and the space to draw it, do so. */
|
|
||||||
if (exitBackButton)
|
|
||||||
{
|
|
||||||
if (!displayPrev)
|
|
||||||
{
|
|
||||||
displayPrev = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exitBackButton = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We allow next/prev to be undrawn if neither exists.
|
|
||||||
* Thus, we only need padding if one of them will be drawn,
|
|
||||||
* or the exit button will be drawn.
|
|
||||||
*/
|
|
||||||
ItemDrawInfo padItem(NULL, ITEMDRAW_SPACER);
|
|
||||||
if (exitButton || (displayNext || displayPrev))
|
|
||||||
{
|
|
||||||
/* If there are no control options,
|
|
||||||
* Instead just pad with invisible slots.
|
|
||||||
*/
|
|
||||||
if (!displayPrev && !displayPrev)
|
|
||||||
{
|
|
||||||
padItem.style = ITEMDRAW_NOTEXT;
|
|
||||||
}
|
|
||||||
/* Add spacers so we can pad to the end */
|
|
||||||
for (unsigned int i=0; i<padding; i++)
|
|
||||||
{
|
|
||||||
position = panel->DrawItem(padItem);
|
|
||||||
slots[position].type = ItemSel_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put a fake spacer before control stuff, if possible */
|
|
||||||
if ((displayPrev || displayNext) || exitButton)
|
|
||||||
{
|
|
||||||
ItemDrawInfo draw("", ITEMDRAW_RAWLINE|ITEMDRAW_SPACER);
|
|
||||||
panel->DrawItem(draw);
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemDrawInfo dr(text, 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If we have one or the other, we need to have spacers for both.
|
|
||||||
*/
|
|
||||||
if (pgn != MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
if (displayPrev || displayNext)
|
|
||||||
{
|
|
||||||
/* PREVIOUS */
|
|
||||||
ItemDrawInfo padCtrlItem(NULL, ITEMDRAW_SPACER|ITEMDRAW_CONTROL);
|
|
||||||
if (displayPrev || canDrawDisabled)
|
|
||||||
{
|
|
||||||
if (exitBackButton)
|
|
||||||
{
|
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Back", NULL);
|
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
|
||||||
position = panel->DrawItem(dr);
|
|
||||||
slots[position].type = ItemSel_ExitBack;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Previous", NULL);
|
|
||||||
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
|
||||||
position = panel->DrawItem(dr);
|
|
||||||
slots[position].type = ItemSel_Back;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (displayNext || exitButton)
|
|
||||||
{
|
|
||||||
/* If we can't display this, and there is an exit button,
|
|
||||||
* we need to pad!
|
|
||||||
*/
|
|
||||||
position = panel->DrawItem(padCtrlItem);
|
|
||||||
slots[position].type = ItemSel_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NEXT */
|
|
||||||
if (displayNext || canDrawDisabled)
|
|
||||||
{
|
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Next", NULL);
|
|
||||||
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
|
||||||
position = panel->DrawItem(dr);
|
|
||||||
slots[position].type = ItemSel_Next;
|
|
||||||
}
|
|
||||||
else if (exitButton)
|
|
||||||
{
|
|
||||||
/* If we can't display this,
|
|
||||||
* but there is an "exit" button, we need to pad!
|
|
||||||
*/
|
|
||||||
position = panel->DrawItem(padCtrlItem);
|
|
||||||
slots[position].type = ItemSel_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Otherwise, bump to two slots! */
|
|
||||||
ItemDrawInfo numBump(NULL, ITEMDRAW_NOTEXT);
|
|
||||||
position = panel->DrawItem(numBump);
|
|
||||||
slots[position].type = ItemSel_None;
|
|
||||||
position = panel->DrawItem(numBump);
|
|
||||||
slots[position].type = ItemSel_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EXIT */
|
|
||||||
if (exitButton)
|
|
||||||
{
|
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Exit", NULL);
|
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
|
||||||
position = panel->DrawItem(dr);
|
|
||||||
slots[position].type = ItemSel_Exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lastly, fill in any slots we could have missed */
|
|
||||||
for (unsigned int i = position + 1; i < 10; i++)
|
|
||||||
{
|
|
||||||
slots[i].type = ItemSel_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do title stuff */
|
|
||||||
mh->OnMenuDisplay(menu, client, panel);
|
|
||||||
panel->DrawTitle(menu->GetDefaultTitle(), true);
|
|
||||||
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuStyle *MenuManager::GetDefaultStyle()
|
|
||||||
{
|
|
||||||
return m_pDefaultStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MenuManager::MenuSoundsEnabled()
|
|
||||||
{
|
|
||||||
return (sm_menu_sounds.GetInt() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigResult MenuManager::OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength)
|
|
||||||
{
|
|
||||||
if (strcmp(key, "MenuItemSound") == 0)
|
|
||||||
{
|
|
||||||
m_SelectSound.assign(value);
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
} else if (strcmp(key, "MenuExitBackSound") == 0) {
|
|
||||||
m_ExitBackSound.assign(value);
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
} else if (strcmp(key, "MenuExitSound") == 0) {
|
|
||||||
m_ExitSound.assign(value);
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *MenuManager::GetMenuSound(ItemSelection sel)
|
|
||||||
{
|
|
||||||
const char *sound = NULL;
|
|
||||||
|
|
||||||
switch (sel)
|
|
||||||
{
|
|
||||||
case ItemSel_Back:
|
|
||||||
case ItemSel_Next:
|
|
||||||
case ItemSel_Item:
|
|
||||||
{
|
|
||||||
if (m_SelectSound.size() > 0)
|
|
||||||
{
|
|
||||||
sound = m_SelectSound.c_str();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ItemSel_ExitBack:
|
|
||||||
{
|
|
||||||
if (m_ExitBackSound.size() > 0)
|
|
||||||
{
|
|
||||||
sound = m_ExitBackSound.c_str();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ItemSel_Exit:
|
|
||||||
{
|
|
||||||
if (m_ExitSound.size() > 0)
|
|
||||||
{
|
|
||||||
sound = m_ExitSound.c_str();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
if (m_SelectSound.size() > 0)
|
|
||||||
{
|
|
||||||
enginesound->PrecacheSound(m_SelectSound.c_str(), true);
|
|
||||||
}
|
|
||||||
if (m_ExitBackSound.size() > 0)
|
|
||||||
{
|
|
||||||
enginesound->PrecacheSound(m_ExitBackSound.c_str(), true);
|
|
||||||
}
|
|
||||||
if (m_ExitSound.size() > 0)
|
|
||||||
{
|
|
||||||
enginesound->PrecacheSound(m_ExitSound.c_str(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::CancelMenu(IBaseMenu *menu)
|
|
||||||
{
|
|
||||||
if (s_VoteHandler.GetCurrentMenu() == menu
|
|
||||||
&& !s_VoteHandler.IsCancelling())
|
|
||||||
{
|
|
||||||
s_VoteHandler.CancelVoting();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu->Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MenuManager::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags)
|
|
||||||
{
|
|
||||||
return s_VoteHandler.StartVote(menu, num_clients, clients, max_time, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MenuManager::IsVoteInProgress()
|
|
||||||
{
|
|
||||||
return s_VoteHandler.IsVoteInProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuManager::CancelVoting()
|
|
||||||
{
|
|
||||||
s_VoteHandler.CancelVoting();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MenuManager::GetRemainingVoteDelay()
|
|
||||||
{
|
|
||||||
return s_VoteHandler.GetRemainingVoteDelay();
|
|
||||||
}
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_MENUMANAGER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_MENUMANAGER_H_
|
|
||||||
|
|
||||||
#include <IMenuManager.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class MenuManager :
|
|
||||||
public IMenuManager,
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IHandleTypeDispatch
|
|
||||||
{
|
|
||||||
friend class BroadcastHandler;
|
|
||||||
friend class VoteHandler;
|
|
||||||
friend class CBaseMenu;
|
|
||||||
friend class BaseMenuStyle;
|
|
||||||
public:
|
|
||||||
MenuManager();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModAllShutdown();
|
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength);
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
public: //IMenuManager
|
|
||||||
virtual const char *GetInterfaceName()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_MENUMANAGER_NAME;
|
|
||||||
}
|
|
||||||
virtual unsigned int GetInterfaceVersion()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_MENUMANAGER_VERSION;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
unsigned int GetStyleCount();
|
|
||||||
IMenuStyle *GetStyle(unsigned int index);
|
|
||||||
IMenuStyle *FindStyleByName(const char *name);
|
|
||||||
IMenuStyle *GetDefaultStyle();
|
|
||||||
void AddStyle(IMenuStyle *style);
|
|
||||||
bool SetDefaultStyle(IMenuStyle *style);
|
|
||||||
IMenuPanel *RenderMenu(int client, menu_states_t &states, ItemOrder order);
|
|
||||||
void CancelMenu(IBaseMenu *menu);
|
|
||||||
bool StartVote(IBaseMenu *menu,
|
|
||||||
unsigned int num_clients,
|
|
||||||
int clients[],
|
|
||||||
unsigned int max_time,
|
|
||||||
unsigned int flags=0);
|
|
||||||
bool IsVoteInProgress();
|
|
||||||
void CancelVoting();
|
|
||||||
unsigned int GetRemainingVoteDelay();
|
|
||||||
public: //IHandleTypeDispatch
|
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
|
||||||
public:
|
|
||||||
HandleError ReadMenuHandle(Handle_t handle, IBaseMenu **menu);
|
|
||||||
HandleError ReadStyleHandle(Handle_t handle, IMenuStyle **style);
|
|
||||||
public:
|
|
||||||
bool MenuSoundsEnabled();
|
|
||||||
const char *GetMenuSound(ItemSelection sel);
|
|
||||||
protected:
|
|
||||||
Handle_t CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner);
|
|
||||||
Handle_t CreateStyleHandle(IMenuStyle *style);
|
|
||||||
private:
|
|
||||||
int m_ShowMenu;
|
|
||||||
IMenuStyle *m_pDefaultStyle;
|
|
||||||
CVector<IMenuStyle *> m_Styles;
|
|
||||||
HandleType_t m_StyleType;
|
|
||||||
HandleType_t m_MenuType;
|
|
||||||
String m_SelectSound;
|
|
||||||
String m_ExitBackSound;
|
|
||||||
String m_ExitSound;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern MenuManager g_Menus;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_MENUMANAGER_H_
|
|
||||||
@ -1,830 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "MenuStyle_Base.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#include "MenuManager.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "CellRecipientFilter.h"
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
#include "Logger.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t BaseMenuStyle::GetHandle()
|
|
||||||
{
|
|
||||||
/* Don't create the handle until we need it */
|
|
||||||
if (m_hHandle == BAD_HANDLE)
|
|
||||||
{
|
|
||||||
m_hHandle = g_Menus.CreateStyleHandle(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_hHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMenuStyle::AddClientToWatch(int client)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] AddClientToWatch(%d)", client);
|
|
||||||
#endif
|
|
||||||
m_WatchList.push_back(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMenuStyle::RemoveClientFromWatch(int client)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] RemoveClientFromWatch(%d)", client);
|
|
||||||
#endif
|
|
||||||
m_WatchList.remove(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool bAutoIgnore/* =false */)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] _CancelClientMenu() (client %d) (bAutoIgnore %d) (reason %d)", client, bAutoIgnore, reason);
|
|
||||||
#endif
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
menu_states_t &states = player->states;
|
|
||||||
|
|
||||||
bool bOldIgnore = player->bAutoIgnore;
|
|
||||||
if (bAutoIgnore)
|
|
||||||
{
|
|
||||||
player->bAutoIgnore = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save states */
|
|
||||||
IMenuHandler *mh = states.mh;
|
|
||||||
IBaseMenu *menu = states.menu;
|
|
||||||
|
|
||||||
/* Clear menu */
|
|
||||||
player->bInMenu = false;
|
|
||||||
if (player->menuHoldTime)
|
|
||||||
{
|
|
||||||
RemoveClientFromWatch(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire callbacks */
|
|
||||||
mh->OnMenuCancel(menu, client, reason);
|
|
||||||
|
|
||||||
/* Only fire end if there's a valid menu */
|
|
||||||
if (menu)
|
|
||||||
{
|
|
||||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bAutoIgnore)
|
|
||||||
{
|
|
||||||
player->bAutoIgnore = bOldIgnore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMenuStyle::CancelMenu(CBaseMenu *menu)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] CancelMenu() (menu %p)", menu);
|
|
||||||
#endif
|
|
||||||
int maxClients = g_Players.GetMaxClients();
|
|
||||||
for (int i=1; i<=maxClients; i++)
|
|
||||||
{
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(i);
|
|
||||||
if (player->bInMenu)
|
|
||||||
{
|
|
||||||
menu_states_t &states = player->states;
|
|
||||||
if (states.menu == menu)
|
|
||||||
{
|
|
||||||
_CancelClientMenu(i, MenuCancel_Interrupted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseMenuStyle::CancelClientMenu(int client, bool autoIgnore)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] CancelClientMenu() (client %d) (bAutoIgnore %d)", client, autoIgnore);
|
|
||||||
#endif
|
|
||||||
if (client < 1 || client > g_Players.MaxClients())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
if (!player->bInMenu)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_CancelClientMenu(client, MenuCancel_Interrupted, autoIgnore);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuSource BaseMenuStyle::GetClientMenu(int client, void **object)
|
|
||||||
{
|
|
||||||
if (client < 1 || client > g_Players.GetMaxClients())
|
|
||||||
{
|
|
||||||
return MenuSource_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
|
|
||||||
if (player->bInMenu)
|
|
||||||
{
|
|
||||||
IBaseMenu *menu;
|
|
||||||
if ((menu=player->states.menu) != NULL)
|
|
||||||
{
|
|
||||||
if (object)
|
|
||||||
{
|
|
||||||
*object = menu;
|
|
||||||
}
|
|
||||||
return MenuSource_BaseMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MenuSource_Display;
|
|
||||||
} else if (player->bInExternMenu) {
|
|
||||||
if (player->menuHoldTime != 0
|
|
||||||
&& (gpGlobals->curtime > player->menuStartTime + player->menuHoldTime))
|
|
||||||
{
|
|
||||||
player->bInExternMenu = false;
|
|
||||||
return MenuSource_None;
|
|
||||||
}
|
|
||||||
return MenuSource_External;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MenuSource_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMenuStyle::OnClientDisconnected(int client)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] OnClientDisconnected(%d)", client);
|
|
||||||
#endif
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
if (!player->bInMenu)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_CancelClientMenu(client, MenuCancel_Disconnected, true);
|
|
||||||
|
|
||||||
player->bInMenu = false;
|
|
||||||
player->bInExternMenu = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_lookup[256];
|
|
||||||
void BaseMenuStyle::ProcessWatchList()
|
|
||||||
{
|
|
||||||
if (!m_WatchList.size())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)",
|
|
||||||
m_WatchList.m_Size,
|
|
||||||
m_WatchList.m_FirstLink,
|
|
||||||
m_WatchList.m_FreeNodes,
|
|
||||||
m_WatchList.m_LastLink,
|
|
||||||
m_WatchList.m_MaxSize,
|
|
||||||
m_WatchList.m_Nodes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int total = 0;
|
|
||||||
for (FastLink<int>::iterator iter=m_WatchList.begin(); iter!=m_WatchList.end(); ++iter)
|
|
||||||
{
|
|
||||||
do_lookup[total++] = (*iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
if (total)
|
|
||||||
{
|
|
||||||
g_Logger.LogMessage("[SM_MENU] ProcessWatchList() found %d clients", total);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int client;
|
|
||||||
CBaseMenuPlayer *player;
|
|
||||||
float curTime = gpGlobals->curtime;
|
|
||||||
for (unsigned int i=0; i<total; i++)
|
|
||||||
{
|
|
||||||
client = do_lookup[i];
|
|
||||||
player = GetMenuPlayer(client);
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] ProcessWatchList() (client %d) (bInMenu %d) (menuHoldTime %d) (curTime %f) (menuStartTime %f)",
|
|
||||||
client,
|
|
||||||
player->bInMenu,
|
|
||||||
player->menuHoldTime,
|
|
||||||
curTime,
|
|
||||||
player->menuStartTime);
|
|
||||||
#endif
|
|
||||||
if (!player->bInMenu || !player->menuHoldTime)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] ProcessWatchList() removing client %d", client);
|
|
||||||
#endif
|
|
||||||
m_WatchList.remove(client);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (curTime > player->menuStartTime + player->menuHoldTime)
|
|
||||||
{
|
|
||||||
_CancelClientMenu(client, MenuCancel_Timeout, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] ClientPressedKey() (client %d) (key_press %d)", client, key_press);
|
|
||||||
#endif
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
|
|
||||||
/* First question: Are we in a menu? */
|
|
||||||
if (!player->bInMenu)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cancel = false;
|
|
||||||
unsigned int item = 0;
|
|
||||||
MenuCancelReason reason = MenuCancel_Exit;
|
|
||||||
MenuEndReason end_reason = MenuEnd_Selected;
|
|
||||||
menu_states_t &states = player->states;
|
|
||||||
|
|
||||||
/* Save variables */
|
|
||||||
IMenuHandler *mh = states.mh;
|
|
||||||
IBaseMenu *menu = states.menu;
|
|
||||||
|
|
||||||
unsigned int item_on_page = states.item_on_page;
|
|
||||||
|
|
||||||
assert(mh != NULL);
|
|
||||||
|
|
||||||
if (menu == NULL)
|
|
||||||
{
|
|
||||||
item = key_press;
|
|
||||||
} else if (key_press < 1 || key_press > GetMaxPageItems()) {
|
|
||||||
cancel = true;
|
|
||||||
} else {
|
|
||||||
ItemSelection type = states.slots[key_press].type;
|
|
||||||
|
|
||||||
/* Check if we should play a sound about the type */
|
|
||||||
if (g_Menus.MenuSoundsEnabled() &&
|
|
||||||
(!menu || (menu->GetMenuOptionFlags() & MENUFLAG_NO_SOUND) != MENUFLAG_NO_SOUND))
|
|
||||||
{
|
|
||||||
CellRecipientFilter filter;
|
|
||||||
cell_t clients[1];
|
|
||||||
|
|
||||||
clients[0] = client;
|
|
||||||
filter.Initialize(clients, 1);
|
|
||||||
|
|
||||||
const char *sound = g_Menus.GetMenuSound(type);
|
|
||||||
|
|
||||||
if (sound != NULL)
|
|
||||||
{
|
|
||||||
edict_t *pEdict = engine->PEntityOfEntIndex(client);
|
|
||||||
if (pEdict)
|
|
||||||
{
|
|
||||||
ICollideable *pCollideable = pEdict->GetCollideable();
|
|
||||||
|
|
||||||
if (pCollideable)
|
|
||||||
{
|
|
||||||
const Vector & pos = pCollideable->GetCollisionOrigin();
|
|
||||||
|
|
||||||
enginesound->EmitSound(filter,
|
|
||||||
client,
|
|
||||||
CHAN_AUTO,
|
|
||||||
sound,
|
|
||||||
VOL_NORM,
|
|
||||||
ATTN_NORM,
|
|
||||||
0,
|
|
||||||
PITCH_NORM,
|
|
||||||
&pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For navigational items, we're going to redisplay */
|
|
||||||
if (type == ItemSel_Back)
|
|
||||||
{
|
|
||||||
if (!RedoClientMenu(client, ItemOrder_Descending))
|
|
||||||
{
|
|
||||||
cancel = true;
|
|
||||||
reason = MenuCancel_NoDisplay;
|
|
||||||
end_reason = MenuEnd_Cancelled;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (type == ItemSel_Next) {
|
|
||||||
if (!RedoClientMenu(client, ItemOrder_Ascending))
|
|
||||||
{
|
|
||||||
cancel = true; /* I like Saltines. */
|
|
||||||
reason = MenuCancel_NoDisplay;
|
|
||||||
end_reason = MenuEnd_Cancelled;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (type == ItemSel_Exit || type == ItemSel_None) {
|
|
||||||
cancel = true;
|
|
||||||
reason = MenuCancel_Exit;
|
|
||||||
end_reason = MenuEnd_Exit;
|
|
||||||
} else if (type == ItemSel_ExitBack) {
|
|
||||||
cancel = true;
|
|
||||||
reason = MenuCancel_ExitBack;
|
|
||||||
end_reason = MenuEnd_ExitBack;
|
|
||||||
} else {
|
|
||||||
item = states.slots[key_press].item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear states */
|
|
||||||
player->bInMenu = false;
|
|
||||||
if (player->menuHoldTime)
|
|
||||||
{
|
|
||||||
RemoveClientFromWatch(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancel)
|
|
||||||
{
|
|
||||||
mh->OnMenuCancel(menu, client, reason);
|
|
||||||
} else {
|
|
||||||
mh->OnMenuSelect(menu, client, item);
|
|
||||||
if (mh->GetMenuAPIVersion2() >= 13)
|
|
||||||
{
|
|
||||||
mh->OnMenuSelect2(menu, client, item, item_on_page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only fire end for valid menus */
|
|
||||||
if (menu)
|
|
||||||
{
|
|
||||||
mh->OnMenuEnd(menu, end_reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (panel %p) (mh %p) (time %d)",
|
|
||||||
client,
|
|
||||||
menu,
|
|
||||||
mh,
|
|
||||||
time);
|
|
||||||
#endif
|
|
||||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
|
||||||
if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
if (player->bAutoIgnore)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For the duration of this, we are going to totally ignore whether
|
|
||||||
* the player is already in a menu or not (except to cancel the old one).
|
|
||||||
* Instead, we are simply going to ignore any further menu displays, so
|
|
||||||
* this display can't be interrupted.
|
|
||||||
*/
|
|
||||||
player->bAutoIgnore = true;
|
|
||||||
|
|
||||||
/* Cancel any old menus */
|
|
||||||
menu_states_t &states = player->states;
|
|
||||||
if (player->bInMenu)
|
|
||||||
{
|
|
||||||
_CancelClientMenu(client, MenuCancel_Interrupted, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
states.firstItem = 0;
|
|
||||||
states.lastItem = 0;
|
|
||||||
states.menu = NULL;
|
|
||||||
states.mh = mh;
|
|
||||||
states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
|
|
||||||
player->bInMenu = true;
|
|
||||||
player->bInExternMenu = false;
|
|
||||||
player->menuStartTime = gpGlobals->curtime;
|
|
||||||
player->menuHoldTime = time;
|
|
||||||
|
|
||||||
if (time)
|
|
||||||
{
|
|
||||||
AddClientToWatch(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw the display */
|
|
||||||
SendDisplay(client, menu);
|
|
||||||
|
|
||||||
/* We can be interrupted again! */
|
|
||||||
player->bAutoIgnore = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseMenuStyle::DoClientMenu(int client,
|
|
||||||
CBaseMenu *menu,
|
|
||||||
unsigned int first_item,
|
|
||||||
IMenuHandler *mh,
|
|
||||||
unsigned int time)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (menu %p) (mh %p) (time %d)",
|
|
||||||
client,
|
|
||||||
menu,
|
|
||||||
mh,
|
|
||||||
time);
|
|
||||||
#endif
|
|
||||||
mh->OnMenuStart(menu);
|
|
||||||
|
|
||||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
|
||||||
if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to display to client %d", client);
|
|
||||||
#endif
|
|
||||||
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
|
||||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
if (player->bAutoIgnore)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Client %d is autoIgnoring", client);
|
|
||||||
#endif
|
|
||||||
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
|
||||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For the duration of this, we are going to totally ignore whether
|
|
||||||
* the player is already in a menu or not (except to cancel the old one).
|
|
||||||
* Instead, we are simply going to ignore any further menu displays, so
|
|
||||||
* this display can't be interrupted.
|
|
||||||
*/
|
|
||||||
player->bAutoIgnore = true;
|
|
||||||
|
|
||||||
/* Cancel any old menus */
|
|
||||||
menu_states_t &states = player->states;
|
|
||||||
if (player->bInMenu)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Cancelling old menu to client %d", client);
|
|
||||||
#endif
|
|
||||||
_CancelClientMenu(client, MenuCancel_Interrupted, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
states.firstItem = 0;
|
|
||||||
states.lastItem = first_item;
|
|
||||||
states.menu = menu;
|
|
||||||
states.mh = mh;
|
|
||||||
states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
|
|
||||||
|
|
||||||
IMenuPanel *display = g_Menus.RenderMenu(client, states, ItemOrder_Ascending);
|
|
||||||
if (!display)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to render to client %d", client);
|
|
||||||
#endif
|
|
||||||
player->bAutoIgnore = false;
|
|
||||||
player->bInMenu = false;
|
|
||||||
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
|
||||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, set our states */
|
|
||||||
player->bInMenu = true;
|
|
||||||
player->bInExternMenu = false;
|
|
||||||
player->menuStartTime = gpGlobals->curtime;
|
|
||||||
player->menuHoldTime = time;
|
|
||||||
|
|
||||||
if (time)
|
|
||||||
{
|
|
||||||
AddClientToWatch(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw the display */
|
|
||||||
SendDisplay(client, display);
|
|
||||||
|
|
||||||
/* Free the display pointer */
|
|
||||||
display->DeleteThis();
|
|
||||||
|
|
||||||
/* We can be interrupted again! */
|
|
||||||
player->bAutoIgnore = false;
|
|
||||||
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu() finished successfully (client %d)", client);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] RedoClientMenu() (client %d) (order %d)", client, order);
|
|
||||||
#endif
|
|
||||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
|
||||||
menu_states_t &states = player->states;
|
|
||||||
|
|
||||||
player->bAutoIgnore = true;
|
|
||||||
IMenuPanel *display = g_Menus.RenderMenu(client, states, order);
|
|
||||||
if (!display)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Failed to render menu");
|
|
||||||
#endif
|
|
||||||
if (player->menuHoldTime)
|
|
||||||
{
|
|
||||||
RemoveClientFromWatch(client);
|
|
||||||
}
|
|
||||||
player->bAutoIgnore = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendDisplay(client, display);
|
|
||||||
|
|
||||||
display->DeleteThis();
|
|
||||||
|
|
||||||
player->bAutoIgnore = false;
|
|
||||||
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Succeeded to client %d", client);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
|
|
||||||
m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
|
|
||||||
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
|
|
||||||
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenu::~CBaseMenu()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle_t CBaseMenu::GetHandle()
|
|
||||||
{
|
|
||||||
if (!m_hHandle)
|
|
||||||
{
|
|
||||||
m_hHandle = g_Menus.CreateMenuHandle(this, m_pOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_hHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
|
||||||
{
|
|
||||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
|
||||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CItem item;
|
|
||||||
|
|
||||||
item.infoString = m_Strings.AddString(info);
|
|
||||||
if (draw.display)
|
|
||||||
{
|
|
||||||
item.displayString = m_Strings.AddString(draw.display);
|
|
||||||
}
|
|
||||||
item.style = draw.style;
|
|
||||||
|
|
||||||
m_items.push_back(item);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
|
||||||
{
|
|
||||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
|
||||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position >= m_items.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CItem item;
|
|
||||||
item.infoString = m_Strings.AddString(info);
|
|
||||||
if (draw.display)
|
|
||||||
{
|
|
||||||
item.displayString = m_Strings.AddString(draw.display);
|
|
||||||
}
|
|
||||||
item.style = draw.style;
|
|
||||||
|
|
||||||
CVector<CItem>::iterator iter = m_items.iterAt(position);
|
|
||||||
m_items.insert(iter, item);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBaseMenu::RemoveItem(unsigned int position)
|
|
||||||
{
|
|
||||||
if (position >= m_items.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_items.erase(m_items.iterAt(position));
|
|
||||||
|
|
||||||
if (m_items.size() == 0)
|
|
||||||
{
|
|
||||||
m_Strings.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseMenu::RemoveAllItems()
|
|
||||||
{
|
|
||||||
m_items.clear();
|
|
||||||
m_Strings.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
|
|
||||||
{
|
|
||||||
if (position >= m_items.size())
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draw)
|
|
||||||
{
|
|
||||||
draw->display = m_Strings.GetString(m_items[position].displayString);
|
|
||||||
draw->style = m_items[position].style;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_Strings.GetString(m_items[position].infoString);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CBaseMenu::GetItemCount()
|
|
||||||
{
|
|
||||||
return m_items.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
|
||||||
{
|
|
||||||
if (itemsPerPage > 7 || itemsPerPage == 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemsPerPage == MENU_NO_PAGINATION
|
|
||||||
&& m_Pagination != MENU_NO_PAGINATION)
|
|
||||||
{
|
|
||||||
m_nFlags &= ~MENUFLAG_BUTTON_EXIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Pagination = itemsPerPage;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CBaseMenu::GetPagination()
|
|
||||||
{
|
|
||||||
return m_Pagination;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuStyle *CBaseMenu::GetDrawStyle()
|
|
||||||
{
|
|
||||||
return m_pStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseMenu::SetDefaultTitle(const char *message)
|
|
||||||
{
|
|
||||||
m_Title.assign(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CBaseMenu::GetDefaultTitle()
|
|
||||||
{
|
|
||||||
return m_Title.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseMenu::Cancel()
|
|
||||||
{
|
|
||||||
if (m_bCancelling)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] CBaseMenu::Cancel(%p) (m_bShouldDelete %d)",
|
|
||||||
this,
|
|
||||||
m_bShouldDelete);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_bCancelling = true;
|
|
||||||
Cancel_Finally();
|
|
||||||
m_bCancelling = false;
|
|
||||||
|
|
||||||
if (m_bShouldDelete)
|
|
||||||
{
|
|
||||||
InternalDelete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseMenu::Destroy(bool releaseHandle)
|
|
||||||
{
|
|
||||||
/* Check if we shouldn't be here */
|
|
||||||
if (m_bDeleting)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] CBaseMenu::Destroy(%p) (release %d) (m_bCancelling %d) (m_bShouldDelete %d)",
|
|
||||||
this,
|
|
||||||
releaseHandle,
|
|
||||||
m_bCancelling,
|
|
||||||
m_bShouldDelete);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Save the destruction hint about our handle */
|
|
||||||
m_bWillFreeHandle = releaseHandle;
|
|
||||||
|
|
||||||
/* Now actually do stuff */
|
|
||||||
if (!m_bCancelling || m_bShouldDelete)
|
|
||||||
{
|
|
||||||
Cancel();
|
|
||||||
InternalDelete();
|
|
||||||
} else {
|
|
||||||
m_bShouldDelete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseMenu::InternalDelete()
|
|
||||||
{
|
|
||||||
if (m_bWillFreeHandle && m_hHandle != BAD_HANDLE)
|
|
||||||
{
|
|
||||||
Handle_t hndl = m_hHandle;
|
|
||||||
HandleSecurity sec;
|
|
||||||
|
|
||||||
sec.pOwner = m_pOwner;
|
|
||||||
sec.pIdentity = g_pCoreIdent;
|
|
||||||
|
|
||||||
m_hHandle = BAD_HANDLE;
|
|
||||||
m_bDeleting = true;
|
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pHandler->OnMenuDestroy(this);
|
|
||||||
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CBaseMenu::GetMenuOptionFlags()
|
|
||||||
{
|
|
||||||
return m_nFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBaseMenu::SetMenuOptionFlags(unsigned int flags)
|
|
||||||
{
|
|
||||||
m_nFlags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuHandler *CBaseMenu::GetHandler()
|
|
||||||
{
|
|
||||||
return m_pHandler;
|
|
||||||
}
|
|
||||||
@ -1,156 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_MENUSTYLE_BASE_H
|
|
||||||
#define _INCLUDE_MENUSTYLE_BASE_H
|
|
||||||
|
|
||||||
#include <IMenuManager.h>
|
|
||||||
#include <IPlayerHelpers.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "sm_fastlink.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class CItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CItem()
|
|
||||||
{
|
|
||||||
infoString = -1;
|
|
||||||
displayString = -1;
|
|
||||||
style = 0;
|
|
||||||
access = 0;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
int infoString;
|
|
||||||
int displayString;
|
|
||||||
unsigned int style;
|
|
||||||
unsigned int access;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CBaseMenuPlayer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CBaseMenuPlayer() : bInMenu(false), bAutoIgnore(false), bInExternMenu(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
menu_states_t states;
|
|
||||||
bool bInMenu;
|
|
||||||
bool bAutoIgnore;
|
|
||||||
float menuStartTime;
|
|
||||||
unsigned int menuHoldTime;
|
|
||||||
bool bInExternMenu;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CBaseMenu;
|
|
||||||
|
|
||||||
class BaseMenuStyle :
|
|
||||||
public IMenuStyle,
|
|
||||||
public IClientListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseMenuStyle();
|
|
||||||
public: //IMenuStyle
|
|
||||||
bool CancelClientMenu(int client, bool autoIgnore/* =false */);
|
|
||||||
MenuSource GetClientMenu(int client, void **object);
|
|
||||||
Handle_t GetHandle();
|
|
||||||
public: //IClientListener
|
|
||||||
void OnClientDisconnected(int client);
|
|
||||||
public: //what derived must implement
|
|
||||||
virtual CBaseMenuPlayer *GetMenuPlayer(int client) =0;
|
|
||||||
virtual void SendDisplay(int client, IMenuPanel *display) =0;
|
|
||||||
public: //what derived may implement
|
|
||||||
virtual bool DoClientMenu(int client,
|
|
||||||
CBaseMenu *menu,
|
|
||||||
unsigned int first_item,
|
|
||||||
IMenuHandler *mh,
|
|
||||||
unsigned int time);
|
|
||||||
virtual bool DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time);
|
|
||||||
virtual void AddClientToWatch(int client);
|
|
||||||
virtual void RemoveClientFromWatch(int client);
|
|
||||||
virtual void ProcessWatchList();
|
|
||||||
public: //helpers
|
|
||||||
void CancelMenu(CBaseMenu *menu);
|
|
||||||
void ClientPressedKey(int client, unsigned int key_press);
|
|
||||||
protected:
|
|
||||||
void _CancelClientMenu(int client, MenuCancelReason reason, bool bAutoIgnore=false);
|
|
||||||
bool RedoClientMenu(int client, ItemOrder order);
|
|
||||||
protected:
|
|
||||||
FastLink<int> m_WatchList;
|
|
||||||
Handle_t m_hHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CBaseMenu : public IBaseMenu
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner);
|
|
||||||
virtual ~CBaseMenu();
|
|
||||||
public:
|
|
||||||
virtual bool AppendItem(const char *info, const ItemDrawInfo &draw);
|
|
||||||
virtual bool InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw);
|
|
||||||
virtual bool RemoveItem(unsigned int position);
|
|
||||||
virtual void RemoveAllItems();
|
|
||||||
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL);
|
|
||||||
virtual unsigned int GetItemCount();
|
|
||||||
virtual bool SetPagination(unsigned int itemsPerPage);
|
|
||||||
virtual unsigned int GetPagination();
|
|
||||||
virtual IMenuStyle *GetDrawStyle();
|
|
||||||
virtual void SetDefaultTitle(const char *message);
|
|
||||||
virtual const char *GetDefaultTitle();
|
|
||||||
virtual void Cancel();
|
|
||||||
virtual void Destroy(bool releaseHandle);
|
|
||||||
virtual void Cancel_Finally() =0;
|
|
||||||
virtual Handle_t GetHandle();
|
|
||||||
virtual unsigned int GetMenuOptionFlags();
|
|
||||||
virtual void SetMenuOptionFlags(unsigned int flags);
|
|
||||||
virtual IMenuHandler *GetHandler();
|
|
||||||
private:
|
|
||||||
void InternalDelete();
|
|
||||||
protected:
|
|
||||||
String m_Title;
|
|
||||||
IMenuStyle *m_pStyle;
|
|
||||||
BaseStringTable m_Strings;
|
|
||||||
unsigned int m_Pagination;
|
|
||||||
CVector<CItem> m_items;
|
|
||||||
bool m_bShouldDelete;
|
|
||||||
bool m_bCancelling;
|
|
||||||
IdentityToken_t *m_pOwner;
|
|
||||||
bool m_bDeleting;
|
|
||||||
bool m_bWillFreeHandle;
|
|
||||||
Handle_t m_hHandle;
|
|
||||||
IMenuHandler *m_pHandler;
|
|
||||||
unsigned int m_nFlags;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_MENUSTYLE_BASE_H
|
|
||||||
@ -1,548 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "MenuStyle_Radio.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "UserMessages.h"
|
|
||||||
#include "GameConfigs.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
#include "Logger.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const char *g_RadioNumTable[];
|
|
||||||
CRadioStyle g_RadioMenuStyle;
|
|
||||||
int g_ShowMenuId = -1;
|
|
||||||
bool g_bRadioInit = false;
|
|
||||||
unsigned int g_RadioMenuTimeout = 0;
|
|
||||||
|
|
||||||
CRadioStyle::CRadioStyle()
|
|
||||||
{
|
|
||||||
m_players = new CRadioMenuPlayer[256+1];
|
|
||||||
for (size_t i = 0; i < 256+1; i++)
|
|
||||||
{
|
|
||||||
m_players[i].Radio_SetIndex(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_Players.AddClientListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
if (g_bRadioInit)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_bRadioInit = true;
|
|
||||||
const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
|
|
||||||
if (!msg || msg[0] == '\0')
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
|
|
||||||
|
|
||||||
if (!IsSupported())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *val = g_pGameConf->GetKeyValue("RadioMenuTimeout");
|
|
||||||
if (val != NULL)
|
|
||||||
{
|
|
||||||
g_RadioMenuTimeout = atoi(val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_RadioMenuTimeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Menus.AddStyle(this);
|
|
||||||
g_Menus.SetDefaultStyle(this);
|
|
||||||
|
|
||||||
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
g_Players.RemoveClientListener(this);
|
|
||||||
g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
|
|
||||||
|
|
||||||
while (!m_FreeDisplays.empty())
|
|
||||||
{
|
|
||||||
delete m_FreeDisplays.front();
|
|
||||||
m_FreeDisplays.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioStyle::IsSupported()
|
|
||||||
{
|
|
||||||
return (g_ShowMenuId != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
|
|
||||||
{
|
|
||||||
if (strcmp(cmdname, "menuselect") == 0)
|
|
||||||
{
|
|
||||||
if (!m_players[client].bInMenu)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int arg = atoi(cmd.Arg(1));
|
|
||||||
ClientPressedKey(client, arg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int g_last_holdtime = 0;
|
|
||||||
static unsigned int g_last_client_count = 0;
|
|
||||||
static int g_last_clients[256];
|
|
||||||
|
|
||||||
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
|
||||||
{
|
|
||||||
int count = pFilter->GetRecipientCount();
|
|
||||||
bf_read br(bf->GetBasePointer(), 2);
|
|
||||||
|
|
||||||
br.ReadWord();
|
|
||||||
int c = br.ReadChar();
|
|
||||||
|
|
||||||
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
|
||||||
|
|
||||||
for (int i=0; i<count; i++)
|
|
||||||
{
|
|
||||||
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::OnUserMessageSent(int msg_id)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0; i<g_last_client_count; i++)
|
|
||||||
{
|
|
||||||
int client = g_last_clients[i];
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] CRadioStyle got ShowMenu (client %d) (bInMenu %d)",
|
|
||||||
client,
|
|
||||||
m_players[client].bInExternMenu);
|
|
||||||
#endif
|
|
||||||
if (m_players[client].bInMenu)
|
|
||||||
{
|
|
||||||
_CancelClientMenu(client, MenuCancel_Interrupted, true);
|
|
||||||
}
|
|
||||||
m_players[client].bInExternMenu = true;
|
|
||||||
m_players[client].menuHoldTime = g_last_holdtime;
|
|
||||||
}
|
|
||||||
g_last_client_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
|
|
||||||
{
|
|
||||||
CRadioDisplay *rDisplay = (CRadioDisplay *)display;
|
|
||||||
rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuPanel *CRadioStyle::CreatePanel()
|
|
||||||
{
|
|
||||||
return g_RadioMenuStyle.MakeRadioDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
|
|
||||||
{
|
|
||||||
return new CRadioMenu(pHandler, pOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CRadioStyle::GetMaxPageItems()
|
|
||||||
{
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CRadioStyle::GetStyleName()
|
|
||||||
{
|
|
||||||
return "radio";
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
|
|
||||||
{
|
|
||||||
return &m_players[client];
|
|
||||||
}
|
|
||||||
|
|
||||||
CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
|
|
||||||
{
|
|
||||||
CRadioDisplay *display;
|
|
||||||
if (m_FreeDisplays.empty())
|
|
||||||
{
|
|
||||||
display = new CRadioDisplay();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
display = m_FreeDisplays.front();
|
|
||||||
m_FreeDisplays.pop();
|
|
||||||
display->Reset();
|
|
||||||
}
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuPanel *CRadioStyle::MakeRadioDisplay(const char *str, int keys)
|
|
||||||
{
|
|
||||||
CRadioDisplay *pPanel = MakeRadioDisplay(NULL);
|
|
||||||
|
|
||||||
pPanel->DirectSet(str, keys);
|
|
||||||
|
|
||||||
return pPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
|
|
||||||
{
|
|
||||||
m_FreeDisplays.push(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
CRadioMenuPlayer *CRadioStyle::GetRadioMenuPlayer(int client)
|
|
||||||
{
|
|
||||||
return &m_players[client];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::ProcessWatchList()
|
|
||||||
{
|
|
||||||
if (!g_RadioMenuTimeout)
|
|
||||||
{
|
|
||||||
BaseMenuStyle::ProcessWatchList();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseMenuStyle::ProcessWatchList();
|
|
||||||
|
|
||||||
CRadioMenuPlayer *pPlayer;
|
|
||||||
unsigned int max_clients = g_Players.GetMaxClients();
|
|
||||||
for (unsigned int i = 1; i <= max_clients; i++)
|
|
||||||
{
|
|
||||||
pPlayer = GetRadioMenuPlayer(i);
|
|
||||||
if (!pPlayer->bInMenu || pPlayer->bInExternMenu)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pPlayer->Radio_NeedsRefresh())
|
|
||||||
{
|
|
||||||
pPlayer->Radio_Refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CRadioDisplay::CRadioDisplay()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioDisplay::DrawRawLine(const char *rawline)
|
|
||||||
{
|
|
||||||
m_BufferText.append(rawline);
|
|
||||||
m_BufferText.append("\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioDisplay::Reset()
|
|
||||||
{
|
|
||||||
m_BufferText.assign("");
|
|
||||||
m_Title.assign("");
|
|
||||||
m_NextPos = 1;
|
|
||||||
keys = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioDisplay::DirectSet(const char *str, int keymap)
|
|
||||||
{
|
|
||||||
m_Title.clear();
|
|
||||||
m_BufferText.assign(str);
|
|
||||||
keys = keymap;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CRadioDisplay::GetCurrentKey()
|
|
||||||
{
|
|
||||||
return m_NextPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioDisplay::SetCurrentKey(unsigned int key)
|
|
||||||
{
|
|
||||||
if (key < m_NextPos || m_NextPos > 10)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_NextPos = key;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
|
|
||||||
{
|
|
||||||
return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuStyle *CRadioDisplay::GetParentStyle()
|
|
||||||
{
|
|
||||||
return &g_RadioMenuStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
|
|
||||||
{
|
|
||||||
if (m_Title.size() != 0 && onlyIfEmpty)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_Title.assign(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
|
|
||||||
{
|
|
||||||
if (m_NextPos > 10 || !CanDrawItem(item.style))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.style & ITEMDRAW_RAWLINE)
|
|
||||||
{
|
|
||||||
if (item.style & ITEMDRAW_SPACER)
|
|
||||||
{
|
|
||||||
m_BufferText.append(" \n");
|
|
||||||
} else {
|
|
||||||
m_BufferText.append(item.display);
|
|
||||||
m_BufferText.append("\n");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else if (item.style & ITEMDRAW_SPACER) {
|
|
||||||
m_BufferText.append(" \n");
|
|
||||||
return m_NextPos++;
|
|
||||||
} else if (item.style & ITEMDRAW_NOTEXT) {
|
|
||||||
return m_NextPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.style & ITEMDRAW_DISABLED)
|
|
||||||
{
|
|
||||||
m_BufferText.append(g_RadioNumTable[m_NextPos]);
|
|
||||||
m_BufferText.append(item.display);
|
|
||||||
m_BufferText.append("\n");
|
|
||||||
} else {
|
|
||||||
m_BufferText.append("->");
|
|
||||||
m_BufferText.append(g_RadioNumTable[m_NextPos]);
|
|
||||||
m_BufferText.append(item.display);
|
|
||||||
m_BufferText.append("\n");
|
|
||||||
keys |= (1<<(m_NextPos-1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_NextPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
|
|
||||||
{
|
|
||||||
if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
|
|
||||||
{
|
|
||||||
int _sel_keys = (keys == 0) ? (1<<9) : keys;
|
|
||||||
CRadioMenuPlayer *pPlayer = g_RadioMenuStyle.GetRadioMenuPlayer(client);
|
|
||||||
pPlayer->Radio_Init(_sel_keys, m_Title.c_str(), m_BufferText.c_str());
|
|
||||||
pPlayer->Radio_Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioMenuPlayer::Radio_SetIndex(unsigned int index)
|
|
||||||
{
|
|
||||||
m_index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioMenuPlayer::Radio_NeedsRefresh()
|
|
||||||
{
|
|
||||||
return (gpGlobals->curtime - display_last_refresh >= g_RadioMenuTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
|
||||||
{
|
|
||||||
if (title[0] != '\0')
|
|
||||||
{
|
|
||||||
display_len = UTIL_Format(display_pkt,
|
|
||||||
sizeof(display_pkt),
|
|
||||||
"%s\n%s",
|
|
||||||
title,
|
|
||||||
text);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
display_len = UTIL_Format(display_pkt,
|
|
||||||
sizeof(display_pkt),
|
|
||||||
"%s",
|
|
||||||
text);
|
|
||||||
}
|
|
||||||
display_keys = keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioMenuPlayer::Radio_Refresh()
|
|
||||||
{
|
|
||||||
cell_t players[1] = {m_index};
|
|
||||||
char *ptr = display_pkt;
|
|
||||||
char save = 0;
|
|
||||||
size_t len = display_len;
|
|
||||||
unsigned int time;
|
|
||||||
|
|
||||||
/* Compute the new time */
|
|
||||||
if (menuHoldTime == 0)
|
|
||||||
{
|
|
||||||
time = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (len > 240)
|
|
||||||
{
|
|
||||||
save = ptr[240];
|
|
||||||
ptr[240] = '\0';
|
|
||||||
}
|
|
||||||
bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
|
||||||
buffer->WriteWord(display_keys);
|
|
||||||
buffer->WriteChar(time ? time : -1);
|
|
||||||
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
|
||||||
buffer->WriteString(ptr);
|
|
||||||
g_UserMsgs.EndMessage();
|
|
||||||
if (len > 240)
|
|
||||||
{
|
|
||||||
ptr[240] = save;
|
|
||||||
ptr = &ptr[240];
|
|
||||||
len -= 240;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display_last_refresh = gpGlobals->curtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CRadioDisplay::GetAmountRemaining()
|
|
||||||
{
|
|
||||||
size_t amt = m_Title.size() + 1 + m_BufferText.size();
|
|
||||||
if (amt >= 511)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (int)(511 - amt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioDisplay::DeleteThis()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
|
|
||||||
{
|
|
||||||
keys = (signed)keymap;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
|
||||||
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuPanel *CRadioMenu::CreatePanel()
|
|
||||||
{
|
|
||||||
return g_RadioMenuStyle.MakeRadioDisplay(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioMenu::Display(int client, unsigned int time, IMenuHandler *alt_handler)
|
|
||||||
{
|
|
||||||
return DisplayAtItem(client, time, 0, alt_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRadioMenu::DisplayAtItem(int client,
|
|
||||||
unsigned int time,
|
|
||||||
unsigned int start_item,
|
|
||||||
IMenuHandler *alt_handler)
|
|
||||||
{
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
g_Logger.LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
|
|
||||||
this,
|
|
||||||
client,
|
|
||||||
time);
|
|
||||||
#endif
|
|
||||||
if (m_bCancelling)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_RadioMenuStyle.DoClientMenu(client,
|
|
||||||
this,
|
|
||||||
start_item,
|
|
||||||
alt_handler ? alt_handler : m_pHandler,
|
|
||||||
time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioMenu::Cancel_Finally()
|
|
||||||
{
|
|
||||||
g_RadioMenuStyle.CancelMenu(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *g_RadioNumTable[11] =
|
|
||||||
{
|
|
||||||
"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "
|
|
||||||
};
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_MENUSTYLE_RADIO_H
|
|
||||||
#define _INCLUDE_MENUSTYLE_RADIO_H
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "MenuManager.h"
|
|
||||||
#include "MenuStyle_Base.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include <IPlayerHelpers.h>
|
|
||||||
#include <IUserMessages.h>
|
|
||||||
#include "sm_fastlink.h"
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include <compat_wrappers.h>
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class CRadioDisplay;
|
|
||||||
class CRadioMenu;
|
|
||||||
|
|
||||||
class CRadioMenuPlayer : public CBaseMenuPlayer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Radio_Init(int keys, const char *title, const char *buffer);
|
|
||||||
bool Radio_NeedsRefresh();
|
|
||||||
void Radio_Refresh();
|
|
||||||
void Radio_SetIndex(unsigned int index);
|
|
||||||
private:
|
|
||||||
unsigned int m_index;
|
|
||||||
size_t display_len;
|
|
||||||
char display_pkt[512];
|
|
||||||
int display_keys;
|
|
||||||
float display_last_refresh;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CRadioStyle :
|
|
||||||
public BaseMenuStyle,
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IUserMessageListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRadioStyle();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: //BaseMenuStyle
|
|
||||||
CBaseMenuPlayer *GetMenuPlayer(int client);
|
|
||||||
void SendDisplay(int client, IMenuPanel *display);
|
|
||||||
void ProcessWatchList();
|
|
||||||
public: //IMenuStyle
|
|
||||||
const char *GetStyleName();
|
|
||||||
IMenuPanel *CreatePanel();
|
|
||||||
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
|
||||||
unsigned int GetMaxPageItems();
|
|
||||||
public: //IUserMessageListener
|
|
||||||
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
|
||||||
void OnUserMessageSent(int msg_id);
|
|
||||||
public:
|
|
||||||
bool IsSupported();
|
|
||||||
bool OnClientCommand(int client, const char *cmdname, const CCommand &cmd);
|
|
||||||
public:
|
|
||||||
CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL);
|
|
||||||
void FreeRadioDisplay(CRadioDisplay *display);
|
|
||||||
CRadioMenuPlayer *GetRadioMenuPlayer(int client);
|
|
||||||
IMenuPanel *MakeRadioDisplay(const char *str, int keys);
|
|
||||||
private:
|
|
||||||
CRadioMenuPlayer *m_players;
|
|
||||||
CStack<CRadioDisplay *> m_FreeDisplays;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CRadioDisplay : public IMenuPanel
|
|
||||||
{
|
|
||||||
friend class CRadioStyle;
|
|
||||||
public:
|
|
||||||
CRadioDisplay();
|
|
||||||
CRadioDisplay(CRadioMenu *menu);
|
|
||||||
public: //IMenuPanel
|
|
||||||
IMenuStyle *GetParentStyle();
|
|
||||||
void Reset();
|
|
||||||
void DrawTitle(const char *text, bool onlyIfEmpty=false);
|
|
||||||
unsigned int DrawItem(const ItemDrawInfo &item);
|
|
||||||
bool DrawRawLine(const char *rawline);
|
|
||||||
bool SetExtOption(MenuOption option, const void *valuePtr);
|
|
||||||
bool CanDrawItem(unsigned int drawFlags);
|
|
||||||
bool SendDisplay(int client, IMenuHandler *handler, unsigned int time);
|
|
||||||
void DeleteThis();
|
|
||||||
void SendRawDisplay(int client, unsigned int time);
|
|
||||||
bool SetSelectableKeys(unsigned int keymap);
|
|
||||||
unsigned int GetCurrentKey();
|
|
||||||
bool SetCurrentKey(unsigned int key);
|
|
||||||
int GetAmountRemaining();
|
|
||||||
public:
|
|
||||||
void DirectSet(const char *str, int keymap);
|
|
||||||
private:
|
|
||||||
String m_BufferText;
|
|
||||||
String m_Title;
|
|
||||||
unsigned int m_NextPos;
|
|
||||||
int keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CRadioMenu : public CBaseMenu
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
|
||||||
public:
|
|
||||||
bool SetExtOption(MenuOption option, const void *valuePtr);
|
|
||||||
IMenuPanel *CreatePanel();
|
|
||||||
bool Display(int client, unsigned int time, IMenuHandler *alt_handler=NULL);
|
|
||||||
bool DisplayAtItem(int client,
|
|
||||||
unsigned int time,
|
|
||||||
unsigned int start_item,
|
|
||||||
IMenuHandler *alt_handler/* =NULL */);
|
|
||||||
void Cancel_Finally();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CRadioStyle g_RadioMenuStyle;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_MENUSTYLE_RADIO_H
|
|
||||||
@ -1,430 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#include "MenuStyle_Valve.h"
|
|
||||||
#include "Translator.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#include "ConCmdManager.h"
|
|
||||||
|
|
||||||
SH_DECL_HOOK4_void(IServerPluginHelpers, CreateMessage, SH_NOATTRIB, false, edict_t *, DIALOG_TYPE, KeyValues *, IServerPluginCallbacks *);
|
|
||||||
|
|
||||||
ValveMenuStyle g_ValveMenuStyle;
|
|
||||||
extern const char *g_OptionNumTable[];
|
|
||||||
extern const char *g_OptionCmdTable[];
|
|
||||||
CallClass<IServerPluginHelpers> *g_pSPHCC = NULL;
|
|
||||||
|
|
||||||
ValveMenuStyle::ValveMenuStyle() : m_players(new CValveMenuPlayer[256+1])
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CBaseMenuPlayer *ValveMenuStyle::GetMenuPlayer(int client)
|
|
||||||
{
|
|
||||||
return &m_players[client];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
|
|
||||||
{
|
|
||||||
if (strcmp(cmdname, "sm_vmenuselect") == 0)
|
|
||||||
{
|
|
||||||
int key_press = atoi(cmd.Arg(1));
|
|
||||||
g_ValveMenuStyle.ClientPressedKey(client, key_press);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValveMenuStyle::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_Players.AddClientListener(this);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
|
||||||
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValveMenuStyle::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
|
||||||
g_Players.RemoveClientListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
|
||||||
DIALOG_TYPE type,
|
|
||||||
KeyValues *kv,
|
|
||||||
IServerPluginCallbacks *plugin)
|
|
||||||
{
|
|
||||||
if (type != DIALOG_MENU)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int client = engine->IndexOfEdict(pEdict);
|
|
||||||
if (client < 1 || client > 256)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CValveMenuPlayer *player = &m_players[client];
|
|
||||||
|
|
||||||
/* We don't care if the player is in a menu because, for all intents and purposes,
|
|
||||||
* the menu is completely private. Instead, we just figure out the level we'll need
|
|
||||||
* in order to override it.
|
|
||||||
*/
|
|
||||||
player->curPrioLevel = kv->GetInt("level", player->curPrioLevel);
|
|
||||||
|
|
||||||
/* Oh no! What happens if we got a menu that overwrites ours?! */
|
|
||||||
if (player->bInMenu)
|
|
||||||
{
|
|
||||||
/* Okay, let the external menu survive for now. It may live another
|
|
||||||
* day to avenge its grandfather, killed in the great Menu Interruption
|
|
||||||
* battle.
|
|
||||||
*/
|
|
||||||
_CancelClientMenu(client, MenuCancel_Interrupted, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuPanel *ValveMenuStyle::CreatePanel()
|
|
||||||
{
|
|
||||||
return new CValveMenuDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
IBaseMenu *ValveMenuStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
|
|
||||||
{
|
|
||||||
return new CValveMenu(pHandler, pOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ValveMenuStyle::GetStyleName()
|
|
||||||
{
|
|
||||||
return "valve";
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ValveMenuStyle::GetMaxPageItems()
|
|
||||||
{
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValveMenuStyle::SendDisplay(int client, IMenuPanel *display)
|
|
||||||
{
|
|
||||||
m_players[client].curPrioLevel--;
|
|
||||||
CValveMenuDisplay *vDisplay = (CValveMenuDisplay *)display;
|
|
||||||
vDisplay->SendRawDisplay(client, m_players[client].curPrioLevel, m_players[client].menuHoldTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValveMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
|
|
||||||
{
|
|
||||||
if (vsp_interface == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BaseMenuStyle::DoClientMenu(client, menu, mh, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValveMenuStyle::DoClientMenu(int client, CBaseMenu *menu, unsigned int first_item, IMenuHandler *mh, unsigned int time)
|
|
||||||
{
|
|
||||||
if (vsp_interface == NULL)
|
|
||||||
{
|
|
||||||
mh->OnMenuStart(menu);
|
|
||||||
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
|
||||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BaseMenuStyle::DoClientMenu(client, menu, first_item, mh, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
CValveMenuDisplay::CValveMenuDisplay()
|
|
||||||
{
|
|
||||||
m_pKv = NULL;
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
CValveMenuDisplay::CValveMenuDisplay(CValveMenu *pMenu)
|
|
||||||
{
|
|
||||||
m_pKv = NULL;
|
|
||||||
Reset();
|
|
||||||
m_pKv->SetColor("color", pMenu->m_IntroColor);
|
|
||||||
m_pKv->SetString("title", pMenu->m_IntroMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CValveMenuDisplay::DeleteThis()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CValveMenuDisplay::~CValveMenuDisplay()
|
|
||||||
{
|
|
||||||
m_pKv->deleteThis();
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuStyle *CValveMenuDisplay::GetParentStyle()
|
|
||||||
{
|
|
||||||
return &g_ValveMenuStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CValveMenuDisplay::Reset()
|
|
||||||
{
|
|
||||||
if (m_pKv)
|
|
||||||
{
|
|
||||||
m_pKv->deleteThis();
|
|
||||||
}
|
|
||||||
m_pKv = new KeyValues("menu");
|
|
||||||
m_NextPos = 1;
|
|
||||||
m_TitleDrawn = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CValveMenuDisplay::GetCurrentKey()
|
|
||||||
{
|
|
||||||
return m_NextPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenuDisplay::SetCurrentKey(unsigned int key)
|
|
||||||
{
|
|
||||||
if (key < m_NextPos || key > 9)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_NextPos = key;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenuDisplay::SetExtOption(MenuOption option, const void *valuePtr)
|
|
||||||
{
|
|
||||||
if (option == MenuOption_IntroMessage)
|
|
||||||
{
|
|
||||||
m_pKv->SetString("title", (const char *)valuePtr);
|
|
||||||
return true;
|
|
||||||
} else if (option == MenuOption_IntroColor) {
|
|
||||||
int *array = (int *)valuePtr;
|
|
||||||
m_pKv->SetColor("color", Color(array[0], array[1], array[2], array[3]));
|
|
||||||
return true;
|
|
||||||
} else if (option == MenuOption_Priority) {
|
|
||||||
m_pKv->SetInt("level", *(int *)valuePtr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenuDisplay::CanDrawItem(unsigned int drawFlags)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* ITEMDRAW_RAWLINE - We can't draw random text, and this doesn't add a slot,
|
|
||||||
* so it's completely safe to ignore it.
|
|
||||||
* -----------------------------------------
|
|
||||||
*/
|
|
||||||
if (drawFlags & ITEMDRAW_RAWLINE)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Special cases, explained in DrawItem()
|
|
||||||
*/
|
|
||||||
if ((drawFlags & ITEMDRAW_NOTEXT)
|
|
||||||
|| (drawFlags & ITEMDRAW_SPACER))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We can't draw disabled text. We could bump the position, but we
|
|
||||||
* want DirectDraw() to find some actual items to display.
|
|
||||||
*/
|
|
||||||
if (drawFlags & ITEMDRAW_DISABLED)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CValveMenuDisplay::DrawItem(const ItemDrawInfo &item)
|
|
||||||
{
|
|
||||||
if (m_NextPos > 9 || !CanDrawItem(item.style))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For these cases we can't draw anything at all, but
|
|
||||||
* we can at least bump the position since we were explicitly asked to.
|
|
||||||
*/
|
|
||||||
if ((item.style & ITEMDRAW_NOTEXT)
|
|
||||||
|| (item.style & ITEMDRAW_SPACER))
|
|
||||||
{
|
|
||||||
return m_NextPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[255];
|
|
||||||
UTIL_Format(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
|
|
||||||
|
|
||||||
KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
|
|
||||||
ki->SetString("command", g_OptionCmdTable[m_NextPos]);
|
|
||||||
ki->SetString("msg", buffer);
|
|
||||||
|
|
||||||
return m_NextPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CValveMenuDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
|
|
||||||
{
|
|
||||||
if (onlyIfEmpty && m_TitleDrawn)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pKv->SetString("msg", text);
|
|
||||||
m_TitleDrawn = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenuDisplay::DrawRawLine(const char *rawline)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int time)
|
|
||||||
{
|
|
||||||
m_pKv->SetInt("level", priority);
|
|
||||||
m_pKv->SetInt("time", time ? time : 200);
|
|
||||||
|
|
||||||
SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
|
|
||||||
engine->PEntityOfEntIndex(client),
|
|
||||||
DIALOG_MENU,
|
|
||||||
m_pKv,
|
|
||||||
vsp_interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenuDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
|
|
||||||
{
|
|
||||||
return g_ValveMenuStyle.DoClientMenu(client, this, handler, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenuDisplay::SetSelectableKeys(unsigned int keymap)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CValveMenuDisplay::GetAmountRemaining()
|
|
||||||
{
|
|
||||||
/* :TODO: this is a lie, but nothing really seems meaningful... */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CValveMenu::CValveMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
|
||||||
CBaseMenu(pHandler, &g_ValveMenuStyle, pOwner),
|
|
||||||
m_IntroColor(255, 0, 0, 255)
|
|
||||||
{
|
|
||||||
strcpy(m_IntroMsg, "You have a menu, press ESC");
|
|
||||||
m_Pagination = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CValveMenu::Cancel_Finally()
|
|
||||||
{
|
|
||||||
g_ValveMenuStyle.CancelMenu(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenu::SetPagination(unsigned int itemsPerPage)
|
|
||||||
{
|
|
||||||
if (itemsPerPage > 5)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CBaseMenu::SetPagination(itemsPerPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
|
||||||
{
|
|
||||||
if (option == MenuOption_IntroMessage)
|
|
||||||
{
|
|
||||||
strncopy(m_IntroMsg, (const char *)valuePtr, sizeof(m_IntroMsg));
|
|
||||||
return true;
|
|
||||||
} else if (option == MenuOption_IntroColor) {
|
|
||||||
unsigned int *array = (unsigned int *)valuePtr;
|
|
||||||
m_IntroColor = Color(array[0], array[1], array[2], array[3]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenu::Display(int client, unsigned int time, IMenuHandler *alt_handler)
|
|
||||||
{
|
|
||||||
return DisplayAtItem(client, time, 0, alt_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CValveMenu::DisplayAtItem(int client,
|
|
||||||
unsigned int time,
|
|
||||||
unsigned int start_item,
|
|
||||||
IMenuHandler *alt_handler/* =NULL */)
|
|
||||||
{
|
|
||||||
if (m_bCancelling)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMenuPanel *CValveMenu::CreatePanel()
|
|
||||||
{
|
|
||||||
return new CValveMenuDisplay(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CValveMenu::SetMenuOptionFlags(unsigned int flags)
|
|
||||||
{
|
|
||||||
flags |= MENUFLAG_BUTTON_EXIT;
|
|
||||||
CBaseMenu::SetMenuOptionFlags(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *g_OptionNumTable[] =
|
|
||||||
{
|
|
||||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *g_OptionCmdTable[] =
|
|
||||||
{
|
|
||||||
"sm_vmenuselect 0", /* INVALID! */
|
|
||||||
"sm_vmenuselect 1",
|
|
||||||
"sm_vmenuselect 2",
|
|
||||||
"sm_vmenuselect 3",
|
|
||||||
"sm_vmenuselect 4",
|
|
||||||
"sm_vmenuselect 5",
|
|
||||||
"sm_vmenuselect 6",
|
|
||||||
"sm_vmenuselect 7",
|
|
||||||
"sm_vmenuselect 8",
|
|
||||||
"sm_vmenuselect 9",
|
|
||||||
"sm_vmenuselect 10"
|
|
||||||
};
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_MENUSTYLE_VALVE_H
|
|
||||||
#define _INCLUDE_MENUSTYLE_VALVE_H
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "MenuManager.h"
|
|
||||||
#include "MenuStyle_Base.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "KeyValues.h"
|
|
||||||
#include "sm_fastlink.h"
|
|
||||||
#include <compat_wrappers.h>
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class CValveMenuPlayer : public CBaseMenuPlayer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CValveMenuPlayer() : curPrioLevel(1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
int curPrioLevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CValveMenu;
|
|
||||||
class CValveMenuDisplay;
|
|
||||||
|
|
||||||
class ValveMenuStyle :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public BaseMenuStyle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ValveMenuStyle();
|
|
||||||
bool OnClientCommand(int client, const char *cmdname, const CCommand &cmd);
|
|
||||||
public: //BaseMenuStyle
|
|
||||||
CBaseMenuPlayer *GetMenuPlayer(int client);
|
|
||||||
void SendDisplay(int client, IMenuPanel *display);
|
|
||||||
bool DoClientMenu(int client, CBaseMenu *menu, unsigned int first_item, IMenuHandler *mh, unsigned int time);
|
|
||||||
bool DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time);
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: //IMenuStyle
|
|
||||||
const char *GetStyleName();
|
|
||||||
IMenuPanel *CreatePanel();
|
|
||||||
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
|
||||||
unsigned int GetMaxPageItems();
|
|
||||||
private:
|
|
||||||
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
|
|
||||||
private:
|
|
||||||
CValveMenuPlayer *m_players;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CValveMenu;
|
|
||||||
|
|
||||||
class CValveMenuDisplay : public IMenuPanel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CValveMenuDisplay();
|
|
||||||
CValveMenuDisplay(CValveMenu *pMenu);
|
|
||||||
~CValveMenuDisplay();
|
|
||||||
public:
|
|
||||||
IMenuStyle *GetParentStyle();
|
|
||||||
void Reset();
|
|
||||||
void DrawTitle(const char *text, bool onlyIfEmpty=false);
|
|
||||||
unsigned int DrawItem(const ItemDrawInfo &item);
|
|
||||||
bool DrawRawLine(const char *rawline);
|
|
||||||
bool SendDisplay(int client, IMenuHandler *handler, unsigned int time);
|
|
||||||
bool SetExtOption(MenuOption option, const void *valuePtr);
|
|
||||||
bool CanDrawItem(unsigned int drawFlags);
|
|
||||||
void SendRawDisplay(int client, int priority, unsigned int time);
|
|
||||||
void DeleteThis();
|
|
||||||
bool SetSelectableKeys(unsigned int keymap);
|
|
||||||
unsigned int GetCurrentKey();
|
|
||||||
bool SetCurrentKey(unsigned int key);
|
|
||||||
int GetAmountRemaining();
|
|
||||||
private:
|
|
||||||
KeyValues *m_pKv;
|
|
||||||
unsigned int m_NextPos;
|
|
||||||
bool m_TitleDrawn;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CValveMenu : public CBaseMenu
|
|
||||||
{
|
|
||||||
friend class CValveMenuDisplay;
|
|
||||||
public:
|
|
||||||
CValveMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
|
||||||
public: //IBaseMenu
|
|
||||||
bool SetExtOption(MenuOption option, const void *valuePtr);
|
|
||||||
IMenuPanel *CreatePanel();
|
|
||||||
bool GetExitButton();
|
|
||||||
bool SetExitButton(bool set);
|
|
||||||
bool SetPagination(unsigned int itemsPerPage);
|
|
||||||
bool Display(int client, unsigned int time, IMenuHandler *alt_handler=NULL);
|
|
||||||
bool DisplayAtItem(int client,
|
|
||||||
unsigned int time,
|
|
||||||
unsigned int start_item,
|
|
||||||
IMenuHandler *alt_handler/* =NULL */);
|
|
||||||
void SetMenuOptionFlags(unsigned int flags);
|
|
||||||
public: //CBaseMenu
|
|
||||||
void Cancel_Finally();
|
|
||||||
private:
|
|
||||||
Color m_IntroColor;
|
|
||||||
char m_IntroMsg[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ValveMenuStyle g_ValveMenuStyle;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_MENUSTYLE_VALVE_H
|
|
||||||
@ -1,413 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "MenuVoting.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
|
|
||||||
float g_next_vote = 0.0f;
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
|
|
||||||
#else
|
|
||||||
void OnVoteDelayChange(ConVar *cvar, const char *value);
|
|
||||||
#endif
|
|
||||||
ConVar sm_vote_delay("sm_vote_delay",
|
|
||||||
"30",
|
|
||||||
0,
|
|
||||||
"Sets the recommended time in between public votes",
|
|
||||||
false,
|
|
||||||
0.0,
|
|
||||||
false,
|
|
||||||
0.0,
|
|
||||||
OnVoteDelayChange);
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
|
|
||||||
#else
|
|
||||||
void OnVoteDelayChange(ConVar *cvar, const char *value)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* See if the new vote delay isn't something we need to account for */
|
|
||||||
if (sm_vote_delay.GetFloat() < 1.0f)
|
|
||||||
{
|
|
||||||
g_next_vote = 0.0f;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there was never a last vote, ignore this change */
|
|
||||||
if (g_next_vote < 0.1f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Subtract the original value, then add the new one. */
|
|
||||||
g_next_vote -= (float)atof(value);
|
|
||||||
g_next_vote += sm_vote_delay.GetFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int VoteMenuHandler::GetRemainingVoteDelay()
|
|
||||||
{
|
|
||||||
if (g_next_vote <= gpGlobals->curtime)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (unsigned int)(g_next_vote - gpGlobals->curtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_Players.AddClientListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
g_Players.RemoveClientListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
g_next_vote = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int VoteMenuHandler::GetMenuAPIVersion2()
|
|
||||||
{
|
|
||||||
return m_pHandler->GetMenuAPIVersion2();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnClientDisconnected(int client)
|
|
||||||
{
|
|
||||||
if (!IsVoteInProgress())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wipe out their vote if they had one */
|
|
||||||
int item;
|
|
||||||
if ((item = m_ClientVotes[client]) >= 0)
|
|
||||||
{
|
|
||||||
assert((unsigned)item < m_Items);
|
|
||||||
assert(m_Votes[item] > 0);
|
|
||||||
m_Votes[item]--;
|
|
||||||
m_ClientVotes[client] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoteMenuHandler::IsVoteInProgress()
|
|
||||||
{
|
|
||||||
return (m_pCurMenu != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags/* =0 */)
|
|
||||||
{
|
|
||||||
if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float fVoteDelay = sm_vote_delay.GetFloat();
|
|
||||||
if (fVoteDelay < 1.0)
|
|
||||||
{
|
|
||||||
g_next_vote = 0.0;
|
|
||||||
} else {
|
|
||||||
/* This little trick breaks for infinite votes!
|
|
||||||
* However, we just ignore that since those 1) shouldn't exist and
|
|
||||||
* 2) people must be checking IsVoteInProgress() beforehand anyway.
|
|
||||||
*/
|
|
||||||
g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i=0; i<num_clients; i++)
|
|
||||||
{
|
|
||||||
menu->Display(clients[i], max_time, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
StartVoting();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
|
||||||
IMenuHandler *handler,
|
|
||||||
unsigned int time,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
|
||||||
if (IsVoteInProgress())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
InternalReset();
|
|
||||||
|
|
||||||
/* Mark all clients as not voting */
|
|
||||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
|
||||||
{
|
|
||||||
m_ClientVotes[i] = -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Items = menu->GetItemCount();
|
|
||||||
|
|
||||||
if (m_Votes.size() < (size_t)m_Items)
|
|
||||||
{
|
|
||||||
/* Only clear the items we need to... */
|
|
||||||
size_t size = m_Votes.size();
|
|
||||||
for (size_t i=0; i<size; i++)
|
|
||||||
{
|
|
||||||
m_Votes[i] = 0;
|
|
||||||
}
|
|
||||||
m_Votes.resize(m_Items, 0);
|
|
||||||
} else {
|
|
||||||
for (unsigned int i=0; i<m_Items; i++)
|
|
||||||
{
|
|
||||||
m_Votes[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pCurMenu = menu;
|
|
||||||
m_VoteTime = time;
|
|
||||||
m_VoteFlags = flags;
|
|
||||||
m_pHandler = handler;
|
|
||||||
|
|
||||||
m_pHandler->OnMenuStart(m_pCurMenu);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::StartVoting()
|
|
||||||
{
|
|
||||||
if (!m_pCurMenu)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bStarted = true;
|
|
||||||
|
|
||||||
m_pHandler->OnMenuVoteStart(m_pCurMenu);
|
|
||||||
|
|
||||||
/* By now we know how many clients were set.
|
|
||||||
* If there are none, we should end IMMEDIATELY.
|
|
||||||
*/
|
|
||||||
if (m_Clients == 0)
|
|
||||||
{
|
|
||||||
EndVoting();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::DecrementPlayerCount()
|
|
||||||
{
|
|
||||||
assert(m_Clients > 0);
|
|
||||||
|
|
||||||
m_Clients--;
|
|
||||||
|
|
||||||
if (m_bStarted && m_Clients == 0)
|
|
||||||
{
|
|
||||||
EndVoting();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int SortVoteItems(const void *item1, const void *item2)
|
|
||||||
{
|
|
||||||
return ((menu_vote_result_t::menu_item_vote_t *)item2)->count
|
|
||||||
- ((menu_vote_result_t::menu_item_vote_t *)item1)->count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::EndVoting()
|
|
||||||
{
|
|
||||||
/* Set when the next delay ends. We ignore cancellation because a menu
|
|
||||||
* was, at one point, displayed, which is all that counts. However, we
|
|
||||||
* do re-calculate the time just in case the menu had no time limit.
|
|
||||||
*/
|
|
||||||
float fVoteDelay = sm_vote_delay.GetFloat();
|
|
||||||
if (fVoteDelay < 1.0)
|
|
||||||
{
|
|
||||||
g_next_vote = 0.0;
|
|
||||||
} else {
|
|
||||||
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_bCancelled)
|
|
||||||
{
|
|
||||||
/* If we were cancelled, don't bother tabulating anything.
|
|
||||||
* Reset just in case someone tries to redraw, which means
|
|
||||||
* we need to save our states.
|
|
||||||
*/
|
|
||||||
IBaseMenu *menu = m_pCurMenu;
|
|
||||||
IMenuHandler *handler = m_pHandler;
|
|
||||||
InternalReset();
|
|
||||||
handler->OnMenuVoteCancel(menu, VoteCancel_Generic);
|
|
||||||
handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_vote_result_t vote;
|
|
||||||
menu_vote_result_t::menu_client_vote_t client_vote[256];
|
|
||||||
menu_vote_result_t::menu_item_vote_t item_vote[256];
|
|
||||||
|
|
||||||
memset(&vote, 0, sizeof(vote));
|
|
||||||
|
|
||||||
/* Build the item list */
|
|
||||||
for (unsigned int i=0; i<m_Items; i++)
|
|
||||||
{
|
|
||||||
if (m_Votes[i] > 0)
|
|
||||||
{
|
|
||||||
item_vote[vote.num_items].count = m_Votes[i];
|
|
||||||
item_vote[vote.num_items].item = i;
|
|
||||||
vote.num_votes += m_Votes[i];
|
|
||||||
vote.num_items++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vote.item_list = item_vote;
|
|
||||||
|
|
||||||
if (!vote.num_votes)
|
|
||||||
{
|
|
||||||
IBaseMenu *menu = m_pCurMenu;
|
|
||||||
IMenuHandler *handler = m_pHandler;
|
|
||||||
InternalReset();
|
|
||||||
handler->OnMenuVoteCancel(menu, VoteCancel_NoVotes);
|
|
||||||
handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build the client list */
|
|
||||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
|
||||||
{
|
|
||||||
if (m_ClientVotes[i] >= -1)
|
|
||||||
{
|
|
||||||
client_vote[vote.num_clients].client = i;
|
|
||||||
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
|
||||||
vote.num_clients++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vote.client_list = client_vote;
|
|
||||||
|
|
||||||
/* Sort the item list descending like we promised */
|
|
||||||
qsort(item_vote,
|
|
||||||
vote.num_items,
|
|
||||||
sizeof(menu_vote_result_t::menu_item_vote_t),
|
|
||||||
SortVoteItems);
|
|
||||||
|
|
||||||
/* Save states, then clear what we've saved.
|
|
||||||
* This makes us re-entrant, which is always the safe way to go.
|
|
||||||
*/
|
|
||||||
IBaseMenu *menu = m_pCurMenu;
|
|
||||||
IMenuHandler *handler = m_pHandler;
|
|
||||||
InternalReset();
|
|
||||||
|
|
||||||
/* Send vote info */
|
|
||||||
handler->OnMenuVoteResults(menu, &vote);
|
|
||||||
handler->OnMenuEnd(menu, MenuEnd_VotingDone);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
|
|
||||||
{
|
|
||||||
m_Clients++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
|
|
||||||
{
|
|
||||||
DecrementPlayerCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
|
|
||||||
{
|
|
||||||
m_pHandler->OnMenuCancel(menu, client, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
|
||||||
{
|
|
||||||
m_ClientVotes[client] = -1;
|
|
||||||
m_pHandler->OnMenuDisplay(menu, client, display);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr)
|
|
||||||
{
|
|
||||||
return m_pHandler->OnMenuDisplayItem(menu, client, panel, item, dr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
|
|
||||||
{
|
|
||||||
m_pHandler->OnMenuDrawItem(menu, client, item, style);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
|
|
||||||
{
|
|
||||||
/* Check by our item count, NOT the vote array size */
|
|
||||||
if (item < m_Items)
|
|
||||||
{
|
|
||||||
m_ClientVotes[client] = item;
|
|
||||||
m_Votes[item]++;
|
|
||||||
m_NumVotes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pHandler->OnMenuSelect(menu, client, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
|
|
||||||
{
|
|
||||||
if (m_pHandler->GetMenuAPIVersion2() >= 13)
|
|
||||||
{
|
|
||||||
m_pHandler->OnMenuSelect2(menu, client, item, item_on_page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::InternalReset()
|
|
||||||
{
|
|
||||||
m_Clients = 0;
|
|
||||||
m_Items = 0;
|
|
||||||
m_bStarted = false;
|
|
||||||
m_pCurMenu = NULL;
|
|
||||||
m_NumVotes = 0;
|
|
||||||
m_bCancelled = false;
|
|
||||||
m_pHandler = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoteMenuHandler::CancelVoting()
|
|
||||||
{
|
|
||||||
if (m_bCancelled || !m_pCurMenu)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_bCancelled = true;
|
|
||||||
m_pCurMenu->Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
IBaseMenu *VoteMenuHandler::GetCurrentMenu()
|
|
||||||
{
|
|
||||||
return m_pCurMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoteMenuHandler::IsCancelling()
|
|
||||||
{
|
|
||||||
return m_bCancelled;
|
|
||||||
}
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_MENUVOTING_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_MENUVOTING_H_
|
|
||||||
|
|
||||||
#include <IMenuManager.h>
|
|
||||||
#include <IPlayerHelpers.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class VoteMenuHandler :
|
|
||||||
public IMenuHandler,
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IClientListener
|
|
||||||
{
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
public: //IClientListener
|
|
||||||
void OnClientDisconnected(int client);
|
|
||||||
public: //IMenuHandler
|
|
||||||
unsigned int GetMenuAPIVersion2();
|
|
||||||
void OnMenuStart(IBaseMenu *menu);
|
|
||||||
void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
|
|
||||||
void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
|
|
||||||
void OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page);
|
|
||||||
void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
|
|
||||||
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
|
||||||
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
|
|
||||||
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
|
|
||||||
public:
|
|
||||||
bool StartVote(IBaseMenu *menu,
|
|
||||||
unsigned int num_clients,
|
|
||||||
int clients[],
|
|
||||||
unsigned int max_time,
|
|
||||||
unsigned int flags=0);
|
|
||||||
bool IsVoteInProgress();
|
|
||||||
void CancelVoting();
|
|
||||||
IBaseMenu *GetCurrentMenu();
|
|
||||||
bool IsCancelling();
|
|
||||||
unsigned int GetRemainingVoteDelay();
|
|
||||||
private:
|
|
||||||
void Reset(IMenuHandler *mh);
|
|
||||||
void DecrementPlayerCount();
|
|
||||||
void EndVoting();
|
|
||||||
void InternalReset();
|
|
||||||
bool InitializeVoting(IBaseMenu *menu,
|
|
||||||
IMenuHandler *handler,
|
|
||||||
unsigned int time,
|
|
||||||
unsigned int flags);
|
|
||||||
void StartVoting();
|
|
||||||
private:
|
|
||||||
IMenuHandler *m_pHandler;
|
|
||||||
unsigned int m_Clients;
|
|
||||||
unsigned int m_Items;
|
|
||||||
CVector<unsigned int> m_Votes;
|
|
||||||
IBaseMenu *m_pCurMenu;
|
|
||||||
bool m_bStarted;
|
|
||||||
bool m_bCancelled;
|
|
||||||
unsigned int m_NumVotes;
|
|
||||||
unsigned int m_VoteTime;
|
|
||||||
unsigned int m_VoteFlags;
|
|
||||||
int m_ClientVotes[256+1];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,197 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include <eiface.h>
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include <IForwardSys.h>
|
|
||||||
#include <IPlayerHelpers.h>
|
|
||||||
#include <IAdminSystem.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
#define PLAYER_LIFE_UNKNOWN 0
|
|
||||||
#define PLAYER_LIFE_ALIVE 1
|
|
||||||
#define PLAYER_LIFE_DEAD 2
|
|
||||||
|
|
||||||
#define MIN_API_FOR_ADMINCALLS 7
|
|
||||||
|
|
||||||
class CPlayer : public IGamePlayer
|
|
||||||
{
|
|
||||||
friend class PlayerManager;
|
|
||||||
public:
|
|
||||||
CPlayer();
|
|
||||||
public:
|
|
||||||
const char *GetName();
|
|
||||||
const char *GetIPAddress();
|
|
||||||
const char *GetAuthString();
|
|
||||||
edict_t *GetEdict();
|
|
||||||
bool IsInGame();
|
|
||||||
bool WasCountedAsInGame();
|
|
||||||
bool IsConnected();
|
|
||||||
bool IsAuthorized();
|
|
||||||
bool IsFakeClient();
|
|
||||||
void SetAdminId(AdminId id, bool temporary);
|
|
||||||
AdminId GetAdminId();
|
|
||||||
void Kick(const char *str);
|
|
||||||
IPlayerInfo *GetPlayerInfo();
|
|
||||||
unsigned int GetLanguageId();
|
|
||||||
int GetUserId();
|
|
||||||
bool RunAdminCacheChecks();
|
|
||||||
void NotifyPostAdminChecks();
|
|
||||||
public:
|
|
||||||
void DoBasicAdminChecks();
|
|
||||||
bool IsInKickQueue();
|
|
||||||
void MarkAsBeingKicked();
|
|
||||||
int GetLifeState();
|
|
||||||
private:
|
|
||||||
void Initialize(const char *name, const char *ip, edict_t *pEntity);
|
|
||||||
void Connect();
|
|
||||||
void Disconnect();
|
|
||||||
void SetName(const char *name);
|
|
||||||
void DumpAdmin(bool deleting);
|
|
||||||
void Authorize(const char *auth);
|
|
||||||
void Authorize_Post();
|
|
||||||
void DoPostConnectAuthorization();
|
|
||||||
private:
|
|
||||||
bool m_IsConnected;
|
|
||||||
bool m_IsInGame;
|
|
||||||
bool m_IsAuthorized;
|
|
||||||
bool m_bIsInKickQueue;
|
|
||||||
String m_Name;
|
|
||||||
String m_Ip;
|
|
||||||
String m_IpNoPort;
|
|
||||||
String m_AuthID;
|
|
||||||
AdminId m_Admin;
|
|
||||||
bool m_TempAdmin;
|
|
||||||
edict_t *m_pEdict;
|
|
||||||
IPlayerInfo *m_Info;
|
|
||||||
String m_LastPassword;
|
|
||||||
bool m_bAdminCheckSignalled;
|
|
||||||
int m_iIndex;
|
|
||||||
unsigned int m_LangId;
|
|
||||||
int m_UserId;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PlayerManager :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IPlayerManager
|
|
||||||
{
|
|
||||||
friend class CPlayer;
|
|
||||||
public:
|
|
||||||
PlayerManager();
|
|
||||||
~PlayerManager();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
void OnSourceModLevelEnd();
|
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
|
|
||||||
public:
|
|
||||||
CPlayer *GetPlayerByIndex(int client) const;
|
|
||||||
void RunAuthChecks();
|
|
||||||
void ClearAdminId(AdminId id);
|
|
||||||
void ClearAllAdmins();
|
|
||||||
public:
|
|
||||||
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
|
||||||
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
|
||||||
void OnClientPutInServer(edict_t *pEntity, char const *playername);
|
|
||||||
void OnClientDisconnect(edict_t *pEntity);
|
|
||||||
void OnClientDisconnect_Post(edict_t *pEntity);
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void OnClientCommand(edict_t *pEntity, const CCommand &args);
|
|
||||||
#else
|
|
||||||
void OnClientCommand(edict_t *pEntity);
|
|
||||||
#endif
|
|
||||||
void OnClientSettingsChanged(edict_t *pEntity);
|
|
||||||
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
|
||||||
public: //IPlayerManager
|
|
||||||
void AddClientListener(IClientListener *listener);
|
|
||||||
void RemoveClientListener(IClientListener *listener);
|
|
||||||
IGamePlayer *GetGamePlayer(int client);
|
|
||||||
IGamePlayer *GetGamePlayer(edict_t *pEdict);
|
|
||||||
int GetMaxClients();
|
|
||||||
int GetNumPlayers();
|
|
||||||
int GetClientOfUserId(int userid);
|
|
||||||
bool IsServerActivated();
|
|
||||||
int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags);
|
|
||||||
int InternalFilterCommandTarget(CPlayer *pAdmin, CPlayer *pTarget, int flags);
|
|
||||||
void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
|
||||||
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
|
||||||
void ProcessCommandTarget(cmd_target_info_t *info);
|
|
||||||
public:
|
|
||||||
inline int MaxClients()
|
|
||||||
{
|
|
||||||
return m_maxClients;
|
|
||||||
}
|
|
||||||
inline int NumPlayers()
|
|
||||||
{
|
|
||||||
return m_PlayerCount;
|
|
||||||
}
|
|
||||||
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
|
||||||
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
|
|
||||||
const char *GetPassInfoVar();
|
|
||||||
void RecheckAnyAdmins();
|
|
||||||
unsigned int GetReplyTo();
|
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
|
||||||
private:
|
|
||||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
|
||||||
private:
|
|
||||||
List<IClientListener *> m_hooks;
|
|
||||||
IForward *m_clconnect;
|
|
||||||
IForward *m_cldisconnect;
|
|
||||||
IForward *m_cldisconnect_post;
|
|
||||||
IForward *m_clputinserver;
|
|
||||||
IForward *m_clcommand;
|
|
||||||
IForward *m_clinfochanged;
|
|
||||||
IForward *m_clauth;
|
|
||||||
IForward *m_onActivate;
|
|
||||||
IForward *m_onActivate2;
|
|
||||||
CPlayer *m_Players;
|
|
||||||
int *m_UserIdLookUp;
|
|
||||||
int m_maxClients;
|
|
||||||
int m_PlayerCount;
|
|
||||||
bool m_FirstPass;
|
|
||||||
unsigned int *m_AuthQueue;
|
|
||||||
String m_PassInfoVar;
|
|
||||||
bool m_QueryLang;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern PlayerManager g_Players;
|
|
||||||
extern bool g_OnMapStarted;
|
|
||||||
extern const unsigned int *g_NumPlayersToAuth;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_
|
|
||||||
1053
core/TextParsers.cpp
1053
core/TextParsers.cpp
File diff suppressed because it is too large
Load Diff
@ -1,85 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
|
||||||
|
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param void * IN: Stream pointer
|
|
||||||
* @param char * IN/OUT: Stream buffer
|
|
||||||
* @param size_t IN: Maximum size of buffer
|
|
||||||
* @param unsigned int * OUT: Number of bytes read (0 = end of stream)
|
|
||||||
* @return True on success, false on failure
|
|
||||||
*/
|
|
||||||
typedef bool (*STREAMREADER)(void *, char *, size_t, unsigned int *);
|
|
||||||
|
|
||||||
class TextParsers :
|
|
||||||
public ITextParsers,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TextParsers();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
public:
|
|
||||||
bool ParseFile_INI(const char *file,
|
|
||||||
ITextListener_INI *ini_listener,
|
|
||||||
unsigned int *line,
|
|
||||||
unsigned int *col);
|
|
||||||
|
|
||||||
SMCError ParseFile_SMC(const char *file,
|
|
||||||
ITextListener_SMC *smc_listener,
|
|
||||||
SMCStates *states);
|
|
||||||
|
|
||||||
unsigned int GetUTF8CharBytes(const char *stream);
|
|
||||||
|
|
||||||
const char *GetSMCErrorString(SMCError err);
|
|
||||||
bool IsWhitespace(const char *stream);
|
|
||||||
private:
|
|
||||||
SMCError ParseString_SMC(const char *stream,
|
|
||||||
ITextListener_SMC *smc,
|
|
||||||
SMCStates *states);
|
|
||||||
SMCError ParseStream_SMC(void *stream,
|
|
||||||
STREAMREADER srdr,
|
|
||||||
ITextListener_SMC *smc,
|
|
||||||
SMCStates *states);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
extern TextParsers g_TextParser;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
|
||||||
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ThreadSupport.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
|
|
||||||
#if defined PLATFORM_POSIX
|
|
||||||
#include "thread/PosixThreads.h"
|
|
||||||
#elif defined PLATFORM_WINDOWS
|
|
||||||
#include "thread/WinThreads.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MainThreader g_MainThreader;
|
|
||||||
IThreader *g_pThreader = &g_MainThreader;
|
|
||||||
|
|
||||||
class RegThreadStuff : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, g_pThreader);
|
|
||||||
}
|
|
||||||
} s_RegThreadStuff;
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
|
||||||
#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
|
||||||
|
|
||||||
#include <IThreader.h>
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
extern IThreader *g_pThreader;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
|
||||||
@ -1,514 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "TimerSys.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "frame_hooks.h"
|
|
||||||
|
|
||||||
#define TIMER_MIN_ACCURACY 0.1
|
|
||||||
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
|
||||||
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
|
||||||
#else
|
|
||||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TimerSystem g_Timers;
|
|
||||||
double g_fUniversalTime = 0.0f;
|
|
||||||
float g_fGameStartTime = 0.0f; /* Game game start time, non-universal */
|
|
||||||
double g_fTimerThink = 0.0f; /* Timer's next think time */
|
|
||||||
const double *g_pUniversalTime = &g_fUniversalTime;
|
|
||||||
ConVar *mp_timelimit = NULL;
|
|
||||||
int g_TimeLeftMode = 0;
|
|
||||||
|
|
||||||
ConVar sm_time_adjustment("sm_time_adjustment", "0", 0, "Adjusts the server time in seconds");
|
|
||||||
|
|
||||||
inline double GetSimulatedTime()
|
|
||||||
{
|
|
||||||
return g_fUniversalTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t GetAdjustedTime(time_t *buf)
|
|
||||||
{
|
|
||||||
time_t val = time(NULL) + sm_time_adjustment.GetInt();
|
|
||||||
if (buf)
|
|
||||||
{
|
|
||||||
*buf = val;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DefaultMapTimer :
|
|
||||||
public IMapTimer,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DefaultMapTimer()
|
|
||||||
{
|
|
||||||
m_bInUse = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
g_fGameStartTime = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetMapTimeLimit()
|
|
||||||
{
|
|
||||||
return mp_timelimit->GetInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetMapTimerStatus(bool enabled)
|
|
||||||
{
|
|
||||||
if (enabled && !m_bInUse)
|
|
||||||
{
|
|
||||||
Enable();
|
|
||||||
}
|
|
||||||
else if (!enabled && m_bInUse)
|
|
||||||
{
|
|
||||||
Disable();
|
|
||||||
}
|
|
||||||
m_bInUse = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExtendMapTimeLimit(int extra_time)
|
|
||||||
{
|
|
||||||
if (extra_time == 0)
|
|
||||||
{
|
|
||||||
mp_timelimit->SetValue(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
extra_time /= 60;
|
|
||||||
|
|
||||||
mp_timelimit->SetValue(mp_timelimit->GetInt() + extra_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void GlobalChangeCallback(ConVar *pVar, const char *old_value, float flOldValue)
|
|
||||||
#else
|
|
||||||
void GlobalChangeCallback(ConVar *pVar, const char *old_value)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (pVar != mp_timelimit)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atoi(old_value) == pVar->GetInt())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Timers.MapTimeLeftChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Enable()
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_MEMFUNC(ICvar, CallGlobalChangeCallbacks, icvar, this, &DefaultMapTimer::GlobalChangeCallback, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disable()
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, CallGlobalChangeCallbacks, icvar, this, &DefaultMapTimer::GlobalChangeCallback, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_bInUse;
|
|
||||||
} s_DefaultMapTimer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the ticking process has run amok (should be impossible), we
|
|
||||||
* take care of this by "skipping" the in-between time, to prevent
|
|
||||||
* a bazillion times from firing on accident. This has the result
|
|
||||||
* that a drastic jump in time will continue acting normally. Users
|
|
||||||
* may not expect this, but... I think it is the best solution.
|
|
||||||
*/
|
|
||||||
inline double CalcNextThink(double last, float interval)
|
|
||||||
{
|
|
||||||
if (g_fUniversalTime - last - interval <= TIMER_MIN_ACCURACY)
|
|
||||||
{
|
|
||||||
return last + interval;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return g_fUniversalTime + interval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
|
|
||||||
{
|
|
||||||
m_Listener = pCallbacks;
|
|
||||||
m_Interval = fInterval;
|
|
||||||
m_ToExec = fToExec;
|
|
||||||
m_pData = pData;
|
|
||||||
m_Flags = flags;
|
|
||||||
m_InExec = false;
|
|
||||||
m_KillMe = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerSystem::TimerSystem()
|
|
||||||
{
|
|
||||||
m_pMapTimer = NULL;
|
|
||||||
m_bHasMapTickedYet = false;
|
|
||||||
m_bHasMapSimulatedYet = false;
|
|
||||||
m_fLastTickedTime = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerSystem::~TimerSystem()
|
|
||||||
{
|
|
||||||
CStack<ITimer *>::iterator iter;
|
|
||||||
for (iter=m_FreeTimers.begin(); iter!=m_FreeTimers.end(); iter++)
|
|
||||||
{
|
|
||||||
delete (*iter);
|
|
||||||
}
|
|
||||||
m_FreeTimers.popall();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
|
||||||
m_pOnMapTimeLeftChanged = g_Forwards.CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::OnSourceModGameInitialized()
|
|
||||||
{
|
|
||||||
mp_timelimit = icvar->FindVar("mp_timelimit");
|
|
||||||
|
|
||||||
if (m_pMapTimer == NULL && mp_timelimit != NULL)
|
|
||||||
{
|
|
||||||
SetMapTimer(&s_DefaultMapTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
SetMapTimer(NULL);
|
|
||||||
g_Forwards.ReleaseForward(m_pOnGameFrame);
|
|
||||||
g_Forwards.ReleaseForward(m_pOnMapTimeLeftChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
MapChange(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::OnSourceModLevelEnd()
|
|
||||||
{
|
|
||||||
m_bHasMapTickedYet = false;
|
|
||||||
m_bHasMapSimulatedYet = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::GameFrame(bool simulating)
|
|
||||||
{
|
|
||||||
if (simulating && m_bHasMapTickedYet)
|
|
||||||
{
|
|
||||||
g_fUniversalTime += gpGlobals->curtime - m_fLastTickedTime;
|
|
||||||
if (!m_bHasMapSimulatedYet)
|
|
||||||
{
|
|
||||||
m_bHasMapSimulatedYet = true;
|
|
||||||
MapTimeLeftChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_fUniversalTime += gpGlobals->interval_per_tick;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fLastTickedTime = gpGlobals->curtime;
|
|
||||||
m_bHasMapTickedYet = true;
|
|
||||||
|
|
||||||
if (g_fUniversalTime >= g_fTimerThink)
|
|
||||||
{
|
|
||||||
RunFrame();
|
|
||||||
|
|
||||||
g_fTimerThink = CalcNextThink(g_fTimerThink, TIMER_MIN_ACCURACY);
|
|
||||||
}
|
|
||||||
|
|
||||||
RunFrameHooks();
|
|
||||||
|
|
||||||
if (m_pOnGameFrame->GetFunctionCount())
|
|
||||||
{
|
|
||||||
m_pOnGameFrame->Execute(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::RunFrame()
|
|
||||||
{
|
|
||||||
ITimer *pTimer;
|
|
||||||
TimerIter iter;
|
|
||||||
|
|
||||||
double curtime = GetSimulatedTime();
|
|
||||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
|
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
if (curtime >= pTimer->m_ToExec)
|
|
||||||
{
|
|
||||||
pTimer->m_InExec = true;
|
|
||||||
pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
iter = m_SingleTimers.erase(iter);
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultType res;
|
|
||||||
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
|
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
if (curtime >= pTimer->m_ToExec)
|
|
||||||
{
|
|
||||||
pTimer->m_InExec = true;
|
|
||||||
res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
|
||||||
if (pTimer->m_KillMe || (res == Pl_Stop))
|
|
||||||
{
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
iter = m_LoopTimers.erase(iter);
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pTimer->m_InExec = false;
|
|
||||||
pTimer->m_ToExec = CalcNextThink(pTimer->m_ToExec, pTimer->m_Interval);
|
|
||||||
}
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
|
|
||||||
{
|
|
||||||
ITimer *pTimer;
|
|
||||||
TimerIter iter;
|
|
||||||
float to_exec = GetSimulatedTime() + fInterval;
|
|
||||||
|
|
||||||
if (m_FreeTimers.empty())
|
|
||||||
{
|
|
||||||
pTimer = new ITimer;
|
|
||||||
} else {
|
|
||||||
pTimer = m_FreeTimers.front();
|
|
||||||
m_FreeTimers.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
|
|
||||||
|
|
||||||
if (flags & TIMER_FLAG_REPEAT)
|
|
||||||
{
|
|
||||||
m_LoopTimers.push_back(pTimer);
|
|
||||||
goto return_timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_SingleTimers.size() >= 1)
|
|
||||||
{
|
|
||||||
iter = --m_SingleTimers.end();
|
|
||||||
if ((*iter)->m_ToExec <= to_exec)
|
|
||||||
{
|
|
||||||
goto normal_insert_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
|
||||||
{
|
|
||||||
if ((*iter)->m_ToExec >= to_exec)
|
|
||||||
{
|
|
||||||
m_SingleTimers.insert(iter, pTimer);
|
|
||||||
goto return_timer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
normal_insert_end:
|
|
||||||
m_SingleTimers.push_back(pTimer);
|
|
||||||
|
|
||||||
return_timer:
|
|
||||||
return pTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
|
|
||||||
{
|
|
||||||
ResultType res;
|
|
||||||
|
|
||||||
if (pTimer->m_InExec)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pTimer->m_InExec = true;
|
|
||||||
res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
|
||||||
|
|
||||||
if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
|
|
||||||
{
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
m_SingleTimers.remove(pTimer);
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((res != Pl_Stop) && !pTimer->m_KillMe)
|
|
||||||
{
|
|
||||||
if (delayExec)
|
|
||||||
{
|
|
||||||
pTimer->m_ToExec = GetSimulatedTime() + pTimer->m_Interval;
|
|
||||||
}
|
|
||||||
pTimer->m_InExec = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
m_LoopTimers.remove(pTimer);
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::KillTimer(ITimer *pTimer)
|
|
||||||
{
|
|
||||||
if (pTimer->m_KillMe)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pTimer->m_InExec)
|
|
||||||
{
|
|
||||||
pTimer->m_KillMe = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
|
|
||||||
if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
|
|
||||||
{
|
|
||||||
m_LoopTimers.remove(pTimer);
|
|
||||||
} else {
|
|
||||||
m_SingleTimers.remove(pTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
CStack<ITimer *> s_tokill;
|
|
||||||
void TimerSystem::MapChange(bool real_mapchange)
|
|
||||||
{
|
|
||||||
ITimer *pTimer;
|
|
||||||
TimerIter iter;
|
|
||||||
|
|
||||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
if (real_mapchange && (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE))
|
|
||||||
{
|
|
||||||
s_tokill.push(pTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
|
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
if (real_mapchange && (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE))
|
|
||||||
{
|
|
||||||
s_tokill.push(pTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!s_tokill.empty())
|
|
||||||
{
|
|
||||||
KillTimer(s_tokill.front());
|
|
||||||
s_tokill.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IMapTimer *TimerSystem::SetMapTimer(IMapTimer *pTimer)
|
|
||||||
{
|
|
||||||
IMapTimer *old = m_pMapTimer;
|
|
||||||
|
|
||||||
m_pMapTimer = pTimer;
|
|
||||||
|
|
||||||
if (m_pMapTimer)
|
|
||||||
{
|
|
||||||
m_pMapTimer->SetMapTimerStatus(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old)
|
|
||||||
{
|
|
||||||
old->SetMapTimerStatus(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMapTimer *TimerSystem::GetMapTimer()
|
|
||||||
{
|
|
||||||
return m_pMapTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::MapTimeLeftChanged()
|
|
||||||
{
|
|
||||||
m_pOnMapTimeLeftChanged->Execute(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerSystem::NotifyOfGameStart(float offset)
|
|
||||||
{
|
|
||||||
g_fGameStartTime = gpGlobals->curtime + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
float TimerSystem::GetTickedTime()
|
|
||||||
{
|
|
||||||
return g_fUniversalTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimerSystem::GetMapTimeLeft(float *time_left)
|
|
||||||
{
|
|
||||||
if (!m_pMapTimer)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int time_limit;
|
|
||||||
if (!m_bHasMapSimulatedYet || (time_limit = m_pMapTimer->GetMapTimeLimit()) < 1)
|
|
||||||
{
|
|
||||||
*time_left = -1.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*time_left = (g_fGameStartTime + time_limit * 60.0f) - gpGlobals->curtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
111
core/TimerSys.h
111
core/TimerSys.h
@ -1,111 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
|
||||||
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <ITimerSystem.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
typedef List<ITimer *> TimerList;
|
|
||||||
typedef List<ITimer *>::iterator TimerIter;
|
|
||||||
|
|
||||||
class SourceMod::ITimer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags);
|
|
||||||
ITimedEvent *m_Listener;
|
|
||||||
void *m_pData;
|
|
||||||
float m_Interval;
|
|
||||||
double m_ToExec;
|
|
||||||
int m_Flags;
|
|
||||||
bool m_InExec;
|
|
||||||
bool m_KillMe;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TimerSystem :
|
|
||||||
public ITimerSystem,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TimerSystem();
|
|
||||||
~TimerSystem();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
void OnSourceModLevelEnd();
|
|
||||||
void OnSourceModGameInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: //ITimerSystem
|
|
||||||
ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
|
|
||||||
void KillTimer(ITimer *pTimer);
|
|
||||||
void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
|
|
||||||
void MapTimeLeftChanged();
|
|
||||||
IMapTimer *SetMapTimer(IMapTimer *pTimer);
|
|
||||||
float GetTickedTime();
|
|
||||||
void NotifyOfGameStart(float offset /* = 0.0f */);
|
|
||||||
bool GetMapTimeLeft(float *pTime);
|
|
||||||
public:
|
|
||||||
void RunFrame();
|
|
||||||
void MapChange(bool real_mapchange);
|
|
||||||
void GameFrame(bool simulating);
|
|
||||||
IMapTimer *GetMapTimer();
|
|
||||||
private:
|
|
||||||
List<ITimer *> m_SingleTimers;
|
|
||||||
List<ITimer *> m_LoopTimers;
|
|
||||||
CStack<ITimer *> m_FreeTimers;
|
|
||||||
IMapTimer *m_pMapTimer;
|
|
||||||
|
|
||||||
/* This is stuff for our manual ticking escapades. */
|
|
||||||
bool m_bHasMapTickedYet; /** Has the map ticked yet? */
|
|
||||||
bool m_bHasMapSimulatedYet; /** Has the map simulated yet? */
|
|
||||||
float m_fLastTickedTime; /** Last time that the game currently gave
|
|
||||||
us while ticking.
|
|
||||||
*/
|
|
||||||
|
|
||||||
IForward *m_pOnGameFrame;
|
|
||||||
IForward *m_pOnMapTimeLeftChanged;
|
|
||||||
};
|
|
||||||
|
|
||||||
time_t GetAdjustedTime(time_t *buf = NULL);
|
|
||||||
|
|
||||||
extern const double *g_pUniversalTime;
|
|
||||||
extern TimerSystem g_Timers;
|
|
||||||
extern int g_TimeLeftMode;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
|
||||||
|
|
||||||
1027
core/Translator.cpp
1027
core/Translator.cpp
File diff suppressed because it is too large
Load Diff
@ -1,168 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_TRANSLATOR_H_
|
|
||||||
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "ITextParsers.h"
|
|
||||||
|
|
||||||
#define MAX_TRANSLATE_PARAMS 32
|
|
||||||
#define CORELANG_ENGLISH 0
|
|
||||||
|
|
||||||
/* :TODO: write a templatized version of tries? */
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
class Translator;
|
|
||||||
|
|
||||||
enum PhraseParseState
|
|
||||||
{
|
|
||||||
PPS_None = 0,
|
|
||||||
PPS_Phrases,
|
|
||||||
PPS_InPhrase,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Language
|
|
||||||
{
|
|
||||||
char m_code2[3];
|
|
||||||
int m_FullName;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Translation
|
|
||||||
{
|
|
||||||
const char *szPhrase; /**< Translated phrase. */
|
|
||||||
unsigned int fmt_count; /**< Number of format parameters. */
|
|
||||||
int *fmt_order; /**< Format phrase order. */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LANGUAGE_ENGLISH 0
|
|
||||||
|
|
||||||
enum TransError
|
|
||||||
{
|
|
||||||
Trans_Okay = 0,
|
|
||||||
Trans_BadLanguage = 1,
|
|
||||||
Trans_BadPhrase = 2,
|
|
||||||
Trans_BadPhraseLanguage = 3,
|
|
||||||
Trans_BadPhraseFile = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPhraseFile : public ITextListener_SMC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CPhraseFile(Translator *pTranslator, const char *file);
|
|
||||||
~CPhraseFile();
|
|
||||||
public:
|
|
||||||
void ReparseFile();
|
|
||||||
const char *GetFilename();
|
|
||||||
TransError GetTranslation(const char *szPhrase, unsigned int lang_id, Translation *pTrans);
|
|
||||||
public: //ITextListener_SMC
|
|
||||||
void ReadSMC_ParseStart();
|
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
|
||||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
|
||||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
|
||||||
private:
|
|
||||||
void ParseError(const char *message, ...);
|
|
||||||
void ParseWarning(const char *message, ...);
|
|
||||||
private:
|
|
||||||
Trie *m_pPhraseLookup;
|
|
||||||
String m_File;
|
|
||||||
Translator *m_pTranslator;
|
|
||||||
PhraseParseState m_ParseState;
|
|
||||||
int m_CurPhrase;
|
|
||||||
BaseMemTable *m_pMemory;
|
|
||||||
BaseStringTable *m_pStringTab;
|
|
||||||
unsigned int m_LangCount;
|
|
||||||
String m_ParseError;
|
|
||||||
String m_LastPhraseString;
|
|
||||||
bool m_FileLogged;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Translator :
|
|
||||||
public ITextListener_SMC,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Translator();
|
|
||||||
~Translator();
|
|
||||||
public: // SMGlobalClass
|
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength);
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
public: // ITextListener_SMC
|
|
||||||
void ReadSMC_ParseStart();
|
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
|
||||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
|
||||||
public:
|
|
||||||
void RebuildLanguageDatabase(const char *lang_header_file);
|
|
||||||
unsigned int FindOrAddPhraseFile(const char *phrase_file);
|
|
||||||
BaseStringTable *GetStringTable();
|
|
||||||
unsigned int GetLanguageCount();
|
|
||||||
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
|
|
||||||
bool GetLanguageByCode(const char *code, unsigned int *index);
|
|
||||||
bool GetLanguageByName(const char *name, unsigned int *index);
|
|
||||||
size_t Translate(char *buffer, size_t maxlength, void **params, const Translation *pTrans);
|
|
||||||
CPhraseFile *GetFileByIndex(unsigned int index);
|
|
||||||
TransError CoreTrans(int client,
|
|
||||||
char *buffer,
|
|
||||||
size_t maxlength,
|
|
||||||
const char *phrase,
|
|
||||||
void **params,
|
|
||||||
size_t *outlen=NULL);
|
|
||||||
unsigned int GetServerLanguage();
|
|
||||||
unsigned int GetClientLanguage(int client);
|
|
||||||
private:
|
|
||||||
bool AddLanguage(const char *langcode, const char *description);
|
|
||||||
private:
|
|
||||||
CVector<Language *> m_Languages;
|
|
||||||
CVector<CPhraseFile *> m_Files;
|
|
||||||
BaseStringTable *m_pStringTab;
|
|
||||||
Trie *m_pLCodeLookup;
|
|
||||||
bool m_InLanguageSection;
|
|
||||||
String m_CustomError;
|
|
||||||
unsigned int m_ServerLang;
|
|
||||||
char m_InitialLang[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CPhraseFile *g_pCorePhrases;
|
|
||||||
extern unsigned int g_pCorePhraseID;
|
|
||||||
extern Translator g_Translator;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_TRANSLATOR_H_
|
|
||||||
@ -1,477 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "UserMessages.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
|
|
||||||
UserMessages g_UserMsgs;
|
|
||||||
|
|
||||||
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
|
||||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
|
||||||
|
|
||||||
UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
|
||||||
{
|
|
||||||
m_Names = sm_trie_create();
|
|
||||||
m_HookCount = 0;
|
|
||||||
m_InExec = false;
|
|
||||||
m_InHook = false;
|
|
||||||
m_CurFlags = 0;
|
|
||||||
m_CurId = INVALID_MESSAGE_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserMessages::~UserMessages()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_Names);
|
|
||||||
|
|
||||||
CStack<ListenerInfo *>::iterator iter;
|
|
||||||
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
|
||||||
{
|
|
||||||
delete (*iter);
|
|
||||||
}
|
|
||||||
m_FreeListeners.popall();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserMessages::OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
/* -1 means SourceMM was unable to get the user message list */
|
|
||||||
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserMessages::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserMessages::OnSourceModAllShutdown()
|
|
||||||
{
|
|
||||||
if (m_HookCount)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
|
||||||
}
|
|
||||||
m_HookCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int UserMessages::GetMessageIndex(const char *msg)
|
|
||||||
{
|
|
||||||
int msgid;
|
|
||||||
|
|
||||||
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
|
|
||||||
{
|
|
||||||
if (m_FallbackSearch)
|
|
||||||
{
|
|
||||||
char msgbuf[64];
|
|
||||||
int size;
|
|
||||||
msgid = 0;
|
|
||||||
|
|
||||||
while (gamedll->GetUserMessageInfo(msgid, msgbuf, sizeof(msgbuf), size))
|
|
||||||
{
|
|
||||||
if (strcmp(msgbuf, msg) == 0)
|
|
||||||
{
|
|
||||||
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
msgid++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msgid = g_SMAPI->FindUserMessage(msg);
|
|
||||||
|
|
||||||
if (msgid != INVALID_MESSAGE_ID)
|
|
||||||
{
|
|
||||||
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
|
||||||
{
|
|
||||||
if (m_FallbackSearch)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
return gamedll->GetUserMessageInfo(msgid, buffer, maxlength, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *msg = g_SMAPI->GetUserMessage(msgid);
|
|
||||||
|
|
||||||
if (msg)
|
|
||||||
{
|
|
||||||
strncopy(buffer, msg, maxlength);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
|
||||||
{
|
|
||||||
bf_write *buffer;
|
|
||||||
|
|
||||||
if (m_InExec || m_InHook)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (msg_id < 0 || msg_id >= 255)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_CellRecFilter.Initialize(players, playersNum);
|
|
||||||
|
|
||||||
m_CurFlags = flags;
|
|
||||||
if (m_CurFlags & USERMSG_INITMSG)
|
|
||||||
{
|
|
||||||
m_CellRecFilter.SetToInit(true);
|
|
||||||
}
|
|
||||||
if (m_CurFlags & USERMSG_RELIABLE)
|
|
||||||
{
|
|
||||||
m_CellRecFilter.SetToReliable(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_InExec = true;
|
|
||||||
|
|
||||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
|
||||||
{
|
|
||||||
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
|
||||||
} else {
|
|
||||||
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UserMessages::EndMessage()
|
|
||||||
{
|
|
||||||
if (!m_InExec)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
|
||||||
{
|
|
||||||
ENGINE_CALL(MessageEnd)();
|
|
||||||
} else {
|
|
||||||
engine->MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_InExec = false;
|
|
||||||
m_CurFlags = 0;
|
|
||||||
m_CellRecFilter.Reset();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
|
||||||
{
|
|
||||||
if (msg_id < 0 || msg_id >= 255)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListenerInfo *pInfo;
|
|
||||||
if (m_FreeListeners.empty())
|
|
||||||
{
|
|
||||||
pInfo = new ListenerInfo;
|
|
||||||
} else {
|
|
||||||
pInfo = m_FreeListeners.front();
|
|
||||||
m_FreeListeners.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->Callback = pListener;
|
|
||||||
pInfo->IsHooked = false;
|
|
||||||
pInfo->KillMe = false;
|
|
||||||
|
|
||||||
if (!m_HookCount++)
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intercept)
|
|
||||||
{
|
|
||||||
m_msgIntercepts[msg_id].push_back(pInfo);
|
|
||||||
} else {
|
|
||||||
m_msgHooks[msg_id].push_back(pInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
|
||||||
{
|
|
||||||
MsgList *pList;
|
|
||||||
MsgIter iter;
|
|
||||||
ListenerInfo *pInfo;
|
|
||||||
bool deleted = false;
|
|
||||||
|
|
||||||
if (msg_id < 0 || msg_id >= 255)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pList = (intercept) ? &m_msgIntercepts[msg_id] : &m_msgHooks[msg_id];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); iter++)
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
if (pInfo->Callback == pListener)
|
|
||||||
{
|
|
||||||
if (pInfo->IsHooked)
|
|
||||||
{
|
|
||||||
pInfo->KillMe = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
pList->erase(iter);
|
|
||||||
deleted = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deleted)
|
|
||||||
{
|
|
||||||
_DecRefCounter();
|
|
||||||
}
|
|
||||||
|
|
||||||
return deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserMessages::_DecRefCounter()
|
|
||||||
{
|
|
||||||
if (--m_HookCount == 0)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
|
|
||||||
{
|
|
||||||
bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
|
|
||||||
bool is_hook_empty = m_msgHooks[msg_type].empty();
|
|
||||||
|
|
||||||
if ((is_intercept_empty && is_hook_empty)
|
|
||||||
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
|
||||||
{
|
|
||||||
m_InHook = false;
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_CurId = msg_type;
|
|
||||||
m_CurRecFilter = filter;
|
|
||||||
m_InHook = true;
|
|
||||||
m_BlockEndPost = false;
|
|
||||||
|
|
||||||
if (!is_intercept_empty)
|
|
||||||
{
|
|
||||||
m_InterceptBuffer.Reset();
|
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
|
|
||||||
{
|
|
||||||
if (!m_InHook)
|
|
||||||
{
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
|
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserMessages::OnMessageEnd_Post()
|
|
||||||
{
|
|
||||||
if (!m_InHook || m_BlockEndPost)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgList *pList;
|
|
||||||
MsgIter iter;
|
|
||||||
ListenerInfo *pInfo;
|
|
||||||
|
|
||||||
pList = &m_msgIntercepts[m_CurId];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
pInfo->IsHooked = true;
|
|
||||||
pInfo->Callback->OnUserMessageSent(m_CurId);
|
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
|
||||||
{
|
|
||||||
iter = pList->erase(iter);
|
|
||||||
m_FreeListeners.push(pInfo);
|
|
||||||
_DecRefCounter();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->IsHooked = false;
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_InHook = false;
|
|
||||||
|
|
||||||
pList = &m_msgHooks[m_CurId];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
pInfo->IsHooked = true;
|
|
||||||
pInfo->Callback->OnUserMessageSent(m_CurId);
|
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
|
||||||
{
|
|
||||||
iter = pList->erase(iter);
|
|
||||||
m_FreeListeners.push(pInfo);
|
|
||||||
_DecRefCounter();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->IsHooked = false;
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserMessages::OnMessageEnd_Pre()
|
|
||||||
{
|
|
||||||
if (!m_InHook)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgList *pList;
|
|
||||||
MsgIter iter;
|
|
||||||
ListenerInfo *pInfo;
|
|
||||||
|
|
||||||
ResultType res;
|
|
||||||
bool intercepted = false;
|
|
||||||
bool handled = false;
|
|
||||||
|
|
||||||
pList = &m_msgIntercepts[m_CurId];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
pInfo->IsHooked = true;
|
|
||||||
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
|
|
||||||
|
|
||||||
intercepted = true;
|
|
||||||
|
|
||||||
switch (res)
|
|
||||||
{
|
|
||||||
case Pl_Stop:
|
|
||||||
{
|
|
||||||
if (pInfo->KillMe)
|
|
||||||
{
|
|
||||||
pList->erase(iter);
|
|
||||||
m_FreeListeners.push(pInfo);
|
|
||||||
_DecRefCounter();
|
|
||||||
goto supercede;
|
|
||||||
}
|
|
||||||
pInfo->IsHooked = false;
|
|
||||||
goto supercede;
|
|
||||||
}
|
|
||||||
case Pl_Handled:
|
|
||||||
{
|
|
||||||
handled = true;
|
|
||||||
if (pInfo->KillMe)
|
|
||||||
{
|
|
||||||
iter = pList->erase(iter);
|
|
||||||
m_FreeListeners.push(pInfo);
|
|
||||||
_DecRefCounter();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (pInfo->KillMe)
|
|
||||||
{
|
|
||||||
iter = pList->erase(iter);
|
|
||||||
m_FreeListeners.push(pInfo);
|
|
||||||
_DecRefCounter();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pInfo->IsHooked = false;
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handled)
|
|
||||||
{
|
|
||||||
goto supercede;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intercepted)
|
|
||||||
{
|
|
||||||
bf_write *engine_bfw;
|
|
||||||
|
|
||||||
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
|
|
||||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
|
||||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
|
||||||
ENGINE_CALL(MessageEnd)();
|
|
||||||
}
|
|
||||||
|
|
||||||
pList = &m_msgHooks[m_CurId];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
pInfo->IsHooked = true;
|
|
||||||
pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
|
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
|
||||||
{
|
|
||||||
iter = pList->erase(iter);
|
|
||||||
m_FreeListeners.push(pInfo);
|
|
||||||
_DecRefCounter();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pInfo->IsHooked = false;
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
|
||||||
supercede:
|
|
||||||
m_InHook = false;
|
|
||||||
m_BlockEndPost = true;
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
|
||||||
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <IUserMessages.h>
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "CellRecipientFilter.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
#define INVALID_MESSAGE_ID -1
|
|
||||||
|
|
||||||
struct ListenerInfo
|
|
||||||
{
|
|
||||||
IUserMessageListener *Callback;
|
|
||||||
bool IsHooked;
|
|
||||||
bool KillMe;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef List<ListenerInfo *> MsgList;
|
|
||||||
typedef List<ListenerInfo *>::iterator MsgIter;
|
|
||||||
|
|
||||||
class UserMessages :
|
|
||||||
public IUserMessages,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UserMessages();
|
|
||||||
~UserMessages();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModStartup(bool late);
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModAllShutdown();
|
|
||||||
public: //IUserMessages
|
|
||||||
int GetMessageIndex(const char *msg);
|
|
||||||
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
|
||||||
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
|
||||||
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
|
||||||
bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
|
||||||
bool EndMessage();
|
|
||||||
public:
|
|
||||||
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type);
|
|
||||||
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type);
|
|
||||||
void OnMessageEnd_Pre();
|
|
||||||
void OnMessageEnd_Post();
|
|
||||||
private:
|
|
||||||
void _DecRefCounter();
|
|
||||||
private:
|
|
||||||
List<ListenerInfo *> m_msgHooks[255];
|
|
||||||
List<ListenerInfo *> m_msgIntercepts[255];
|
|
||||||
CStack<ListenerInfo *> m_FreeListeners;
|
|
||||||
unsigned char m_pBase[2500];
|
|
||||||
IRecipientFilter *m_CurRecFilter;
|
|
||||||
bf_write m_InterceptBuffer;
|
|
||||||
bf_write *m_OrigBuffer;
|
|
||||||
bf_read m_ReadBuffer;
|
|
||||||
size_t m_HookCount;
|
|
||||||
bool m_InHook;
|
|
||||||
bool m_BlockEndPost;
|
|
||||||
bool m_FallbackSearch;
|
|
||||||
|
|
||||||
Trie *m_Names;
|
|
||||||
CellRecipientFilter m_CellRecFilter;
|
|
||||||
bool m_InExec;
|
|
||||||
int m_CurFlags;
|
|
||||||
int m_CurId;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern UserMessages g_UserMsgs;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
|
||||||
961
core/bitbuf.cpp
961
core/bitbuf.cpp
@ -1,961 +0,0 @@
|
|||||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// $NoKeywords: $
|
|
||||||
//
|
|
||||||
//=============================================================================//
|
|
||||||
|
|
||||||
#include "bitbuf.h"
|
|
||||||
#include "coordsize.h"
|
|
||||||
#include "vector.h"
|
|
||||||
#include "mathlib/math_base.h"
|
|
||||||
#include "vstdlib/strtools.h"
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools
|
|
||||||
// This is used by VVIS and fails to link
|
|
||||||
// NOTE: This must be the last file included!!!
|
|
||||||
//#include "tier0/memdbgon.h"
|
|
||||||
|
|
||||||
#ifdef _XBOX
|
|
||||||
// mandatory ... wary of above comment and isolating, tier0 is built as MT though
|
|
||||||
#include "tier0/memdbgon.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static BitBufErrorHandler g_BitBufErrorHandler = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName )
|
|
||||||
{
|
|
||||||
if ( g_BitBufErrorHandler )
|
|
||||||
g_BitBufErrorHandler( errorType, pDebugName );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SetBitBufErrorHandler( BitBufErrorHandler fn )
|
|
||||||
{
|
|
||||||
g_BitBufErrorHandler = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #define BB_PROFILING
|
|
||||||
|
|
||||||
|
|
||||||
// Precalculated bit masks for WriteUBitLong. Using these tables instead of
|
|
||||||
// doing the calculations gives a 33% speedup in WriteUBitLong.
|
|
||||||
unsigned long g_BitWriteMasks[32][33];
|
|
||||||
|
|
||||||
// (1 << i) - 1
|
|
||||||
unsigned long g_ExtraMasks[32];
|
|
||||||
|
|
||||||
class CBitWriteMasksInit
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CBitWriteMasksInit()
|
|
||||||
{
|
|
||||||
for( unsigned int startbit=0; startbit < 32; startbit++ )
|
|
||||||
{
|
|
||||||
for( unsigned int nBitsLeft=0; nBitsLeft < 33; nBitsLeft++ )
|
|
||||||
{
|
|
||||||
unsigned int endbit = startbit + nBitsLeft;
|
|
||||||
g_BitWriteMasks[startbit][nBitsLeft] = (1 << startbit) - 1;
|
|
||||||
if(endbit < 32)
|
|
||||||
g_BitWriteMasks[startbit][nBitsLeft] |= ~((1 << endbit) - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( unsigned int maskBit=0; maskBit < 32; maskBit++ )
|
|
||||||
g_ExtraMasks[maskBit] = (1 << maskBit) - 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
CBitWriteMasksInit g_BitWriteMasksInit;
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------- //
|
|
||||||
// bf_write
|
|
||||||
// ---------------------------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
bf_write::bf_write()
|
|
||||||
{
|
|
||||||
m_pData = NULL;
|
|
||||||
m_nDataBytes = 0;
|
|
||||||
m_nDataBits = -1; // set to -1 so we generate overflow on any operation
|
|
||||||
m_iCurBit = 0;
|
|
||||||
m_bOverflow = false;
|
|
||||||
m_bAssertOnOverflow = true;
|
|
||||||
m_pDebugName = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_write::bf_write( const char *pDebugName, void *pData, int nBytes, int nBits )
|
|
||||||
{
|
|
||||||
m_bAssertOnOverflow = true;
|
|
||||||
m_pDebugName = pDebugName;
|
|
||||||
StartWriting( pData, nBytes, 0, nBits );
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_write::bf_write( void *pData, int nBytes, int nBits )
|
|
||||||
{
|
|
||||||
m_bAssertOnOverflow = true;
|
|
||||||
StartWriting( pData, nBytes, 0, nBits );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::StartWriting( void *pData, int nBytes, int iStartBit, int nBits )
|
|
||||||
{
|
|
||||||
// Make sure it's dword aligned and padded.
|
|
||||||
Assert( (nBytes % 4) == 0 );
|
|
||||||
Assert(((unsigned long)pData & 3) == 0);
|
|
||||||
|
|
||||||
m_pData = (unsigned char*)pData;
|
|
||||||
m_nDataBytes = nBytes;
|
|
||||||
|
|
||||||
if ( nBits == -1 )
|
|
||||||
{
|
|
||||||
m_nDataBits = nBytes << 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert( nBits <= nBytes*8 );
|
|
||||||
m_nDataBits = nBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_iCurBit = iStartBit;
|
|
||||||
m_bOverflow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::Reset()
|
|
||||||
{
|
|
||||||
m_iCurBit = 0;
|
|
||||||
m_bOverflow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void bf_write::SetAssertOnOverflow( bool bAssert )
|
|
||||||
{
|
|
||||||
m_bAssertOnOverflow = bAssert;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* bf_write::GetDebugName()
|
|
||||||
{
|
|
||||||
return m_pDebugName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void bf_write::SetDebugName( const char *pDebugName )
|
|
||||||
{
|
|
||||||
m_pDebugName = pDebugName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void bf_write::SeekToBit( int bitPos )
|
|
||||||
{
|
|
||||||
m_iCurBit = bitPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Sign bit comes first
|
|
||||||
void bf_write::WriteSBitLong( int data, int numbits )
|
|
||||||
{
|
|
||||||
// Do we have a valid # of bits to encode with?
|
|
||||||
Assert( numbits >= 1 );
|
|
||||||
|
|
||||||
// Note: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
|
|
||||||
// (Some old code writes direct integers right into the buffer).
|
|
||||||
if(data < 0)
|
|
||||||
{
|
|
||||||
#ifdef _DEBUG
|
|
||||||
if( numbits < 32 )
|
|
||||||
{
|
|
||||||
// Make sure it doesn't overflow.
|
|
||||||
|
|
||||||
if( data < 0 )
|
|
||||||
{
|
|
||||||
Assert( data >= -(1 << (numbits-1)) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert( data < (1 << (numbits-1)) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WriteUBitLong( (unsigned int)(0x80000000 + data), numbits - 1, false );
|
|
||||||
WriteOneBit( 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteUBitLong((unsigned int)data, numbits - 1);
|
|
||||||
WriteOneBit( 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// writes an unsigned integer with variable bit length
|
|
||||||
void bf_write::WriteUBitVar( unsigned int data )
|
|
||||||
{
|
|
||||||
unsigned int bits = 0;
|
|
||||||
unsigned int base = 0;
|
|
||||||
|
|
||||||
while (data > (base<<1))
|
|
||||||
{
|
|
||||||
bits++;
|
|
||||||
base = (1<<bits)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// how many bits do we use
|
|
||||||
if ( bits > 0)
|
|
||||||
WriteUBitLong( 0, bits );
|
|
||||||
|
|
||||||
// end marker
|
|
||||||
WriteOneBit( 1 );
|
|
||||||
|
|
||||||
// write the value
|
|
||||||
if ( bits > 0)
|
|
||||||
WriteUBitLong( data - base , bits );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitLong(unsigned int data, int numbits, bool bSigned)
|
|
||||||
{
|
|
||||||
if(bSigned)
|
|
||||||
WriteSBitLong((int)data, numbits);
|
|
||||||
else
|
|
||||||
WriteUBitLong(data, numbits);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bf_write::WriteBits(const void *pInData, int nBits)
|
|
||||||
{
|
|
||||||
#if defined( BB_PROFILING )
|
|
||||||
VPROF( "bf_write::WriteBits" );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned char *pOut = (unsigned char*)pInData;
|
|
||||||
int nBitsLeft = nBits;
|
|
||||||
|
|
||||||
if((m_iCurBit+nBits) > m_nDataBits)
|
|
||||||
{
|
|
||||||
SetOverflowFlag();
|
|
||||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get output dword-aligned.
|
|
||||||
while(((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8)
|
|
||||||
{
|
|
||||||
|
|
||||||
WriteUBitLong( *pOut, 8, false );
|
|
||||||
++pOut;
|
|
||||||
nBitsLeft -= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we can use fast memcpy if m_iCurBit is byte aligned
|
|
||||||
if ( (nBitsLeft >= 32) && (m_iCurBit & 7) == 0 )
|
|
||||||
{
|
|
||||||
int numbytes = (nBitsLeft >> 3);
|
|
||||||
int numbits = numbytes << 3;
|
|
||||||
|
|
||||||
// Bounds checking..
|
|
||||||
// TODO: May not need this check anymore
|
|
||||||
if((m_iCurBit+numbits) > m_nDataBits)
|
|
||||||
{
|
|
||||||
m_iCurBit = m_nDataBits;
|
|
||||||
SetOverflowFlag();
|
|
||||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_memcpy( m_pData+(m_iCurBit>>3), pOut, numbytes );
|
|
||||||
pOut += numbytes;
|
|
||||||
nBitsLeft -= numbits;
|
|
||||||
m_iCurBit += numbits;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read dwords.
|
|
||||||
while(nBitsLeft >= 32)
|
|
||||||
{
|
|
||||||
WriteUBitLong( *((unsigned long*)pOut), 32, false );
|
|
||||||
pOut += sizeof(unsigned long);
|
|
||||||
nBitsLeft -= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the remaining bytes.
|
|
||||||
while(nBitsLeft >= 8)
|
|
||||||
{
|
|
||||||
WriteUBitLong( *pOut, 8, false );
|
|
||||||
++pOut;
|
|
||||||
nBitsLeft -= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the remaining bits.
|
|
||||||
if(nBitsLeft)
|
|
||||||
{
|
|
||||||
WriteUBitLong( *pOut, nBitsLeft, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
return !IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool bf_write::WriteBitsFromBuffer( bf_read *pIn, int nBits )
|
|
||||||
{
|
|
||||||
// This could be optimized a little by
|
|
||||||
while ( nBits > 32 )
|
|
||||||
{
|
|
||||||
WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 );
|
|
||||||
nBits -= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits );
|
|
||||||
return !IsOverflowed() && !pIn->IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void bf_write::WriteBitAngle( float fAngle, int numbits )
|
|
||||||
{
|
|
||||||
int d;
|
|
||||||
unsigned int mask;
|
|
||||||
unsigned int shift;
|
|
||||||
|
|
||||||
shift = (1<<numbits);
|
|
||||||
mask = shift - 1;
|
|
||||||
|
|
||||||
d = (int)( (fAngle / 360.0) * shift );
|
|
||||||
d &= mask;
|
|
||||||
|
|
||||||
WriteUBitLong((unsigned int)d, numbits);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitCoord (const float f)
|
|
||||||
{
|
|
||||||
#if defined( BB_PROFILING )
|
|
||||||
VPROF( "bf_write::WriteBitCoord" );
|
|
||||||
#endif
|
|
||||||
int signbit = (f <= -COORD_RESOLUTION);
|
|
||||||
int intval = abs(static_cast<int>(f));
|
|
||||||
int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1);
|
|
||||||
|
|
||||||
|
|
||||||
// Send the bit flags that indicate whether we have an integer part and/or a fraction part.
|
|
||||||
WriteOneBit( intval );
|
|
||||||
WriteOneBit( fractval );
|
|
||||||
|
|
||||||
if ( intval || fractval )
|
|
||||||
{
|
|
||||||
// Send the sign bit
|
|
||||||
WriteOneBit( signbit );
|
|
||||||
|
|
||||||
// Send the integer if we have one.
|
|
||||||
if ( intval )
|
|
||||||
{
|
|
||||||
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
|
|
||||||
intval--;
|
|
||||||
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the fraction if we have one
|
|
||||||
if ( fractval )
|
|
||||||
{
|
|
||||||
WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitFloat(float val)
|
|
||||||
{
|
|
||||||
long intVal;
|
|
||||||
|
|
||||||
Assert(sizeof(long) == sizeof(float));
|
|
||||||
Assert(sizeof(float) == 4);
|
|
||||||
|
|
||||||
void *v = &val;
|
|
||||||
intVal = *reinterpret_cast<long *>(v);
|
|
||||||
WriteUBitLong( intVal, 32 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitVec3Coord( const Vector& fa )
|
|
||||||
{
|
|
||||||
int xflag, yflag, zflag;
|
|
||||||
|
|
||||||
xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION);
|
|
||||||
yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION);
|
|
||||||
zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION);
|
|
||||||
|
|
||||||
WriteOneBit( xflag );
|
|
||||||
WriteOneBit( yflag );
|
|
||||||
WriteOneBit( zflag );
|
|
||||||
|
|
||||||
if ( xflag )
|
|
||||||
WriteBitCoord( fa[0] );
|
|
||||||
if ( yflag )
|
|
||||||
WriteBitCoord( fa[1] );
|
|
||||||
if ( zflag )
|
|
||||||
WriteBitCoord( fa[2] );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitNormal( float f )
|
|
||||||
{
|
|
||||||
int signbit = (f <= -NORMAL_RESOLUTION);
|
|
||||||
|
|
||||||
// NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones
|
|
||||||
unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) );
|
|
||||||
|
|
||||||
// clamp..
|
|
||||||
if (fractval > NORMAL_DENOMINATOR)
|
|
||||||
fractval = NORMAL_DENOMINATOR;
|
|
||||||
|
|
||||||
// Send the sign bit
|
|
||||||
WriteOneBit( signbit );
|
|
||||||
|
|
||||||
// Send the fractional component
|
|
||||||
WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitVec3Normal( const Vector& fa )
|
|
||||||
{
|
|
||||||
int xflag, yflag;
|
|
||||||
|
|
||||||
xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION);
|
|
||||||
yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION);
|
|
||||||
|
|
||||||
WriteOneBit( xflag );
|
|
||||||
WriteOneBit( yflag );
|
|
||||||
|
|
||||||
if ( xflag )
|
|
||||||
WriteBitNormal( fa[0] );
|
|
||||||
if ( yflag )
|
|
||||||
WriteBitNormal( fa[1] );
|
|
||||||
|
|
||||||
// Write z sign bit
|
|
||||||
int signbit = (fa[2] <= -NORMAL_RESOLUTION);
|
|
||||||
WriteOneBit( signbit );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteBitAngles( const QAngle& fa )
|
|
||||||
{
|
|
||||||
// FIXME:
|
|
||||||
Vector tmp( fa.x, fa.y, fa.z );
|
|
||||||
WriteBitVec3Coord( tmp );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteChar(int val)
|
|
||||||
{
|
|
||||||
WriteSBitLong(val, sizeof(char) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteByte(int val)
|
|
||||||
{
|
|
||||||
WriteUBitLong(val, sizeof(unsigned char) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteShort(int val)
|
|
||||||
{
|
|
||||||
WriteSBitLong(val, sizeof(short) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteWord(int val)
|
|
||||||
{
|
|
||||||
WriteUBitLong(val, sizeof(unsigned short) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteLong(long val)
|
|
||||||
{
|
|
||||||
WriteSBitLong(val, sizeof(long) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_write::WriteFloat(float val)
|
|
||||||
{
|
|
||||||
WriteBits(&val, sizeof(val) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bf_write::WriteBytes( const void *pBuf, int nBytes )
|
|
||||||
{
|
|
||||||
return WriteBits(pBuf, nBytes << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bf_write::WriteString(const char *pStr)
|
|
||||||
{
|
|
||||||
if(pStr)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
WriteChar( *pStr );
|
|
||||||
++pStr;
|
|
||||||
} while( *(pStr-1) != 0 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteChar( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
return !IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------- //
|
|
||||||
// bf_read
|
|
||||||
// ---------------------------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
bf_read::bf_read()
|
|
||||||
{
|
|
||||||
m_pData = NULL;
|
|
||||||
m_nDataBytes = 0;
|
|
||||||
m_nDataBits = -1; // set to -1 so we overflow on any operation
|
|
||||||
m_iCurBit = 0;
|
|
||||||
m_bOverflow = false;
|
|
||||||
m_bAssertOnOverflow = true;
|
|
||||||
m_pDebugName = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_read::bf_read( const void *pData, int nBytes, int nBits )
|
|
||||||
{
|
|
||||||
m_bAssertOnOverflow = true;
|
|
||||||
StartReading( pData, nBytes, 0, nBits );
|
|
||||||
}
|
|
||||||
|
|
||||||
bf_read::bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits )
|
|
||||||
{
|
|
||||||
m_bAssertOnOverflow = true;
|
|
||||||
m_pDebugName = pDebugName;
|
|
||||||
StartReading( pData, nBytes, 0, nBits );
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::StartReading( const void *pData, int nBytes, int iStartBit, int nBits )
|
|
||||||
{
|
|
||||||
// Make sure we're dword aligned.
|
|
||||||
Assert(((unsigned long)pData & 3) == 0);
|
|
||||||
|
|
||||||
m_pData = (unsigned char*)pData;
|
|
||||||
m_nDataBytes = nBytes;
|
|
||||||
|
|
||||||
if ( nBits == -1 )
|
|
||||||
{
|
|
||||||
m_nDataBits = m_nDataBytes << 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert( nBits <= nBytes*8 );
|
|
||||||
m_nDataBits = nBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_iCurBit = iStartBit;
|
|
||||||
m_bOverflow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::Reset()
|
|
||||||
{
|
|
||||||
m_iCurBit = 0;
|
|
||||||
m_bOverflow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::SetAssertOnOverflow( bool bAssert )
|
|
||||||
{
|
|
||||||
m_bAssertOnOverflow = bAssert;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* bf_read::GetDebugName()
|
|
||||||
{
|
|
||||||
return m_pDebugName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::SetDebugName( const char *pName )
|
|
||||||
{
|
|
||||||
m_pDebugName = pName;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int bf_read::CheckReadUBitLong(int numbits)
|
|
||||||
{
|
|
||||||
// Ok, just read bits out.
|
|
||||||
int i, nBitValue;
|
|
||||||
unsigned int r = 0;
|
|
||||||
|
|
||||||
for(i=0; i < numbits; i++)
|
|
||||||
{
|
|
||||||
nBitValue = ReadOneBitNoCheck();
|
|
||||||
r |= nBitValue << i;
|
|
||||||
}
|
|
||||||
m_iCurBit -= numbits;
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bf_read::ReadBits(void *pOutData, int nBits)
|
|
||||||
{
|
|
||||||
#if defined( BB_PROFILING )
|
|
||||||
VPROF( "bf_write::ReadBits" );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned char *pOut = (unsigned char*)pOutData;
|
|
||||||
int nBitsLeft = nBits;
|
|
||||||
|
|
||||||
|
|
||||||
// Get output dword-aligned.
|
|
||||||
while(((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8)
|
|
||||||
{
|
|
||||||
*pOut = (unsigned char)ReadUBitLong(8);
|
|
||||||
++pOut;
|
|
||||||
nBitsLeft -= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read dwords.
|
|
||||||
while(nBitsLeft >= 32)
|
|
||||||
{
|
|
||||||
*((unsigned long*)pOut) = ReadUBitLong(32);
|
|
||||||
pOut += sizeof(unsigned long);
|
|
||||||
nBitsLeft -= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the remaining bytes.
|
|
||||||
while(nBitsLeft >= 8)
|
|
||||||
{
|
|
||||||
*pOut = ReadUBitLong(8);
|
|
||||||
++pOut;
|
|
||||||
nBitsLeft -= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the remaining bits.
|
|
||||||
if(nBitsLeft)
|
|
||||||
{
|
|
||||||
*pOut = ReadUBitLong(nBitsLeft);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
float bf_read::ReadBitAngle( int numbits )
|
|
||||||
{
|
|
||||||
float fReturn;
|
|
||||||
int i;
|
|
||||||
float shift;
|
|
||||||
|
|
||||||
shift = (float)( 1 << numbits );
|
|
||||||
|
|
||||||
i = ReadUBitLong( numbits );
|
|
||||||
fReturn = (float)i * (360.0 / shift);
|
|
||||||
|
|
||||||
return fReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int bf_read::PeekUBitLong( int numbits )
|
|
||||||
{
|
|
||||||
unsigned int r;
|
|
||||||
int i, nBitValue;
|
|
||||||
#ifdef BIT_VERBOSE
|
|
||||||
int nShifts = numbits;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bf_read savebf;
|
|
||||||
|
|
||||||
savebf = *this; // Save current state info
|
|
||||||
|
|
||||||
r = 0;
|
|
||||||
for(i=0; i < numbits; i++)
|
|
||||||
{
|
|
||||||
nBitValue = ReadOneBit();
|
|
||||||
|
|
||||||
// Append to current stream
|
|
||||||
if ( nBitValue )
|
|
||||||
{
|
|
||||||
r |= 1 << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*this = savebf;
|
|
||||||
|
|
||||||
#ifdef BIT_VERBOSE
|
|
||||||
Con_Printf( "PeekBitLong: %i %i\n", nShifts, (unsigned int)r );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append numbits least significant bits from data to the current bit stream
|
|
||||||
int bf_read::ReadSBitLong( int numbits )
|
|
||||||
{
|
|
||||||
int r, sign;
|
|
||||||
|
|
||||||
r = ReadUBitLong(numbits - 1);
|
|
||||||
|
|
||||||
// Note: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
|
|
||||||
// (Some old code writes direct integers right into the buffer).
|
|
||||||
sign = ReadOneBit();
|
|
||||||
if(sign)
|
|
||||||
r = -((1 << (numbits-1)) - r);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int bf_read::ReadUBitVar()
|
|
||||||
{
|
|
||||||
int bits = 0; // how many bits are used to encode delta offset
|
|
||||||
|
|
||||||
// how many bits do we use
|
|
||||||
while ( ReadOneBit() == 0 )
|
|
||||||
bits++;
|
|
||||||
|
|
||||||
unsigned int data = (1<<bits)-1;
|
|
||||||
|
|
||||||
// read the value
|
|
||||||
if ( bits > 0)
|
|
||||||
data += ReadUBitLong( bits );
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int bf_read::ReadBitLong(int numbits, bool bSigned)
|
|
||||||
{
|
|
||||||
if(bSigned)
|
|
||||||
return (unsigned int)ReadSBitLong(numbits);
|
|
||||||
else
|
|
||||||
return ReadUBitLong(numbits);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants)
|
|
||||||
float bf_read::ReadBitCoord (void)
|
|
||||||
{
|
|
||||||
#if defined( BB_PROFILING )
|
|
||||||
VPROF( "bf_write::ReadBitCoord" );
|
|
||||||
#endif
|
|
||||||
int intval=0,fractval=0,signbit=0;
|
|
||||||
float value = 0.0;
|
|
||||||
|
|
||||||
|
|
||||||
// Read the required integer and fraction flags
|
|
||||||
intval = ReadOneBit();
|
|
||||||
fractval = ReadOneBit();
|
|
||||||
|
|
||||||
// If we got either parse them, otherwise it's a zero.
|
|
||||||
if ( intval || fractval )
|
|
||||||
{
|
|
||||||
// Read the sign bit
|
|
||||||
signbit = ReadOneBit();
|
|
||||||
|
|
||||||
// If there's an integer, read it in
|
|
||||||
if ( intval )
|
|
||||||
{
|
|
||||||
// Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE]
|
|
||||||
intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's a fraction, read it in
|
|
||||||
if ( fractval )
|
|
||||||
{
|
|
||||||
fractval = ReadUBitLong( COORD_FRACTIONAL_BITS );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the correct floating point value
|
|
||||||
value = intval + ((float)fractval * COORD_RESOLUTION);
|
|
||||||
|
|
||||||
// Fixup the sign if negative.
|
|
||||||
if ( signbit )
|
|
||||||
value = -value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::ReadBitVec3Coord( Vector& fa )
|
|
||||||
{
|
|
||||||
int xflag, yflag, zflag;
|
|
||||||
|
|
||||||
// This vector must be initialized! Otherwise, If any of the flags aren't set,
|
|
||||||
// the corresponding component will not be read and will be stack garbage.
|
|
||||||
fa.Init( 0, 0, 0 );
|
|
||||||
|
|
||||||
xflag = ReadOneBit();
|
|
||||||
yflag = ReadOneBit();
|
|
||||||
zflag = ReadOneBit();
|
|
||||||
|
|
||||||
if ( xflag )
|
|
||||||
fa[0] = ReadBitCoord();
|
|
||||||
if ( yflag )
|
|
||||||
fa[1] = ReadBitCoord();
|
|
||||||
if ( zflag )
|
|
||||||
fa[2] = ReadBitCoord();
|
|
||||||
}
|
|
||||||
|
|
||||||
float bf_read::ReadBitNormal (void)
|
|
||||||
{
|
|
||||||
// Read the sign bit
|
|
||||||
int signbit = ReadOneBit();
|
|
||||||
|
|
||||||
// Read the fractional part
|
|
||||||
unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS );
|
|
||||||
|
|
||||||
// Calculate the correct floating point value
|
|
||||||
float value = (float)fractval * NORMAL_RESOLUTION;
|
|
||||||
|
|
||||||
// Fixup the sign if negative.
|
|
||||||
if ( signbit )
|
|
||||||
value = -value;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::ReadBitVec3Normal( Vector& fa )
|
|
||||||
{
|
|
||||||
int xflag = ReadOneBit();
|
|
||||||
int yflag = ReadOneBit();
|
|
||||||
|
|
||||||
if (xflag)
|
|
||||||
fa[0] = ReadBitNormal();
|
|
||||||
else
|
|
||||||
fa[0] = 0.0f;
|
|
||||||
|
|
||||||
if (yflag)
|
|
||||||
fa[1] = ReadBitNormal();
|
|
||||||
else
|
|
||||||
fa[1] = 0.0f;
|
|
||||||
|
|
||||||
// The first two imply the third (but not its sign)
|
|
||||||
int znegative = ReadOneBit();
|
|
||||||
|
|
||||||
float fafafbfb = fa[0] * fa[0] + fa[1] * fa[1];
|
|
||||||
if (fafafbfb < 1.0f)
|
|
||||||
fa[2] = sqrt( 1.0f - fafafbfb );
|
|
||||||
else
|
|
||||||
fa[2] = 0.0f;
|
|
||||||
|
|
||||||
if (znegative)
|
|
||||||
fa[2] = -fa[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::ReadBitAngles( QAngle& fa )
|
|
||||||
{
|
|
||||||
Vector tmp;
|
|
||||||
ReadBitVec3Coord( tmp );
|
|
||||||
fa.Init( tmp.x, tmp.y, tmp.z );
|
|
||||||
}
|
|
||||||
|
|
||||||
int bf_read::ReadChar()
|
|
||||||
{
|
|
||||||
return ReadSBitLong(sizeof(char) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bf_read::ReadByte()
|
|
||||||
{
|
|
||||||
return ReadUBitLong(sizeof(unsigned char) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bf_read::ReadShort()
|
|
||||||
{
|
|
||||||
return ReadSBitLong(sizeof(short) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bf_read::ReadWord()
|
|
||||||
{
|
|
||||||
return ReadUBitLong(sizeof(unsigned short) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
long bf_read::ReadLong()
|
|
||||||
{
|
|
||||||
return ReadSBitLong(sizeof(long) << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
float bf_read::ReadFloat()
|
|
||||||
{
|
|
||||||
float ret;
|
|
||||||
Assert( sizeof(ret) == 4 );
|
|
||||||
ReadBits(&ret, 32);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bf_read::ReadBytes(void *pOut, int nBytes)
|
|
||||||
{
|
|
||||||
return ReadBits(pOut, nBytes << 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bf_read::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars )
|
|
||||||
{
|
|
||||||
Assert( maxLen != 0 );
|
|
||||||
|
|
||||||
bool bTooSmall = false;
|
|
||||||
int iChar = 0;
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
char val = ReadChar();
|
|
||||||
if ( val == 0 )
|
|
||||||
break;
|
|
||||||
else if ( bLine && val == '\n' )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ( iChar < (maxLen-1) )
|
|
||||||
{
|
|
||||||
pStr[iChar] = val;
|
|
||||||
++iChar;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bTooSmall = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure it's null-terminated.
|
|
||||||
Assert( iChar < maxLen );
|
|
||||||
pStr[iChar] = 0;
|
|
||||||
|
|
||||||
if ( pOutNumChars )
|
|
||||||
*pOutNumChars = iChar;
|
|
||||||
|
|
||||||
return !IsOverflowed() && !bTooSmall;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* bf_read::ReadAndAllocateString( bool *pOverflow )
|
|
||||||
{
|
|
||||||
char str[2048];
|
|
||||||
|
|
||||||
int nChars;
|
|
||||||
bool bOverflow = !ReadString( str, sizeof( str ), false, &nChars );
|
|
||||||
if ( pOverflow )
|
|
||||||
*pOverflow = bOverflow;
|
|
||||||
|
|
||||||
// Now copy into the output and return it;
|
|
||||||
char *pRet = new char[ nChars + 1 ];
|
|
||||||
for ( int i=0; i <= nChars; i++ )
|
|
||||||
pRet[i] = str[i];
|
|
||||||
|
|
||||||
return pRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool bf_read::Seek(int iBit)
|
|
||||||
{
|
|
||||||
if(iBit < 0)
|
|
||||||
{
|
|
||||||
SetOverflowFlag();
|
|
||||||
m_iCurBit = m_nDataBits;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if(iBit > m_nDataBits)
|
|
||||||
{
|
|
||||||
SetOverflowFlag();
|
|
||||||
m_iCurBit = m_nDataBits;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_iCurBit = iBit;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bf_read::ExciseBits( int startbit, int bitstoremove )
|
|
||||||
{
|
|
||||||
int endbit = startbit + bitstoremove;
|
|
||||||
int remaining_to_end = m_nDataBits - endbit;
|
|
||||||
|
|
||||||
bf_write temp;
|
|
||||||
temp.StartWriting( (void *)m_pData, m_nDataBits << 3, startbit );
|
|
||||||
|
|
||||||
Seek( endbit );
|
|
||||||
|
|
||||||
for ( int i = 0; i < remaining_to_end; i++ )
|
|
||||||
{
|
|
||||||
temp.WriteOneBit( ReadOneBit() );
|
|
||||||
}
|
|
||||||
|
|
||||||
Seek( startbit );
|
|
||||||
|
|
||||||
m_nDataBits -= bitstoremove;
|
|
||||||
m_nDataBytes = m_nDataBits >> 3;
|
|
||||||
}
|
|
||||||
@ -1,175 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <convar.h>
|
|
||||||
#include "concmd_cleaner.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
struct ConCommandInfo
|
|
||||||
{
|
|
||||||
ConCommandBase *pBase;
|
|
||||||
IConCommandTracker *cls;
|
|
||||||
char name[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
List<ConCommandInfo *> tracked_bases;
|
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name);
|
|
||||||
|
|
||||||
class ConCommandCleaner : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void UnlinkConCommandBase(ConCommandBase *pBase)
|
|
||||||
{
|
|
||||||
ConCommandInfo *pInfo;
|
|
||||||
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
|
||||||
|
|
||||||
if (pBase)
|
|
||||||
{
|
|
||||||
while (iter != tracked_bases.end())
|
|
||||||
{
|
|
||||||
if ((*iter)->pBase == pBase)
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
iter = tracked_bases.erase(iter);
|
|
||||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (iter != tracked_bases.end())
|
|
||||||
{
|
|
||||||
/* This is just god-awful! */
|
|
||||||
if (FindConCommandBase((*iter)->name) != (*iter)->pBase)
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
iter = tracked_bases.erase(iter);
|
|
||||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
|
||||||
{
|
|
||||||
ConCommandInfo *info = new ConCommandInfo;
|
|
||||||
|
|
||||||
info->pBase = pBase;
|
|
||||||
info->cls = cls;
|
|
||||||
strncopy(info->name, pBase->GetName(), sizeof(info->name));
|
|
||||||
|
|
||||||
tracked_bases.push_back(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
|
||||||
{
|
|
||||||
List<ConCommandInfo *>::iterator iter;
|
|
||||||
ConCommandInfo *pInfo;
|
|
||||||
|
|
||||||
iter = tracked_bases.begin();
|
|
||||||
while (iter != tracked_bases.end())
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
if (pInfo->pBase == pBase && pInfo->cls == cls)
|
|
||||||
{
|
|
||||||
delete pInfo;
|
|
||||||
iter = tracked_bases.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} s_ConCmdTracker;
|
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name)
|
|
||||||
{
|
|
||||||
const ConCommandBase *pBase = icvar->GetCommands();
|
|
||||||
|
|
||||||
while (pBase != NULL)
|
|
||||||
{
|
|
||||||
if (strcmp(pBase->GetName(), name) == 0)
|
|
||||||
{
|
|
||||||
return const_cast<ConCommandBase *>(pBase);
|
|
||||||
}
|
|
||||||
pBase = pBase->GetNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
|
|
||||||
{
|
|
||||||
s_ConCmdTracker.AddTarget(pBase, me);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
|
|
||||||
{
|
|
||||||
s_ConCmdTracker.RemoveTarget(pBase, me);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase)
|
|
||||||
{
|
|
||||||
s_ConCmdTracker.UnlinkConCommandBase(pBase);
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_CONCMD_TRACKER_H_
|
|
||||||
#define _INCLUDE_CONCMD_TRACKER_H_
|
|
||||||
|
|
||||||
class IConCommandTracker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name);
|
|
||||||
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
|
||||||
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
|
||||||
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
|
|
||||||
|
|
||||||
#endif //_INCLUDE_CONCMD_TRACKER_H_
|
|
||||||
551
core/convar_sm.h
551
core/convar_sm.h
@ -1,551 +0,0 @@
|
|||||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// $Workfile: $
|
|
||||||
// $Date: 2006-08-13 06:34:30 -0500 (Sun, 13 Aug 2006) $
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// $NoKeywords: $
|
|
||||||
//=============================================================================//
|
|
||||||
|
|
||||||
#ifndef CONVAR_H
|
|
||||||
#define CONVAR_H
|
|
||||||
#if _WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tier0/dbg.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FORCEINLINE_CVAR FORCEINLINE
|
|
||||||
#elif _LINUX
|
|
||||||
#define FORCEINLINE_CVAR __inline__ FORCEINLINE
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The default, no flags at all
|
|
||||||
#define FCVAR_NONE 0
|
|
||||||
|
|
||||||
// Command to ConVars and ConCommands
|
|
||||||
// ConVar Systems
|
|
||||||
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
|
|
||||||
#define FCVAR_LAUNCHER (1<<1) // defined by launcher
|
|
||||||
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
|
|
||||||
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
|
|
||||||
#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system.
|
|
||||||
#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system.
|
|
||||||
#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system.
|
|
||||||
#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system.
|
|
||||||
#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin.
|
|
||||||
#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library
|
|
||||||
#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library
|
|
||||||
#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll
|
|
||||||
#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system
|
|
||||||
// NOTE!! if you add a cvar system, add it here too!!!!
|
|
||||||
// the engine lacks a cvar flag, but needs it for xbox
|
|
||||||
// an engine cvar is thus a cvar not marked with any other system
|
|
||||||
#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM))
|
|
||||||
|
|
||||||
// ConVar only
|
|
||||||
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
|
||||||
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
|
||||||
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
|
|
||||||
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
|
|
||||||
#define FCVAR_USERINFO (1<<9) // changes the client's info string
|
|
||||||
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
|
|
||||||
|
|
||||||
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
|
||||||
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
|
||||||
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
|
|
||||||
|
|
||||||
// It's a ConVar that's shared between the client and the server.
|
|
||||||
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
|
|
||||||
// client, of course )
|
|
||||||
// If a change is requested it must come from the console (i.e., no remote client changes)
|
|
||||||
// If a value is changed while a server is active, it's replicated to all connected clients
|
|
||||||
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
|
|
||||||
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
|
|
||||||
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
|
|
||||||
|
|
||||||
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
|
|
||||||
|
|
||||||
#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox
|
|
||||||
|
|
||||||
|
|
||||||
// #define FCVAR_AVAILABLE (1<<27)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<28)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<29)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<30)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<31)
|
|
||||||
|
|
||||||
|
|
||||||
class ConVar;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
|
|
||||||
// Any executable that wants to use ConVars need to implement one of
|
|
||||||
// these to hook up access to console variables.
|
|
||||||
class IConCommandBaseAccessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Flags is a combination of FCVAR flags in cvar.h.
|
|
||||||
// hOut is filled in with a handle to the variable.
|
|
||||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// You don't have to instantiate one of these, just call its
|
|
||||||
// OneTimeInit function when your executable is initializing.
|
|
||||||
class ConCommandBaseMgr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Call this ONCE when the executable starts up.
|
|
||||||
static void OneTimeInit( IConCommandBaseAccessor *pAccessor );
|
|
||||||
#ifdef _XBOX
|
|
||||||
static bool Fixup( ConCommandBase* pConCommandBase );
|
|
||||||
#ifndef _RETAIL
|
|
||||||
static void PublishCommands( bool bForce );
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// Called when a ConVar changes value
|
|
||||||
typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString );
|
|
||||||
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
typedef void ( *FnCommandCallback )( void );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class ConCommandBaseMgr;
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( char const *pName, char const *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsBitSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
|
|
||||||
// Return name of cvar
|
|
||||||
virtual char const *GetName( void ) const;
|
|
||||||
|
|
||||||
// Return help text for cvar
|
|
||||||
virtual char const *GetHelpText( void ) const;
|
|
||||||
|
|
||||||
// Deal with next pointer
|
|
||||||
const ConCommandBase *GetNext( void ) const;
|
|
||||||
void SetNext( ConCommandBase *next );
|
|
||||||
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Global methods
|
|
||||||
static ConCommandBase const *GetCommands( void );
|
|
||||||
static void AddToList( ConCommandBase *var );
|
|
||||||
static void RemoveFlaggedCommands( int flag );
|
|
||||||
static void RevertFlaggedCvars( int flag );
|
|
||||||
static ConCommandBase const *FindCommand( char const *name );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void Create( char const *pName, char const *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
// Internal copy routine ( uses new operator from correct module )
|
|
||||||
char *CopyString( char const *from );
|
|
||||||
|
|
||||||
// Next ConVar in chain
|
|
||||||
ConCommandBase *m_pNext;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Has the cvar been added to the global list?
|
|
||||||
bool m_bRegistered;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
char const *m_pszName;
|
|
||||||
char const *m_pszHelpString;
|
|
||||||
|
|
||||||
// ConVar flags
|
|
||||||
int m_nFlags;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
|
|
||||||
// all the console variables and registers them.
|
|
||||||
static ConCommandBase *s_pConCommandBases;
|
|
||||||
|
|
||||||
// ConVars in this executable use this 'global' to access values.
|
|
||||||
static IConCommandBaseAccessor *s_pAccessor;
|
|
||||||
|
|
||||||
public: // Hackalicous
|
|
||||||
inline int GetFlags() const
|
|
||||||
{
|
|
||||||
return m_nFlags;
|
|
||||||
}
|
|
||||||
inline void SetFlags(int flags)
|
|
||||||
{
|
|
||||||
m_nFlags = flags;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The console invoked command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommand : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class ConCommandBaseMgr;
|
|
||||||
friend class CCvar;
|
|
||||||
#ifdef _STATIC_LINKED
|
|
||||||
friend class G_ConCommand;
|
|
||||||
friend class C_ConCommand;
|
|
||||||
friend class M_ConCommand;
|
|
||||||
friend class S_ConCommand;
|
|
||||||
friend class D_ConCommand;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConCommand( void );
|
|
||||||
ConCommand( char const *pName, FnCommandCallback callback,
|
|
||||||
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommand( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
virtual bool CanAutoComplete( void );
|
|
||||||
|
|
||||||
// Invoke the function
|
|
||||||
virtual void Dispatch( void );
|
|
||||||
private:
|
|
||||||
virtual void Create( char const *pName, FnCommandCallback callback,
|
|
||||||
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
|
|
||||||
// Call this function when executing the command
|
|
||||||
FnCommandCallback m_fnCommandCallback;
|
|
||||||
|
|
||||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
|
||||||
bool m_bHasCompletionCallback;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline FnCommandCallback GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnCommandCallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: A console variable
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class ConCommandBaseMgr;
|
|
||||||
friend class CCvar;
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
#ifdef _STATIC_LINKED
|
|
||||||
friend class G_ConVar;
|
|
||||||
friend class C_ConVar;
|
|
||||||
friend class M_ConVar;
|
|
||||||
friend class S_ConVar;
|
|
||||||
friend class D_ConVar;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags = 0);
|
|
||||||
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString );
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString, FnChangeCallback callback );
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
|
||||||
FnChangeCallback callback );
|
|
||||||
|
|
||||||
virtual ~ConVar( void );
|
|
||||||
|
|
||||||
virtual bool IsBitSet( int flag ) const;
|
|
||||||
virtual char const* GetHelpText( void ) const;
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
virtual char const *GetName( void ) const;
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Install a change callback (there shouldn't already be one....)
|
|
||||||
void InstallChangeCallback( FnChangeCallback callback );
|
|
||||||
|
|
||||||
// Retrieve value
|
|
||||||
FORCEINLINE_CVAR float GetFloat( void ) const;
|
|
||||||
FORCEINLINE_CVAR int GetInt( void ) const;
|
|
||||||
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
|
||||||
FORCEINLINE_CVAR char const *GetString( void ) const;
|
|
||||||
|
|
||||||
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
|
||||||
// from alloc/free across dll/exe boundaries.
|
|
||||||
|
|
||||||
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
|
||||||
virtual void SetValue( char const *value );
|
|
||||||
virtual void SetValue( float value );
|
|
||||||
virtual void SetValue( int value );
|
|
||||||
|
|
||||||
// Reset to default value
|
|
||||||
void Revert( void );
|
|
||||||
|
|
||||||
// True if it has a min/max setting
|
|
||||||
bool GetMin( float& minVal ) const;
|
|
||||||
bool GetMax( float& maxVal ) const;
|
|
||||||
char const *GetDefault( void ) const;
|
|
||||||
|
|
||||||
static void RevertAll( void );
|
|
||||||
private:
|
|
||||||
// Called by CCvar when the value of a var is changing.
|
|
||||||
virtual void InternalSetValue(char const *value);
|
|
||||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
|
||||||
virtual void InternalSetFloatValue( float fNewValue );
|
|
||||||
virtual void InternalSetIntValue( int nValue );
|
|
||||||
|
|
||||||
virtual bool ClampValue( float& value );
|
|
||||||
virtual void ChangeStringValue( char const *tempVal );
|
|
||||||
|
|
||||||
virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0,
|
|
||||||
char const *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
|
||||||
bool bMax = false, float fMax = false, FnChangeCallback callback = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// This either points to "this" or it points to the original declaration of a ConVar.
|
|
||||||
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
|
|
||||||
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
|
|
||||||
ConVar *m_pParent;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
char const *m_pszDefaultValue;
|
|
||||||
|
|
||||||
// Value
|
|
||||||
// Dynamically allocated
|
|
||||||
char *m_pszString;
|
|
||||||
int m_StringLength;
|
|
||||||
|
|
||||||
// Values
|
|
||||||
float m_fValue;
|
|
||||||
int m_nValue;
|
|
||||||
|
|
||||||
// Min/Max values
|
|
||||||
bool m_bHasMin;
|
|
||||||
float m_fMinVal;
|
|
||||||
bool m_bHasMax;
|
|
||||||
float m_fMaxVal;
|
|
||||||
|
|
||||||
// Call this function when ConVar changes
|
|
||||||
FnChangeCallback m_fnChangeCallback;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline FnChangeCallback GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnChangeCallback;
|
|
||||||
}
|
|
||||||
inline void SetMin(bool set, float min=0.0)
|
|
||||||
{
|
|
||||||
m_bHasMin = set;
|
|
||||||
m_fMinVal = min;
|
|
||||||
}
|
|
||||||
inline void SetMax(bool set, float max=0.0)
|
|
||||||
{
|
|
||||||
m_bHasMax = set;
|
|
||||||
m_fMaxVal = max;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a float
|
|
||||||
// Output : float
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
|
|
||||||
{
|
|
||||||
return m_pParent->m_fValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as an int
|
|
||||||
// Output : int
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
|
|
||||||
{
|
|
||||||
return m_pParent->m_nValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
|
||||||
// Output : char const *
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR char const *ConVar::GetString( void ) const
|
|
||||||
{
|
|
||||||
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
|
|
||||||
{
|
|
||||||
return "FCVAR_NEVER_AS_STRING";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _STATIC_LINKED
|
|
||||||
// identifies subsystem via piggybacking constructors with flags
|
|
||||||
class G_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class C_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class M_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class S_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class D_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString );
|
|
||||||
|
|
||||||
class G_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class C_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class M_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class S_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class D_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// redirect these declarations to their specific subsystem
|
|
||||||
#ifdef GAME_DLL
|
|
||||||
#define ConCommand G_ConCommand
|
|
||||||
#define ConVar G_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef CLIENT_DLL
|
|
||||||
#define ConCommand C_ConCommand
|
|
||||||
#define ConVar C_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef MATERIALSYSTEM_DLL
|
|
||||||
#define ConCommand M_ConCommand
|
|
||||||
#define ConVar M_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef STUDIORENDER_DLL
|
|
||||||
#define ConCommand S_ConCommand
|
|
||||||
#define ConVar S_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef DATACACHE_DLL
|
|
||||||
#define ConCommand D_ConCommand
|
|
||||||
#define ConVar D_ConVar
|
|
||||||
#endif
|
|
||||||
#endif // _STATIC_LINKED
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility to quicky generate a simple console command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define CON_COMMAND( name, description ) \
|
|
||||||
static void name(); \
|
|
||||||
static ConCommand name##_command( #name, name, description ); \
|
|
||||||
static void name()
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility to quicky generate a simple console command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define CON_COMMAND_F( name, description, flags ) \
|
|
||||||
static void name(); \
|
|
||||||
static ConCommand name##_command( #name, name, description, flags ); \
|
|
||||||
static void name()
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CONVAR_H
|
|
||||||
@ -1,709 +0,0 @@
|
|||||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// $Workfile: $
|
|
||||||
// $Date: $
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// $NoKeywords: $
|
|
||||||
//===========================================================================//
|
|
||||||
|
|
||||||
#ifndef CONVAR_H
|
|
||||||
#define CONVAR_H
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tier0/dbg.h"
|
|
||||||
#include "tier1/iconvar.h"
|
|
||||||
#include "tier1/utlvector.h"
|
|
||||||
#include "tier1/utlstring.h"
|
|
||||||
#include "icvar.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FORCEINLINE_CVAR FORCEINLINE
|
|
||||||
#elif _LINUX
|
|
||||||
#define FORCEINLINE_CVAR inline
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Forward declarations
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar;
|
|
||||||
class CCommand;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
struct characterset_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Any executable that wants to use ConVars need to implement one of
|
|
||||||
// these to hook up access to console variables.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class IConCommandBaseAccessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Flags is a combination of FCVAR flags in cvar.h.
|
|
||||||
// hOut is filled in with a handle to the variable.
|
|
||||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helper method for console development
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined( _X360 ) && !defined( _RETAIL )
|
|
||||||
void ConVar_PublishToVXConsole();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef void ( *FnCommandCallbackV1_t )( void );
|
|
||||||
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Interface version
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ICommandCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void CommandCallback( const CCommand &command ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
|
||||||
friend void ConVar_PublishToVXConsole();
|
|
||||||
|
|
||||||
// FIXME: Remove when ConVar changes are done
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
|
|
||||||
// Return name of cvar
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
|
|
||||||
// Return help text for cvar
|
|
||||||
virtual const char *GetHelpText( void ) const;
|
|
||||||
|
|
||||||
// Deal with next pointer
|
|
||||||
const ConCommandBase *GetNext( void ) const;
|
|
||||||
ConCommandBase *GetNext( void );
|
|
||||||
|
|
||||||
void SetNext(ConCommandBase *pBase)
|
|
||||||
{
|
|
||||||
m_pNext = pBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Returns the DLL identifier
|
|
||||||
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void Create( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize/shutdown
|
|
||||||
virtual void Init();
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// Internal copy routine ( uses new operator from correct module )
|
|
||||||
char *CopyString( const char *from );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Next ConVar in chain
|
|
||||||
// Prior to register, it points to the next convar in the DLL.
|
|
||||||
// Once registered, though, m_pNext is reset to point to the next
|
|
||||||
// convar in the global list
|
|
||||||
ConCommandBase *m_pNext;
|
|
||||||
|
|
||||||
// Has the cvar been added to the global list?
|
|
||||||
bool m_bRegistered;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
const char *m_pszName;
|
|
||||||
const char *m_pszHelpString;
|
|
||||||
|
|
||||||
// ConVar flags
|
|
||||||
int m_nFlags;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// ConVars add themselves to this list for the executable.
|
|
||||||
// Then ConVar_Register runs through all the console variables
|
|
||||||
// and registers them into a global list stored in vstdlib.dll
|
|
||||||
static ConCommandBase *s_pConCommandBases;
|
|
||||||
|
|
||||||
// ConVars in this executable use this 'global' to access values.
|
|
||||||
static IConCommandBaseAccessor *s_pAccessor;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline int GetFlags() const
|
|
||||||
{
|
|
||||||
return m_nFlags;
|
|
||||||
}
|
|
||||||
inline void SetFlags(int flags)
|
|
||||||
{
|
|
||||||
m_nFlags = flags;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Command tokenizer
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class CCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCommand();
|
|
||||||
CCommand( int nArgC, const char **ppArgV );
|
|
||||||
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
int ArgC() const;
|
|
||||||
const char **ArgV() const;
|
|
||||||
const char *ArgS() const; // All args that occur after the 0th arg, in string form
|
|
||||||
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
|
|
||||||
const char *operator[]( int nIndex ) const; // Gets at arguments
|
|
||||||
const char *Arg( int nIndex ) const; // Gets at arguments
|
|
||||||
|
|
||||||
// Helper functions to parse arguments to commands.
|
|
||||||
const char* FindArg( const char *pName ) const;
|
|
||||||
int FindArgInt( const char *pName, int nDefaultVal ) const;
|
|
||||||
|
|
||||||
static int MaxCommandLength();
|
|
||||||
static characterset_t* DefaultBreakSet();
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
COMMAND_MAX_ARGC = 64,
|
|
||||||
COMMAND_MAX_LENGTH = 512,
|
|
||||||
};
|
|
||||||
|
|
||||||
int m_nArgc;
|
|
||||||
int m_nArgv0Size;
|
|
||||||
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
|
|
||||||
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
|
|
||||||
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int CCommand::MaxCommandLength()
|
|
||||||
{
|
|
||||||
return COMMAND_MAX_LENGTH - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int CCommand::ArgC() const
|
|
||||||
{
|
|
||||||
return m_nArgc;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char **CCommand::ArgV() const
|
|
||||||
{
|
|
||||||
return m_nArgc ? (const char**)m_ppArgv : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::ArgS() const
|
|
||||||
{
|
|
||||||
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::GetCommandString() const
|
|
||||||
{
|
|
||||||
return m_nArgc ? m_pArgSBuffer : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::Arg( int nIndex ) const
|
|
||||||
{
|
|
||||||
// FIXME: Many command handlers appear to not be particularly careful
|
|
||||||
// about checking for valid argc range. For now, we're going to
|
|
||||||
// do the extra check and return an empty string if it's out of range
|
|
||||||
if ( nIndex < 0 || nIndex >= m_nArgc )
|
|
||||||
return "";
|
|
||||||
return m_ppArgv[nIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::operator[]( int nIndex ) const
|
|
||||||
{
|
|
||||||
return Arg( nIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The console invoked command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommand : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
ConCommand( const char *pName, FnCommandCallback_t callback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
ConCommand( const char *pName, ICommandCallback *pCallback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommand( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
|
|
||||||
|
|
||||||
virtual bool CanAutoComplete( void );
|
|
||||||
|
|
||||||
// Invoke the function
|
|
||||||
virtual void Dispatch( const CCommand &command );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// NOTE: To maintain backward compat, we have to be very careful:
|
|
||||||
// All public virtual methods must appear in the same order always
|
|
||||||
// since engine code will be calling into this code, which *does not match*
|
|
||||||
// in the mod code; it's using slightly different, but compatible versions
|
|
||||||
// of this class. Also: Be very careful about adding new fields to this class.
|
|
||||||
// Those fields will not exist in the version of this class that is instanced
|
|
||||||
// in mod code.
|
|
||||||
|
|
||||||
// Call this function when executing the command
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
|
||||||
FnCommandCallback_t m_fnCommandCallback;
|
|
||||||
ICommandCallback *m_pCommandCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
|
||||||
ICommandCompletionCallback *m_pCommandCompletionCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool m_bHasCompletionCallback : 1;
|
|
||||||
bool m_bUsingNewCommandCallback : 1;
|
|
||||||
bool m_bUsingCommandCallbackInterface : 1;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline FnCommandCallback_t GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnCommandCallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: A console variable
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar : public ConCommandBase, public IConVar
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVarRef;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
|
|
||||||
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, FnChangeCallback_t callback );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
|
||||||
FnChangeCallback_t callback );
|
|
||||||
|
|
||||||
virtual ~ConVar( void );
|
|
||||||
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
virtual const char* GetHelpText( void ) const;
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Install a change callback (there shouldn't already be one....)
|
|
||||||
void InstallChangeCallback( FnChangeCallback_t callback );
|
|
||||||
|
|
||||||
// Retrieve value
|
|
||||||
FORCEINLINE_CVAR float GetFloat( void ) const;
|
|
||||||
FORCEINLINE_CVAR int GetInt( void ) const;
|
|
||||||
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
|
||||||
FORCEINLINE_CVAR char const *GetString( void ) const;
|
|
||||||
|
|
||||||
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
|
||||||
// from alloc/free across dll/exe boundaries.
|
|
||||||
|
|
||||||
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
|
||||||
virtual void SetValue( const char *value );
|
|
||||||
virtual void SetValue( float value );
|
|
||||||
virtual void SetValue( int value );
|
|
||||||
|
|
||||||
// Reset to default value
|
|
||||||
void Revert( void );
|
|
||||||
|
|
||||||
// True if it has a min/max setting
|
|
||||||
bool GetMin( float& minVal ) const;
|
|
||||||
bool GetMax( float& maxVal ) const;
|
|
||||||
const char *GetDefault( void ) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Called by CCvar when the value of a var is changing.
|
|
||||||
virtual void InternalSetValue(const char *value);
|
|
||||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
|
||||||
virtual void InternalSetFloatValue( float fNewValue );
|
|
||||||
virtual void InternalSetIntValue( int nValue );
|
|
||||||
|
|
||||||
virtual bool ClampValue( float& value );
|
|
||||||
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
|
|
||||||
|
|
||||||
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
|
|
||||||
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
|
||||||
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// This either points to "this" or it points to the original declaration of a ConVar.
|
|
||||||
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
|
|
||||||
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
|
|
||||||
ConVar *m_pParent;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
const char *m_pszDefaultValue;
|
|
||||||
|
|
||||||
// Value
|
|
||||||
// Dynamically allocated
|
|
||||||
char *m_pszString;
|
|
||||||
int m_StringLength;
|
|
||||||
|
|
||||||
// Values
|
|
||||||
float m_fValue;
|
|
||||||
int m_nValue;
|
|
||||||
|
|
||||||
// Min/Max values
|
|
||||||
bool m_bHasMin;
|
|
||||||
float m_fMinVal;
|
|
||||||
bool m_bHasMax;
|
|
||||||
float m_fMaxVal;
|
|
||||||
|
|
||||||
// Call this function when ConVar changes
|
|
||||||
FnChangeCallback_t m_fnChangeCallback;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline FnChangeCallback_t GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnChangeCallback;
|
|
||||||
}
|
|
||||||
inline void SetMin(bool set, float min=0.0)
|
|
||||||
{
|
|
||||||
m_bHasMin = set;
|
|
||||||
m_fMinVal = min;
|
|
||||||
}
|
|
||||||
inline void SetMax(bool set, float max=0.0)
|
|
||||||
{
|
|
||||||
m_bHasMax = set;
|
|
||||||
m_fMaxVal = max;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a float
|
|
||||||
// Output : float
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
|
|
||||||
{
|
|
||||||
return m_pParent->m_fValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as an int
|
|
||||||
// Output : int
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
|
|
||||||
{
|
|
||||||
return m_pParent->m_nValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
|
||||||
// Output : const char *
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
|
|
||||||
{
|
|
||||||
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
|
|
||||||
return "FCVAR_NEVER_AS_STRING";
|
|
||||||
|
|
||||||
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Used to read/write convars that already exist (replaces the FindVar method)
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVarRef
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConVarRef( const char *pName );
|
|
||||||
ConVarRef( const char *pName, bool bIgnoreMissing );
|
|
||||||
ConVarRef( IConVar *pConVar );
|
|
||||||
|
|
||||||
void Init( const char *pName, bool bIgnoreMissing );
|
|
||||||
bool IsValid() const;
|
|
||||||
bool IsFlagSet( int nFlags ) const;
|
|
||||||
IConVar *GetLinkedConVar();
|
|
||||||
|
|
||||||
// Get/Set value
|
|
||||||
float GetFloat( void ) const;
|
|
||||||
int GetInt( void ) const;
|
|
||||||
bool GetBool() const { return !!GetInt(); }
|
|
||||||
const char *GetString( void ) const;
|
|
||||||
|
|
||||||
void SetValue( const char *pValue );
|
|
||||||
void SetValue( float flValue );
|
|
||||||
void SetValue( int nValue );
|
|
||||||
void SetValue( bool bValue );
|
|
||||||
|
|
||||||
const char *GetName() const;
|
|
||||||
|
|
||||||
const char *GetDefault() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// High-speed method to read convar data
|
|
||||||
IConVar *m_pConVar;
|
|
||||||
ConVar *m_pConVarState;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Did we find an existing convar of that name?
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
|
|
||||||
{
|
|
||||||
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
|
|
||||||
{
|
|
||||||
return m_pConVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
|
|
||||||
{
|
|
||||||
return m_pConVar->GetName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a float
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
|
|
||||||
{
|
|
||||||
return m_pConVarState->m_fValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as an int
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
|
|
||||||
{
|
|
||||||
return m_pConVarState->m_nValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
|
|
||||||
{
|
|
||||||
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
|
|
||||||
return m_pConVarState->m_pszString;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( pValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( flValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( nValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( bValue ? 1 : 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
|
|
||||||
{
|
|
||||||
return m_pConVarState->m_pszDefaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called by the framework to register ConCommands with the ICVar
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
|
|
||||||
void ConVar_Unregister( );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Utility methods
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void ConVar_PrintFlags( const ConCommandBase *var );
|
|
||||||
void ConVar_PrintDescription( const ConCommandBase *pVar );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility class to quickly allow ConCommands to call member methods
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined _MSC_VER
|
|
||||||
#pragma warning (disable : 4355 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template< class T >
|
|
||||||
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
typedef ConCommand BaseClass;
|
|
||||||
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
|
|
||||||
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
|
|
||||||
|
|
||||||
public:
|
|
||||||
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
|
|
||||||
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
|
|
||||||
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
|
|
||||||
{
|
|
||||||
m_pOwner = pOwner;
|
|
||||||
m_Func = callback;
|
|
||||||
m_CompletionFunc = completionFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CConCommandMemberAccessor()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetOwner( T* pOwner )
|
|
||||||
{
|
|
||||||
m_pOwner = pOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void CommandCallback( const CCommand &command )
|
|
||||||
{
|
|
||||||
Assert( m_pOwner && m_Func );
|
|
||||||
(m_pOwner->*m_Func)( command );
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
|
|
||||||
{
|
|
||||||
Assert( m_pOwner && m_CompletionFunc );
|
|
||||||
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* m_pOwner;
|
|
||||||
FnMemberCommandCallback_t m_Func;
|
|
||||||
FnMemberCommandCompletionCallback_t m_CompletionFunc;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined _MSC_VER
|
|
||||||
#pragma warning ( default : 4355 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility macros to quicky generate a simple console command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define CON_COMMAND( name, description ) \
|
|
||||||
static void name( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, name, description ); \
|
|
||||||
static void name( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_F( name, description, flags ) \
|
|
||||||
static void name( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, name, description, flags ); \
|
|
||||||
static void name( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
|
|
||||||
static void name( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, name, description, flags, completion ); \
|
|
||||||
static void name( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
|
|
||||||
void _funcname( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, _funcname, description ); \
|
|
||||||
void _funcname( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
|
|
||||||
void _funcname( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, _funcname, description, flags ); \
|
|
||||||
void _funcname( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
|
|
||||||
void _funcname( const CCommand &args ); \
|
|
||||||
friend class CCommandMemberInitializer_##_funcname; \
|
|
||||||
class CCommandMemberInitializer_##_funcname \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
|
|
||||||
{ \
|
|
||||||
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
|
|
||||||
} \
|
|
||||||
private: \
|
|
||||||
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CONVAR_H
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
#include "frame_hooks.h"
|
|
||||||
#include "TimerSys.h"
|
|
||||||
#include "Database.h"
|
|
||||||
#include "HalfLife2.h"
|
|
||||||
#include "MenuStyle_Valve.h"
|
|
||||||
#include "MenuStyle_Radio.h"
|
|
||||||
#include "PlayerManager.h"
|
|
||||||
|
|
||||||
float g_LastMenuTime = 0.0f;
|
|
||||||
float g_LastAuthCheck = 0.0f;
|
|
||||||
|
|
||||||
void RunFrameHooks()
|
|
||||||
{
|
|
||||||
/* Frame based hooks */
|
|
||||||
g_DBMan.RunFrame();
|
|
||||||
g_HL2.ProcessFakeCliCmdQueue();
|
|
||||||
|
|
||||||
float curtime = *g_pUniversalTime;
|
|
||||||
|
|
||||||
if (curtime - g_LastMenuTime >= 1.0f)
|
|
||||||
{
|
|
||||||
g_ValveMenuStyle.ProcessWatchList();
|
|
||||||
g_RadioMenuStyle.ProcessWatchList();
|
|
||||||
g_LastMenuTime = curtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*g_NumPlayersToAuth && curtime - g_LastAuthCheck >= 0.7f)
|
|
||||||
{
|
|
||||||
g_Players.RunAuthChecks();
|
|
||||||
g_LastAuthCheck = curtime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
|
||||||
|
|
||||||
void RunFrameHooks();
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
|
||||||
# Visual Studio 2005
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sourcemod_mm", "sourcemod_mm.vcproj", "{E39527CD-7CAB-4420-97CC-DA1B93B260BC}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
CrazyDebug|Win32 = CrazyDebug|Win32
|
|
||||||
Debug - Episode 1|Win32 = Debug - Episode 1|Win32
|
|
||||||
Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32
|
|
||||||
Debug - Orange Box|Win32 = Debug - Orange Box|Win32
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release - Episode 1|Win32 = Release - Episode 1|Win32
|
|
||||||
Release - Old Metamod|Win32 = Release - Old Metamod|Win32
|
|
||||||
Release - Orange Box|Win32 = Release - Orange Box|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug|Win32.ActiveCfg = CrazyDebug|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug|Win32.Build.0 = CrazyDebug|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Old Metamod|Win32.ActiveCfg = Debug - Old Metamod|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug|Win32.ActiveCfg = CrazyDebug|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug|Win32.Build.0 = CrazyDebug|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Old Metamod|Win32.ActiveCfg = Release - Old Metamod|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Old Metamod|Win32.Build.0 = Release - Old Metamod|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release|Win32.ActiveCfg = Debug - Old Metamod|Win32
|
|
||||||
{E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release|Win32.Build.0 = Debug - Old Metamod|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,38 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_autonatives.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
|
|
||||||
void CoreNativesToAdd::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_PluginSys.RegisterNativesFromCore(m_NativeList);
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CORE_AUTONATIVES_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CORE_AUTONATIVES_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
#define REGISTER_NATIVES(globname) \
|
|
||||||
extern sp_nativeinfo_t globNatives##globname[]; \
|
|
||||||
CoreNativesToAdd globNativesCls##globname(globNatives##globname); \
|
|
||||||
sp_nativeinfo_t globNatives##globname[] =
|
|
||||||
|
|
||||||
class CoreNativesToAdd : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CoreNativesToAdd(sp_nativeinfo_t *pList)
|
|
||||||
: m_NativeList(pList)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
sp_nativeinfo_t *m_NativeList;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CORE_AUTONATIVES_H_
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_crc32.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Polynomial: 0x04C11DB7
|
|
||||||
*/
|
|
||||||
const unsigned int CRCTable[256] = {
|
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
|
||||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
|
||||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
|
||||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
|
||||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
|
||||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
|
||||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
|
||||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
|
||||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
|
||||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
|
||||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
|
||||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
|
||||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
|
||||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
|
||||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
|
||||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
|
||||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
|
||||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
|
||||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
|
||||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
|
||||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
|
||||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
|
||||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
|
||||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
|
||||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
|
||||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
|
||||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
|
||||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
|
||||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
|
||||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
|
||||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
|
||||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
|
||||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
|
||||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
|
||||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
|
||||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
|
||||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
|
||||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
|
||||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
|
||||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
|
||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
|
||||||
|
|
||||||
unsigned int UTIL_CRC32(const void *pdata, size_t data_length)
|
|
||||||
{
|
|
||||||
unsigned char *data = (unsigned char *)pdata;
|
|
||||||
unsigned int crc = 0xFFFFFFFF;
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
for (size_t i=0; i<data_length; i++, data++)
|
|
||||||
{
|
|
||||||
c = (unsigned char)((crc ^ *data) & 0xFF);
|
|
||||||
crc = CRCTable[c] ^ (crc >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CRC32_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CRC32_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
unsigned int UTIL_CRC32(const void *data, size_t data_length);
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CRC32_H_
|
|
||||||
|
|
||||||
@ -1,218 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_FASTLINK_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_FASTLINK_H_
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class FastLink
|
|
||||||
{
|
|
||||||
friend class iterator;
|
|
||||||
public:
|
|
||||||
struct FastLinkNode
|
|
||||||
{
|
|
||||||
unsigned int prev;
|
|
||||||
unsigned int next;
|
|
||||||
unsigned int freeNode;
|
|
||||||
T obj;
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
FastLink(unsigned int maxsize) : m_Size(0), m_FirstLink(0), m_FreeNodes(0), m_LastLink(0), m_UsableIndex(0)
|
|
||||||
{
|
|
||||||
m_MaxSize = maxsize;
|
|
||||||
m_Nodes = new FastLinkNode[m_MaxSize+1];
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
bool push_back(const T & obj)
|
|
||||||
{
|
|
||||||
unsigned int new_node = GetFreeIndex();
|
|
||||||
if (!new_node)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_Nodes[new_node].obj = obj;
|
|
||||||
m_Nodes[new_node].next = 0;
|
|
||||||
if (!m_FirstLink)
|
|
||||||
{
|
|
||||||
m_Nodes[new_node].prev = 0;
|
|
||||||
m_FirstLink = new_node;
|
|
||||||
m_LastLink = new_node;
|
|
||||||
} else {
|
|
||||||
m_Nodes[new_node].prev = m_LastLink;
|
|
||||||
m_Nodes[m_LastLink].next = new_node;
|
|
||||||
m_LastLink = new_node;
|
|
||||||
}
|
|
||||||
m_Size++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
unsigned int GetFreeIndex()
|
|
||||||
{
|
|
||||||
if (m_FreeNodes)
|
|
||||||
{
|
|
||||||
return m_Nodes[m_FreeNodes--].freeNode;
|
|
||||||
} else {
|
|
||||||
if (m_UsableIndex >= m_MaxSize)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m_UsableIndex++;
|
|
||||||
return m_UsableIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
class iterator
|
|
||||||
{
|
|
||||||
friend class FastLink;
|
|
||||||
public:
|
|
||||||
iterator()
|
|
||||||
{
|
|
||||||
link = NULL;
|
|
||||||
position = 0;
|
|
||||||
}
|
|
||||||
iterator(const FastLink *_link, unsigned int _position)
|
|
||||||
{
|
|
||||||
link = _link;
|
|
||||||
position = _position;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
bool operator ==(const iterator &where) const
|
|
||||||
{
|
|
||||||
return (link == where.link && position == where.position);
|
|
||||||
}
|
|
||||||
bool operator !=(const iterator &where) const
|
|
||||||
{
|
|
||||||
return (link != where.link || position != where.position);
|
|
||||||
}
|
|
||||||
T & operator *()
|
|
||||||
{
|
|
||||||
return link->m_Nodes[position].obj;
|
|
||||||
}
|
|
||||||
const T & operator *() const
|
|
||||||
{
|
|
||||||
return link->m_Nodes[position].obj;
|
|
||||||
}
|
|
||||||
iterator & operator++()
|
|
||||||
{
|
|
||||||
position = link->m_Nodes[position].next;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
const FastLink *link;
|
|
||||||
unsigned int position;
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
iterator begin() const
|
|
||||||
{
|
|
||||||
return iterator(this, m_FirstLink);
|
|
||||||
}
|
|
||||||
iterator end() const
|
|
||||||
{
|
|
||||||
return iterator(this, 0);
|
|
||||||
}
|
|
||||||
void remove(const T & obj)
|
|
||||||
{
|
|
||||||
for (iterator iter=begin(); iter!=end(); ++iter)
|
|
||||||
{
|
|
||||||
if ((*iter) == obj)
|
|
||||||
{
|
|
||||||
erase(iter);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator erase(const iterator &where)
|
|
||||||
{
|
|
||||||
/* Whoa, this better be right! */
|
|
||||||
assert(where.link == this);
|
|
||||||
|
|
||||||
iterator iter(where.link, where.position);
|
|
||||||
++iter;
|
|
||||||
|
|
||||||
unsigned int index = where.position;
|
|
||||||
|
|
||||||
/* Each case is different, we have no sentinel.
|
|
||||||
* CASE: We're the HEAD AND the TAIL */
|
|
||||||
if (index == m_FirstLink
|
|
||||||
&& index == m_LastLink)
|
|
||||||
{
|
|
||||||
m_FirstLink = 0;
|
|
||||||
m_LastLink = 0;
|
|
||||||
}
|
|
||||||
/* We're the HEAD */
|
|
||||||
else if (index == m_FirstLink)
|
|
||||||
{
|
|
||||||
m_FirstLink = m_Nodes[index].next;
|
|
||||||
m_Nodes[m_FirstLink].prev = 0;
|
|
||||||
}
|
|
||||||
/* We're the TAIL */
|
|
||||||
else if (index == m_LastLink)
|
|
||||||
{
|
|
||||||
m_LastLink = m_Nodes[index].prev;
|
|
||||||
m_Nodes[m_LastLink].next = 0;
|
|
||||||
}
|
|
||||||
/* We're in the middle! */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Patch forward reference */
|
|
||||||
m_Nodes[m_Nodes[index].next].prev = m_Nodes[index].prev;
|
|
||||||
/* Patch backward reference */
|
|
||||||
m_Nodes[m_Nodes[index].prev].next = m_Nodes[index].next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add us to the free list */
|
|
||||||
m_Nodes[++m_FreeNodes].freeNode = index;
|
|
||||||
|
|
||||||
m_Size--;
|
|
||||||
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
#if defined MENU_DEBUG
|
|
||||||
public:
|
|
||||||
#else
|
|
||||||
private:
|
|
||||||
#endif
|
|
||||||
size_t m_Size;
|
|
||||||
unsigned int m_FirstLink;
|
|
||||||
unsigned int m_FreeNodes;
|
|
||||||
unsigned int m_LastLink;
|
|
||||||
unsigned int m_MaxSize;
|
|
||||||
unsigned int m_UsableIndex;
|
|
||||||
FastLinkNode *m_Nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_FASTLINK_H_
|
|
||||||
@ -1,174 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_GLOBALS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_GLOBALS_H_
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file Contains global headers that most files in SourceMod will need.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sp_vm_types.h>
|
|
||||||
#include <sp_vm_api.h>
|
|
||||||
#include "sm_platform.h"
|
|
||||||
#include <IShareSys.h>
|
|
||||||
|
|
||||||
using namespace SourcePawn;
|
|
||||||
using namespace SourceMod;
|
|
||||||
|
|
||||||
class IServerPluginCallbacks;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Lists result codes possible from attempting to set a core configuration option.
|
|
||||||
*/
|
|
||||||
enum ConfigResult
|
|
||||||
{
|
|
||||||
ConfigResult_Accept = 0, /**< Config option was successfully set */
|
|
||||||
ConfigResult_Reject = 1, /**< Config option was given an invalid value and was rejected */
|
|
||||||
ConfigResult_Ignore = 2 /**< Config option was invalid, but ignored */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Lists possible sources of a config option change
|
|
||||||
*/
|
|
||||||
enum ConfigSource
|
|
||||||
{
|
|
||||||
ConfigSource_File = 0, /**< Config option was set from config file (core.cfg) */
|
|
||||||
ConfigSource_Console = 1, /**< Config option was set from console command (sm config) */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Any class deriving from this will be automatically initiated/shutdown by SourceMod
|
|
||||||
*/
|
|
||||||
class SMGlobalClass
|
|
||||||
{
|
|
||||||
friend class SourceMod_Core;
|
|
||||||
friend class SourceModBase;
|
|
||||||
friend class CoreConfig;
|
|
||||||
friend class CExtensionManager;
|
|
||||||
public:
|
|
||||||
SMGlobalClass();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Called when SourceMod is initially loading
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called after all global classes have initialized
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called when SourceMod is shutting down
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called after SourceMod is completely shut down
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModAllShutdown()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called when a core config option is changed.
|
|
||||||
* @note This is called once BEFORE OnSourceModStartup() when SourceMod is loading
|
|
||||||
* @note It can then be called again when the 'sm config' command is used
|
|
||||||
*/
|
|
||||||
virtual ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength)
|
|
||||||
{
|
|
||||||
return ConfigResult_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called when the level changes.
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModLevelChange(const char *mapName)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called when the level ends.
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModLevelEnd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called after plugins are loaded on mapchange.
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModPluginsLoaded()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called when SourceMod receives a pointer to IServerPluginCallbacks from SourceMM
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModVSPReceived()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called once all MM:S plugins are loaded.
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModGameInitialized()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called when an identity is dropped (right now, extensions only)
|
|
||||||
*/
|
|
||||||
virtual void OnSourceModIdentityDropped(IdentityToken_t *pToken)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
SMGlobalClass *m_pGlobalClassNext;
|
|
||||||
static SMGlobalClass *head;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ISourcePawnEngine *g_pSourcePawn;
|
|
||||||
extern IVirtualMachine *g_pVM;
|
|
||||||
extern IdentityToken_t *g_pCoreIdent;
|
|
||||||
|
|
||||||
#include "sm_autonatives.h"
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_GLOBALS_H_
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
|
|
||||||
BaseMemTable::BaseMemTable(unsigned int init_size)
|
|
||||||
{
|
|
||||||
membase = (unsigned char *)malloc(init_size);
|
|
||||||
size = init_size;
|
|
||||||
tail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseMemTable::~BaseMemTable()
|
|
||||||
{
|
|
||||||
free(membase);
|
|
||||||
membase = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BaseMemTable::CreateMem(unsigned int addsize, void **addr)
|
|
||||||
{
|
|
||||||
int idx = (int)tail;
|
|
||||||
|
|
||||||
while (tail + addsize >= size)
|
|
||||||
{
|
|
||||||
size *= 2;
|
|
||||||
membase = (unsigned char *)realloc(membase, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
tail += addsize;
|
|
||||||
|
|
||||||
if (addr)
|
|
||||||
{
|
|
||||||
*addr = (void *)&membase[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *BaseMemTable::GetAddress(int index)
|
|
||||||
{
|
|
||||||
if (index < 0 || (unsigned int)index >= tail)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &membase[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMemTable::Reset()
|
|
||||||
{
|
|
||||||
tail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseStringTable::BaseStringTable(unsigned int init_size) : m_table(init_size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseStringTable::~BaseStringTable()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int BaseStringTable::AddString(const char *string)
|
|
||||||
{
|
|
||||||
size_t len = strlen(string) + 1;
|
|
||||||
int idx;
|
|
||||||
char *addr;
|
|
||||||
|
|
||||||
idx = m_table.CreateMem(len, (void **)&addr);
|
|
||||||
strcpy(addr, string);
|
|
||||||
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*const char *BaseStringTable::GetString(int str)
|
|
||||||
{
|
|
||||||
return (const char *)m_table.GetAddress(str);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void BaseStringTable::Reset()
|
|
||||||
{
|
|
||||||
m_table.Reset();
|
|
||||||
}
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
|
|
||||||
|
|
||||||
class BaseMemTable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseMemTable(unsigned int init_size);
|
|
||||||
~BaseMemTable();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Allocates 'size' bytes of memory.
|
|
||||||
* Optionally outputs the address through 'addr'.
|
|
||||||
* Returns an index >= 0 on success, < 0 on failure.
|
|
||||||
*/
|
|
||||||
int CreateMem(unsigned int size, void **addr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an index into the memory table, returns its address.
|
|
||||||
* Returns NULL if invalid.
|
|
||||||
*/
|
|
||||||
void *GetAddress(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scraps the memory table. For caching purposes, the memory
|
|
||||||
* is not freed, however subsequent calls to CreateMem() will
|
|
||||||
* begin at the first index again.
|
|
||||||
*/
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned char *membase;
|
|
||||||
unsigned int size;
|
|
||||||
unsigned int tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BaseStringTable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseStringTable(unsigned int init_size);
|
|
||||||
~BaseStringTable();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Adds a string to the string table and returns its index.
|
|
||||||
*/
|
|
||||||
int AddString(const char *string);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an index into the string table, returns the associated string.
|
|
||||||
*/
|
|
||||||
inline const char *GetString(int str)
|
|
||||||
{
|
|
||||||
return (const char *)m_table.GetAddress(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scraps the string table. For caching purposes, the memory
|
|
||||||
* is not freed, however subsequent calls to AddString() will
|
|
||||||
* begin at the first index again.
|
|
||||||
*/
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the parent BaseMemTable that this string table uses.
|
|
||||||
*/
|
|
||||||
inline BaseMemTable *GetMemTable()
|
|
||||||
{
|
|
||||||
return &m_table;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
BaseMemTable m_table;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
|
|
||||||
333
core/sm_queue.h
333
core/sm_queue.h
@ -1,333 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SM_QUEUE_H
|
|
||||||
#define _INCLUDE_SM_QUEUE_H
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
/*
|
|
||||||
A circular, doubly-linked List with one sentinel node
|
|
||||||
|
|
||||||
Empty:
|
|
||||||
m_Head = sentinel
|
|
||||||
m_Head->next = m_Head;
|
|
||||||
m_Head->prev = m_Head;
|
|
||||||
One element:
|
|
||||||
m_Head = sentinel
|
|
||||||
m_Head->next = node1
|
|
||||||
m_Head->prev = node1
|
|
||||||
node1->next = m_Head
|
|
||||||
node1->prev = m_Head
|
|
||||||
Two elements:
|
|
||||||
m_Head = sentinel
|
|
||||||
m_Head->next = node1
|
|
||||||
m_Head->prev = node2
|
|
||||||
node1->next = node2
|
|
||||||
node1->prev = m_Head
|
|
||||||
node2->next = m_Head
|
|
||||||
node2->prev = node1
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
class Queue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class iterator;
|
|
||||||
friend class iterator;
|
|
||||||
class QueueNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
T obj;
|
|
||||||
QueueNode *next;
|
|
||||||
QueueNode *prev;
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
// Initializes the sentinel node.
|
|
||||||
QueueNode *_Initialize()
|
|
||||||
{
|
|
||||||
QueueNode *n = (QueueNode *)malloc(sizeof(QueueNode));
|
|
||||||
n->next = n;
|
|
||||||
n->prev = n;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
Queue() : m_Head(_Initialize()), m_Size(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Queue(const Queue &src) : m_Head(_Initialize()), m_Size(0)
|
|
||||||
{
|
|
||||||
iterator iter;
|
|
||||||
for (iter=src.begin(); iter!=src.end(); iter++)
|
|
||||||
{
|
|
||||||
push_back( (*iter) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~Queue()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
|
|
||||||
// Don't forget to free the sentinel
|
|
||||||
if (m_Head)
|
|
||||||
{
|
|
||||||
free(m_Head);
|
|
||||||
m_Head = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!m_FreeNodes.empty())
|
|
||||||
{
|
|
||||||
free(m_FreeNodes.front());
|
|
||||||
m_FreeNodes.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void push(const T &obj)
|
|
||||||
{
|
|
||||||
QueueNode *node;
|
|
||||||
|
|
||||||
if (m_FreeNodes.empty())
|
|
||||||
{
|
|
||||||
node = (QueueNode *)malloc(sizeof(QueueNode));
|
|
||||||
} else {
|
|
||||||
node = m_FreeNodes.front();
|
|
||||||
m_FreeNodes.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the object */
|
|
||||||
new (&node->obj) T(obj);
|
|
||||||
|
|
||||||
/* Install into the Queue */
|
|
||||||
node->prev = m_Head->prev;
|
|
||||||
node->next = m_Head;
|
|
||||||
m_Head->prev->next = node;
|
|
||||||
m_Head->prev = node;
|
|
||||||
|
|
||||||
m_Size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
QueueNode *node = m_Head->next;
|
|
||||||
QueueNode *temp;
|
|
||||||
m_Head->next = m_Head;
|
|
||||||
m_Head->prev = m_Head;
|
|
||||||
|
|
||||||
// Iterate through the nodes until we find g_Head (the sentinel) again
|
|
||||||
while (node != m_Head)
|
|
||||||
{
|
|
||||||
temp = node->next;
|
|
||||||
node->obj.~T();
|
|
||||||
m_FreeNodes.push(node);
|
|
||||||
node = temp;
|
|
||||||
}
|
|
||||||
m_Size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const
|
|
||||||
{
|
|
||||||
return (m_Size == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QueueNode *m_Head;
|
|
||||||
size_t m_Size;
|
|
||||||
CStack<QueueNode *> m_FreeNodes;
|
|
||||||
public:
|
|
||||||
class iterator
|
|
||||||
{
|
|
||||||
friend class Queue;
|
|
||||||
public:
|
|
||||||
iterator()
|
|
||||||
{
|
|
||||||
m_This = NULL;
|
|
||||||
}
|
|
||||||
iterator(const Queue &src)
|
|
||||||
{
|
|
||||||
m_This = src.m_Head;
|
|
||||||
}
|
|
||||||
iterator(QueueNode *n) : m_This(n)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
iterator(const iterator &where)
|
|
||||||
{
|
|
||||||
m_This = where.m_This;
|
|
||||||
}
|
|
||||||
//pre decrement
|
|
||||||
iterator & operator--()
|
|
||||||
{
|
|
||||||
if (m_This)
|
|
||||||
m_This = m_This->prev;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
//post decrement
|
|
||||||
iterator operator--(int)
|
|
||||||
{
|
|
||||||
iterator old(*this);
|
|
||||||
if (m_This)
|
|
||||||
m_This = m_This->prev;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
//pre increment
|
|
||||||
iterator & operator++()
|
|
||||||
{
|
|
||||||
if (m_This)
|
|
||||||
m_This = m_This->next;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
//post increment
|
|
||||||
iterator operator++(int)
|
|
||||||
{
|
|
||||||
iterator old(*this);
|
|
||||||
if (m_This)
|
|
||||||
m_This = m_This->next;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T & operator * () const
|
|
||||||
{
|
|
||||||
return m_This->obj;
|
|
||||||
}
|
|
||||||
T & operator * ()
|
|
||||||
{
|
|
||||||
return m_This->obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
T * operator -> ()
|
|
||||||
{
|
|
||||||
return &(m_This->obj);
|
|
||||||
}
|
|
||||||
const T * operator -> () const
|
|
||||||
{
|
|
||||||
return &(m_This->obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator != (const iterator &where) const
|
|
||||||
{
|
|
||||||
return (m_This != where.m_This);
|
|
||||||
}
|
|
||||||
bool operator ==(const iterator &where) const
|
|
||||||
{
|
|
||||||
return (m_This == where.m_This);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
QueueNode *m_This;
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
iterator begin() const
|
|
||||||
{
|
|
||||||
return iterator(m_Head->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator end() const
|
|
||||||
{
|
|
||||||
return iterator(m_Head);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator erase(iterator &where)
|
|
||||||
{
|
|
||||||
QueueNode *pNode = where.m_This;
|
|
||||||
iterator iter(where);
|
|
||||||
iter++;
|
|
||||||
|
|
||||||
|
|
||||||
// Works for all cases: empty Queue, erasing first element, erasing tail, erasing in the middle...
|
|
||||||
pNode->prev->next = pNode->next;
|
|
||||||
pNode->next->prev = pNode->prev;
|
|
||||||
|
|
||||||
pNode->obj.~T();
|
|
||||||
m_FreeNodes.push(pNode);
|
|
||||||
m_Size--;
|
|
||||||
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
void remove(const T & obj)
|
|
||||||
{
|
|
||||||
iterator b;
|
|
||||||
for (b=begin(); b!=end(); b++)
|
|
||||||
{
|
|
||||||
if ( (*b) == obj )
|
|
||||||
{
|
|
||||||
erase( b );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename U>
|
|
||||||
iterator find(const U & equ) const
|
|
||||||
{
|
|
||||||
iterator iter;
|
|
||||||
for (iter=begin(); iter!=end(); iter++)
|
|
||||||
{
|
|
||||||
if ( (*iter) == equ )
|
|
||||||
{
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
Queue & operator =(const Queue &src)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
iterator iter;
|
|
||||||
for (iter=src.begin(); iter!=src.end(); iter++)
|
|
||||||
{
|
|
||||||
push_back( (*iter) );
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
T & first() const
|
|
||||||
{
|
|
||||||
iterator i = begin();
|
|
||||||
|
|
||||||
return (*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop()
|
|
||||||
{
|
|
||||||
iterator iter = begin();
|
|
||||||
erase(iter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SM_QUEUE_H
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_queue.h"
|
|
||||||
#include <IDBDriver.h>
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class PrioQueue
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
Queue<T> m_HighQueue;
|
|
||||||
Queue<T> m_NormalQueue;
|
|
||||||
Queue<T> m_LowQueue;
|
|
||||||
public:
|
|
||||||
inline Queue<T> & GetQueue(PrioQueueLevel level)
|
|
||||||
{
|
|
||||||
if (level == PrioQueue_High)
|
|
||||||
{
|
|
||||||
return m_HighQueue;
|
|
||||||
} else if (level == PrioQueue_Normal) {
|
|
||||||
return m_NormalQueue;
|
|
||||||
} else {
|
|
||||||
return m_LowQueue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline Queue<T> & GetLikelyQueue()
|
|
||||||
{
|
|
||||||
if (!m_HighQueue.empty())
|
|
||||||
{
|
|
||||||
return m_HighQueue;
|
|
||||||
}
|
|
||||||
if (!m_NormalQueue.empty())
|
|
||||||
{
|
|
||||||
return m_NormalQueue;
|
|
||||||
}
|
|
||||||
return m_LowQueue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,352 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_version.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "CoreConfig.h"
|
|
||||||
|
|
||||||
RootConsoleMenu g_RootMenu;
|
|
||||||
|
|
||||||
ConVar sourcemod_version("sourcemod_version", SVN_FULL_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version");
|
|
||||||
|
|
||||||
RootConsoleMenu::RootConsoleMenu()
|
|
||||||
{
|
|
||||||
m_pCommands = sm_trie_create();
|
|
||||||
m_CfgExecDone = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootConsoleMenu::~RootConsoleMenu()
|
|
||||||
{
|
|
||||||
sm_trie_destroy(m_pCommands);
|
|
||||||
|
|
||||||
List<ConsoleEntry *>::iterator iter;
|
|
||||||
for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
|
|
||||||
{
|
|
||||||
delete (*iter);
|
|
||||||
}
|
|
||||||
m_Menu.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
extern void _IntExt_OnHostnameChanged(IConVar *var, const char *pOldValue, float flOldValue);
|
|
||||||
#else
|
|
||||||
extern void _IntExt_OnHostnameChanged(ConVar *pConVar, char const *oldValue);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void RootConsoleMenu::OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
g_pCVar = icvar;
|
|
||||||
#endif
|
|
||||||
CONVAR_REGISTER(this);
|
|
||||||
AddRootConsoleCommand("version", "Display version information", this);
|
|
||||||
AddRootConsoleCommand("credits", "Display credits listing", this);
|
|
||||||
|
|
||||||
ConVar *pHost = icvar->FindVar("hostname");
|
|
||||||
pHost->InstallChangeCallback(_IntExt_OnHostnameChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RootConsoleMenu::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
RemoveRootConsoleCommand("credits", this);
|
|
||||||
RemoveRootConsoleCommand("version", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
|
|
||||||
{
|
|
||||||
META_REGCVAR(pCommand);
|
|
||||||
|
|
||||||
/* Override values of convars created by SourceMod convar manager if specified on command line */
|
|
||||||
const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName());
|
|
||||||
if (cmdLineValue && !pCommand->IsCommand())
|
|
||||||
{
|
|
||||||
static_cast<ConVar *>(pCommand)->SetValue(cmdLineValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
char buffer[512];
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (len >= sizeof(buffer) - 1)
|
|
||||||
{
|
|
||||||
buffer[510] = '\n';
|
|
||||||
buffer[511] = '\0';
|
|
||||||
} else {
|
|
||||||
buffer[len++] = '\n';
|
|
||||||
buffer[len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
META_CONPRINT(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
|
|
||||||
{
|
|
||||||
if (sm_trie_retrieve(m_pCommands, cmd, NULL))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sm_trie_insert(m_pCommands, cmd, pHandler);
|
|
||||||
|
|
||||||
/* Sort this into the menu */
|
|
||||||
List<ConsoleEntry *>::iterator iter = m_Menu.begin();
|
|
||||||
ConsoleEntry *pEntry;
|
|
||||||
bool inserted = false;
|
|
||||||
while (iter != m_Menu.end())
|
|
||||||
{
|
|
||||||
pEntry = (*iter);
|
|
||||||
if (strcmp(cmd, pEntry->command.c_str()) < 0)
|
|
||||||
{
|
|
||||||
ConsoleEntry *pNew = new ConsoleEntry;
|
|
||||||
pNew->command.assign(cmd);
|
|
||||||
pNew->description.assign(text);
|
|
||||||
m_Menu.insert(iter, pNew);
|
|
||||||
inserted = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!inserted)
|
|
||||||
{
|
|
||||||
ConsoleEntry *pNew = new ConsoleEntry;
|
|
||||||
pNew->command.assign(cmd);
|
|
||||||
pNew->description.assign(text);
|
|
||||||
m_Menu.push_back(pNew);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler)
|
|
||||||
{
|
|
||||||
/* Sanity tests */
|
|
||||||
IRootConsoleCommand *object;
|
|
||||||
if (sm_trie_retrieve(m_pCommands, cmd, (void **)&object))
|
|
||||||
{
|
|
||||||
if (object != pHandler)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sm_trie_delete(m_pCommands, cmd);
|
|
||||||
|
|
||||||
List<ConsoleEntry *>::iterator iter;
|
|
||||||
ConsoleEntry *pEntry;
|
|
||||||
for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
|
|
||||||
{
|
|
||||||
pEntry = (*iter);
|
|
||||||
if (pEntry->command.compare(cmd) == 0)
|
|
||||||
{
|
|
||||||
delete pEntry;
|
|
||||||
m_Menu.erase(iter);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
|
|
||||||
{
|
|
||||||
char buffer[255];
|
|
||||||
size_t len, cmdlen = strlen(cmd);
|
|
||||||
|
|
||||||
len = UTIL_Format(buffer, sizeof(buffer), " %s", cmd);
|
|
||||||
if (cmdlen < 16)
|
|
||||||
{
|
|
||||||
size_t num = 16 - cmdlen;
|
|
||||||
for (size_t i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
buffer[len++] = ' ';
|
|
||||||
}
|
|
||||||
len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
|
|
||||||
ConsolePrint("%s", buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void _IntExt_EnableYams();
|
|
||||||
|
|
||||||
void RootConsoleMenu::GotRootCmd(const CCommand &cmd)
|
|
||||||
{
|
|
||||||
unsigned int argnum = cmd.ArgC();
|
|
||||||
|
|
||||||
if (argnum >= 2)
|
|
||||||
{
|
|
||||||
const char *cmdname = cmd.Arg(1);
|
|
||||||
if (strcmp(cmdname, "text") == 0)
|
|
||||||
{
|
|
||||||
_IntExt_EnableYams();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (strcmp(cmdname, "internal") == 0)
|
|
||||||
{
|
|
||||||
if (argnum >= 3)
|
|
||||||
{
|
|
||||||
const char *arg = cmd.Arg(2);
|
|
||||||
if (strcmp(arg, "1") == 0)
|
|
||||||
{
|
|
||||||
SM_ConfigsExecuted_Global();
|
|
||||||
}
|
|
||||||
else if (strcmp(arg, "2") == 0)
|
|
||||||
{
|
|
||||||
if (argnum >= 4)
|
|
||||||
{
|
|
||||||
SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IRootConsoleCommand *pHandler;
|
|
||||||
if (sm_trie_retrieve(m_pCommands, cmdname, (void **)&pHandler))
|
|
||||||
{
|
|
||||||
pHandler->OnRootConsoleCommand(cmdname, cmd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConsolePrint("SourceMod Menu:");
|
|
||||||
ConsolePrint("Usage: sm <command> [arguments]");
|
|
||||||
|
|
||||||
List<ConsoleEntry *>::iterator iter;
|
|
||||||
ConsoleEntry *pEntry;
|
|
||||||
for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
|
|
||||||
{
|
|
||||||
pEntry = (*iter);
|
|
||||||
DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
|
||||||
{
|
|
||||||
if (strcmp(cmdname, "credits") == 0)
|
|
||||||
{
|
|
||||||
ConsolePrint(" SourceMod was developed by AlliedModders, LLC.");
|
|
||||||
ConsolePrint(" Development would not have been possible without the following people:");
|
|
||||||
ConsolePrint(" David \"BAILOPAN\" Anderson, lead developer");
|
|
||||||
ConsolePrint(" Borja \"faluco\" Ferrer, Core developer");
|
|
||||||
ConsolePrint(" Scott \"Damaged Soul\" Ehlert, Core developer");
|
|
||||||
ConsolePrint(" Pavol \"PM OnoTo\" Marko, SourceHook developer");
|
|
||||||
ConsolePrint(" Special thanks to Viper of GameConnect");
|
|
||||||
ConsolePrint(" Special thanks to Mani of Mani-Admin-Plugin");
|
|
||||||
ConsolePrint(" http://www.sourcemod.net/");
|
|
||||||
} else if (strcmp(cmdname, "version") == 0) {
|
|
||||||
ConsolePrint(" SourceMod Version Information:");
|
|
||||||
ConsolePrint(" SourceMod Version: %s", SVN_FULL_VERSION);
|
|
||||||
ConsolePrint(" JIT Version: %s, %s", g_pVM->GetVMName(), g_pVM->GetVersionString());
|
|
||||||
ConsolePrint(" JIT Settings: %s", g_pVM->GetCPUOptimizations());
|
|
||||||
ConsolePrint(" http://www.sourcemod.net/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CON_COMMAND(sm, "SourceMod Menu")
|
|
||||||
{
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
|
||||||
CCommand args;
|
|
||||||
#endif
|
|
||||||
g_RootMenu.GotRootCmd(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *g_pHndlLog = NULL;
|
|
||||||
|
|
||||||
void write_handles_to_log(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(g_pHndlLog, fmt, ap);
|
|
||||||
fprintf(g_pHndlLog, "\n");
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_handles_to_game(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
va_list ap;
|
|
||||||
char buffer[1024];
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
buffer[len] = '\n';
|
|
||||||
buffer[len+1] = '\0';
|
|
||||||
|
|
||||||
engine->LogPrint(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
|
|
||||||
{
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
|
||||||
CCommand args;
|
|
||||||
#endif
|
|
||||||
if (args.ArgC() < 2)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(args.Arg(1), "log") != 0)
|
|
||||||
{
|
|
||||||
const char *arg = args.Arg(1);
|
|
||||||
FILE *fp = fopen(arg, "wt");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pHndlLog = fp;
|
|
||||||
g_HandleSys.Dump(write_handles_to_log);
|
|
||||||
g_pHndlLog = NULL;
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_HandleSys.Dump(write_handles_to_game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user