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